Class: Roleback::RuleBook
- Inherits:
-
Object
- Object
- Roleback::RuleBook
- Defined in:
- lib/roleback/rule_book.rb
Instance Attribute Summary collapse
-
#rules ⇒ Object
readonly
Returns the value of attribute rules.
Class Method Summary collapse
-
.sort(rules) ⇒ Object
sorts the rules, based on the rules’ numerical value.
Instance Method Summary collapse
- #[](key) ⇒ Object
- #add(rule) ⇒ Object
- #can?(resource:, scope:, action:) ⇒ Boolean
- #clear_rules ⇒ Object
-
#initialize(role) ⇒ RuleBook
constructor
A new instance of RuleBook.
- #keys ⇒ Object
- #length ⇒ Object
- #match_all(resource:, scope:, action:) ⇒ Object
- #sort ⇒ Object
- #sort! ⇒ Object
- #to_a ⇒ Object
- #to_s ⇒ Object
Constructor Details
#initialize(role) ⇒ RuleBook
Returns a new instance of RuleBook.
5 6 7 8 |
# File 'lib/roleback/rule_book.rb', line 5 def initialize(role) @rules = {} @role = role end |
Instance Attribute Details
#rules ⇒ Object (readonly)
Returns the value of attribute rules.
3 4 5 |
# File 'lib/roleback/rule_book.rb', line 3 def rules @rules end |
Class Method Details
.sort(rules) ⇒ Object
sorts the rules, based on the rules’ numerical value
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/roleback/rule_book.rb', line 90 def self.sort(rules) # rules should be a hash raise ::ArgumentError, "rules should be a hash but it is a #{rules.class}" unless rules.is_a?(Hash) # rules is a hash, so we need to convert it to an array rules = rules.values # sort the rules rules.sort! do |a, b| an = a.numerical_value bn = b.numerical_value # if the numerical values are the same, sort by key, otherwise sort by numerical value if an == bn a.key <=> b.key else bn <=> an end end end |
Instance Method Details
#[](key) ⇒ Object
45 46 47 |
# File 'lib/roleback/rule_book.rb', line 45 def [](key) @rules[key] end |
#add(rule) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/roleback/rule_book.rb', line 10 def add(rule) raise ::Roleback::BadConfiguration, "Adding a rule with no role" unless rule.role if @rules[rule.key] if @rules[rule.key].outcome.outcome == rule.outcome.outcome # don't allow it if they share a rulebook if @role.name == rule.role.name raise ::Roleback::BadConfiguration, "Rule #{rule.key} already defined" else # this duplicate is through inheritance, so we can safely ignore it return end else raise ::Roleback::BadConfiguration, "Rule #{rule.key} already defined with a different outcome (conflicting rules)" end end # detect conflicting rules @rules.each do |key, existing_rule| if existing_rule.conflicts_with?(rule) raise ::Roleback::BadConfiguration, "Rule #{rule.key} conflicts with #{existing_rule.key}" end end @rules[rule.key] = rule end |
#can?(resource:, scope:, action:) ⇒ Boolean
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/roleback/rule_book.rb', line 62 def can?(resource:, scope:, action:) # get all rules that matches the given resource, scope and action rules = match_all(resource: resource, scope: scope, action: action) # if there are no rules, return false return false if rules.empty? # create a rule book with the matching rules match_book = self.class.new(@role) rules.each do |rule| match_book.add(rule) end # sort the rules sorted_rules = self.class.sort(match_book.rules) # iterate over the sorted rules and find the first rule that matches sorted_rules.each do |rule| if rule.match(resource: resource, scope: scope, action: action) return rule.outcome.allowed? end end # if no rule matches, return false return false end |
#clear_rules ⇒ Object
37 38 39 |
# File 'lib/roleback/rule_book.rb', line 37 def clear_rules @rules = {} end |
#keys ⇒ Object
49 50 51 |
# File 'lib/roleback/rule_book.rb', line 49 def keys @rules.keys end |
#length ⇒ Object
41 42 43 |
# File 'lib/roleback/rule_book.rb', line 41 def length @rules.length end |
#match_all(resource:, scope:, action:) ⇒ Object
53 54 55 56 57 58 59 60 |
# File 'lib/roleback/rule_book.rb', line 53 def match_all(resource:, scope:, action:) result = [] @rules.each do |key, rule| result << rule if rule.match(resource: resource, scope: scope, action: action) end result end |
#sort ⇒ Object
115 116 117 |
# File 'lib/roleback/rule_book.rb', line 115 def sort self.class.sort(@rules) end |
#sort! ⇒ Object
111 112 113 |
# File 'lib/roleback/rule_book.rb', line 111 def sort! @rules = self.class.sort(@rules) end |
#to_a ⇒ Object
123 124 125 |
# File 'lib/roleback/rule_book.rb', line 123 def to_a @rules.values end |
#to_s ⇒ Object
119 120 121 |
# File 'lib/roleback/rule_book.rb', line 119 def to_s @rules.values.map(&:to_s).join("\n") end |