bali 1.1.0rc1 → 1.1.0rc2

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 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."