i_am_i_can 4.2.0 → 4.3.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: edde7fa4072a2d78c7b5017f9d42e0aab9925f1f
4
- data.tar.gz: 99d658e9ce576ed82207f577cfcba96202a6cdfc
3
+ metadata.gz: 7afc85dd06b6aefeec8da4d575782398aca2f5c0
4
+ data.tar.gz: f23e1e9768cbfdac758e7df5a3be484ebbebf2e8
5
5
  SHA512:
6
- metadata.gz: 195ed325b75c8b7a7b7e94cb6cd601214451044f438f25c26c357187d9cd229ca5c37000cf5ca28b03f95b22964be0f3e7131f4c4cc36926036ccc75d9871d2b
7
- data.tar.gz: 96a3122e55433bfb0115051c4da61fd465d9909e4d977fb7a84819d8dd88c310aa87e58ea30397c9bdb2fb71bb27362f4fc5ddfa136f3f8ef5d8dc551a2c37dd
6
+ metadata.gz: 6aa217add1124db25b3f79d5a3ff40ee43b18dcb28dfaad9fc9ebbd4d7eb3997be8bdb18f0ce88492817296b0aaae31963a935a4f54ea180d4c457730b773aca
7
+ data.tar.gz: ef73fda2b4d9bdcbe779d5a748ddfafe09561943f4520620cf441ae852bc1fa9f2b7db7afd978d5cca845740b0271ed63bb76f27d3781feeba0dd2bd5aca14c6
data/README.md CHANGED
@@ -168,8 +168,9 @@ Very simple. Really simple. Sooooo Simple.
168
168
 
169
169
  ```ruby
170
170
  class User
171
- has_and_belongs_to_many :stored_roles,
172
- join_table: 'users_and_user_roles', foreign_key: 'user_role_id', class_name: 'UserRole', association_foreign_key: 'user_id'
171
+ has_and_belongs_to_many :stored_roles, -> { where('expire_at IS NULL OR expire_at > ?', Time.current) },
172
+ join_table: 'users_and_user_roles', foreign_key: 'user_id',
173
+ class_name: 'UserRole', association_foreign_key: 'user_role_id'
173
174
  has_many_temporary_roles
174
175
  acts_as_subject
175
176
  end
@@ -255,7 +256,7 @@ UserRoleGroup.which(name: :vip).members.names # => %i[vip1 vip2 vip3]
255
256
  2. `has_role` / `has_roles`
256
257
  3. `role_is` / `role_are`
257
258
  2. `is_a_temporary`: just like the name, the assignment occurs only
258
- in instance variable (will be in the cache).
259
+ in **instance variable** not in database (will be in the cache).
259
260
  3. cancel assignment by calling:
260
261
  1. `falls_from`, or it's aliases:
261
262
  1. `removes_role`
@@ -273,6 +274,7 @@ UserRoleGroup.which(name: :vip).members.names # => %i[vip1 vip2 vip3]
273
274
  1. relation with stored role, defaults to `stored_roles`.
274
275
  2. `temporary_roles` and `valid_temporary_roles`
275
276
  3. `roles`
277
+ 4. `assoc_with_<roles>`, like: `assoc_with_stored_roles`
276
278
 
277
279
  Explanation:
278
280
  ```ruby
@@ -284,10 +286,23 @@ User.have_roles :admin, :coder
284
286
  # method signature
285
287
  becomes_a *roles, which_can: [ ], obj: nil,
286
288
  _d: config.auto_definition,
287
- auto_definition: _d || which_can.present?
288
- # examples
289
+ auto_definition: _d || which_can.present?,
290
+ expires_in: nil, expires_at: (expires_in.after if expires_in)
291
+ # 1. example of giving Symbol to `roles` params
289
292
  he.becomes_a :admin # => 'Role Assignment Done' or error message
290
293
  he.stored_roles # => [<#UserRole id: 1>]
294
+ # 2. example of giving role instances to `roles` params
295
+ he.becomes_a *UserRole.all # => 'Role Assignment Done' or error message
296
+ he.stored_roles # => [<#UserRole id: 1>, <#UserRole id: 2>]
297
+ # 3. `expires` (subject assocates roles with a `expire_at` scope)
298
+ he.is_a :visitor, expires_in: 1.hour # or `expires_at: 1.hour.after`
299
+ he.is? :visitor # => true
300
+ # an hour later ...
301
+ he.is? :visitor # => false
302
+
303
+ # assoc_with_<roles>: for getting the relation records between subject and it's roles
304
+ he.assoc_with_stored_roles # => UsersAndUserRoles::ActiveRecord_Associations_CollectionProxy
305
+
291
306
 
292
307
  # === Temporary Assignment ===
293
308
  # signature as `becomes_a`
@@ -394,6 +409,8 @@ can *actions, resource: nil, obj: resource, # you can use `resource` or `obj`
394
409
  # examples
395
410
  role.can :fly # => 'Permission Assignment Done' or error message
396
411
  role.permissions # => [<#UserPermission id: ..>]
412
+ # you can also passing permission instances to `actions` params, like:
413
+ role.can *UserPermission.all
397
414
 
398
415
  # === Cancel Assignment ===
399
416
  # method signature
@@ -52,8 +52,9 @@ module IAmICan
52
52
  puts "\nAdd the code below to #{name_c}:".green
53
53
  puts <<~TIPS
54
54
  |
55
- | has_and_belongs_to_many :stored_roles,
56
- | join_table: '#{subj_role_tb}', foreign_key: '#{role_u}_id', class_name: '#{role_c}', association_foreign_key: '#{name_u}_id'
55
+ | has_and_belongs_to_many :stored_roles, -> { where('expire_at IS NULL OR expire_at > ?', Time.current) },
56
+ | join_table: '#{subj_role_tb}', foreign_key: '#{name_u}_id',
57
+ | class_name: '#{role_c}', association_foreign_key: '#{role_u}_id'
57
58
  |
58
59
  | has_many_temporary_roles
59
60
  |
@@ -41,11 +41,12 @@ class <%= name_c %>Am<%= name_c %>Can < ActiveRecord::Migration::Current
41
41
  create_table :<%= subj_role_tb %>, id: false, force: :cascade do |t|
42
42
  t.belongs_to :<%= name_u %>, null: false#, index: false
43
43
  t.belongs_to :<%= role_u %>, null: false#, index: false
44
+ t.datetime :expire_at
44
45
  end
45
46
 
46
47
  # add_index :<%= subj_role_tb %>, :<%= name_u %>_id, name: ':<%= subj_role_tb %>_index1'
47
48
  # add_index :<%= subj_role_tb %>, :<%= role_u %>_id, name: ':<%= subj_role_tb %>_index2'
48
- add_index :<%= subj_role_tb %>, [ :<%= name_u %>_id, :<%= role_u %>_id ],
49
+ add_index :<%= subj_role_tb %>, [ :<%= name_u %>_id, :<%= role_u %>_id, :expire_at ],
49
50
  unique: true, name: '<%= subj_role_tb %>_uniq_index'
50
51
 
51
52
  # === end of subject-role table ===
@@ -1,9 +1,11 @@
1
1
  class <%= permission_c %> < ActiveRecord::Base
2
2
  has_and_belongs_to_many :related_roles,
3
- join_table: '<%= role_pms_tb %>', foreign_key: :<%= role_u %>_id, class_name: '<%= role_c %>', association_foreign_key: :<%= permission_u %>_id
3
+ join_table: '<%= role_pms_tb %>', foreign_key: :<%= permission_u %>_id,
4
+ class_name: '<%= role_c %>', association_foreign_key: :<%= role_u %>_id
4
5
  <% unless @ii_opts[:without_group] %>
5
6
  has_and_belongs_to_many :related_role_groups,
6
- join_table: '<%= group_pms_tb %>', foreign_key: :<%= group_u %>_id, class_name: '<%= group_c %>', association_foreign_key: :<%= permission_u %>_id
7
+ join_table: '<%= group_pms_tb %>', foreign_key: :<%= permission_u %>_id,
8
+ class_name: '<%= group_c %>', association_foreign_key: :<%= group_u %>_id
7
9
  <% end %>
8
10
  belongs_to :resource, polymorphic: true
9
11
 
@@ -1,12 +1,15 @@
1
1
  class <%= role_c %> < ActiveRecord::Base
2
2
  has_and_belongs_to_many :related_users,
3
- join_table: '<%= subj_role_tb %>', foreign_key: :<%= name_u %>_id, class_name: '<%= name_c %>', association_foreign_key: :<%= role_u %>_id
3
+ join_table: '<%= subj_role_tb %>', foreign_key: :<%= role_u %>_id,
4
+ class_name: '<%= name_c %>', association_foreign_key: :<%= name_u %>_id
4
5
  <% unless @ii_opts[:without_group] %>
5
6
  has_and_belongs_to_many :related_groups,
6
- join_table: '<%= group_role_tb %>', foreign_key: :<%= group_u %>_id, class_name: '<%= group_c %>', association_foreign_key: :<%= role_u %>_id
7
+ join_table: '<%= group_role_tb %>', foreign_key: :<%= role_u %>_id,
8
+ class_name: '<%= group_c %>', association_foreign_key: :<%= group_u %>_id
7
9
  <% end %>
8
10
  has_and_belongs_to_many :permissions,
9
- join_table: '<%= role_pms_tb %>', foreign_key: :<%= permission_u %>_id, class_name: '<%= permission_c %>', association_foreign_key: :<%= role_u %>_id
11
+ join_table: '<%= role_pms_tb %>', foreign_key: :<%= role_u %>_id,
12
+ class_name: '<%= permission_c %>', association_foreign_key: :<%= permission_u %>_id
10
13
 
11
14
  acts_as_role
12
15
 
@@ -1,9 +1,11 @@
1
1
  class RoleGroup < ActiveRecord::Base
2
2
  has_and_belongs_to_many :permissions,
3
- join_table: '<%= group_pms_tb %>', foreign_key: :<%= permission_u %>_id, class_name: '<%= permission_c %>', association_foreign_key: :<%= group_u %>_id
3
+ join_table: '<%= group_pms_tb %>', foreign_key: :<%= group_u %>_id,
4
+ class_name: '<%= permission_c %>', association_foreign_key: :<%= permission_u %>_id
4
5
 
5
6
  has_and_belongs_to_many :members,
6
- join_table: '<%= group_role_tb %>', foreign_key: :<%= role_u %>_id, class_name: '<%= role_c %>', association_foreign_key: :<%= group_u %>_id
7
+ join_table: '<%= group_role_tb %>', foreign_key: :<%= group_u %>_id,
8
+ class_name: '<%= role_c %>', association_foreign_key: :<%= role_u %>_id
7
9
 
8
10
  acts_as_role_group
9
11
 
@@ -1,8 +1,8 @@
1
1
  module IAmICan
2
2
  module Permission
3
3
  module Definition
4
- def have_permission *actions, obj: nil
5
- permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o) } }
4
+ def have_permission *actions, obj: nil, remarks: nil
5
+ permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o), remarks: remarks } }
6
6
  definition = _create_permissions(permissions)
7
7
  ResultOf.roles definition, i_am_i_can, given: permissions.map { |pms| pms.values.compact.join('_').to_sym }
8
8
  end
@@ -2,12 +2,11 @@ module IAmICan
2
2
  module Role
3
3
  module Assignment
4
4
  def becomes_a *roles, which_can: [ ], obj: nil,
5
- _d: i_am_i_can.auto_definition,
6
- auto_definition: _d || which_can.present?,
7
- save: true
5
+ _d: i_am_i_can.auto_definition, auto_definition: _d || which_can.present?,
6
+ expires_in: nil, expires_at: (expires_in.after if expires_in), save: true
8
7
  self.class.have_roles *roles, which_can: which_can, obj: obj if auto_definition
9
8
  run_callbacks(:role_assign) do
10
- _roles_assignment(roles, save)
9
+ _roles_assignment(roles, save, exp: expires_at)
11
10
  end
12
11
  end
13
12
 
@@ -35,10 +34,11 @@ module IAmICan
35
34
  %i[ is_not_a will_not_be removes_role leaves has_not_role has_not_roles ].each { |aname| alias_method aname, :falls_from }
36
35
  %i[ currently_is_a ].each { |aname| alias_method aname, :is_only_a }
37
36
 
38
- def _roles_assignment(action = :assign, roles, save)
37
+ def _roles_assignment(action = :assign, roles, save, exp: nil)
39
38
  instances, names = Role.extract(roles, i_am_i_can)
40
39
  if save
41
40
  assignment = _stored_roles_exec(action, instances, name: names)
41
+ _set_roles_expire(exp, assignment.map(&:id)) if exp
42
42
  else
43
43
  to_be_assigned_names = (instances.map(&:name).map(&:to_sym) + names).uniq
44
44
  assignment = _temporary_roles_exec(action, to_be_assigned_names)
@@ -46,6 +46,12 @@ module IAmICan
46
46
 
47
47
  ResultOf.role assignment, i_am_i_can, given: [instances, names]
48
48
  end
49
+
50
+ def _set_roles_expire(exp, ids)
51
+ send("assoc_with_#{__roles}")
52
+ .where("#{i_am_i_can.role_class.underscore}_id" => ids)
53
+ .update_all(expire_at: exp)
54
+ end
49
55
  end
50
56
  end
51
57
  end
@@ -1,10 +1,10 @@
1
1
  module IAmICan
2
2
  module Role
3
3
  module Definition
4
- def have_role *roles, which_can: [ ], obj: nil
4
+ def have_role *roles, which_can: [ ], obj: nil, remarks: nil
5
5
  return unless roles.first.class.in?([ Symbol, String ])
6
6
  roles.map!(&:to_sym) ; i = i_am_i_can
7
- definition = _create_roles(roles.map { |role| { name: role } })
7
+ definition = _create_roles(roles.map { |role| { name: role, remarks: remarks } })
8
8
 
9
9
  Role.modeling(roles, i).each { |r| r.can *which_can, obj: obj, auto_definition: true } if which_can.present?
10
10
  ResultOf.roles definition, i, given: roles
@@ -10,6 +10,11 @@ module IAmICan
10
10
 
11
11
  included do
12
12
  define_model_callbacks :role_assign, :cancel_role_assign, :role_update
13
+
14
+ Object.const_set (role_assoc_class = reflections[__roles].options[:join_table].camelize),
15
+ Class.new(ActiveRecord::Base)
16
+ has_many :"assoc_with_#{__roles}", -> { where('expire_at IS NULL OR expire_at > ?', Time.current) },
17
+ class_name: role_assoc_class
13
18
  end
14
19
  end
15
20
  end
@@ -27,8 +27,10 @@ module IAmICan
27
27
  included do
28
28
  # user._roles => Association CollectionProxy, same as: `user.stored_roles`
29
29
  %w[ subjects roles role_groups permissions ].each do |k|
30
+ delegate "__#{k}", to: self
31
+
30
32
  define_method "_#{k}" do
31
- send(self.class.send("__#{k}")) rescue (raise NoMethodError)
33
+ send(send("__#{k}")) rescue (raise NoMethodError)
32
34
  end
33
35
  end
34
36
  end
@@ -1,3 +1,3 @@
1
1
  module IAmICan
2
- VERSION = '4.2.0'
2
+ VERSION = '4.3.0'
3
3
  end
data/lib/i_am_i_can.rb CHANGED
@@ -16,6 +16,7 @@ require 'i_am_i_can/resource'
16
16
  module IAmICan
17
17
  def acts_as_subject
18
18
  i_am_i_can&.act = :subject
19
+ include Reflection
19
20
  include Subject
20
21
 
21
22
  extend Role::Definition
@@ -24,7 +25,6 @@ module IAmICan
24
25
  include Subject::RoleQuerying
25
26
  include Subject::PermissionQuerying
26
27
 
27
- include Reflection
28
28
  instance_exec(%i[ role ], &Dynamic.scopes)
29
29
  instance_exec(&Dynamic.class_reflections)
30
30
  instance_exec(%w[ role ], &Dynamic.assignment_helpers)
@@ -33,12 +33,12 @@ module IAmICan
33
33
 
34
34
  def acts_as_role
35
35
  i_am_i_can&.act = :role
36
+ include Reflection
36
37
  include Role
37
38
 
38
39
  extend Permission::Definition
39
40
  include Permission::Assignment
40
41
 
41
- include Reflection
42
42
  instance_exec(%i[ subject role_group permission ], &Dynamic.scopes)
43
43
  instance_exec(&Dynamic.class_reflections)
44
44
  instance_exec(%w[ permission ], &Dynamic.assignment_helpers)
@@ -50,6 +50,7 @@ module IAmICan
50
50
 
51
51
  def acts_as_role_group
52
52
  i_am_i_can&.act = :role_group
53
+ include Reflection
53
54
  include Role
54
55
  # include RoleGroup
55
56
 
@@ -57,7 +58,6 @@ module IAmICan
57
58
  extend Permission::Definition
58
59
  include Permission::Assignment
59
60
 
60
- include Reflection
61
61
  instance_exec(%i[ permission role ], &Dynamic.scopes)
62
62
  instance_exec(&Dynamic.class_reflections)
63
63
  instance_exec(%w[ role permission ], &Dynamic.assignment_helpers)
@@ -69,9 +69,9 @@ module IAmICan
69
69
 
70
70
  def acts_as_permission
71
71
  i_am_i_can&.act = :permission
72
+ include Reflection
72
73
  include Permission
73
74
 
74
- include Reflection
75
75
  instance_exec(%i[ role role_group ], &Dynamic.scopes)
76
76
  instance_exec(&Dynamic.class_reflections)
77
77
 
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.2.0
4
+ version: 4.3.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-12-10 00:00:00.000000000 Z
11
+ date: 2018-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler