More roles, less code.
Authorization module is the most complete module in Signum Extensions. It contains all the necessary stuff to write a complex multi-role application without letting this complexity invade your code.
On its basis it provides two simple entities:
- User: Represents a person (or any other entity) that has access to the system. Basically it contains a Username and Password (only the Hash is stored), and a Role. Anonymous user can also be represented as a user.
- Role: Represents a group of users which share a common set of authorization rules. Roles can inherit from other roles, and even multiple inheritance is allowed. In case of multiple inheritance, union or intersection can be selected to merge the authorization rules
Additionally, it provides the screens for managing those entities and basic windows / pages for login, change password, etc… There's no page to let users self-register in the system since it depends too much on the application, so if necessary you'll you can write your own.
On top of this, there are three sub-modules to improve some common scenarios:
- UserTicket: Uses a chain of tickets, typically stored as cookies in the client machine, to implement the typical ‘Remember me’ functionality in the Login window.
- ResetPasswordRequest: If the user has an e-mail address, implements the typical ‘I forgot my password’ functionality by generating a secret code and send an email with a link to the user inbox. With this code the user is able to change his password.
- PasswordExpiration: On corporative environments, it’s common to have policies for password expiration. This functionality let you set a default password expiration and will warn users to change their password when they are close, or force a change when they have exceeded the limit.
But where Authorization module shines, is in the rich set of authorization rules to enable or disable access to each role to different sources.
- Types: Each role can have granted or denied access to any particular entity type. The possibilities can be
None. This rules will be enforced on any database operation and will also hide the necessary buttons in the user interface, giving a consistent experience to the end-user. (i.e., Anonymous users can only see Products, but not modify them)
- Type conditions: Often, the rules should not be applied to all the entities of a particular type,but to a subset of them. Using type conditions we can define conditions using lambdas expression and set special rules for the entities that satisfy this conditions. The rules are also applied on any database operation, and affect the user interface. The rules also be prioritized. (i.e., Teachers can only edit the Test in their classes, but can see any Test in their School).
- Operations: If necessary, individual operations can be granted or denied to a particular role. Denied operations are hidden to the end-user (in opposition to operations disabled because invalid state of the entity) and are also enforced when executed in the business logic. (i.e., hide Delete operation on Order, but show Cancel). By default the operation settings are inherited from the type settings but this behaviour can be avoided for special, risky, operations.
- Properties: If necessary, individual properties can be granted or denied to a particular role. Denied properties are hidden in the user interface, and when a request is received and the columns are also hidden in any search dialog. (i.e., hide Salary property on Employee). By default the property settings are inherited from the settings of the type that owns the property, but this behaviour can be avoided for special, risky, properties.
- Queries: If necessary, individual queries can be granted or denied to a particular role. Denied queries are hidden in the user interface. By default the query settings are inherited from the settings of the principal type of the query, but this behaviour can be avoided for special, risky, queries.
- Permissions: Permissions are
enums) that can be registered for particular scenarios not covered by any of the four cases above. Once registered, rules can be set to grant or deny a permission to a particular role. A simple API is available to check (or assert) if a particular Permission is granted for the current role.(i.e., show advance invoice view)
It’s possible to export an XML file with the role graph and their permission rules from one environment and import the file into another environment.
The result is a flexible authorization system where end-users are able to:
- Creating or remove users, change password, etc...
- Create new roles, optionally inheriting the authorization rules from other roles.
- Visually change, for each role, the authorization rules for
Additionally, the developers are relief from a lot of complexity associated with security restrictions:
- The module takes care of security transparently in at least 80% of the cases, by asserting at the database level or automatically hiding controls in the user interface.
- For the special restriction (the remaining 20%), the developer just has to define new
Permissions and check if its granted, without hard-coding role names and letting the schema synchronizer create the permission in the database.