Advanced Permission Management

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

livetronix
Forum Newbie
Posts: 6
Joined: Mon Aug 30, 2004 1:53 am

Advanced Permission Management

Post by livetronix »

I am trying to setup an intranet management system with some very pain in the *** permission levels.

You can have 3 users: (more to come alter)
- Admin
- Employee
- Secretary

Each user should get access to certian areas and see certian links while the other should not.

Also users can be part of multiple groups. A user could be an Admin and an Employee. They're are also different companies

Company 1
-> Seattle Branch
-> Sacramento Branch
Company 2
-> New York
-> Dallas

There would be a super admin of all the companies that can add employees any permission, than there would be Seattle Branch Admin, etc.

I need a system that is very flexible and can be expanded upon easily without a whole rewrite.

It needs to work two ways:
1. On menu pages, don't show this link if user doesn't have permission.
2. Give permission denied if they try to access certian pages.

I know it's probably not going to be too friendly on the database but it is a requirement for this project.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

sounds like a simple many-to-many relationship set up to me.

http://www.oreilly.com/catalog/javadtab ... r/ch02.pdf

you'll probably need a function to slap together all the permissions for any given location..
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

You probably don't need that complicated a system. I would suggest just having two fields in each user record: company and access. Company can contain a 1,2,3... so you can select data and display for only the user's company. The access field can be as simple as a comma delimited string: Admin,Employee,Secretary. Then for access control you can do something like this:

// assuming you have authenticated the user and stored info in session
$access = explode(',', $_SESSION['user']['access']);
$groups = array_intersect ($access, array('Admin', 'Employee'));
if ($groups) {
// access allowed
} else {
// access denied
}
livetronix
Forum Newbie
Posts: 6
Joined: Mon Aug 30, 2004 1:53 am

Post by livetronix »

Arborint,

Thats a start, but here are a couple problems I feel I will face...

1. For Modular Purposes, I want to define the groups dynamically.
2. Somehow the Super Admin should be able to redefine permissions for specific users.
3. If a user is a member of multiple companies they could have multiple permissions.

I had a meeting with the people tonight, we kind of decided that they should pick there role on a menu. Since different roles have different admins. So at least we can limit them to one role and one company at a time - that should simplify the process.

IE: Groups: The user is a member of Admin, Secretary in Company 1 and Reviewer and Processor in Company 2.
Right now they are acting as a Sec in Company 1.

I don't know if that makes sense to anyone, I am kind of confused as it is.
livetronix
Forum Newbie
Posts: 6
Joined: Mon Aug 30, 2004 1:53 am

Post by livetronix »

Code: Select all

User
	UserID
	Email
	FirstName
	LastName

Group
	GroupID
	GroupName

PermissionGroup
	PermissionGroupID
	PageID
	GroupID
	Level (Y, N, L) Yes, No, Limited

PermissionUser – overrides the group permissions
	UserPermissionID
	UserID
	PageID
	CompanyID
	Level (Y, N, L) Yes, No, Limited

Page
	PageID
	Fuseaction

Session
	SessionID
	UserID
	Hash
	StartTimeStamp
	LastTimeStamp

Company
	CompanyID
	CompanyName

CompanyUser
	CompanyUserID
	CompanyID
	UserID
This is how I think the database could work. It should work the way I've concepulized things, is it the most productive way? Database heavey?
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

I haven't used phpgacl but it might be worth a look.
livetronix
Forum Newbie
Posts: 6
Joined: Mon Aug 30, 2004 1:53 am

Post by livetronix »

McGruff wrote:I haven't used phpgacl but it might be worth a look.
I looked at PHPGacl, the tutorial they have doesn't make any sense to me, it doesn't show how to use their confusing Admin Panel. Anyone used it before?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

1. For Modular Purposes, I want to define the groups dynamically.
Not sure what you mean here. I assume that the groups are just names that are specific to each implementation. In this case Admin/User, in another Teacher/Student. Or you could have a separate table where 1=Admin, 2=User and look up the descriptions.

2. Somehow the Super Admin should be able to redefine permissions for specific users.
Since the groups and companies are fields in each user's database record, the admin can updated them as needed. The example assumed that the groups had been previously loaded into a session var when the user signed-in. The example has array_intersect ($access, array('Admin', 'Employee')) where $access contains the groups from the user's record and array('Admin', 'Employee') are what are allowed to view this page.

3. If a user is a member of multiple companies they could have multiple permissions.
IE: Groups: The user is a member of Admin, Secretary in Company 1 and Reviewer and Processor in Company 2.
Right now they are acting as a Sec in Company 1.

The simplest would be to have a different account for each company. You could also make the format of the permissions with company and role info like "1:Admin,2:Admin,2:Secretary" but then they would have to select which role the were in. Multiple accounts for these people might be simpler. [/i][/quote]
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

Arborint: that's not a good database structure. See http://www.oreilly.com/catalog/javadtab ... r/ch02.pdf
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

I have found that Java Best Practices are often PHP Worst Practices. Things like phpgacl are good examples of Java inspired overkill. It may be good for some massive system, but I got it working and never used it because it was too big, slow and complicated. The theories might be great.
(#10850)
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

You might be right about phpgacl - as I said I haven't used it.

Sorry I was a bit terse. However, db normalisation is important, whichever lanugage you're coding in. Storing all that data in one field is not a flexible solution, I think.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Actually I think I was the one who was a bit terse, sorry.

I think my take on this is that it is not a database problem at all. I doubt the site would be doing any SELECTs on the "access" field. Maybe on an admin page somewhere, but certainly not a high traffic page.

The data in the "access" field is loaded once when the user is authenticated. Then I'm assuming that it is saved in the session (or a cookie). After that the access control code in a page uses the data in the session to check if the user has access to the page. You don't want to go to the database on each page for access control in PHP. In Java with data persistance or caching it is a whole different thing.

This is a case of the Perl coder in me beating up the Java coder in me (they fight a lot) and I lapse into string splitting, arrays and regexp. I have used similar (optimized) code on sites with >25k users so I know its fast and works. Also building the access fields is simply imploding the value of a multi-select form var. I doubt I would even head down the "1:Admin,2:Admin,2:Secretary" road, but it does only gets parsed once at authentication. Access control is still just an array check (e.g. array_intersect($access[$company], array('Admin', 'Employee')).

Finally I like the explicit, self documenting quality of code like:

if ($access->allow(array('Admin', 'Secretary')) {
or
$controller->allowAccess(array('Admin', 'Secretary'));
(#10850)
livetronix
Forum Newbie
Posts: 6
Joined: Mon Aug 30, 2004 1:53 am

Post by livetronix »

I was going to program it as a multi query select to see if they have access.

Code: Select all

SELECT Level FROM UserPermission WHERE UserID = $UserID AND PageID = $PageID AND CompanyID = $CompanyID 

if ($Level == Yes) {
 // they have permission
} else {
// Load Groups User is IN
   /* code here */
// Check permission
SELECT Level FROM GroupPermission WHERE GroupID = $GroupID AND PageID = $PageID
if ($Level == Yes) { // on any group since we take highest permission
 // they have permission
} else {
 // Permission Denied
}
}
Thats like an extra 3-4 queries per page, nothing huge. This site will be a log in only system and we will be making money from the logged in users so it doesn't have to be fast as lightening, but I don't want to build a system that chugs and is not scalable.

How would you do the authentication part looking at my database structure (posted above).
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

What about this (<--> denotes a many-to-many relationship and an intermediate join table, not shown):

user <--> user_groups <--> page_groups <--> pages

User_groups could be Seattle admin, Charleston employees, etc. Unless you need to find permissions based on level or company alone (which you don't, if I understand you right), that might be an acceptable denormalisation.

The super-admin is simply a user group with one member. Possibly there is no need for a parallel system of permissions allocated at the user and group levels.

The page_groups table (ie defined sections or areas of the site) might make managing permissions easier in the same way as the user groups table: ie you can assign groups of pages to user groups rather than one page at a time. Or it might not really be necessary.

A single INNER JOIN query gets all the user's permissions.
livetronix
Forum Newbie
Posts: 6
Joined: Mon Aug 30, 2004 1:53 am

Post by livetronix »

Only problem is permission levels should be, first group based and than user based.

IE: You can put a user in certian groups, but you have the ability to overwrite certian permission by specific user.

Plus for each individual company a member is involved in they should get a different permission basis. IE: SuperAdmin of one company but regular user of another company.

This is getting very confusing...
Post Reply