i_am_i_can 4.0.0 → 4.1.0

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: bd4d579c7635be07c436c9d2f76913fdbaf14638
4
- data.tar.gz: 4028733df55abde29ef7a4365e538211bf6192cb
3
+ metadata.gz: f5c54e75b43df8cbfb0e8acd30cb0fc40e0aeda0
4
+ data.tar.gz: 5a0a6c5198cdb76ca0a251b99d7320cc2a081854
5
5
  SHA512:
6
- metadata.gz: 187dad10491e715a62224579b03906d75ae8716e399d4bc73f006eb3a1bf672693120f14b2d9221daab958a6c6aebdb05ec19dbc738a68f8ebafd1ef31ba6bd7
7
- data.tar.gz: 8ad7aff9edb8342d472e08dfaf86e2dc63c26f2b5a90efcf491d637c69f9a60248cc1d730385a0c46a1aff1757cf709ee927ae4a252e8fcabc6a3ec795faac53
6
+ metadata.gz: 00ed26e8fe4e750241e92eda7d5acb084bc3a733f654af380e61f052c8723c62e5f8b82ef9e1907466caf02a8f7a2cc6c2d30fd44a20848b60965e53333e65f1
7
+ data.tar.gz: f6d4a8bbab40bfe9017f38a0f7acc63aa5784743e279a15c4b26611bab9ee8f39d1c58e572de1f48b9acfc36d464454869be057354329dad5119bc14d5bde1a3
data/README.md CHANGED
@@ -58,8 +58,9 @@ Resource.that_allow(user, to: :manage) # => ActiveRecord_Relation[]
58
58
  - [About role group](#about-role-group)
59
59
  - [Three steps to use this gem](#three-steps-to-use-this-gem)
60
60
  - [Two Concepts of this gem](#two-concepts-of-this-gem)
61
+ - [How it work?](#how-it-work)
61
62
 
62
- 2. [Installation And Setup](#installation-and-setup)
63
+ 2. [Installation and Setup](#installation-and-setup)
63
64
 
64
65
  3. [Usage](#usage)
65
66
  - [Config Options](#config-options)
@@ -133,9 +134,20 @@ Resource.that_allow(user, to: :manage) # => ActiveRecord_Relation[]
133
134
  1. Stored (save in database) TODO
134
135
  2. Temporary (save in instance variable) TODO
135
136
 
137
+ ### How it work?
138
+
139
+ Very simple. Really simple. Sooooo Simple.
140
+
141
+ 1. To define something, you actually `create` records.
142
+ [see here](https://github.com/zhandao/i_am_i_can/blob/master/lib/i_am_i_can/helpers/dynamic.rb#L92)
143
+ 2. To assign something, you actually call one of the activerecord association methods.
144
+ [see here](https://github.com/zhandao/i_am_i_can/blob/master/lib/i_am_i_can/helpers/dynamic.rb#L67)
145
+ 2. To query something, you actually call the querying interfaces of activerecord.
146
+ [see here](https://github.com/zhandao/i_am_i_can/tree/master/lib/i_am_i_can/subject)
147
+
136
148
  [Feature List: needs you](https://github.com/zhandao/i_am_i_can/issues/2)
137
149
 
138
- ## Installation And Setup
150
+ ## Installation and Setup
139
151
 
140
152
  1. Add this line to your application's Gemfile and then `bundle`:
141
153
 
@@ -251,7 +263,13 @@ UserRoleGroup.which(name: :vip).members.names # => %i[vip1 vip2 vip3]
251
263
  3. `is_not_a` / `has_not_role` / `has_not_roles`
252
264
  4. `will_not_be`
253
265
  2. `is_not_a_temporary`
254
- 4. helpers:
266
+ 4. replacement assignment by calling: `is_only_a`, alias `currently_is`.
267
+ (makes the role collection contain only the supplied roles, by adding and deleting as appropriate)
268
+ 5. callbacks - before / after / around:
269
+ 1. `role_assign`: assignment
270
+ 2. `cancel_role_assign`: cancel assignment
271
+ 3. `role_update`:
272
+ 6. helpers:
255
273
  1. relation with stored role, defaults to `stored_roles`.
256
274
  2. `temporary_roles` and `valid_temporary_roles`
257
275
  3. `roles`
@@ -287,6 +305,12 @@ is_not_a_temporary *roles
287
305
  he.falls_from :admin # => 'Role Assignment Done' or error message
288
306
  he.is_not_a_temporary :coder # => 'Role Assignment Done' or error message
289
307
  he.roles # => []
308
+
309
+ # === Replacement Assignment ===
310
+ # method signature
311
+ is_only_a *roles
312
+ # examples
313
+ he.is_only_a :role1, :role2
290
314
  ```
291
315
 
292
316
  #### D. [Role / Group Querying](https://github.com/zhandao/i_am_i_can/blob/master/lib/i_am_i_can/subject/role_querying.rb)
@@ -347,6 +371,12 @@ UserPermission.count # => 1 + 2
347
371
  1. caller: role / role group instance, like `UserRole.which(name: :admin)`
348
372
  2. assignment by calling `can`. alias `has_permission`
349
373
  3. cancel assignment by calling `cannot`. alias `is_not_allowed_to`
374
+ 4. replacement assignment by calling: `can_only`,.
375
+ (makes the permission collection contain only the supplied permissions, by adding and deleting as appropriate)
376
+ 5. callbacks - before / after / around:
377
+ 1. `permission_assign`: assignment
378
+ 2. `cancel_permission_assign`: cancel assignment
379
+ 3. `permission_update`: replacement assignment
350
380
  4. helpers:
351
381
  1. relation with stored permission, defaults to `permissions`.
352
382
 
@@ -359,11 +389,23 @@ UserRole.have_permission :fly
359
389
 
360
390
  # === Assignment ===
361
391
  # method signature
362
- can *actions, resource: nil, obj: resource,
392
+ can *actions, resource: nil, obj: resource, # you can use `resource` or `obj`
363
393
  _d: config.auto_definition, auto_definition: _d
364
394
  # examples
365
395
  role.can :fly # => 'Permission Assignment Done' or error message
366
396
  role.permissions # => [<#UserPermission id: ..>]
397
+
398
+ # === Cancel Assignment ===
399
+ # method signature
400
+ cannot *actions, resource: nil, obj: resource
401
+ # examples
402
+ role.cannot :fly
403
+
404
+ # === Replacement Assignment ===
405
+ # method signature
406
+ can_only *actions, resource: nil, obj: resource
407
+ # examples
408
+ role.can_only :run
367
409
  ```
368
410
 
369
411
  #### G. [Permission Querying](https://github.com/zhandao/i_am_i_can/blob/master/lib/i_am_i_can/subject/role_querying.rb)
@@ -397,8 +439,8 @@ he.can? :perform, obj: :magic
397
439
  he.cannot? :perform, :magic
398
440
  he.can! :perform, :magic
399
441
 
400
- he.can_each? %i[fly jump] # return false if he can not `fly` or `jump`
401
- he.can_one_of! %i[fly jump] # return true if he can `fly` or `jump`
442
+ he.can_each? %i[ fly jump ] # return false if he can not `fly` or `jump`
443
+ he.can_one_of! %i[ fly jump ] # return true if he can `fly` or `jump`
402
444
  ```
403
445
 
404
446
  #### H. Shortcut Combinations - which_can
@@ -5,7 +5,7 @@ class <%= permission_c %> < ActiveRecord::Base
5
5
  has_and_belongs_to_many :related_role_groups,
6
6
  join_table: '<%= group_pms_tb %>', foreign_key: :<%= group_u %>_id, class_name: '<%= group_c %>', association_foreign_key: :<%= permission_u %>_id
7
7
  <% end %>
8
- belongs_to :obj, polymorphic: true
8
+ belongs_to :resource, polymorphic: true
9
9
 
10
10
  acts_as_permission
11
11
  end
@@ -2,17 +2,15 @@ class <%= role_c %> < ActiveRecord::Base
2
2
  has_and_belongs_to_many :related_users,
3
3
  join_table: '<%= subj_role_tb %>', foreign_key: :<%= name_u %>_id, class_name: '<%= name_c %>', association_foreign_key: :<%= role_u %>_id
4
4
  <% unless @ii_opts[:without_group] %>
5
- has_and_belongs_to_many :related_stored_groups,
5
+ has_and_belongs_to_many :related_groups,
6
6
  join_table: '<%= group_role_tb %>', foreign_key: :<%= group_u %>_id, class_name: '<%= group_c %>', association_foreign_key: :<%= role_u %>_id
7
7
  <% end %>
8
8
  has_and_belongs_to_many :permissions,
9
9
  join_table: '<%= role_pms_tb %>', foreign_key: :<%= permission_u %>_id, class_name: '<%= permission_c %>', association_foreign_key: :<%= role_u %>_id
10
10
 
11
- has_many_temporary_permissions
12
-
13
11
  acts_as_role
14
12
 
15
- # default_scope { with_stored_permissions }
13
+ # default_scope { with_permissions }
16
14
  end
17
15
 
18
16
  __END__
@@ -5,11 +5,11 @@ class RoleGroup < ActiveRecord::Base
5
5
  has_and_belongs_to_many :members,
6
6
  join_table: '<%= group_role_tb %>', foreign_key: :<%= role_u %>_id, class_name: '<%= role_c %>', association_foreign_key: :<%= group_u %>_id
7
7
 
8
- has_many_temporary_permissions
9
-
10
8
  acts_as_role_group
11
9
 
12
- # default_scope { with_members.with_stored_permissions) }
10
+ # default_scope { with_members) }
11
+
12
+ # default_scope { with_permissions) }
13
13
  end
14
14
 
15
15
  __END__
@@ -53,23 +53,21 @@ module IAmICan
53
53
  # You call the proc below by given contents [:role], then:
54
54
  #
55
55
  proc { |contents| contents.each do |content|
56
- content_cls = i_am_i_can.send("#{content}_class")
56
+ content_cls = i_am_i_can.send("#{content}_class") rescue next
57
57
  _plural = '_' + content.to_s.pluralize
58
+ __plural = send("_#{_plural}")
58
59
 
59
60
  # _stored_roles_exec
60
61
  # Add / Remove (by passing action :cancel) roles to a user instance
61
- define_method "_#{_reflect_of(content)}_exec" do |action = :assignment, instances = [ ], **conditions|
62
- collection = send(_plural)
63
- if conditions.present? && action == :assignment
64
- # Role.where(name: [...]).where.not(id: roles.ids)
65
- query_result = content_cls.constantize.where(conditions).where.not(id: collection.ids)
66
- elsif conditions.present? && action == :cancel
67
- # Role.where(id: roles.ids, name: [...])
68
- query_result = content_cls.constantize.where(id: collection.ids, **conditions)
69
- end
62
+ define_method "_#{_reflect_of(content)}_exec" do |action = :assign, instances = [ ], **conditions|
63
+ collection, objects = send(_plural), [ ]
64
+ records = conditions.present? ? content_cls.constantize.where(conditions) : [ ]
70
65
 
71
- objects = [*(query_result || [ ]), *(instances - collection)].uniq
72
- action == :assignment ? collection << objects : collection.destroy(objects)
66
+ case action
67
+ when :assign then collection << objects = (records + instances).uniq - collection
68
+ when :cancel then collection.destroy objects = (records + instances).uniq & collection
69
+ when :replace then send("#{__plural}=", objects = (records + instances).uniq) # collection=
70
+ end
73
71
  objects
74
72
  end
75
73
  #
@@ -86,7 +84,7 @@ module IAmICan
86
84
  # You call the proc below by given contents [:role], then:
87
85
  #
88
86
  proc { |contents| contents.each do |content|
89
- content_cls = i_am_i_can.send("#{content}_class")
87
+ content_cls = i_am_i_can.send("#{content}_class") rescue next
90
88
  _plural = '_' + content.to_s.pluralize
91
89
 
92
90
  # _create_roles
@@ -1,22 +1,31 @@
1
1
  module IAmICan
2
2
  module Permission
3
3
  module Assignment
4
- def can *actions,
5
- resource: nil, obj: resource,
4
+ def can *actions, resource: nil, obj: resource,
6
5
  _d: i_am_i_can.auto_definition, auto_definition: _d
7
6
  self.class.have_permissions *actions, obj: obj if auto_definition
8
- _permissions_assignment(actions, obj)
7
+ run_callbacks(:permission_assign) do
8
+ _permissions_assignment(actions, obj)
9
+ end
9
10
  end
10
11
 
11
12
  alias has_permission can
12
13
 
13
- def cannot *actions, obj: nil
14
- _permissions_assignment(:cancel, actions, obj)
14
+ def cannot *actions, resource: nil, obj: resource
15
+ run_callbacks(:cancel_permission_assign) do
16
+ _permissions_assignment(:cancel, actions, obj)
17
+ end
15
18
  end
16
19
 
17
20
  alias is_not_allowed_to cannot
18
21
 
19
- def _permissions_assignment(action = :assignment, actions, obj)
22
+ def can_only *actions, resource: nil, obj: resource
23
+ run_callbacks(:permission_update) do
24
+ _permissions_assignment(:replace, actions, obj)
25
+ end
26
+ end
27
+
28
+ def _permissions_assignment(action = :assign, actions, obj)
20
29
  permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o) } }
21
30
  assignment = _stored_permissions_exec(action,
22
31
  permissions.reduce({ }) { |a, b| a.merge(b) { |_, x, y| [x, y] } })
@@ -6,26 +6,36 @@ module IAmICan
6
6
  auto_definition: _d || which_can.present?,
7
7
  save: true
8
8
  self.class.have_roles *roles, which_can: which_can, obj: obj if auto_definition
9
- _roles_assignment(roles, save)
9
+ run_callbacks(:role_assign) do
10
+ _roles_assignment(roles, save)
11
+ end
10
12
  end
11
13
 
12
- %i[ is is_a is_a_role is_roles has_role has_roles role_is role_are ].each { |aname| alias_method aname, :becomes_a }
13
-
14
14
  def is_a_temporary *roles, **options
15
15
  becomes_a *roles, save: false, **options
16
16
  end
17
17
 
18
18
  def falls_from *roles, saved: true
19
- _roles_assignment(:cancel, roles, saved)
19
+ run_callbacks(:cancel_role_assign) do
20
+ _roles_assignment(:cancel, roles, saved)
21
+ end
20
22
  end
21
23
 
22
- %i[ is_not_a will_not_be removes_role leaves has_not_role has_not_roles ].each { |aname| alias_method aname, :falls_from }
23
-
24
24
  def is_not_a_temporary *roles
25
25
  falls_from *roles, saved: false
26
26
  end
27
27
 
28
- def _roles_assignment(action = :assignment, roles, save)
28
+ def is_only_a *roles
29
+ run_callbacks(:role_update) do
30
+ _roles_assignment(:replace, roles, true)
31
+ end
32
+ end
33
+
34
+ %i[ is is_a is_a_role is_roles has_role has_roles role_is role_are ].each { |aname| alias_method aname, :becomes_a }
35
+ %i[ is_not_a will_not_be removes_role leaves has_not_role has_not_roles ].each { |aname| alias_method aname, :falls_from }
36
+ %i[ currently_is_a ].each { |aname| alias_method aname, :is_only_a }
37
+
38
+ def _roles_assignment(action = :assign, roles, save)
29
39
  instances, names = Role.extract(roles, i_am_i_can)
30
40
  if save
31
41
  assignment = _stored_roles_exec(action, instances, name: names)
@@ -0,0 +1,6 @@
1
+ module IAmICan
2
+ module Role
3
+ module Grouping
4
+ end
5
+ end
6
+ end
@@ -1,7 +1,7 @@
1
1
  require 'i_am_i_can/role/definition'
2
2
  require 'i_am_i_can/role/assignment'
3
+ require 'i_am_i_can/role/grouping'
3
4
  require 'i_am_i_can/role_group/definition'
4
- require 'i_am_i_can/role_group/assignment'
5
5
 
6
6
  module IAmICan
7
7
  module Role
@@ -18,9 +18,7 @@ module IAmICan
18
18
  end
19
19
 
20
20
  included do
21
- # def attributes
22
- # super.symbolize_keys
23
- # end
21
+ define_model_callbacks :permission_assign, :cancel_permission_assign, :permission_update
24
22
 
25
23
  # `can? :manage, User` / `can? :manage, obj: User`
26
24
  def can? action, o = nil, obj: o
@@ -4,7 +4,7 @@ module IAmICan
4
4
  def group_roles *members, by_name:, which_can: [ ], obj: nil
5
5
  group = (i = i_am_i_can).role_group_model.where(name: by_name).first_or_create
6
6
  instances, names = Role.extract(members, i)
7
- assignment = group._members_exec(:assignment, instances, name: names)
7
+ assignment = group._members_exec(:assign, instances, name: names)
8
8
  ResultOf.members assignment, i, given: [instances, names]
9
9
  end
10
10
 
@@ -9,6 +9,7 @@ module IAmICan
9
9
  end
10
10
 
11
11
  included do
12
+ define_model_callbacks :role_assign, :cancel_role_assign, :role_update
12
13
  end
13
14
  end
14
15
  end
@@ -35,8 +35,8 @@ module IAmICan
35
35
  end
36
36
  end
37
37
 
38
- define_method :_temporary_roles_exec do |action = :assignment, names|
39
- send('_temporary_roles_' + (action == :assignment ? 'add' : 'rmv'), names)
38
+ define_method :_temporary_roles_exec do |action = :assign, names|
39
+ send('_temporary_roles_' + (action == :assign ? 'add' : 'rmv'), names)
40
40
  end
41
41
  end
42
42
  end
@@ -4,7 +4,7 @@ module IAmICan
4
4
 
5
5
  class_methods do
6
6
  def _reflect_of(key)
7
- _name = i_am_i_can.send("#{key}_class")
7
+ _name = i_am_i_can&.send("#{key}_class")
8
8
  reflections.each do |name, reflection|
9
9
  return name if reflection.class_name == _name
10
10
  end; nil
@@ -1,3 +1,3 @@
1
1
  module IAmICan
2
- VERSION = '4.0.0'
2
+ VERSION = '4.1.0'
3
3
  end
data/lib/i_am_i_can.rb CHANGED
@@ -15,7 +15,7 @@ require 'i_am_i_can/resource'
15
15
 
16
16
  module IAmICan
17
17
  def acts_as_subject
18
- i_am_i_can.act = :subject
18
+ i_am_i_can&.act = :subject
19
19
  include Subject
20
20
 
21
21
  extend Role::Definition
@@ -32,7 +32,7 @@ module IAmICan
32
32
  end
33
33
 
34
34
  def acts_as_role
35
- i_am_i_can.act = :role
35
+ i_am_i_can&.act = :role
36
36
  include Role
37
37
 
38
38
  extend Permission::Definition
@@ -49,10 +49,11 @@ module IAmICan
49
49
  end
50
50
 
51
51
  def acts_as_role_group
52
- i_am_i_can.act = :role_group
52
+ i_am_i_can&.act = :role_group
53
53
  include Role
54
54
  # include RoleGroup
55
55
 
56
+ include Role::Grouping
56
57
  extend Permission::Definition
57
58
  include Permission::Assignment
58
59
 
@@ -67,7 +68,7 @@ module IAmICan
67
68
  end
68
69
 
69
70
  def acts_as_permission
70
- i_am_i_can.act = :permission
71
+ i_am_i_can&.act = :permission
71
72
  include Permission
72
73
 
73
74
  include Reflection
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i_am_i_can
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - zhandao
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-30 00:00:00.000000000 Z
11
+ date: 2018-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -204,7 +204,7 @@ files:
204
204
  - lib/i_am_i_can/role.rb
205
205
  - lib/i_am_i_can/role/assignment.rb
206
206
  - lib/i_am_i_can/role/definition.rb
207
- - lib/i_am_i_can/role_group/assignment.rb
207
+ - lib/i_am_i_can/role/grouping.rb
208
208
  - lib/i_am_i_can/role_group/definition.rb
209
209
  - lib/i_am_i_can/subject.rb
210
210
  - lib/i_am_i_can/subject/permission_querying.rb
@@ -1,6 +0,0 @@
1
- module IAmICan
2
- module RoleGroup
3
- module Assignment
4
- end
5
- end
6
- end