bali 1.1.0rc1 → 1.1.0rc2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 340aadebc55874ca95a0b864e0117d2d93e798c3
4
- data.tar.gz: 7019bbc158e229ff267012ae472e6969fa03f5ef
3
+ metadata.gz: fd5c0fb2638885502b2fdb39ecaba159b90dac24
4
+ data.tar.gz: 2d6308b4df6d3d363bed7d2ce4b72ec9b7368e57
5
5
  SHA512:
6
- metadata.gz: 0a88ac2145d2c73d087b286e3046b30a839b50bb5564b2747b4a60822a571db72b5fe8de53d4eb7b97debb1f93b40a5220b2d4471bd6b696649d9440b112f879
7
- data.tar.gz: 6be3dcc843c90c4c08e07303d863c7ae43550951980b1e28b86994c8432f26a1420011cd3efdccb494077cdac473360ba0654ca3bebe2e69c0e5340ab1581f42
6
+ metadata.gz: 5f675d90ac77a7558ce6cb545a3dbf3aa5c05bf6856df44b50331b34ed3c786200453efa371c13ac13b3b3eaef7d38a9b1d3d8ee05cfadb473246a0982e9224e
7
+ data.tar.gz: 33919e7f7c83e50aee8afb59704bef97f902d257099f3af799a947ab955353b4144f7df3243623dee88d9d3f37ba298216b65313ae1638ad5a6a513f7649fc78
data/README.md CHANGED
@@ -24,9 +24,9 @@ And then execute:
24
24
 
25
25
  ## Usage
26
26
 
27
- ### First things first: defining rules
27
+ ### Defining access rules
28
28
 
29
- Rule in Bali is the law determining whether a user (called `subtarget`) can do or perform specific operation on a target (which is your resource/model).
29
+ Rule in Bali is the law determining whether a user (called `subtarget`) can do or perform a specific operation on a target (which is your resource/model).
30
30
 
31
31
  ```ruby
32
32
  Bali.map_rules do
@@ -53,7 +53,20 @@ Rule in Bali is the law determining whether a user (called `subtarget`) can do o
53
53
 
54
54
  You may or may not assign an alias name (`as`). Make sure to keep it unique had you decided to give alias name to your rules group.
55
55
 
56
- ### Can and Cannot testing
56
+ It is also possible for a rule to be defined for multiple subtarget at once:
57
+
58
+ ```ruby
59
+ Bali.map_rules do
60
+ rules_for My::Transaction do
61
+ # rules described bellow will affect both :general_user and :finance_user
62
+ describe :general_user, :finance_user do
63
+ can :update, :edit
64
+ end
65
+ end
66
+ end
67
+ ```
68
+
69
+ ### Can and Cant? testing
57
70
 
58
71
  Say:
59
72
 
@@ -105,30 +118,54 @@ My::Employee.can?(:undefined_subtarget, :new) # => false, rule class for this i
105
118
 
106
119
  As we have never define the `rules_for` My::Employee before, any attempt to `can?` for `My::Employee` will return `false`, so does any attempt to object `cant?` on which will only return `true` for any given subtarget and operation.
107
120
 
121
+ ### Can and Cant testing with multiple-roles subtarget
122
+
123
+ A subtarget may have multiple roles. For eg., a user may have a role of `finance_user` and `general_user`. A general user normally by itself cannot `delete`, or `cancel`; but a `finance_user` does can, so long the condition is met. But, if a subtarget has role of both `finance_user` and `general_user`, he/she can perform `delete` or `cancel` (so far that the condition is met.)
124
+
125
+ Thus, if we have:
126
+
127
+ ```ruby
128
+ txn = My::Transaction.new
129
+ txn.process_transaction(from_user_input)
130
+
131
+ # delete or cancel can only happen when a transaction is settled
132
+ # as per rule definition
133
+ txn.is_settled = true
134
+ txn.save
135
+
136
+ subtarget = User.new
137
+ subtarget.roles = [:finance_user, :general_user]
138
+
139
+ txn.can?(subtarget.roles, :delete) # => true
140
+ txn.cant?(subtarget.roles, :delete) # => false
141
+ txn.can?(:general_user, :delete) # => false
142
+ ```
143
+
144
+ That is, we can check `can?` and `cant?` with multiple roles by passing array of roles to it.
145
+
108
146
  ## Contributing
109
147
 
110
148
  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.
111
149
 
112
-
113
150
  ## License
114
151
 
115
152
  Bali is proudly available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
116
153
 
117
- ### Changelog
154
+ ## Changelog
118
155
 
119
- #### Version 1.0.0beta1
156
+ ### Version 1.0.0beta1
120
157
  1. Initial version
121
158
 
122
- #### Version 1.0.0rc1
159
+ ### Version 1.0.0rc1
123
160
  1. Fix bug where user can't check on class
124
161
  2. Adding new clause: cant_all
125
162
 
126
- #### Version 1.0.0rc2
163
+ ### Version 1.0.0rc2
127
164
  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)
128
165
  2. Allow describing rule for `nil`, useful if user is not authenticated thus role is probably `nil`
129
166
  3. Remove pry from development dependency
130
167
 
131
- #### Version 1.0.0rc3
168
+ ### Version 1.0.0rc3
132
169
  1. Each target class should includes `Bali::Objector`, for the following reasons:
133
170
  - Makes it clear that class do want to include the Bali::Objector
134
171
  - Transparant, and thus less confusing as to where "can?" and "cant" come from
@@ -136,11 +173,15 @@ Bali is proudly available as open source under the terms of the [MIT License](ht
136
173
  2. Return `true` to any `can?` for undefined target/subtarget alike
137
174
  3. Return `false` to any `cant?` for undefined target/subtarget alike
138
175
 
139
- #### Version 1.0.0
176
+ ### Version 1.0.0
140
177
  1. Released the stable version of this gem
141
178
 
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)
179
+ ### Version 1.1.0rc1
180
+ 1. Ability for rule class to be parsed later by passing `later: true` to rule class definition
181
+ 2. Add `Bali.parse` and `Bali.parse!` (`Bali.parse!` executes "later"-tagged rule class, Bali.parse executes automatically after all rules are defined)
145
182
  3. Added more thorough testing specs
146
- 4. Proc can be served under `unless` for defining the rule's decider
183
+ 4. Proc can be served under `unless` for defining the rule's decider
184
+
185
+ ### Version 1.1.0rc2
186
+ 1. Ability to check `can?` and `cant?` for subtarget with multiple roles
187
+ 2. Describe multiple rules at once for multiple subtarget
@@ -17,4 +17,8 @@ class Bali::MapRulesDsl
17
17
  Bali.add_rule_class(self.current_rule_class)
18
18
  end
19
19
  end
20
+
21
+ def describe(*params)
22
+ raise Bali::DslError, "describe block must be within rules_for block"
23
+ end
20
24
  end
@@ -9,38 +9,63 @@ class Bali::RulesForDsl
9
9
  self.map_rules_dsl = map_rules_dsl
10
10
  end
11
11
 
12
- def describe(subtarget, rules = {})
12
+ def current_rule_class
13
+ self.map_rules_dsl.current_rule_class
14
+ end
15
+
16
+ def describe(*params)
17
+
18
+ subtargets = []
19
+ rules = {}
20
+
21
+ params.each do |passed_argument|
22
+ if passed_argument.is_a?(Symbol) || passed_argument.is_a?(String)
23
+ subtargets << passed_argument
24
+ elsif passed_argument.is_a?(NilClass)
25
+ subtargets << passed_argument
26
+ elsif passed_argument.is_a?(Array)
27
+ subtargets += passed_argument
28
+ elsif passed_argument.is_a?(Hash)
29
+ rules = passed_argument
30
+ else
31
+ raise Bali::DslError, "Allowed argument: symbol, string, nil and hash"
32
+ end
33
+ end
34
+
13
35
  target_class = self.map_rules_dsl.current_rule_class.target_class
14
36
  target_alias = self.map_rules_dsl.current_rule_class.alias_name
15
37
 
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)
38
+ subtargets.each do |subtarget|
39
+ @@lock.synchronize do
40
+ rule_group = self.current_rule_class.rules_for(subtarget)
41
+ if rule_group.nil?
42
+ rule_group = Bali::RuleGroup.new(target_class, target_alias, subtarget)
43
+ end
44
+
45
+ self.current_rule_group = rule_group
46
+
47
+ if block_given?
48
+ yield
49
+ else
50
+ # auth_val is either can or cant
51
+ rules.each do |auth_val, operations|
52
+ if operations.is_a?(Array)
53
+ operations.each do |op|
54
+ rule = Bali::Rule.new(auth_val, op)
55
+ self.current_rule_group.add_rule(rule)
56
+ end
57
+ else
58
+ operation = operations # well, basically is 1 only
59
+ rule = Bali::Rule.new(auth_val, operation)
60
+ self.current_rule_group.add_rule(rule)
32
61
  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
62
+ end # each rules
63
+ end # block_given?
64
+
65
+ # add current_rule_group
66
+ self.map_rules_dsl.current_rule_class.add_rule_group(self.current_rule_group)
67
+ end # mutex synchronize
68
+ end # each subtarget
44
69
  end # describe
45
70
 
46
71
  # to define can and cant is basically using this method
@@ -38,6 +38,8 @@ class Bali::RuleGroup
38
38
  end
39
39
 
40
40
  def add_rule(rule)
41
+ raise Bali::DslError, "Rule must be of class Bali::Rule" unless rule.is_a?(Bali::Rule)
42
+
41
43
  # operation cannot be defined twice
42
44
  operation = rule.operation.to_sym
43
45
 
@@ -5,17 +5,23 @@ module Bali::Objector
5
5
  base.extend Bali::Objector::Statics
6
6
  end
7
7
 
8
- def can?(subtarget, operation)
9
- self.class.can?(subtarget, operation, self)
8
+ def can?(subtargets, operation)
9
+ self.class.can?(subtargets, operation, self)
10
10
  end
11
11
 
12
- def cant?(subtarget, operation)
13
- self.class.cant?(subtarget, operation, self)
12
+ def cant?(subtargets, operation)
13
+ self.class.cant?(subtargets, operation, self)
14
14
  end
15
15
  end
16
16
 
17
17
  module Bali::Objector::Statics
18
- def can?(subtarget, operation, record = self, options = {})
18
+
19
+ ### options passable to __can__? and __cant__? are:
20
+ ### cross_action: if set to true wouldn't call its counterpart so as to prevent
21
+ ### overflowing stack
22
+ ###
23
+
24
+ def __can__?(subtarget, operation, record = self, options = {})
19
25
  # if performed on a class-level, don't call its class or it will return
20
26
  # Class. That's not what is expected.
21
27
  if self.is_a?(Class)
@@ -67,10 +73,9 @@ module Bali::Objector::Statics
67
73
  return true
68
74
  end
69
75
  end
70
-
71
76
  end
72
77
 
73
- def cant?(subtarget, operation, record = self, options = {})
78
+ def __cant__?(subtarget, operation, record = self, options = {})
74
79
  if self.is_a?(Class)
75
80
  rule_group = Bali.rule_group_for(self, subtarget)
76
81
  else
@@ -119,4 +124,24 @@ module Bali::Objector::Statics
119
124
  end # if rule has decider
120
125
  end # if rule is nil
121
126
  end
127
+
128
+ def can?(subtargets, operation, record = self, options = {})
129
+ subs = (subtargets.is_a?(Array)) ? subtargets : [subtargets]
130
+
131
+ subs.each do |subtarget|
132
+ can_value = __can__?(subtarget, operation, record, options)
133
+ return true if can_value == true
134
+ end
135
+ false
136
+ end
137
+
138
+ def cant?(subtargets, operation, record = self, options = {})
139
+ subs = (subtargets.is_a?(Array)) ? subtargets : [subtargets]
140
+
141
+ subs.each do |subtarget|
142
+ cant_value = __cant__?(subtarget, operation, record, options)
143
+ return false if cant_value == false
144
+ end
145
+ true
146
+ end
122
147
  end
@@ -1,3 +1,3 @@
1
1
  module Bali
2
- VERSION = "1.1.0rc1"
2
+ VERSION = "1.1.0rc2"
3
3
  end
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.1.0rc1
4
+ version: 1.1.0rc2
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-22 00:00:00.000000000 Z
11
+ date: 2015-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,20 +52,6 @@ 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'
69
55
  description: "Bali (Bulwark Authorization Library) is a universal authorization library,
70
56
  in the sense that \n it does not assume you to use specific
71
57
  Ruby library/gem/framework."