i_am_i_can 4.0.0 → 4.1.0

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: 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