In this part I'll describe main blocks of security system architecture, i.e. roles & permissions.
First of all, let's start with roles. As you might remember, there is a list of positions in our imaginary sales organization:
- Stock manager
- Sales representative
- Sales manager
- Sales president
Role hierarchy for the imaginary sales company:
Note, that each role is defined as a separate class. This approach as any other one has advantages and well as drawbacks. It is less dynamic, but provides natural inheritance, doesn't require persistence and is more intuitive, visual and understandable. Moreover, as roles in a company are mostly static, I've found the approach highly advantageous.
Look, EmployeeRole inherits a Role class. This is the base role class, it provides inheritors with necessary infrastructure: a set of Permissions for a role, name of a role and a method for permission registration.
To continue with roles hierarchy configuration we should define a permission first. According to the access matrix in the previous post, there are 2 common permissions that are actual for all kind of entities: Read permission & Write permission. In addition to these basic ones, there might be extended permissions as well, like Approve permission defined for Order entity type. Thus, we've defined a base Permission type and OrderPermission inheritor that provides requested functionality:
Here is how EmployeeRole is declared:
public class EmployeeRole : Role { public EmployeeRole() { // This is base role for every employee // All employees can read products RegisterPermission(new Permission<Product>()); // All employees can read employees RegisterPermission(new Permission<Employee>()); } }
That's it. Now all employees have a permission to read Products & Employees.
What about the Stock manager role? Stock manager should inherit the base EmployeeRole and add permission for editing products.
public class StockManagerRole : EmployeeRole { public StockManagerRole() { // Stock manager inherits Employee permissions // Stock managers can read and edit products RegisterPermission(new Permission<Product>(canWrite:true)); } }
As I've already mentioned, the advantage of the class-based approach in role hierarchy definition is in its essential inheritance support. Derived role can inherit all permissions and other options of the base class and override something if is necessary. This is achievable in the most natural way for developers: make an inheritor & override all you need.
On the other branch of roles hierarchy, Sales representative role also inherits the base EmployeeRole and should add permissions to edit customers and orders. In order to add Order permission we should define OrderPermission first, where a property CanApprove should be included. Here it is:
public class OrderPermission : Permission<Order> { public bool CanApprove { get; private set; } public OrderPermission(bool canWrite, bool canApprove) : base(canWrite) { CanApprove = canApprove; } }
Having declared the OrderPermission, we can proceed with SaleRepresentativeRole class:
public class SalesRepresentativeRole : EmployeeRole { public SalesRepresentativeRole() { // Sales representative inherits Employee permissions // Sales representative can read and edit customers RegisterPermission(new Permission<Customer>(canWrite:true)); // Sales representative can read and edit sale orders but not approve RegisterPermission(new OrderPermission(canWrite:true, canApprove:false)); } }
As for Sales manager role, it inherits Sales representative role and adds permission to approve orders. Here is how:
public class SalesManagerRole : SalesRepresentativeRole { public SalesManagerRole() { // Sales manager inherits Sales representative permissions // Sales manager can do sale orders approval, in addition RegisterPermission(new OrderPermission(canWrite:true, canApprove:true)); } }
The last one is Sales president role. It in turn has access to all entities in read-only mode plus write permission to Employees, so we have to override permissions declared in its ansector (SalesManagerRole):
public class SalesPresidentRole : SalesManagerRole { public SalesPresidentRole() { // Sales president inherits Sales manager permissions // Sales President can read all, but can't alter any details, except employees. They usually need read-only aggregated reports, actually RegisterPermission(new Permission<Customer>()); RegisterPermission(new Permission<Order>()); RegisterPermission(new Permission<Product>()); RegisterPermission(new Permission<Employee>(canWrite:true)); } }
Note the clarity and the ease of permissions overriding.
That's all for today. For now we have permissions and roles defined. Hence, we've got a mechanism that can be used to describe the access matrix from the previous post in full manner:
This is what i am expecting you do, but i'am interesting how this interact with DO4 with queries, sessions, etc...
ReplyDeletePeter, that was an absolutely required preamble.
ReplyDeleteThis internet site is my breathing in, very great pattern and perfect content. Insta stalker is one of the best anonymous Instagram stories viewer. You can use it to stalk stories and users.
ReplyDelete