2 minute read

Permission Mask Diagram
Permission Mask Diagram

Permission systems in enterprise applications often rely on compact and efficient representations of access rights. One of the most common techniques is the permission mask, where a single numeric value encodes many individual permissions through bitwise operations. This approach may look complex at first glance, but understanding how these masks are constructed makes the system both predictable and powerful.

What a Permission Mask Represents

A permission mask is essentially a collection of bits, where each bit corresponds to a specific permission. Turning a bit on means the permission is granted. This compact storage makes permission checks extremely fast and easy to manage.

For example:


0000 0010 → view
0000 1000 → delete
0001 0000 → edit attributes

When combined, these bits form a single value representing multiple access rights simultaneously.

How the Mask Is Built

Consider the following structure:

ulong permissionMask = 128;

if (HasPermission(perms, "see"))
    permissionMask |= 2;

if (HasPermission(perms, "see_contents"))
    permissionMask |= 36865;

if (HasPermission(perms, "modify"))
    permissionMask |= 65536;

if (HasPermission(perms, "edit_attributes"))
    permissionMask |= 131072;

if (HasPermission(perms, "delete_versions"))
    permissionMask |= 16384;

if (HasPermission(perms, "add_items"))
    permissionMask |= 4;

if (HasPermission(perms, "delete"))
    permissionMask |= 8;

if (HasPermission(perms, "reserve"))
    permissionMask |= 8192;

if (HasPermission(perms, "edit_permissions"))
    permissionMask |= 16;

if (HasPermission(perms, "add_major_version"))
    permissionMask |= 256;

Each permission name corresponds to a numeric value, and the expression |= (bitwise OR assignment) enables the selected bit in the mask. This ensures that the mask gradually accumulates all applicable flags.

Permission Flags Table

Permission Name Flag Value Description
see 2 Allows viewing the object.
add_items 4 Allows adding new child items or documents.
delete 8 Allows deleting the object.
edit_permissions 16 Allows modifying the object’s permissions.
reserve 8192 Allows reserving (checking out) the object.
delete_versions 16384 Allows deleting previous versions of the object.
modify 65536 Allows modifying the object’s content or metadata.
edit_attributes 131072 Allows editing attribute values.
add_major_version 256 Allows creating a major version of the object.
see_contents 36865 Allows viewing contents inside containers (folders, cabinets, etc.).

Each value is a predefined bit pattern representing a unique permission.

Step-by-Step Mask Construction

Suppose the evaluated permissions include see, delete, and reserve. The mask evolves as follows:

  1. Start with:

    128
    
  2. Apply see (2):

    128 | 2 = 130
    
  3. Apply delete (8):

    130 | 8 = 138
    
  4. Apply reserve (8192):

    138 | 8192 = 8330
    

The resulting mask, 8330, now encapsulates all three permissions within one numeric value.

Why This Approach Works Well

Bitwise masking offers several advantages:

  • Performance: Binary comparisons are extremely fast.
  • Compactness: Dozens of permissions can be stored in a single integer.
  • Simplicity: Checking a permission requires one expression:

    bool canDelete = (permissionMask & 8) != 0;
    
  • Scalability: Additional permissions can be added by assigning new bits.

Final Thoughts

Permission masks strike a balance between efficiency and clarity. By representing each permission as a bit and combining them into a single value through bitwise OR operations, enterprise applications gain a reliable and scalable system for managing access rights. This technique continues to serve as a foundational pattern in authorization design across many platforms and frameworks.

Leave a comment