I need a bitwise permissions system (I think)

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

I need a bitwise permissions system (I think)

Post by Luke »

I am building an application large enough that it needs a robust permissions system. I have read this thread once viewtopic.php?t=43510&start=15&postdays ... ons+system and will read it thoroughly again, but the math just doesn't make sense to me. Is there somebody willing to explain to me in sub-laymen's terms how a bitwise permissions system works?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Why do you need a bitwise permission system? You're going to use OOP yes? Then just use boolean properties.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

see this is exactly why there was the (I think) attached to the end of the thread title. I did some searching around and that seemed to be the solution that was recommended. I just need to be able to assign permissions to groups as well as users, and I've read in a few places (and my knowledge about permissions is far from expansive) that one-to-one relationships between users and permissions is bad.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

Bitwise permissions can develop problems that you might not see now. What is the structure of your permissions? Maybe there is a better way to do it.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

I will have a handful of "admins" which have (more or less) full access to the system. These will be myself and the owner of the application, and maybe a few others (so I may need some access as an admin that they do not have). Then there will be "members" which can move about the application, but their access is severely limited, BUT they can be granted "Team leader" status, which allows emailing access and a few other "team" administration rights. Then there is "Project Leader" status. There are projects that the team can partake in, and this member would be the "leader" of the project. He would need some rights that not everybody has. And lastly "Team Co-leader" status, which is just a step down from "Team Leader". There will also need to be room for expansion.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

So will each level be a subset of the level above it?
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

yes, but each level will need to be granted or restricted privileges on top of their "set" privileges. So let's say there is a "Team Leader". All team leaders have the following rights:
Email My Team,
Email Admins,
Edit My Team Settings
Add My Team to Projects

but I've decided I really like "Team Leader" "Steve" so I let him have this right as well...
"Add events to event calendar"

That's the part where I have issues... :?
Begby
Forum Regular
Posts: 575
Joined: Wed Dec 13, 2006 10:28 am

Post by Begby »

I use bitwise permissions, perhaps one of these guys will explain to both of us why its a bad idea.

Even if you don't use it, it is something that is good to know in case you are looking at someone else's code or maybe knowing the drawbacks can see uses for it. The advantage is you can store multiple true/false properties for an entity in a single field. You might recognize fields like this in some databases you see. Often they are referred to as flags.

You setup permissions as powers of 2, like this (its a bit clearer to put them in hex, but don't worry about that right now)

Code: Select all

define( 'TACO', 1 ) ;
define( 'POTATO_CHIP', 2 ) ;
define( 'PIZZA', 4 ) ;
define( 'MEATLOAF', 8 ) ;

// or in a class in PHP 5 that (this is nice because it doesn't pollute the namespace)

class food
{
  const TACO = 1 ;
  const POTATO_CHIP = 2 ;
  const PIZZA = 4 ;
  const MEATLOAF = 8 ;
}

One thing to notice is that with powers of two, when you look at them in binary, look like this

Code: Select all

1 = 0000001
2 = 0000010
4 = 0000100
8 = 0001000
16= 0010000
Lets look at what happens when we add up the numbers

Code: Select all

2 + 8 = 0001010
16 + 1 = 0010001
1 + 2 + 4 + 8 + 16 = 0011111
Imagine a row of light switches, adding up the numbers is kinda like switching some of the lightswitches on. Now consider the bitwise operator '&'. This does a binary comparison where it compares the bits one by one by one between two numbers. If the bits are 1 in both numbers, then the bit in the result in the same spot will also be one, otherwise the bit will be zero. That might be confusing so look at this

Code: Select all

$foods = food::TACO + food::PIZZA ; // This is 1+4, so the binary is 0000101

$result1 = food::TACO & $foods ;
/*
This does a binary comparison like
0000101
0000001

The value in $result1 is 
0000001
because there is a one in the last column in both numbers
*/
$result2 = food::MEATLOAF & $foods ;

/*
0000101
0001000

This time the value in $result 2 is
0000000
because no ones match in any column
*/

Ok, so hopefully that will clear it up a bit in laymanese. How this works in real life is you can create a set of permission with binary values, like read, write, delete, and move. Then you can add them up. So if user X has read/write you would say $rights = READ + WRITE. To check if that user had READ access you would do if( $rights & READ ) { echo 'has read' }.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

What happens when you want to add a permission in between 4 and 8?
Begby
Forum Regular
Posts: 575
Joined: Wed Dec 13, 2006 10:28 am

Post by Begby »

From your last response it looks like you might want to research ACLs. There are some libraries out there that will do what you want to accomplish. Google it. You can assign rights at the group level and also the user level and it will assign to the user the most restrictive rights. This is something that you can accomplish with bitwise operators too but you can probably get by with an existing library.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

wow... what an excellent explanation. Thank you... that makes sense now. :D
Begby
Forum Regular
Posts: 575
Joined: Wed Dec 13, 2006 10:28 am

Post by Begby »

Everah wrote:What happens when you want to add a permission in between 4 and 8?
You don't add a permission between 4 and 8, you add it at the end. The order of the permissions is meaningless.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

Begby wrote:From your last response it looks like you might want to research ACLs. There are some libraries out there that will do what you want to accomplish. Google it. You can assign rights at the group level and also the user level and it will assign to the user the most restrictive rights. This is something that you can accomplish with bitwise operators too but you can probably get by with an existing library.
phpgacl is the only one I've found. I've always had a difficult time with ACL systems, but then again I haven't tried messing with any for a while. I understand at least 50% more than I did a few months back, so let's see if I get it now.
Begby
Forum Regular
Posts: 575
Joined: Wed Dec 13, 2006 10:28 am

Post by Begby »

The Ninja Space Goat wrote:
Begby wrote:From your last response it looks like you might want to research ACLs. There are some libraries out there that will do what you want to accomplish. Google it. You can assign rights at the group level and also the user level and it will assign to the user the most restrictive rights. This is something that you can accomplish with bitwise operators too but you can probably get by with an existing library.
phpgacl is the only one I've found. I've always had a difficult time with ACL systems, but then again I haven't tried messing with any for a while. I understand at least 50% more than I did a few months back, so let's see if I get it now.
Cake has one too that is simpler. I think codeigniter might also. You can probably ninja some code from one of those, you are THE ninja space goat after all!
User avatar
Kieran Huggins
DevNet Master
Posts: 3635
Joined: Wed Dec 06, 2006 4:14 pm
Location: Toronto, Canada
Contact:

Post by Kieran Huggins »

I would use named permission array templates, then merging them for the final permission array. They're easier to see in code then $perm='0000110101101010'; An example (for forum posts):

Code: Select all

// level 1: default permissions
$default = array(
		'posting'	=>	'no',
		'reading'	=>	'yes',
		'deleting'	=>	'no',
		'editing'	=>	'no',
		'moderating'=>	'no',
		'use_html'	=>	'no'
	);

// level 2: role templates
$user = array( // everyone is a user (how cynical!)
		'posting'	=>	'yes'
	);

	$moderator = array( // is also a user
			'editing'	=>	'yes',
			'moderating'=>	'yes'
		);
	$admin = array( // is also a user
			'editing'	=>	'yes',
			'moderating'=>	'yes',
			'deleting'=>	'yes'
		);

// level 3: individual account permissions
$frank = array(
		'use_html'	=>	'yes', // we're enabling html for frank
		'editing'	=>	'no'   // but we don't trust him to edit
	);


// now we create frank's total permission set: (frank is a moderator)
$franks_permissions = array_merge($default,$user,$moderator,$frank);

// print out frank's permissions:
print_r($franks_permissions);

/* output:
Array
(
    [posting] => yes
    [reading] => yes
    [deleting] => no
    [editing] => no
    [moderating] => yes
    [use_html] => yes
)
*/

// awesome - that's exactly what I wanted

// example permission check: can frank post html?
if($franks_permissions['use_html']='yes'){/* yes he can */}
Hope that gets you started.

Cheers,
Kieran
Post Reply