bali 2.2.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.gitignore +2 -0
- data/lib/bali.rb +0 -5
- data/lib/bali/dsl/map_rules_dsl.rb +13 -16
- data/lib/bali/dsl/rules_for_dsl.rb +31 -89
- data/lib/bali/foundations/judger/judge.rb +2 -2
- data/lib/bali/foundations/rule/rule.rb +3 -4
- data/lib/bali/foundations/rule/rule_class.rb +5 -14
- data/lib/bali/foundations/rule/rule_group.rb +2 -4
- data/lib/bali/integrators/all_integrators.rb +6 -2
- data/lib/bali/integrators/rule_class_integrator.rb +27 -0
- data/lib/bali/integrators/rule_group_integrator.rb +29 -0
- data/lib/bali/integrators/rule_integrator.rb +56 -0
- data/lib/bali/version.rb +1 -1
- metadata +5 -7
- data/CHANGELOG.md +0 -80
- data/CODE_OF_CONDUCT.md +0 -13
- data/LICENSE.txt +0 -21
- data/README.md +0 -158
- data/lib/bali/integrators/rules_integrator.rb +0 -37
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
M2I3NWNjNmVlNWM4YzQyMGU0YzAyNzBmZGJmNTBjMTUxMGYxOWMxYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzhkMjlhYzA4NDU3M2M4ODE1ODkxZTU0ZDA3NDJjZGUwODNmOTZhYg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTJhOTRkODJhMWM5OTIzNjA0NTQ0OWVjMTMzOTgwZDFlZDBhZjQzNjQ0N2Y2
|
10
|
+
YWViMDExYzMyZjI5Y2YyOTYxNDdhZWJmYWU5YTVlNDYwODgwZDA1NDhhZWRm
|
11
|
+
NTliMTI1ZGEyMjNjY2QyNGEwNTM5YjNjNDc5OGIxYjk2MTYyNTI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTMzMzBjNTczZmM2MDE1YmI0NjA0ZjY1MDRhZGZmNWRiNTRjZGYzMDRmMWI4
|
14
|
+
Zjk4ZTEzNGZkZDg0NzFmZjg0YjYwNDQ2OGVlYjgwNzkwNTY4MGFlZDE1NjI3
|
15
|
+
ZDI1ZjlhNmFhODA4OGQzZDFhMjBkNjdjMjk1ZTI0YTkzZmQ4MTY=
|
data/lib/bali.rb
CHANGED
@@ -3,51 +3,48 @@ class Bali::MapRulesDsl
|
|
3
3
|
attr_accessor :current_rule_class
|
4
4
|
|
5
5
|
def initialize
|
6
|
-
@@lock
|
6
|
+
@@lock ||= Mutex.new
|
7
7
|
end
|
8
8
|
|
9
9
|
# defining rules
|
10
10
|
def rules_for(target_class, options_hash = {}, &block)
|
11
11
|
@@lock.synchronize do
|
12
|
-
raise Bali::DslError "rules_for must describe a target which is a class" unless target_class.is_a?(Class)
|
13
12
|
self.current_rule_class = Bali::RuleClass.new(target_class)
|
14
13
|
|
15
14
|
parent_class = options_hash[:inherits] || options_hash["inherits"]
|
16
15
|
if parent_class
|
17
16
|
# in case there is inherits specification
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
parent_is_class = parent_class.class
|
18
|
+
fail Bali::DslError, 'inherits must take a class' unless parent_is_class
|
19
|
+
rule_class_from_parent = Bali::Integrator::RuleClass.for(parent_class)
|
20
|
+
fail Bali::DslError, "not yet defined a rule class for #{parent_class}" if rule_class_from_parent.nil?
|
21
21
|
self.current_rule_class = rule_class_from_parent.clone(target_class: target_class)
|
22
22
|
end
|
23
23
|
|
24
24
|
Bali::RulesForDsl.new(self).instance_eval(&block)
|
25
25
|
|
26
26
|
# done processing the block, now add the rule class
|
27
|
-
Bali::
|
27
|
+
Bali::Integrator::RuleClass.add(self.current_rule_class)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
# subtarget_class is the subtarget's class definition
|
32
32
|
# field_name is the field that will be consulted when instantiated object of this class is passed in can? or cant?
|
33
33
|
def roles_for(subtarget_class, field_name)
|
34
|
-
raise Bali::DslError, "Subtarget must be a class" unless subtarget_class.is_a?(Class)
|
35
|
-
raise Bali::DslError, "Field name must be a symbol/string" if !(field_name.is_a?(Symbol) || field_name.is_a?(String))
|
36
|
-
|
37
34
|
Bali::TRANSLATED_SUBTARGET_ROLES[subtarget_class.to_s] = field_name
|
38
35
|
nil
|
39
36
|
end
|
40
37
|
|
41
38
|
def describe(*params)
|
42
|
-
|
39
|
+
fail Bali::DslError, "describe block must be within rules_for block"
|
43
40
|
end
|
44
41
|
|
45
42
|
def role(*params)
|
46
|
-
|
43
|
+
fail Bali::DslError, "role block must be within rules_for block"
|
47
44
|
end
|
48
45
|
|
49
46
|
def can(*params)
|
50
|
-
|
47
|
+
fail Bali::DslError, "can block must be within role block"
|
51
48
|
end
|
52
49
|
|
53
50
|
def cant(*params)
|
@@ -56,15 +53,15 @@ class Bali::MapRulesDsl
|
|
56
53
|
end
|
57
54
|
|
58
55
|
def cannot(*params)
|
59
|
-
|
56
|
+
fail Bali::DslError, "cant block must be within role block"
|
60
57
|
end
|
61
58
|
|
62
59
|
def can_all(*params)
|
63
|
-
|
60
|
+
fail Bali::DslError, "can_all block must be within role block"
|
64
61
|
end
|
65
62
|
|
66
63
|
def clear_rules
|
67
|
-
|
64
|
+
fail Bali::DslError, "clear_rules must be called within role block"
|
68
65
|
end
|
69
66
|
|
70
67
|
def cant_all(*params)
|
@@ -73,6 +70,6 @@ class Bali::MapRulesDsl
|
|
73
70
|
end
|
74
71
|
|
75
72
|
def cannot_all(*params)
|
76
|
-
|
73
|
+
fail Bali::DslError, "cant_all block must be within role block"
|
77
74
|
end
|
78
75
|
end
|
@@ -6,11 +6,9 @@ class Bali::RulesForDsl
|
|
6
6
|
|
7
7
|
# all to be processed subtargets
|
8
8
|
attr_accessor :current_subtargets
|
9
|
-
# rules defined with hash can: [] and cannot: []
|
10
|
-
attr_accessor :shortcut_rules
|
11
9
|
|
12
10
|
def initialize(map_rules_dsl)
|
13
|
-
@@lock
|
11
|
+
@@lock ||= Mutex.new
|
14
12
|
self.map_rules_dsl = map_rules_dsl
|
15
13
|
end
|
16
14
|
|
@@ -22,17 +20,29 @@ class Bali::RulesForDsl
|
|
22
20
|
def role(*params)
|
23
21
|
@@lock.synchronize do
|
24
22
|
bali_scrap_actors(*params)
|
25
|
-
bali_scrap_shortcut_rules(*params)
|
26
23
|
current_subtargets.each do |subtarget|
|
24
|
+
bali_set_subtarget(subtarget)
|
25
|
+
|
27
26
|
if block_given?
|
28
|
-
|
29
|
-
yield
|
30
|
-
end
|
27
|
+
yield
|
31
28
|
else
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
# if no block, then rules are defined using shortcut notation, eg:
|
30
|
+
# role :user, can: [:edit]
|
31
|
+
# the last element of which params must be a hash
|
32
|
+
shortcut_rules = params[-1]
|
33
|
+
unless shortcut_rules.is_a?(Hash)
|
34
|
+
raise Bali::DslError, "Pass a hash for shortcut notation"
|
35
|
+
end
|
36
|
+
|
37
|
+
shortcut_can_rules = shortcut_rules[:can] || shortcut_rules["can"]
|
38
|
+
shortcut_cannot_rules = shortcut_rules[:cannot] || shortcut_rules["cannot"]
|
39
|
+
|
40
|
+
shortcut_rules.each do |auth_val, args|
|
41
|
+
Bali::Integrator::Rule.add(auth_val, self.current_rule_group, *args)
|
42
|
+
end # each shortcut rules
|
43
|
+
end # whether block is given or not
|
44
|
+
end # each subtarget
|
45
|
+
end # sync
|
36
46
|
end # role
|
37
47
|
|
38
48
|
def describe(*params)
|
@@ -61,12 +71,12 @@ class Bali::RulesForDsl
|
|
61
71
|
true
|
62
72
|
end
|
63
73
|
|
64
|
-
def can(*
|
65
|
-
|
74
|
+
def can(*args)
|
75
|
+
Bali::Integrator::Rule.add_can(self.current_rule_group, *args)
|
66
76
|
end
|
67
77
|
|
68
|
-
def cannot(*
|
69
|
-
|
78
|
+
def cannot(*args)
|
79
|
+
Bali::Integrator::Rule.add_cannot(self.current_rule_group, *args)
|
70
80
|
end
|
71
81
|
|
72
82
|
def cant(*operations)
|
@@ -75,13 +85,11 @@ class Bali::RulesForDsl
|
|
75
85
|
end
|
76
86
|
|
77
87
|
def can_all
|
78
|
-
self.current_rule_group
|
79
|
-
self.current_rule_group.plant = false
|
88
|
+
Bali::Integrator::RuleGroup.make_zeus(self.current_rule_group)
|
80
89
|
end
|
81
90
|
|
82
91
|
def cannot_all
|
83
|
-
self.current_rule_group
|
84
|
-
self.current_rule_group.zeus = false
|
92
|
+
Bali::Integrator::RuleGroup.make_plant(self.current_rule_group)
|
85
93
|
end
|
86
94
|
|
87
95
|
def cant_all
|
@@ -104,19 +112,10 @@ class Bali::RulesForDsl
|
|
104
112
|
nil
|
105
113
|
end
|
106
114
|
|
107
|
-
|
108
|
-
|
109
|
-
params.each do |passed_argument|
|
110
|
-
if passed_argument.is_a?(Hash)
|
111
|
-
self.shortcut_rules = passed_argument
|
112
|
-
end
|
113
|
-
end
|
114
|
-
nil
|
115
|
-
end
|
116
|
-
|
117
|
-
def bali_process_subtarget(subtarget)
|
118
|
-
target_class = self.map_rules_dsl.current_rule_class.target_class
|
115
|
+
# set the current processing on a specific subtarget
|
116
|
+
def bali_set_subtarget(subtarget)
|
119
117
|
rule_class = self.map_rules_dsl.current_rule_class
|
118
|
+
target_class = rule_class.target_class
|
120
119
|
|
121
120
|
rule_group = rule_class.rules_for(subtarget)
|
122
121
|
|
@@ -124,65 +123,8 @@ class Bali::RulesForDsl
|
|
124
123
|
rule_group = Bali::RuleGroup.new(target_class, subtarget)
|
125
124
|
end
|
126
125
|
|
126
|
+
rule_class.add_rule_group rule_group
|
127
127
|
self.current_rule_group = rule_group
|
128
|
-
|
129
|
-
if block_given?
|
130
|
-
yield
|
131
|
-
else
|
132
|
-
# auth_val is either can or cannot
|
133
|
-
shortcut_rules.each do |auth_val, operations|
|
134
|
-
if operations.is_a?(Array)
|
135
|
-
operations.each do |op|
|
136
|
-
rule = Bali::Rule.new(auth_val, op)
|
137
|
-
rule_group.add_rule(rule)
|
138
|
-
end
|
139
|
-
else
|
140
|
-
operation = operations # well, basically is 1 only
|
141
|
-
rule = Bali::Rule.new(auth_val, operation)
|
142
|
-
rule_group.add_rule(rule)
|
143
|
-
end
|
144
|
-
end # each rules
|
145
|
-
end # block_given?
|
146
|
-
|
147
|
-
# add current_rule_group
|
148
|
-
rule_class.add_rule_group(rule_group)
|
149
|
-
|
150
|
-
nil
|
151
128
|
end
|
152
129
|
|
153
|
-
# to define can and cant is basically using this method
|
154
|
-
def bali_process_auth_rules(auth_val, args)
|
155
|
-
conditional_hash = nil
|
156
|
-
operations = []
|
157
|
-
|
158
|
-
# scan args for options
|
159
|
-
args.each do |elm|
|
160
|
-
if elm.is_a?(Hash)
|
161
|
-
conditional_hash = elm
|
162
|
-
else
|
163
|
-
operations << elm
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
# add operation one by one
|
168
|
-
operations.each do |op|
|
169
|
-
rule = Bali::Rule.new(auth_val, op)
|
170
|
-
bali_embed_conditions(rule, conditional_hash)
|
171
|
-
self.current_rule_group.add_rule(rule)
|
172
|
-
end
|
173
|
-
end # bali_process_auth_rules
|
174
|
-
|
175
|
-
# process conditional statement in rule definition
|
176
|
-
def bali_embed_conditions(rule, conditional_hash = nil)
|
177
|
-
return if conditional_hash.nil?
|
178
|
-
|
179
|
-
condition_type = conditional_hash.keys[0].to_s.downcase
|
180
|
-
condition_type_symb = condition_type.to_sym
|
181
|
-
|
182
|
-
if condition_type_symb == :if || condition_type_symb == :unless
|
183
|
-
rule.decider = conditional_hash.values[0]
|
184
|
-
rule.decider_type = condition_type_symb
|
185
|
-
end
|
186
|
-
nil
|
187
|
-
end
|
188
130
|
end # class
|
@@ -79,7 +79,7 @@ module Bali::Judger
|
|
79
79
|
|
80
80
|
def rule_group
|
81
81
|
unless @rule_group_checked
|
82
|
-
@rule_group = Bali::
|
82
|
+
@rule_group = Bali::Integrator::RuleGroup.for(record_class, subtarget)
|
83
83
|
@rule_group_checked = true
|
84
84
|
end
|
85
85
|
@rule_group
|
@@ -87,7 +87,7 @@ module Bali::Judger
|
|
87
87
|
|
88
88
|
def other_rule_group
|
89
89
|
unless @other_rule_group_checked
|
90
|
-
@other_rule_group = Bali::
|
90
|
+
@other_rule_group = Bali::Integrator::RuleGroup.for(record_class, "__*__")
|
91
91
|
@other_rule_group_checked = true
|
92
92
|
end
|
93
93
|
@other_rule_group
|
@@ -32,7 +32,7 @@ class Bali::Rule
|
|
32
32
|
elsif aval == :cant
|
33
33
|
@auth_val = :cannot
|
34
34
|
else
|
35
|
-
|
35
|
+
fail Bali::DslError, "auth_val can only either be :can or :cannot"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -40,7 +40,7 @@ class Bali::Rule
|
|
40
40
|
if dectype == :if || dectype == :unless
|
41
41
|
@decider_type = dectype
|
42
42
|
else
|
43
|
-
|
43
|
+
fail Bali::DslError, "decider type not allowed"
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -50,7 +50,6 @@ class Bali::Rule
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def has_decider?
|
53
|
-
|
54
|
-
self.decider.is_a?(Proc)
|
53
|
+
self.decider.is_a?(Proc) && !self.decider_type.nil?
|
55
54
|
end
|
56
55
|
end
|
@@ -13,26 +13,17 @@ class Bali::RuleClass
|
|
13
13
|
attr_accessor :others_rule_group
|
14
14
|
|
15
15
|
def initialize(target_class)
|
16
|
-
|
17
|
-
@target_class = target_class
|
18
|
-
else
|
19
|
-
raise Bali::DslError, "Target class must be a Class"
|
20
|
-
end
|
21
|
-
|
16
|
+
@target_class = target_class
|
22
17
|
self.rule_groups = {}
|
23
18
|
self.others_rule_group = Bali::RuleGroup.new(target_class, "__*__")
|
24
19
|
end
|
25
20
|
|
26
21
|
def add_rule_group(rule_group)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
self.others_rule_group = rule_group
|
31
|
-
else
|
32
|
-
self.rule_groups[rule_group.subtarget] = rule_group
|
33
|
-
end
|
22
|
+
target_user = rule_group.subtarget
|
23
|
+
if target_user == "__*__" || target_user == :"__*__"
|
24
|
+
self.others_rule_group = rule_group
|
34
25
|
else
|
35
|
-
|
26
|
+
self.rule_groups[rule_group.subtarget] = rule_group
|
36
27
|
end
|
37
28
|
end
|
38
29
|
|
@@ -51,12 +51,10 @@ class Bali::RuleGroup
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def add_rule(rule)
|
54
|
-
raise Bali::DslError, "Rule must be of class Bali::Rule, got: #{rule.class.name}" unless rule.is_a?(Bali::Rule)
|
55
|
-
|
56
54
|
# operation cannot be defined twice
|
57
55
|
operation = rule.operation.to_sym
|
58
56
|
|
59
|
-
|
57
|
+
return if self.cants[operation] && self.cans[operation]
|
60
58
|
|
61
59
|
if rule.is_discouragement?
|
62
60
|
self.cants[operation] = rule
|
@@ -80,7 +78,7 @@ class Bali::RuleGroup
|
|
80
78
|
when :cannot, "cannot"
|
81
79
|
rule = self.cants[operation.to_sym]
|
82
80
|
else
|
83
|
-
|
81
|
+
fail Bali::DslError, "Undefined operation: #{auth_val}"
|
84
82
|
end
|
85
83
|
|
86
84
|
rule
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Bali
|
2
|
+
module Integrator
|
3
|
+
# high-level functions to access and manage RuleClass classes
|
4
|
+
module RuleClass
|
5
|
+
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# return all rule classes
|
9
|
+
def all
|
10
|
+
Bali::RULE_CLASS_MAP
|
11
|
+
end
|
12
|
+
|
13
|
+
# return all rule class of a target
|
14
|
+
def for(target)
|
15
|
+
Bali::RULE_CLASS_MAP[target.to_s]
|
16
|
+
end
|
17
|
+
|
18
|
+
# add a new rule class
|
19
|
+
def add(rule_class)
|
20
|
+
target = rule_class.target_class
|
21
|
+
|
22
|
+
Bali::RULE_CLASS_MAP[target.to_s] = rule_class
|
23
|
+
rule_class
|
24
|
+
end # add_rule_class
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Bali
|
2
|
+
module Integrator
|
3
|
+
module RuleGroup
|
4
|
+
|
5
|
+
module_function
|
6
|
+
|
7
|
+
# attempt to search the rule group,
|
8
|
+
# but if not exist, will return nil
|
9
|
+
def for(target_class, subtarget)
|
10
|
+
rule_class = Bali::Integrator::RuleClass.for(target_class)
|
11
|
+
rule_class.nil? ? nil : rule_class.rules_for(subtarget)
|
12
|
+
end
|
13
|
+
|
14
|
+
# make a rule group a zeus, that is, he can do everything, unless
|
15
|
+
# specified more specifically otherwise by a definite rule
|
16
|
+
def make_zeus(rule_group)
|
17
|
+
rule_group.zeus = true
|
18
|
+
rule_group.plant = false
|
19
|
+
end
|
20
|
+
|
21
|
+
# make a rule group a plant, that is, he cannot do everything, unless
|
22
|
+
# specified more specifically otherwise by a definite rule
|
23
|
+
def make_plant(rule_group)
|
24
|
+
rule_group.plant = true
|
25
|
+
rule_group.zeus = false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Bali
|
2
|
+
module Integrator
|
3
|
+
module Rule
|
4
|
+
|
5
|
+
module_function
|
6
|
+
|
7
|
+
# process conditional statement in rule definition
|
8
|
+
# conditional hash: {if: proc} or {unless: proc}
|
9
|
+
def embed_condition(rule, conditional_hash = nil)
|
10
|
+
return if conditional_hash.nil?
|
11
|
+
|
12
|
+
condition_type = conditional_hash.keys[0].to_s.downcase
|
13
|
+
condition_type_symb = condition_type.to_sym
|
14
|
+
|
15
|
+
if condition_type_symb == :if || condition_type_symb == :unless
|
16
|
+
rule.decider = conditional_hash.values[0]
|
17
|
+
rule.decider_type = condition_type_symb
|
18
|
+
end
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# to define can and cant is basically using this method
|
23
|
+
# args can comprises of symbols, and hash (for condition)
|
24
|
+
def add(auth_val, rule_group, *args)
|
25
|
+
conditional_hash = nil
|
26
|
+
operations = []
|
27
|
+
|
28
|
+
# scan args for options
|
29
|
+
args.each do |elm|
|
30
|
+
if elm.is_a?(Hash)
|
31
|
+
conditional_hash = elm
|
32
|
+
else
|
33
|
+
operations << elm
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# add operation one by one
|
38
|
+
operations.each do |op|
|
39
|
+
rule = Bali::Rule.new(auth_val, op)
|
40
|
+
Bali::Integrator::Rule.embed_condition(rule, conditional_hash)
|
41
|
+
rule_group.add_rule(rule)
|
42
|
+
end
|
43
|
+
end # bali_process_auth_rules
|
44
|
+
|
45
|
+
# add can rule programatically
|
46
|
+
def add_can(rule_group, *args)
|
47
|
+
add :can, rule_group, *args
|
48
|
+
end
|
49
|
+
|
50
|
+
# add cannot rule programatically
|
51
|
+
def add_cannot(rule_group, *args)
|
52
|
+
add :cannot, rule_group, *args
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
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: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Pahlevi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -64,11 +64,7 @@ files:
|
|
64
64
|
- .gitignore
|
65
65
|
- .rspec
|
66
66
|
- .travis.yml
|
67
|
-
- CHANGELOG.md
|
68
|
-
- CODE_OF_CONDUCT.md
|
69
67
|
- Gemfile
|
70
|
-
- LICENSE.txt
|
71
|
-
- README.md
|
72
68
|
- Rakefile
|
73
69
|
- bali.gemspec
|
74
70
|
- bin/console
|
@@ -89,7 +85,9 @@ files:
|
|
89
85
|
- lib/bali/foundations/rule/rule_class.rb
|
90
86
|
- lib/bali/foundations/rule/rule_group.rb
|
91
87
|
- lib/bali/integrators/all_integrators.rb
|
92
|
-
- lib/bali/integrators/
|
88
|
+
- lib/bali/integrators/rule_class_integrator.rb
|
89
|
+
- lib/bali/integrators/rule_group_integrator.rb
|
90
|
+
- lib/bali/integrators/rule_integrator.rb
|
93
91
|
- lib/bali/objector.rb
|
94
92
|
- lib/bali/printer.rb
|
95
93
|
- lib/bali/version.rb
|
data/CHANGELOG.md
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
## Changelog
|
2
|
-
|
3
|
-
== Version 1.0.0beta1
|
4
|
-
|
5
|
-
1. Initial version
|
6
|
-
|
7
|
-
== Version 1.0.0rc1
|
8
|
-
|
9
|
-
1. Fix bug where user can't check on class
|
10
|
-
2. Adding new clause: cant_all
|
11
|
-
|
12
|
-
== Version 1.0.0rc2
|
13
|
-
|
14
|
-
1. [Fix bug when class's name, as a constant, is reloaded](http://stackoverflow.com/questions/2509350/rails-class-object-id-changes-after-i-make-a-request) (re-allocated to different address in the memory)
|
15
|
-
2. Allow describing rule for `nil`, useful if user is not authenticated thus role is probably `nil`
|
16
|
-
3. Remove pry from development dependency
|
17
|
-
|
18
|
-
== Version 1.0.0rc3
|
19
|
-
|
20
|
-
1. Each target class should includes `Bali::Objector`, for the following reasons:
|
21
|
-
- Makes it clear that class do want to include the Bali::Objector
|
22
|
-
- Transparant, and thus less confusing as to where "can?" and "cant" come from
|
23
|
-
- When ruby re-parse the class's codes for any reasons, parser will be for sure include Bali::Objector
|
24
|
-
2. Return `true` to any `can?` for undefined target/subtarget alike
|
25
|
-
3. Return `false` to any `cant?` for undefined target/subtarget alike
|
26
|
-
|
27
|
-
== Version 1.0.0
|
28
|
-
|
29
|
-
1. Released the stable version of this gem
|
30
|
-
|
31
|
-
== Version 1.1.0rc1
|
32
|
-
|
33
|
-
1. Ability for rule class to be parsed later by passing `later: true` to rule class definition
|
34
|
-
2. Add `Bali.parse` and `Bali.parse!` (`Bali.parse!` executes "later"-tagged rule class, Bali.parse executes automatically after all rules are defined)
|
35
|
-
3. Added more thorough testing specs
|
36
|
-
4. Proc can be served under `unless` for defining the rule's decider
|
37
|
-
|
38
|
-
== Version 1.1.0rc2
|
39
|
-
|
40
|
-
1. Ability to check `can?` and `cant?` for subtarget with multiple roles
|
41
|
-
2. Describe multiple rules at once for multiple subtarget
|
42
|
-
|
43
|
-
== Version 1.2.0
|
44
|
-
|
45
|
-
1. Passing real object as subtarget's role, instead of symbol or array of symbol
|
46
|
-
2. Clause can also yielding user, along with the object in question
|
47
|
-
|
48
|
-
== Version 2.0.0rc1
|
49
|
-
|
50
|
-
1. `Bali::AuthorizationError` subclass of `StandardError` tailored for raising error regarding with authorisation
|
51
|
-
2. Deprecating `cant`, `cant?`, and `cant_all` in favor of `cannot`, `cannot?` and `cannot_all`
|
52
|
-
3. new objectors `can!` and `cannot!` to raise error on inappropriate access
|
53
|
-
|
54
|
-
== Version 2.0.0
|
55
|
-
|
56
|
-
1. Release!
|
57
|
-
|
58
|
-
== Version 2.1.0
|
59
|
-
|
60
|
-
1. `others` block would allow for rule definitions within it to be applied for all undefined subtargets of a target
|
61
|
-
2. Fixing bug when roles_for of a user object retrieves `nil` as the user's role, it won't acknowledge that the user is indeed having `nil`-role and raising an error instead.
|
62
|
-
3. Inherits rules by passing `:inherits` option when defining `rules_for`
|
63
|
-
4. `clear_rules` within `describe` or `others` block to remove all inherited rules (or any rules previously defined) for that subtarget
|
64
|
-
5. Adding `Bali::Printer` that would enable for rules to be printed by calling `.pretty_print` on it
|
65
|
-
|
66
|
-
== Version 2.1.1
|
67
|
-
|
68
|
-
1. Bug fixes on `clear_rules` which it clear rules defined in `others` even when not asked to
|
69
|
-
2. Bug fixes on `Bali::Printer` where inherited rules print the wrong target class due to another bug in an internal file (but doesn't hamper rules-checking logic)
|
70
|
-
|
71
|
-
== Version 2.1.2
|
72
|
-
|
73
|
-
1. `nil` will be printed <nil> when objecting with can! or cannot! for better readability.
|
74
|
-
2. Bug fixes on declaring multiple rules with decider. Previously, others were ignored--now, every single rule will get defined whether decider is present or not.
|
75
|
-
|
76
|
-
== Version 2.2.0
|
77
|
-
|
78
|
-
1. Deprecating `describe` block in favour of `role` block, `describe` is to be deprecated in version 3.0.
|
79
|
-
2. Using strategy pattern, heavy refactoring
|
80
|
-
3. Human-readable authorisation error message when invoking !-version of can/cannot, for eg: Role general_user is not allowed to perform operation `update` on My::Transaction
|
data/CODE_OF_CONDUCT.md
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# Contributor Code of Conduct
|
2
|
-
|
3
|
-
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
-
|
5
|
-
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
-
|
7
|
-
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
-
|
9
|
-
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
-
|
11
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
-
|
13
|
-
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/LICENSE.txt
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2015 Adam Pahlevi
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
data/README.md
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
# Bali
|
2
|
-
|
3
|
-
[ ![Codeship Status for saveav/bali](https://codeship.com/projects/d2f3ded0-20cf-0133-e425-0eade5a669ff/status?branch=release)](https://codeship.com/projects/95727)
|
4
|
-
|
5
|
-
[![Code Climate](https://codeclimate.com/github/saveav/bali/badges/gpa.svg)](https://codeclimate.com/github/saveav/bali)
|
6
|
-
|
7
|
-
Bali is a powerful, framework-agnostic, thread-safe Ruby language authorization library. It is a universal authorization library, in the sense that it does not assume you to use specific Ruby library/gem/framework in order for successful use of this gem.
|
8
|
-
|
9
|
-
Bali is short for Bulwark Authorization Library.
|
10
|
-
|
11
|
-
## Installation
|
12
|
-
|
13
|
-
It can be installed directly by using bundler's install:
|
14
|
-
|
15
|
-
$ gem install bali
|
16
|
-
|
17
|
-
Otherwise, if you are using a framework such as Rails, you can add this into your gemfile:
|
18
|
-
|
19
|
-
```ruby
|
20
|
-
gem 'bali'
|
21
|
-
```
|
22
|
-
|
23
|
-
And then execute:
|
24
|
-
|
25
|
-
$ bundle
|
26
|
-
|
27
|
-
## Deprecation notice
|
28
|
-
|
29
|
-
1. `cant` and `cant_all` which are used to declare rules will be deprecated on version 3.0, in favor of `cannot` and `cannot_all`. The reason behind this is that `can` and `cant` only differ by 1 letter, it is thought to be better to make it less ambiguous.
|
30
|
-
2. `cant?` and subsequently new-introduced `cant!` will be deprecated on version 3.0, in favor of `cannot?` and `cannot!` for the same reason as above.
|
31
|
-
3. Since version 2.1.3, `describe` block is replaced with `role` block. `describe` block will be deprecated on version 3.0.
|
32
|
-
|
33
|
-
## Usage
|
34
|
-
|
35
|
-
Please access [wiki pages](https://github.com/saveav/bali/wiki) for a more detailed, guided explanation, and see what Bali can do. This usage is a simple demonstration what average, standard use of Bali would looks like.
|
36
|
-
|
37
|
-
Say:
|
38
|
-
|
39
|
-
```ruby
|
40
|
-
class My::Transaction
|
41
|
-
include Bali::Objector
|
42
|
-
|
43
|
-
attr_accessor :is_settled
|
44
|
-
attr_accessor :payment_channel
|
45
|
-
|
46
|
-
alias :is_settled? :is_settled
|
47
|
-
end
|
48
|
-
|
49
|
-
class My::Employee
|
50
|
-
include Bali::Objector
|
51
|
-
|
52
|
-
# working experience in the company
|
53
|
-
attr_accessor :exp_years
|
54
|
-
|
55
|
-
# role/roles of this employee
|
56
|
-
attr_accessor :roles
|
57
|
-
end
|
58
|
-
```
|
59
|
-
|
60
|
-
Your task is to define rule, with context to `My::Transaction` object, in which:
|
61
|
-
|
62
|
-
1. Supreme user can do everything
|
63
|
-
2. Admin user can do everything, but:
|
64
|
-
- Can only cancel transaction if the transaction is done using credit card, and the transaction itself is not settled yet
|
65
|
-
3. General user can:
|
66
|
-
- Download transaction
|
67
|
-
4. Finance user can:
|
68
|
-
- Index transaction
|
69
|
-
- Download transaction
|
70
|
-
- Delete transaction if the transaction is settled
|
71
|
-
- Cancel transaction if the transaction is settled
|
72
|
-
5. Monitoring user can:
|
73
|
-
- Index transaction
|
74
|
-
- Download transaction
|
75
|
-
6. Sales team can:
|
76
|
-
- Index transaction
|
77
|
-
- Download transaction
|
78
|
-
6. Unlogged in user can:
|
79
|
-
- Index transaction
|
80
|
-
- Download transaction
|
81
|
-
- Report fraud
|
82
|
-
7. Guest user can:
|
83
|
-
- Index transaction
|
84
|
-
- Download transaction
|
85
|
-
- Report fraud
|
86
|
-
|
87
|
-
The specification above seems very terrifying, but with Bali, those can be defined in a succinct way, as follow:
|
88
|
-
|
89
|
-
```ruby
|
90
|
-
Bali.map_rules do
|
91
|
-
rules_for My::Transaction do
|
92
|
-
role(:supreme_user) { can_all }
|
93
|
-
role :admin_user do
|
94
|
-
can_all
|
95
|
-
# a more specific rule would be executed even if can_all is present
|
96
|
-
can :cancel,
|
97
|
-
if: proc { |record| record.payment_channel == "CREDIT_CARD" &&
|
98
|
-
!record.is_settled? }
|
99
|
-
end
|
100
|
-
role "general user", can: [:download]
|
101
|
-
role "finance" do
|
102
|
-
can :delete, if: proc { |record| record.is_settled? }
|
103
|
-
can :cancel, unless: proc { |record| record.is_settled? }
|
104
|
-
end # finance_user description
|
105
|
-
role :guest, nil { can :report_fraud }
|
106
|
-
role :client do
|
107
|
-
can :create
|
108
|
-
end
|
109
|
-
others do
|
110
|
-
cannot_all
|
111
|
-
can :download, :index
|
112
|
-
cannot :create
|
113
|
-
end
|
114
|
-
end # rules_for
|
115
|
-
end
|
116
|
-
```
|
117
|
-
|
118
|
-
## Can and Cant? testing
|
119
|
-
|
120
|
-
Assuming that there exist a variable `transaction` which is an instance of `My::Transaction`:
|
121
|
-
|
122
|
-
```ruby
|
123
|
-
transaction.cant?(:general_user, :delete) # => false
|
124
|
-
transaction.can("general user", :download) # => true
|
125
|
-
transaction.can?(:finance, :delete) # depends on context
|
126
|
-
transaction.can?(:monitoring, :index) # => true
|
127
|
-
transaction.can?(:sales, :download) # => true
|
128
|
-
transaction.can?(:admin_user, :cancel) # depends on context
|
129
|
-
transaction.can?(:supreme_user, :cancel) # => true
|
130
|
-
transaction.can?(:guest, :download) # => false
|
131
|
-
transaction.can?(nil, :download) # => true
|
132
|
-
transaction.can?(nil, :report_fraud) # => true
|
133
|
-
transaction.can?(:undefined_subtarget, :see) # => false
|
134
|
-
transaction.cant?(:undefined_subtarget, :index) # => true
|
135
|
-
transaction.can?(:client, :create) # => true
|
136
|
-
transaction.can?(:finance, :create) # => false
|
137
|
-
transaction.can?(:admin, :create) # => true
|
138
|
-
```
|
139
|
-
|
140
|
-
Rule can also be tested on a class:
|
141
|
-
|
142
|
-
```ruby
|
143
|
-
My::Transaction.can?(:client, :create) # => true
|
144
|
-
My::Transaction.can?(:guest, :create) # => false
|
145
|
-
My::Employee.can?(:undefined_subtarget, :create) # => false
|
146
|
-
```
|
147
|
-
|
148
|
-
## Contributing
|
149
|
-
|
150
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/saveav/bali. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
151
|
-
|
152
|
-
## License
|
153
|
-
|
154
|
-
Bali is proudly available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
155
|
-
|
156
|
-
## Changelog
|
157
|
-
|
158
|
-
Please refer to CHANGELOG.md to see it
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module Bali::Integrators::Rule
|
2
|
-
extend self
|
3
|
-
|
4
|
-
def rule_classes
|
5
|
-
Bali::RULE_CLASS_MAP
|
6
|
-
end
|
7
|
-
|
8
|
-
def rule_class_for(target)
|
9
|
-
raise Bali::DslError, "Target must be a class" unless target.is_a?(Class)
|
10
|
-
rule_class = Bali::RULE_CLASS_MAP[target.to_s]
|
11
|
-
return rule_class.nil? ? nil : rule_class
|
12
|
-
end
|
13
|
-
|
14
|
-
# attempt to search the rule group, but if not exist, will return nil
|
15
|
-
def rule_group_for(target_class, subtarget)
|
16
|
-
rule_class = rule_class_for(target_class)
|
17
|
-
if rule_class
|
18
|
-
rule_group = rule_class.rules_for(subtarget)
|
19
|
-
return rule_group
|
20
|
-
else
|
21
|
-
return nil
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def add_rule_class(rule_class)
|
26
|
-
if rule_class.is_a?(Bali::RuleClass)
|
27
|
-
target = rule_class.target_class
|
28
|
-
|
29
|
-
raise Bali::DslError, "Target must be a class" unless target.is_a?(Class)
|
30
|
-
|
31
|
-
Bali::RULE_CLASS_MAP[target.to_s] = rule_class
|
32
|
-
rule_class
|
33
|
-
else
|
34
|
-
raise Bali::DslError, "Only allow instance of Bali::RuleClass"
|
35
|
-
end
|
36
|
-
end # add_rule_class
|
37
|
-
end
|