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 +4 -4
- data/README.md +48 -6
- data/lib/generators/i_am_i_can/templates/models/permission.erb +1 -1
- data/lib/generators/i_am_i_can/templates/models/role.erb +2 -4
- data/lib/generators/i_am_i_can/templates/models/role_group.erb +3 -3
- data/lib/i_am_i_can/helpers/dynamic.rb +11 -13
- data/lib/i_am_i_can/permission/assignment.rb +15 -6
- data/lib/i_am_i_can/role/assignment.rb +17 -7
- data/lib/i_am_i_can/role/grouping.rb +6 -0
- data/lib/i_am_i_can/role.rb +2 -4
- data/lib/i_am_i_can/role_group/definition.rb +1 -1
- data/lib/i_am_i_can/subject.rb +1 -0
- data/lib/i_am_i_can/support/association_class_methods.rb +2 -2
- data/lib/i_am_i_can/support/reflection.rb +1 -1
- data/lib/i_am_i_can/version.rb +1 -1
- data/lib/i_am_i_can.rb +5 -4
- metadata +3 -3
- data/lib/i_am_i_can/role_group/assignment.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5c54e75b43df8cbfb0e8acd30cb0fc40e0aeda0
|
4
|
+
data.tar.gz: 5a0a6c5198cdb76ca0a251b99d7320cc2a081854
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
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.
|
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 :
|
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 :
|
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 {
|
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
|
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 = :
|
62
|
-
collection = send(_plural)
|
63
|
-
|
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
|
-
|
72
|
-
|
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
|
-
|
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:
|
14
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
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)
|
data/lib/i_am_i_can/role.rb
CHANGED
@@ -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
|
-
|
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(:
|
7
|
+
assignment = group._members_exec(:assign, instances, name: names)
|
8
8
|
ResultOf.members assignment, i, given: [instances, names]
|
9
9
|
end
|
10
10
|
|
data/lib/i_am_i_can/subject.rb
CHANGED
@@ -35,8 +35,8 @@ module IAmICan
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
define_method :_temporary_roles_exec do |action = :
|
39
|
-
send('_temporary_roles_' + (action == :
|
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
|
data/lib/i_am_i_can/version.rb
CHANGED
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
|
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
|
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
|
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
|
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.
|
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
|
+
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/
|
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
|