i_am_i_can 4.2.0 → 4.3.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: 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