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 +4 -4
- data/README.md +22 -5
- data/lib/generators/i_am_i_can/setup_generator.rb +3 -2
- data/lib/generators/i_am_i_can/templates/migrations/i_am_i_can.erb +2 -1
- data/lib/generators/i_am_i_can/templates/models/permission.erb +4 -2
- data/lib/generators/i_am_i_can/templates/models/role.erb +6 -3
- data/lib/generators/i_am_i_can/templates/models/role_group.erb +4 -2
- data/lib/i_am_i_can/permission/definition.rb +2 -2
- data/lib/i_am_i_can/role/assignment.rb +11 -5
- data/lib/i_am_i_can/role/definition.rb +2 -2
- data/lib/i_am_i_can/subject.rb +5 -0
- data/lib/i_am_i_can/support/reflection.rb +3 -1
- data/lib/i_am_i_can/version.rb +1 -1
- data/lib/i_am_i_can.rb +4 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7afc85dd06b6aefeec8da4d575782398aca2f5c0
|
4
|
+
data.tar.gz: f23e1e9768cbfdac758e7df5a3be484ebbebf2e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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: '
|
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
|
-
|
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: '#{
|
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: :<%=
|
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: :<%=
|
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: :<%=
|
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: :<%=
|
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: :<%=
|
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: :<%=
|
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: :<%=
|
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
|
-
|
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
|
data/lib/i_am_i_can/subject.rb
CHANGED
@@ -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(
|
33
|
+
send(send("__#{k}")) rescue (raise NoMethodError)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
data/lib/i_am_i_can/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2018-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|