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