Monday, 16 April 2012

Using bitwise operators to assign permission levels of users

Bitwise operators if tactfully used can be very efficient in storing permission levels of users in an application. Notice there is something special about the numbers 1, 2, 4, 8 and 16. In each of these values the left- most 1 - bit advances a placeholder. These are powers of 2 (20=1, 21 =2, 22 =4, 23 =8, 24 =16 and so forth). This is the reason why they can be used as the integer values for the permission constants.

For eg., let the permissions be

1 = 0000 0001 for READ,
2 = 0000 0010 for CREATE,
4 = 0000 0100 for UPDATE,
8 = 0000 1000 for DELETE

This means, permissions of READ and UPDATE both would be specified by turning the 1st and 3rd bits on from the right, i.e., 0000 0101, which we can get by applying bitwise ‘or’ on 1 and 4.
1 |4 = 5 = 0000 0101.

<?php

class User
{
 //Permission levels
   const READ=1;
   const CREATE=2;
   const UPDATE=4;
   const DELETE=8;
     
   public $name;
   public $permission;
     
   public function addPermission($perm)
   {
     $this->permission=$perm;
   }
     
   public function removePermission($perm)
   {
     $this->permission = ~$perm & $this->permission;
   }
     
   public function showDetails()
   {
     echo '<br />';
     echo $this->name;
     echo ($this->permission & self::READ)? '<br />READ - YES':'<br />READ - NO';
     echo ($this->permission & self::CREATE)? '<br />CREATE - YES':'<br />CREATE - NO';
     echo ($this->permission & self::UPDATE)? '<br />UPDATE - YES':'<br />UPDATE - NO';
     echo ($this->permission & self::DELETE)? '<br />DELETE - YES':'<br />DELETE - NO';
    }
     
}

$user=new User();
$user->name='Barun Samanta';

$user->addPermission(User::READ|User::CREATE);
$user->showDetails();

$user->removePermission(User::CREATE);
$user->showDetails();

?>

In the code, to see if the user has been granted a particular permission, just mask out the value you are looking for with bitwise-and.

$this->permission & self::CREATE

Since in the CREATE permission all bits are zeros except the 2nd one from the right, therefore the result of the operation ($this->permission & self::CREATE) would evaluate to true if the 2nd bit from right in $this->permission
is 1 and false if the same bit is 0.

To remove a permission we apply ~$perm & $this->permission.
This means, if the permission we want to remove be UPDATE (0000 0100) from the permission set 0000 0101 (READ, UPDATE) we apply a bitwise AND of ~0000 0100 = 1111 1011 on 0000 0101. We get 0000 0001 as result. In the number 1111 1011, since all the bits are 1 except the 3rd from the right, the bitwise-and operation simply turns-off the bit for UPDATE keeping all other bits in the permission-set 0000 0101 unchanged.



Note: To store the permission in the MySQL database, simply use a column of type int(10) unsigned.

No comments:

Post a Comment

document.write() overwrites the entire page

document.write is a function which basically outputs whatever is given to it. But sometimes, improper usage may overwrite the entire page d...