bali 1.0.0 → 1.1.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|