Class: Authorule::RuleBase
- Inherits:
-
Object
- Object
- Authorule::RuleBase
- Defined in:
- lib/authorule/rule_base.rb
Overview
A permission rule base. This class performs the heart of the permission checking algorithms.
Algorithm description
A rule base is always queried for one permission. The result should be whether it is allowed or denied.
When running a permission through the rule base, the permission itself, and all dependent permissions are run through the rule base. See Permission#dependencies for more info about permission dependencies.
The last defined rule (i.e. the rule with the highest priority) matching any of the checks is taken as the deciding rule.
Example
Let’s illustrate the given algorithm with an example. Let’s say we have the following permissions, taken from the UI library:
-
SpacePermission
: a permission to access a certain UI space (a collection of UI resources) -
ResourcePermission
: a permission to access a certain resource
A resource permission has a dependency on its corresponding space permission. In other words, a user must have access to the resource’s space as well as the resource itself for it to be accessible.
Then, we consider a rule base with the following rules:
-
Deny all
-
Allow space ‘CRM’
-
Deny resource ‘Account’
Now, we need to check whether the user may view the resource ‘Account’:
= ResourcePermission.new(account_resource, :view)
When resolving all dependencies, we end up with the following list of permissions:
= .resolve_dependencies
# => [ SpacePermission.new(crm_space), ResourcePermission.new(account_resource, :view) ]
Both of these permissions are now run through the rule base. The first permission is matched by rules 1 (all) and 2 (space ‘CRM’). The second permission is matched by rules 1 (all) and 3 (resource ‘Account’). The last defined rule is the third rule. As it is set to deny access, the resulting access to the permission is denied. This makes sense because we deny it last in line.
If however, the rule base were to switch around 2 and 3, the rule base would look as follows:
-
Deny all
-
Deny resource ‘Account’
-
Allow space ‘CRM’
Now, the first permission will be matched by rule 3, which is the last rule to match. As it is set to allow access, the resulting access to the permission is allowed. As you can see, the second rule is overruled by the more generic rule 3.
Instance Attribute Summary collapse
-
#rules ⇒ Array
readonly
The rules in the rule base.
Instance Method Summary collapse
-
#initialize(rules) ⇒ RuleBase
constructor
Initializes the rule base with the given rules.
-
#run(permission) ⇒ true|false
Runs the given permission through the rule base.
Constructor Details
#initialize(rules) ⇒ RuleBase
Initializes the rule base with the given rules.
61 62 63 64 |
# File 'lib/authorule/rule_base.rb', line 61 def initialize(rules) @rules = rules.to_a @index = build_index end |
Instance Attribute Details
#rules ⇒ Array (readonly)
Returns The rules in the rule base.
71 72 73 |
# File 'lib/authorule/rule_base.rb', line 71 def rules @rules end |
Instance Method Details
#run(permission) ⇒ true|false
Runs the given permission through the rule base.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/authorule/rule_base.rb', line 96 def run() last_rule_index = nil .with_dependencies.each do || keys = () # Compare the current index with the indices of all rules that match and take the maximum. last_rule_index = ([ last_rule_index ] + keys.map{ |key| @index[key] }.flatten).compact.max end if last_rule_index rules[last_rule_index].allow? else # The default policy is to deny the permission if no rules match. false end end |