bali 1.0.0 → 1.1.0rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/README.md +7 -0
- data/bali.gemspec +1 -0
- data/lib/bali.rb +11 -174
- data/lib/bali/dsl/map_rules_dsl.rb +20 -0
- data/lib/bali/dsl/rules_for_dsl.rb +94 -0
- data/lib/bali/foundations/bali_statics.rb +59 -0
- data/lib/bali/{rule.rb → foundations/rule.rb} +12 -1
- data/lib/bali/{rule_class.rb → foundations/rule_class.rb} +0 -0
- data/lib/bali/{rule_group.rb → foundations/rule_group.rb} +0 -0
- data/lib/bali/objector.rb +62 -30
- data/lib/bali/version.rb +1 -1
- metadata +24 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 340aadebc55874ca95a0b864e0117d2d93e798c3
|
4
|
+
data.tar.gz: 7019bbc158e229ff267012ae472e6969fa03f5ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a88ac2145d2c73d087b286e3046b30a839b50bb5564b2747b4a60822a571db72b5fe8de53d4eb7b97debb1f93b40a5220b2d4471bd6b696649d9440b112f879
|
7
|
+
data.tar.gz: 6be3dcc843c90c4c08e07303d863c7ae43550951980b1e28b86994c8432f26a1420011cd3efdccb494077cdac473360ba0654ca3bebe2e69c0e5340ab1581f42
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -43,6 +43,7 @@ Rule in Bali is the law determining whether a user (called `subtarget`) can do o
|
|
43
43
|
describe "finance user" do
|
44
44
|
can :update, :delete, :edit
|
45
45
|
can :delete, if: proc { |record| record.is_settled? }
|
46
|
+
can :cancel, unless: proc { |record| record.is_settled? }
|
46
47
|
end # finance_user description
|
47
48
|
describe :guest { cant_all }
|
48
49
|
describe nil { cant_all }
|
@@ -137,3 +138,9 @@ Bali is proudly available as open source under the terms of the [MIT License](ht
|
|
137
138
|
|
138
139
|
#### Version 1.0.0
|
139
140
|
1. Released the stable version of this gem
|
141
|
+
|
142
|
+
#### Version 1.1.0rc1
|
143
|
+
1. Ability for rule class to be parsed later by parsing later: true to rule class definition
|
144
|
+
2. Add `Bali.parse` and `Bali.parse!` (Bali.parse! executes "later"-tagged rule class, Bali.parse executes automatically after all rules are defined)
|
145
|
+
3. Added more thorough testing specs
|
146
|
+
4. Proc can be served under `unless` for defining the rule's decider
|
data/bali.gemspec
CHANGED
data/lib/bali.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
require_relative "bali/version"
|
2
|
-
|
3
|
-
|
4
|
-
require_relative "bali/
|
2
|
+
|
3
|
+
# foundations, onto which good-purposed gem is developed upon
|
4
|
+
require_relative "bali/foundations/bali_statics"
|
5
|
+
require_relative "bali/foundations/rule_class"
|
6
|
+
require_relative "bali/foundations/rule_group"
|
7
|
+
require_relative "bali/foundations/rule"
|
8
|
+
|
9
|
+
# load the DSL syntax maker definition, ordered by proper order of invocation
|
10
|
+
require_relative "bali/dsl/map_rules_dsl.rb"
|
11
|
+
require_relative "bali/dsl/rules_for_dsl.rb"
|
5
12
|
|
6
13
|
require_relative "bali/objector"
|
7
14
|
|
8
15
|
# exception classes
|
9
16
|
require_relative "bali/exceptions/dsl_error"
|
17
|
+
|
10
18
|
module Bali
|
11
19
|
# mapping class to a RuleClass
|
12
20
|
RULE_CLASS_MAP = {}
|
@@ -18,177 +26,6 @@ module Bali
|
|
18
26
|
REVERSE_ALIASED_RULE_CLASS_MAP = {}
|
19
27
|
end
|
20
28
|
|
21
|
-
module Bali
|
22
|
-
extend self
|
23
|
-
|
24
|
-
def rule_classes
|
25
|
-
RULE_CLASS_MAP
|
26
|
-
end
|
27
|
-
|
28
|
-
def rule_class_for(target)
|
29
|
-
if target.is_a?(Symbol)
|
30
|
-
class_name = ALIASED_RULE_CLASS_MAP[target]
|
31
|
-
return class_name.nil? ? nil : rule_class_for(class_name)
|
32
|
-
else
|
33
|
-
raise Bali::DslError, "Target must be a class" unless target.is_a?(Class)
|
34
|
-
rule_class = RULE_CLASS_MAP[target.to_s]
|
35
|
-
return rule_class.nil? ? nil : rule_class
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# attempt to search the rule group, but if not exist, will return nil
|
40
|
-
def rule_group_for(target_class, subtarget)
|
41
|
-
rule_class = Bali.rule_class_for(target_class)
|
42
|
-
if rule_class
|
43
|
-
rule_group = rule_class.rules_for(subtarget)
|
44
|
-
return rule_group
|
45
|
-
else
|
46
|
-
return nil
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def add_rule_class(rule_class)
|
51
|
-
if rule_class.is_a?(Bali::RuleClass)
|
52
|
-
target = rule_class.target_class
|
53
|
-
alias_target = rule_class.alias_name
|
54
|
-
|
55
|
-
raise Bali::DslError, "Target must be a class" unless target.is_a?(Class)
|
56
|
-
|
57
|
-
# remove any previous association of rule
|
58
|
-
begin
|
59
|
-
last_associated_alias = Bali::REVERSE_ALIASED_RULE_CLASS_MAP[target]
|
60
|
-
if last_associated_alias
|
61
|
-
Bali::ALIASED_RULE_CLASS_MAP.delete(last_associated_alias)
|
62
|
-
Bali::REVERSE_ALIASED_RULE_CLASS_MAP.delete(target)
|
63
|
-
Bali::RULE_CLASS_MAP.delete(target)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# if "as" is present
|
68
|
-
if alias_target.is_a?(Symbol)
|
69
|
-
Bali::ALIASED_RULE_CLASS_MAP[alias_target] = target
|
70
|
-
Bali::REVERSE_ALIASED_RULE_CLASS_MAP[target] = alias_target
|
71
|
-
end
|
72
|
-
|
73
|
-
Bali::RULE_CLASS_MAP[target.to_s] = rule_class
|
74
|
-
rule_class
|
75
|
-
else
|
76
|
-
raise Bali::DslError, "Only allow instance of Bali::RuleClass"
|
77
|
-
end
|
78
|
-
end # add_rule_class
|
79
|
-
end
|
80
|
-
|
81
|
-
module Bali
|
82
|
-
class Bali::MapRulesDsl
|
83
|
-
attr_accessor :current_rule_class
|
84
|
-
|
85
|
-
def initialize
|
86
|
-
@@lock = Mutex.new
|
87
|
-
end
|
88
|
-
|
89
|
-
def rules_for(target_class, target_alias_hash = {}, &block)
|
90
|
-
@@lock.synchronize do
|
91
|
-
self.current_rule_class = Bali::RuleClass.new(target_class)
|
92
|
-
self.current_rule_class.alias_name = target_alias_hash[:as] || target_alias_hash["as"]
|
93
|
-
|
94
|
-
Bali::MapRulesRulesForDsl.new(self).instance_eval(&block)
|
95
|
-
|
96
|
-
# done processing the block, now add the rule class
|
97
|
-
Bali.add_rule_class(self.current_rule_class)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
module Bali
|
104
|
-
class Bali::MapRulesRulesForDsl
|
105
|
-
attr_accessor :map_rules_dsl
|
106
|
-
attr_accessor :current_rule_group
|
107
|
-
|
108
|
-
def initialize(map_rules_dsl)
|
109
|
-
@@lock = Mutex.new
|
110
|
-
self.map_rules_dsl = map_rules_dsl
|
111
|
-
end
|
112
|
-
|
113
|
-
def describe(subtarget, rules = {})
|
114
|
-
target_class = self.map_rules_dsl.current_rule_class.target_class
|
115
|
-
target_alias = self.map_rules_dsl.current_rule_class.alias_name
|
116
|
-
@@lock.synchronize do
|
117
|
-
rule_group = Bali::RuleGroup.new(target_class, target_alias, subtarget)
|
118
|
-
self.current_rule_group = rule_group
|
119
|
-
|
120
|
-
if block_given?
|
121
|
-
the_object = Object.new
|
122
|
-
# the_object would be the record, or the object of class as specified
|
123
|
-
# in rules_for
|
124
|
-
yield the_object
|
125
|
-
else
|
126
|
-
# auth_val is either can or cant
|
127
|
-
rules.each do |auth_val, operations|
|
128
|
-
if operations.is_a?(Array)
|
129
|
-
operations.each do |op|
|
130
|
-
rule = Bali::Rule.new(auth_val, op)
|
131
|
-
rule_group.add_rule(rule)
|
132
|
-
end
|
133
|
-
else
|
134
|
-
operation = operations # well, basically is 1 only
|
135
|
-
rule = Bali::Rule.new(auth_val, operation)
|
136
|
-
rule_group.add_rule(rule)
|
137
|
-
end
|
138
|
-
end # each rules
|
139
|
-
end # block_given?
|
140
|
-
|
141
|
-
# add current_rule_group
|
142
|
-
self.map_rules_dsl.current_rule_class.add_rule_group(rule_group)
|
143
|
-
end # mutex synchronize
|
144
|
-
end # describe
|
145
|
-
|
146
|
-
|
147
|
-
def process_auth_rules(auth_val, operations)
|
148
|
-
conditional_hash = nil
|
149
|
-
|
150
|
-
# scan opreation for hash
|
151
|
-
operations.each do |elm|
|
152
|
-
if elm.is_a?(Hash)
|
153
|
-
conditional_hash = elm
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
if conditional_hash
|
158
|
-
op = operations[0]
|
159
|
-
rule = Bali::Rule.new(auth_val, op)
|
160
|
-
rule.decider = conditional_hash[:if] || conditional_hash["if"]
|
161
|
-
self.current_rule_group.add_rule(rule)
|
162
|
-
else
|
163
|
-
# no conditional hash, proceed adding operations one by one
|
164
|
-
operations.each do |op|
|
165
|
-
rule = Bali::Rule.new(auth_val, op)
|
166
|
-
self.current_rule_group.add_rule(rule)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end # process_auth_rules
|
170
|
-
|
171
|
-
def can(*operations)
|
172
|
-
process_auth_rules(:can, operations)
|
173
|
-
end
|
174
|
-
|
175
|
-
def cant(*operations)
|
176
|
-
process_auth_rules(:cant, operations)
|
177
|
-
end
|
178
|
-
|
179
|
-
def can_all
|
180
|
-
self.current_rule_group.zeus = true
|
181
|
-
self.current_rule_group.plant = false
|
182
|
-
end
|
183
|
-
|
184
|
-
def cant_all
|
185
|
-
self.current_rule_group.plant = true
|
186
|
-
self.current_rule_group.zeus = false
|
187
|
-
end
|
188
|
-
|
189
|
-
end # class
|
190
|
-
end # module
|
191
|
-
|
192
29
|
module Bali
|
193
30
|
extend self
|
194
31
|
def map_rules(&block)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# grand scheme of things begin here
|
2
|
+
class Bali::MapRulesDsl
|
3
|
+
attr_accessor :current_rule_class
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@@lock = Mutex.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def rules_for(target_class, target_alias_hash = {}, &block)
|
10
|
+
@@lock.synchronize do
|
11
|
+
self.current_rule_class = Bali::RuleClass.new(target_class)
|
12
|
+
self.current_rule_class.alias_name = target_alias_hash[:as] || target_alias_hash["as"]
|
13
|
+
|
14
|
+
Bali::RulesForDsl.new(self).instance_eval(&block)
|
15
|
+
|
16
|
+
# done processing the block, now add the rule class
|
17
|
+
Bali.add_rule_class(self.current_rule_class)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# this class is used to define DSL after rules_for is invoked.
|
2
|
+
# @author Adam Pahlevi Baihaqi
|
3
|
+
class Bali::RulesForDsl
|
4
|
+
attr_accessor :map_rules_dsl
|
5
|
+
attr_accessor :current_rule_group
|
6
|
+
|
7
|
+
def initialize(map_rules_dsl)
|
8
|
+
@@lock = Mutex.new
|
9
|
+
self.map_rules_dsl = map_rules_dsl
|
10
|
+
end
|
11
|
+
|
12
|
+
def describe(subtarget, rules = {})
|
13
|
+
target_class = self.map_rules_dsl.current_rule_class.target_class
|
14
|
+
target_alias = self.map_rules_dsl.current_rule_class.alias_name
|
15
|
+
|
16
|
+
@@lock.synchronize do
|
17
|
+
rule_group = Bali::RuleGroup.new(target_class, target_alias, subtarget)
|
18
|
+
self.current_rule_group = rule_group
|
19
|
+
|
20
|
+
if block_given?
|
21
|
+
the_object = Object.new
|
22
|
+
# the_object would be the record, or the object of class as specified
|
23
|
+
# in rules_for
|
24
|
+
yield the_object
|
25
|
+
else
|
26
|
+
# auth_val is either can or cant
|
27
|
+
rules.each do |auth_val, operations|
|
28
|
+
if operations.is_a?(Array)
|
29
|
+
operations.each do |op|
|
30
|
+
rule = Bali::Rule.new(auth_val, op)
|
31
|
+
rule_group.add_rule(rule)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
operation = operations # well, basically is 1 only
|
35
|
+
rule = Bali::Rule.new(auth_val, operation)
|
36
|
+
rule_group.add_rule(rule)
|
37
|
+
end
|
38
|
+
end # each rules
|
39
|
+
end # block_given?
|
40
|
+
|
41
|
+
# add current_rule_group
|
42
|
+
self.map_rules_dsl.current_rule_class.add_rule_group(rule_group)
|
43
|
+
end # mutex synchronize
|
44
|
+
end # describe
|
45
|
+
|
46
|
+
# to define can and cant is basically using this method
|
47
|
+
def process_auth_rules(auth_val, operations)
|
48
|
+
conditional_hash = nil
|
49
|
+
|
50
|
+
# scan operations for options
|
51
|
+
operations.each do |elm|
|
52
|
+
if elm.is_a?(Hash)
|
53
|
+
conditional_hash = elm
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if conditional_hash
|
58
|
+
op = operations[0]
|
59
|
+
rule = Bali::Rule.new(auth_val, op)
|
60
|
+
if conditional_hash[:if] || conditional_hash["if"]
|
61
|
+
rule.decider = conditional_hash[:if] || conditional_hash["if"]
|
62
|
+
rule.decider_type = :if
|
63
|
+
elsif conditional_hash[:unless] || conditional_hash[:unless]
|
64
|
+
rule.decider = conditional_hash[:unless] || conditional_hash["unless"]
|
65
|
+
rule.decider_type = :unless
|
66
|
+
end
|
67
|
+
self.current_rule_group.add_rule(rule)
|
68
|
+
else
|
69
|
+
# no conditional hash, proceed adding operations one by one
|
70
|
+
operations.each do |op|
|
71
|
+
rule = Bali::Rule.new(auth_val, op)
|
72
|
+
self.current_rule_group.add_rule(rule)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end # process_auth_rules
|
76
|
+
|
77
|
+
def can(*operations)
|
78
|
+
process_auth_rules(:can, operations)
|
79
|
+
end
|
80
|
+
|
81
|
+
def cant(*operations)
|
82
|
+
process_auth_rules(:cant, operations)
|
83
|
+
end
|
84
|
+
|
85
|
+
def can_all
|
86
|
+
self.current_rule_group.zeus = true
|
87
|
+
self.current_rule_group.plant = false
|
88
|
+
end
|
89
|
+
|
90
|
+
def cant_all
|
91
|
+
self.current_rule_group.plant = true
|
92
|
+
self.current_rule_group.zeus = false
|
93
|
+
end
|
94
|
+
end # class
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Bali
|
2
|
+
extend self
|
3
|
+
|
4
|
+
def rule_classes
|
5
|
+
Bali::RULE_CLASS_MAP
|
6
|
+
end
|
7
|
+
|
8
|
+
def rule_class_for(target)
|
9
|
+
if target.is_a?(Symbol)
|
10
|
+
class_name = Bali::ALIASED_RULE_CLASS_MAP[target]
|
11
|
+
return class_name.nil? ? nil : rule_class_for(class_name)
|
12
|
+
else
|
13
|
+
raise Bali::DslError, "Target must be a class" unless target.is_a?(Class)
|
14
|
+
rule_class = Bali::RULE_CLASS_MAP[target.to_s]
|
15
|
+
return rule_class.nil? ? nil : rule_class
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# attempt to search the rule group, but if not exist, will return nil
|
20
|
+
def rule_group_for(target_class, subtarget)
|
21
|
+
rule_class = Bali.rule_class_for(target_class)
|
22
|
+
if rule_class
|
23
|
+
rule_group = rule_class.rules_for(subtarget)
|
24
|
+
return rule_group
|
25
|
+
else
|
26
|
+
return nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_rule_class(rule_class)
|
31
|
+
if rule_class.is_a?(Bali::RuleClass)
|
32
|
+
target = rule_class.target_class
|
33
|
+
alias_target = rule_class.alias_name
|
34
|
+
|
35
|
+
raise Bali::DslError, "Target must be a class" unless target.is_a?(Class)
|
36
|
+
|
37
|
+
# remove any previous association of rule
|
38
|
+
begin
|
39
|
+
last_associated_alias = Bali::REVERSE_ALIASED_RULE_CLASS_MAP[target]
|
40
|
+
if last_associated_alias
|
41
|
+
Bali::ALIASED_RULE_CLASS_MAP.delete(last_associated_alias)
|
42
|
+
Bali::REVERSE_ALIASED_RULE_CLASS_MAP.delete(target)
|
43
|
+
Bali::RULE_CLASS_MAP.delete(target)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# if "as" is present
|
48
|
+
if alias_target.is_a?(Symbol)
|
49
|
+
Bali::ALIASED_RULE_CLASS_MAP[alias_target] = target
|
50
|
+
Bali::REVERSE_ALIASED_RULE_CLASS_MAP[target] = alias_target
|
51
|
+
end
|
52
|
+
|
53
|
+
Bali::RULE_CLASS_MAP[target.to_s] = rule_class
|
54
|
+
rule_class
|
55
|
+
else
|
56
|
+
raise Bali::DslError, "Only allow instance of Bali::RuleClass"
|
57
|
+
end
|
58
|
+
end # add_rule_class
|
59
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# for internal use, representing rule
|
1
|
+
# for internal use, representing one, single, atomic rule
|
2
2
|
class Bali::Rule
|
3
3
|
# auth_val is either :can or :cant
|
4
4
|
attr_reader :auth_val
|
@@ -8,6 +8,8 @@ class Bali::Rule
|
|
8
8
|
|
9
9
|
# if decider is defined, a rule is executed only if decider evaluates to true
|
10
10
|
attr_accessor :decider
|
11
|
+
# either unless or if
|
12
|
+
attr_reader :decider_type
|
11
13
|
|
12
14
|
def initialize(auth_val, operation)
|
13
15
|
self.auth_val = auth_val
|
@@ -23,11 +25,20 @@ class Bali::Rule
|
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
28
|
+
def decider_type=(dectype)
|
29
|
+
if dectype == :if || dectype == :unless
|
30
|
+
@decider_type = dectype
|
31
|
+
else
|
32
|
+
raise Bali::DslError, "decider type can only be either if or unless"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
26
36
|
def is_discouragement?
|
27
37
|
self.auth_val == :cant
|
28
38
|
end
|
29
39
|
|
30
40
|
def has_decider?
|
41
|
+
raise Bali::DslError, "has decider but not sure if it is if or unless type decider" if self.decider.is_a?(Proc) && self.decider_type.nil?
|
31
42
|
self.decider.is_a?(Proc)
|
32
43
|
end
|
33
44
|
end
|
File without changes
|
File without changes
|
data/lib/bali/objector.rb
CHANGED
@@ -10,12 +10,12 @@ module Bali::Objector
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def cant?(subtarget, operation)
|
13
|
-
self.class.
|
13
|
+
self.class.cant?(subtarget, operation, self)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
module Bali::Objector::Statics
|
18
|
-
def can?(subtarget, operation, record = self)
|
18
|
+
def can?(subtarget, operation, record = self, options = {})
|
19
19
|
# if performed on a class-level, don't call its class or it will return
|
20
20
|
# Class. That's not what is expected.
|
21
21
|
if self.is_a?(Class)
|
@@ -31,31 +31,46 @@ module Bali::Objector::Statics
|
|
31
31
|
# get the specific rule
|
32
32
|
rule = rule_group.get_rule(:can, operation)
|
33
33
|
|
34
|
-
# godly subtarget is allowed to do as he wishes
|
35
|
-
# so long that the rule is not specificly defined
|
36
|
-
return true if rule_group.zeus? && rule.nil?
|
37
|
-
|
38
34
|
# plan subtarget is not allowed unless spesificly defined
|
39
35
|
return false if rule_group.plant? && rule.nil?
|
40
36
|
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
if
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
37
|
+
# godly subtarget is allowed to do as he wishes
|
38
|
+
# so long that the rule is not specificly defined
|
39
|
+
# or overwritten by subsequent rule
|
40
|
+
if rule_group.zeus?
|
41
|
+
if rule.nil?
|
42
|
+
# check further whether cant is defined to overwrite this can_all
|
43
|
+
if self.cant?(subtarget, operation, record, cross_check: true)
|
44
|
+
return false
|
45
|
+
else
|
46
|
+
return true
|
47
|
+
end
|
51
48
|
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if rule.nil?
|
52
|
+
# default if can? for undefined rule is false, after related clause
|
53
|
+
# cannot be found in cant?
|
54
|
+
return false if options[:cross_check]
|
55
|
+
return !self.cant?(subtarget, operation, record, cross_check: true)
|
52
56
|
else
|
53
|
-
|
54
|
-
|
57
|
+
if rule.has_decider?
|
58
|
+
# must test first
|
59
|
+
decider = rule.decider
|
60
|
+
if decider.arity == 0
|
61
|
+
return (rule.decider_type == :if) ? decider.() == true : decider.() == false
|
62
|
+
else
|
63
|
+
return (rule.decider_type == :if) ? decider.(record) == true : decider.(record) == false
|
64
|
+
end
|
65
|
+
else
|
66
|
+
# rule is properly defined
|
67
|
+
return true
|
68
|
+
end
|
55
69
|
end
|
70
|
+
|
56
71
|
end
|
57
72
|
|
58
|
-
def cant?(subtarget, operation, record = self)
|
73
|
+
def cant?(subtarget, operation, record = self, options = {})
|
59
74
|
if self.is_a?(Class)
|
60
75
|
rule_group = Bali.rule_group_for(self, subtarget)
|
61
76
|
else
|
@@ -73,18 +88,35 @@ module Bali::Objector::Statics
|
|
73
88
|
return false if rule_group.zeus? && rule.nil?
|
74
89
|
|
75
90
|
# plant subtarget is not allowed to do things unless specificly defined
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
decider.(record) == true
|
91
|
+
if rule_group.plant?
|
92
|
+
if rule.nil?
|
93
|
+
# check further whether defined in can?
|
94
|
+
if self.can?(subtarget, operation, record, cross_check: true)
|
95
|
+
return false # well, it is defined in can, so it must overwrite this cant_all rule
|
96
|
+
else
|
97
|
+
# plant, and then rule is not defined for further inspection. stright
|
98
|
+
# is not allowed to do this thing
|
99
|
+
return true
|
100
|
+
end
|
87
101
|
end
|
88
102
|
end
|
103
|
+
|
104
|
+
# if rule cannot be found, then true is returned for cant? unless
|
105
|
+
# can? is defined exactly for the same target, and subtarget, and record (if given)
|
106
|
+
if rule.nil?
|
107
|
+
return true if options[:cross_check]
|
108
|
+
return !self.can?(subtarget, operation, record, cross_check: true)
|
109
|
+
else
|
110
|
+
if rule.has_decider?
|
111
|
+
decider = rule.decider
|
112
|
+
if decider.arity == 0
|
113
|
+
return (rule.decider_type == :if) ? decider.() == true : decider.() == false
|
114
|
+
else
|
115
|
+
return (rule.decider_type == :if) ? decider.(record) == true : decider.(record) == false
|
116
|
+
end
|
117
|
+
else
|
118
|
+
return true # rule is properly defined
|
119
|
+
end # if rule has decider
|
120
|
+
end # if rule is nil
|
89
121
|
end
|
90
122
|
end
|
data/lib/bali/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bali
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Pahlevi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
description: "Bali (Bulwark Authorization Library) is a universal authorization library,
|
56
70
|
in the sense that \n it does not assume you to use specific
|
57
71
|
Ruby library/gem/framework."
|
@@ -73,11 +87,14 @@ files:
|
|
73
87
|
- bin/console
|
74
88
|
- bin/setup
|
75
89
|
- lib/bali.rb
|
90
|
+
- lib/bali/dsl/map_rules_dsl.rb
|
91
|
+
- lib/bali/dsl/rules_for_dsl.rb
|
76
92
|
- lib/bali/exceptions/dsl_error.rb
|
93
|
+
- lib/bali/foundations/bali_statics.rb
|
94
|
+
- lib/bali/foundations/rule.rb
|
95
|
+
- lib/bali/foundations/rule_class.rb
|
96
|
+
- lib/bali/foundations/rule_group.rb
|
77
97
|
- lib/bali/objector.rb
|
78
|
-
- lib/bali/rule.rb
|
79
|
-
- lib/bali/rule_class.rb
|
80
|
-
- lib/bali/rule_group.rb
|
81
98
|
- lib/bali/version.rb
|
82
99
|
homepage: https://github.com/saveav/bali
|
83
100
|
licenses:
|
@@ -94,9 +111,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
111
|
version: '0'
|
95
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
113
|
requirements:
|
97
|
-
- - "
|
114
|
+
- - ">"
|
98
115
|
- !ruby/object:Gem::Version
|
99
|
-
version:
|
116
|
+
version: 1.3.1
|
100
117
|
requirements: []
|
101
118
|
rubyforge_project:
|
102
119
|
rubygems_version: 2.4.5
|