General description
The system should handle a lot of items organized into nested categories (see visual example below) while giving the clients the ability to define the permission rules (see permission rules below). It should also handle different general permissions that are independent of any items (e.g. 'can view specific page?' or 'can invite new members?').
All users are organized into groups. Each user has a main group that he's belongs to, but he may also have some additional secondary groups.
A few users could be configured as super-admins and should be allowed to do anything.
When deciding if a user is allowed to do something, the permission inheritance is as follow:
When defining the group permission, the client could use inheritance to say something like:
NOTE: I should be able to request the last 10 items from the database that the current user can edit/view, the permission for each item should be decided by the database, I don't want to filter items for permission in the application level if I could decide that based on info stored in the database.
Permission rules
Rules could depend on any property of the item (e.g. item's owner's main group, creation time, category etc...), that info is stored in the database.
Rules could also depend on any property of the current user (e.g. signing-up date, members invited), requested action (e.g. view, list, rename, undo delete etc), and other info already available on run-time (e.g. url parameters, quota limits, item's content, server load), that info is available to the php script.
See sample rules below.
Visual example of database schema:
Category 1
Nested Category A
item x
Nested Category B
Deeply Nested Category
item w
item y
Category 2
item z
Currently, the database schema is like the following but I can change it if it's required: (of course this is only part of the schema, there are other tables and fields as well)
items:
id | title | owner_id | category_id
====================================
1 | item x | 2 | 3
2 | item y | 1 | 4
3 | item z | 3 | 2
4 | item w | 1 | 5
categories:
id | parents | title
=====================================
1 | null | Category 1
2 | null | Category 2
3 | 1 | Nested Category A
4 | 1 | Nested Category B
5 | 1/4 | Deeply Nested Category
users:
id | name | group | all_groups | is_super_admin
===============================================
1 | Tony | 5 | 5 | 1
2 | John | 5 | 5,8,6 | 0
3 | Mike | 4 | 4,7 | 0
4 | Ryan | 6 | 6 | 0
Sample rules
The following rules are just sample of real world cases that should be implemented.
Notice that these rules could be decided in the database level like most of the rules in my case.
Implementation
I've searched symfony docs, stackoverflow etc. There are a lot of interesting articles and questions on the topic of security and acls but I couldn't find the best way to handle such a system.
It's clear that I need some type of dynamic query builder to filter rows based on info stored in the database according to the defined rules. I'm assuming the second step (that involve info that isn't stored in the database like current server load) is probably to implement a voter (see voter example in this article or this question), or sometimes even simpler solution (such as rules that depends on the requested path). If the solution involving more than one thing to handle permissions, please also describe how to integrate and use them together.
Question
I'm asking how to implement such a system, please do not answer with links to symfony documentation or other resources with general idea and common simple cases. Please read and understand my case before answering.
I realize this question is old, but answer is applicable for Symfony 2.3+, so I post it here.
For this approach you should use things like SecurityVoters.
With security voters you can implement any logic for access controls, which you can imagine.
Voters works like
$this->get('security.authorization_checker')->isGranted('update',$post);
which will check all voters, who can operate a Post entities (see docs) and combine their votes with choosen strategy (affirmative, consensus, unanimous) to decide if the current user is authorized to update post (for your first tule example)
You can implement several voters for single action and define strategy hove to decide resulting vote.
All groups and permissions you could store in the repository and fetch them with doctrine inside voter.
Also you can define custom role hierarhy for simplifying security works
Also read these docs on SecurityComponent
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With