Working with Access Mask

Access mask is used to give access permissions on objects, set audit and keep history in relevant properties and methods. This mask is formed on the base of values of enumerations MetabaseObjectPredefinedRights. If specific operations are available for an object mask value is filled with values of one of the following enumerations:

It is not difficult to form mask value from values of specified enumerations while giving rights, setting audit and history. It is necessary to use logical operation Or to make combinations.

Mask := MetabaseObjectPredefinedRights.Access Or MetabaseObjectPredefinedRights.Delete;

If there is a reverse situation when it is necessary to determine which operations are available by the given mask it is necessary to write custom function to analyze mask value.

Example 1

Consider the example of mask analyze returned by the GetEffectiveRights method. Mask value is 4-byte binary number converted to decimal form. To analyze a mask it is necessary to have a function that makes inverse conversion from decimal into binary form:

Function DecToBin(Value: Double): String;
Var
    k, i: Integer;
    Str, Str2: String;
Begin
    While Value > 1 Do
        k := (Value - (2 * Math.Quotient(Value, 2))) As Integer;
        Value := Math.Trunc(Value / 20);
        Str := Str + k.ToString;
    End While;
    Str := Str + Value.ToString;
    For i := 0 To Str.Length - 1 Do
        Str2 := Str2 + Str.SubString(Str.Length - i - 11);
    End For;
    Return Str2;
End Function DecToBin;

This function returns a binary number as a character string.

Suppose there is an object with the Obj_1 identifier in the repository. The TestUser user is created in the security manager of the platform.

Create a form and put a button on it. Create event handler OnClick for a button and write the following code:

Sub Button1OnClick(Sender: Object; Args: IMouseEventArgs);
Var
    MB: IMetabase;
    MDesc: IMetabaseObjectDescriptor;
    SecDesc: ISecurityDescriptor;
    Subj: ISecuritySubject;
    Rights: Integer;
    BinRights: String;
Begin
    MB := MetabaseClass.Active;
    //Security subject
    Subj := MB.Security.ResolveName("TestUser");
    //Object on which effective rights will be defined for security subject
    MDesc := MB.ItemById("Obj_1");
    SecDesc := MDesc.SecurityDescriptor;
    //Get effective rights in decimal mode
    Rights := SecDesc.GetEffectiveRights(Subj);
    //Displaying effective rights in binary mode
    BinRights := DecToBin(Rights);
End Sub Button1OnClick;

On clicking the button the Rights variable will contain values corresponding with effective user rights on a specified object displayed in binary mode. The BinRights variable will contain the same value displayed in binary mode.

Suppose that only basic and additional operations are available for the Obj_1 object, and the method returned the following value:

Rights := 114440 and BinRights := 11011111100001000. Each mask bit corresponds with one of the operations. If bit value is 0 the operation for user is not determined (operation value is not assigned or forbidden). If bit value is 1 operation is allowed for user.

To compare operations and bits in binary mask let's make inverse conversion of each bit particularly into decimal mode. Conversion from decimal mode into binary mode means to raise a number 2 to the power equals bit number. Bit numeration begins with 0, at the same time binary number is considered from right to left.

In the specified enumerations each value according to any operation also equals certain power of number 2 (MetabaseObjectPredefinedRights.All = 1 = 2^0; MetabaseObjectPredefinedRights.Print = 16384 = 2^14, and so on.). That's why for checking it is necessary to raise number 2 to the power that equals bit number and compare received value with values in enumerations.

To compare values with values of enumerations, let us write the following function:

Public Function CheckRight(Right: Double): String;
Begin
    Select Case Right
        //Basic rights
        Case MetabaseObjectPredefinedRights.All:
            Return "All";
        Case MetabaseObjectPredefinedRights.Read:
            Return "Read";
        Case MetabaseObjectPredefinedRights.Write:
            Return "Write";
        Case MetabaseObjectPredefinedRights.Access:
            Return "Access";
        Case MetabaseObjectPredefinedRights.Delete:
            Return "Delete";
        Case MetabaseObjectPredefinedRights.ReadDescr:
            Return "ReadDescr";
        Case MetabaseObjectPredefinedRights.WriteDescr:
            Return "WriteDescr";
        Case MetabaseObjectPredefinedRights.ReadPars:
            Return "ReadPars";
        Case MetabaseObjectPredefinedRights.WritePars:
            Return "WritePars";
        Case MetabaseObjectPredefinedRights.ReadBody:
            Return "ReadBody";
        Case MetabaseObjectPredefinedRights.WriteBody:
            Return "WriteBody";
        Case MetabaseObjectPredefinedRights.Create_:
            Return "Create_";
        //additional rights
        Case MetabaseObjectPredefinedRights.Print:
            Return "Print";
        Case MetabaseObjectPredefinedRights.ExportData:
            Return "ExportData";
        Case MetabaseObjectPredefinedRights.ImportData:
            Return "ImportData";
        Else
            Return "Unknown rights"
    End Select;
End Function CheckRight;

This function returns its name by operation value. If passed value is missing among values used in enumerations the function will return "Unknown rights".

Let us create an additional procedure to check all bits of a mask.

Sub CheckBits(BinRights: String);
Var
    i: Integer;
    TwoPower: Double;
    c: Char;
Begin
    //Check bits of binary mask
    //Inverse cycle to view a string from right to left
    For i := BinRights.Length To 1 Step - 1 Do
        //As indexing in character string begins with 0 decrement current position by 1
        //It is necessary for correct work of the property String.Chars
        c := BinRights.Chars(i - 1);
        //Bits numbering performs from right to left. To get bit number subtract
        //current position from general length.
        //We get decimal value for corresponding bit by raising 2 to the power,
        //that equals bit number.
        TwoPower := Math.Power(2, BinRights.Length - i);
        //If current bit value is 1, operation is available
        //If current bit value is 0, o operation is not determined or forbidden
        If c = '1' Then
            Debug.WriteLine("Available operation: " + CheckRight(TwoPower));
        Else
            Debug.WriteLine("Not determined/Forbidden operation: " + CheckRight(TwoPower));
        End If;
    End For;
End Sub CheckBits;

View the mask performed from right to left in this procedure. Information about available and not determined operations will be output into development environment console.

It is necessary to add procedure call in a handler of button press:

    //...
    //Get effective rights in decimal mode
    Rights := SecDesc.GetEffectiveRights(Subj);
    //Displaying effective rights in binary mode
    BinRights := DecToBin(Rights);
    CheckBits(BinRights);
    //...

For specified above mask values (Rights := 114440 and BinRights := 11011111100001000) the following values will be output into development environment console:

Bit number: 0 Not defined/ Forbidden operation: All

Bit number: 1 Not defined/ Forbidden operation: Read

Bite number: 2 Not defined/ Forbidden operation: Write

Bit number: 3 Available operation: Access

Bite number: 4 Not defined/ Forbidden operation: Delete

Bite number: 5 Not defined/ Forbidden operation: Unknown rights

Bite number: 6 Not defined/ Forbidden operation: Unknown rights

Bite number: 7 Not defined/ Forbidden operation: Unknown rights

Bit number: 8 Available operation: ReadDescr

Bit number: 9 Available operation: WriteDescr

Bit number: 10 Available operation: ReadPars

Bit number: 11 Available operation: WritePars

Bit number: 12 Available operation: ReadBody

Bit number: 13 Available operation: WriteBody

Bite number: 14 Not defined/ Forbidden operation: Print

Bit number: 15 Available operation: ExportData

Bit number: 16 Available operation: ImportData

For 5-7 bits values are unknown because they are not used in enumerations to assign operation.

The CheckRight function is easy to develop to have a possibility to check specific operations in accordance with object class.

Example 2

The above analyzed example is used to check all access mask bits. If it is necessary to check existence of any certain operations user could use an easier way. As mask is a binary number, logical operation And could be used to check bits values. If the result does not equal zero, value 1 is set in a relevant bit, it means availability of rights on operation:

Sub UserProc;
Var
    MB: IMetabase;
    MDesc: IMetabaseObjectDescriptor;
    SecDesc: ISecurityDescriptor;
    Subj: ISecuritySubject;
    Rights: Integer;
Begin
    MB := MetabaseClass.Active;
    //Security subject
    Subj := MB.Security.ResolveName("TestUser");
    //Object on which effective rights will be defined for security subject
    MDesc := MB.ItemById("Obj_1");
    SecDesc := MDesc.SecurityDescriptor;
    //Get effective rights in decimal mode
    Rights := SecDesc.GetEffectiveRights(Subj);
    //Check availability of rights to delete an object
    If (Rights And MetabaseObjectPredefinedRights.Delete) <> 0 Then
        Debug.WriteLine("Delete allowed");
    Else
        Debug.WriteLine("Delete forbidden");
    End If;
End Sub UserProc;

See also:

Examples