i_am_i_can 3.0.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +236 -174
- data/lib/generators/i_am_i_can/setup_generator.rb +3 -7
- data/lib/generators/i_am_i_can/templates/migrations/i_am_i_can.erb +8 -8
- data/lib/generators/i_am_i_can/templates/models/permission.erb +4 -2
- data/lib/generators/i_am_i_can/templates/models/role.erb +3 -1
- data/lib/generators/i_am_i_can/templates/models/role_group.erb +3 -1
- data/lib/i_am_i_can/configs/config.rb +2 -3
- data/lib/i_am_i_can/configs/configs.rb +1 -7
- data/lib/i_am_i_can/helpers/dynamic.rb +102 -0
- data/lib/i_am_i_can/helpers/result_of.rb +71 -0
- data/lib/i_am_i_can/permission/assignment.rb +12 -60
- data/lib/i_am_i_can/permission/definition.rb +8 -28
- data/lib/i_am_i_can/permission.rb +18 -24
- data/lib/i_am_i_can/resource.rb +24 -19
- data/lib/i_am_i_can/role/assignment.rb +24 -45
- data/lib/i_am_i_can/role/definition.rb +17 -47
- data/lib/i_am_i_can/role.rb +14 -0
- data/lib/i_am_i_can/role_group/assignment.rb +6 -0
- data/lib/i_am_i_can/role_group/definition.rb +25 -0
- data/lib/i_am_i_can/subject/permission_querying.rb +28 -40
- data/lib/i_am_i_can/subject/role_querying.rb +8 -8
- data/lib/i_am_i_can/subject.rb +0 -10
- data/lib/i_am_i_can/support/association_class_methods.rb +43 -0
- data/lib/i_am_i_can/{configurable.rb → support/configurable.rb} +0 -7
- data/lib/i_am_i_can/support/reflection.rb +36 -0
- data/lib/i_am_i_can/version.rb +1 -1
- data/lib/i_am_i_can.rb +33 -16
- metadata +9 -9
- data/Gemfile.lock +0 -121
- data/lib/i_am_i_can/dynamic_generate.rb +0 -95
- data/lib/i_am_i_can/permission/helpers.rb +0 -75
- data/lib/i_am_i_can/permission/p_array.rb +0 -22
- data/lib/i_am_i_can/reflection.rb +0 -25
- data/lib/i_am_i_can/role/helpers.rb +0 -76
@@ -5,14 +5,16 @@ 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 :obj, polymorphic: true
|
9
|
+
|
8
10
|
acts_as_permission
|
9
11
|
end
|
10
12
|
|
11
13
|
__END__
|
12
14
|
|
13
|
-
string :
|
15
|
+
string :action, null: false
|
14
16
|
string :obj_type
|
15
17
|
integer :obj_id
|
16
18
|
string :desc
|
17
19
|
|
18
|
-
index %i[
|
20
|
+
index %i[ action obj_type obj_id ], unique: true
|
@@ -5,9 +5,11 @@ class <%= role_c %> < ActiveRecord::Base
|
|
5
5
|
has_and_belongs_to_many :related_stored_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
|
-
has_and_belongs_to_many :
|
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
|
+
|
11
13
|
acts_as_role
|
12
14
|
|
13
15
|
# default_scope { with_stored_permissions }
|
@@ -1,10 +1,12 @@
|
|
1
1
|
class RoleGroup < ActiveRecord::Base
|
2
|
-
has_and_belongs_to_many :
|
2
|
+
has_and_belongs_to_many :permissions,
|
3
3
|
join_table: '<%= group_pms_tb %>', foreign_key: :<%= permission_u %>_id, class_name: '<%= permission_c %>', association_foreign_key: :<%= group_u %>_id
|
4
4
|
|
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
|
+
|
8
10
|
acts_as_role_group
|
9
11
|
|
10
12
|
# default_scope { with_members.with_stored_permissions) }
|
@@ -2,14 +2,13 @@ module IAmICan
|
|
2
2
|
module Configs
|
3
3
|
class Config
|
4
4
|
attr_accessor :subject_class, :role_class, :role_group_class, :permission_class,
|
5
|
-
:
|
5
|
+
:auto_definition, :strict_mode, :without_group, :act
|
6
6
|
|
7
7
|
def initialize(*classes)
|
8
8
|
self.subject_class, self.role_class, self.permission_class, self.role_group_class = classes
|
9
|
-
self.
|
9
|
+
self.auto_definition = false
|
10
10
|
self.strict_mode = false
|
11
11
|
self.without_group = false
|
12
|
-
self.default_save = true
|
13
12
|
end
|
14
13
|
|
15
14
|
def subject_model
|
@@ -2,9 +2,7 @@ require 'i_am_i_can/configs/config'
|
|
2
2
|
|
3
3
|
module IAmICan
|
4
4
|
module Configs
|
5
|
-
cattr_accessor :configs
|
6
|
-
{ }
|
7
|
-
end
|
5
|
+
cattr_accessor :configs, default: { }
|
8
6
|
|
9
7
|
def self.set_for(subject:, role:, permission:, role_group: nil, &block)
|
10
8
|
config = Config.new(subject, role, permission, role_group)
|
@@ -21,9 +19,5 @@ module IAmICan
|
|
21
19
|
def self.get(class_name)
|
22
20
|
configs[class_name]
|
23
21
|
end
|
24
|
-
|
25
|
-
def self.take
|
26
|
-
configs.values.first
|
27
|
-
end
|
28
22
|
end
|
29
23
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module IAmICan
|
2
|
+
module Dynamic
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def scopes
|
6
|
+
#
|
7
|
+
# Generate scopes of each specified i_am_i_can association
|
8
|
+
#
|
9
|
+
# scope :with_stored_roles, -> { includes(:stored_roles) }
|
10
|
+
#
|
11
|
+
proc do |keys|
|
12
|
+
keys.each do |k|
|
13
|
+
scope :"with_#{_reflect_of(k)}", -> { includes(_reflect_of(k)) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def class_reflections
|
19
|
+
#
|
20
|
+
# Extend each associated querying to a class method that returns ActiveRecord::Relation
|
21
|
+
#
|
22
|
+
# Suppose: in UserRole model,
|
23
|
+
# has_and_belongs_to_many :related_users
|
24
|
+
#
|
25
|
+
# It will do like this:
|
26
|
+
# def self.related_users
|
27
|
+
# User.with_stored_roles.where(user_roles: { id: self.ids })
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# Usage:
|
31
|
+
# UserRole.all.related_users
|
32
|
+
#
|
33
|
+
proc do
|
34
|
+
%w[ subject role role_group permission ].each do |k|
|
35
|
+
next if _reflect_of(k).blank?
|
36
|
+
define_singleton_method _reflect_of(k) do
|
37
|
+
model = i_am_i_can.send("#{k}_model")
|
38
|
+
raise NoMethodError unless (reflect_name = model._reflect_of(i_am_i_can.act))
|
39
|
+
|
40
|
+
model.send("with_#{reflect_name}").where(
|
41
|
+
self.name.underscore.pluralize => { id: self.ids }
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def assignment_helpers
|
49
|
+
#
|
50
|
+
# Generate methods for each Content of Assignment
|
51
|
+
#
|
52
|
+
# Example for a subject model called User, which `has_and_belongs_to_many :stored_roles`.
|
53
|
+
# You call the proc below by given contents [:role], then:
|
54
|
+
#
|
55
|
+
proc { |contents| contents.each do |content|
|
56
|
+
content_cls = i_am_i_can.send("#{content}_class")
|
57
|
+
_plural = '_' + content.to_s.pluralize
|
58
|
+
|
59
|
+
# _stored_roles_exec
|
60
|
+
# Add / Remove (by passing action :cancel) roles to a user instance
|
61
|
+
define_method "_#{_reflect_of(content)}_exec" do |action = :assignment, instances = [ ], **conditions|
|
62
|
+
collection = send(_plural)
|
63
|
+
if conditions.present? && action == :assignment
|
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
|
70
|
+
|
71
|
+
objects = [*(query_result || [ ]), *(instances - collection)].uniq
|
72
|
+
action == :assignment ? collection << objects : collection.destroy(objects)
|
73
|
+
objects
|
74
|
+
end
|
75
|
+
#
|
76
|
+
alias_method "_stored#{_plural}_exec", "_#{_reflect_of(content)}_exec"
|
77
|
+
end }
|
78
|
+
end
|
79
|
+
|
80
|
+
def definition_helpers
|
81
|
+
#
|
82
|
+
# Generate class methods for each Content of Definition
|
83
|
+
#
|
84
|
+
# Example for a subject model called User,
|
85
|
+
# which `has_many_temporary_roles` and `has_and_belongs_to_many :stored_roles`.
|
86
|
+
# You call the proc below by given contents [:role], then:
|
87
|
+
#
|
88
|
+
proc { |contents| contents.each do |content|
|
89
|
+
content_cls = i_am_i_can.send("#{content}_class")
|
90
|
+
_plural = '_' + content.to_s.pluralize
|
91
|
+
|
92
|
+
# _create_roles
|
93
|
+
# Define and store roles of Subject
|
94
|
+
define_singleton_method "_create#{_plural}" do |objects|
|
95
|
+
# Role.create([{ name: .. }]).reject { the roles that validation failed }
|
96
|
+
content_cls.constantize.create(objects)
|
97
|
+
.reject {|record| record.new_record? }
|
98
|
+
end
|
99
|
+
end }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module IAmICan
|
2
|
+
module ResultOf
|
3
|
+
module Role
|
4
|
+
def roles definition, i_am_i_can, given: [ ]
|
5
|
+
ResultOf.(definition, [ [], given ], config: i_am_i_can,
|
6
|
+
msg_prefix: 'Role Definition: ',
|
7
|
+
fail_msg: 'have been used by other roles!'
|
8
|
+
)
|
9
|
+
end
|
10
|
+
|
11
|
+
def role assignment, i_am_i_can, given: [ ]
|
12
|
+
ResultOf.(assignment, given, config: i_am_i_can,
|
13
|
+
msg_prefix: 'Role Assignment: ',
|
14
|
+
fail_msg: 'have not been defined or have been repeatedly assigned!'
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
ResultOf.include self
|
19
|
+
end
|
20
|
+
|
21
|
+
module RoleGroup
|
22
|
+
def members assignment, i_am_i_can, given: [ ]
|
23
|
+
ResultOf.(assignment, given, config: i_am_i_can,
|
24
|
+
msg_prefix: 'Role Grouping: ',
|
25
|
+
fail_msg: 'have not been defined!'
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
ResultOf.include self
|
30
|
+
end
|
31
|
+
|
32
|
+
module Permission
|
33
|
+
def permissions definition, i_am_i_can, given: [ ]
|
34
|
+
ResultOf.(definition, [ [], given ], config: i_am_i_can,
|
35
|
+
msg_prefix: 'Permission Definition: ',
|
36
|
+
fail_msg: 'have been used by other permissions!'
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def permission assignment, i_am_i_can, given: [ ]
|
41
|
+
ResultOf.(assignment, given, config: i_am_i_can,
|
42
|
+
msg_prefix: 'Permission Assignment: ',
|
43
|
+
fail_msg: 'have not been defined or have been repeatedly assigned!'
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
ResultOf.include self
|
48
|
+
end
|
49
|
+
|
50
|
+
def call(assignment, given, msg_prefix:, fail_msg:, config:)
|
51
|
+
instances, names = given
|
52
|
+
instances.map!(&:name).map!(&:to_sym)
|
53
|
+
assignment = assignment.map(&:name).map(&:to_sym) unless assignment.first.is_a?(Symbol)
|
54
|
+
|
55
|
+
to_be_assigned_names = (instances + names).uniq
|
56
|
+
failed_items = to_be_assigned_names - assignment
|
57
|
+
|
58
|
+
msg = msg_prefix + (assignment.blank? ? 'do nothing' : "#{assignment} DONE")
|
59
|
+
msg << "; And #{failed_items} #{fail_msg}" if failed_items.present?
|
60
|
+
|
61
|
+
if config.strict_mode && failed_items.present?
|
62
|
+
raise Error, msg
|
63
|
+
else
|
64
|
+
Rails.logger.info(msg) unless ENV['ITEST']
|
65
|
+
assignment
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
extend self
|
70
|
+
end
|
71
|
+
end
|
@@ -1,75 +1,27 @@
|
|
1
|
-
require 'i_am_i_can/permission/helpers'
|
2
|
-
|
3
1
|
module IAmICan
|
4
2
|
module Permission
|
5
3
|
module Assignment
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
not_defined_items, covered_items = [ ], [ ]
|
12
|
-
|
13
|
-
preds.each do |pred|
|
14
|
-
pms_name = pms_naming(pred, obj)
|
15
|
-
covered_items << pms_name if pms_matched?(pms_name, in: stored_permission_names)
|
16
|
-
not_defined_items << pms_name unless stored_permissions_add(pred: pred, **deconstruct_obj(obj))
|
17
|
-
end
|
18
|
-
|
19
|
-
_pms_assignment_result(preds, obj, not_defined_items, covered_items, strict_mode)
|
4
|
+
def can *actions,
|
5
|
+
resource: nil, obj: resource,
|
6
|
+
_d: i_am_i_can.auto_definition, auto_definition: _d
|
7
|
+
self.class.have_permissions *actions, obj: obj if auto_definition
|
8
|
+
_permissions_assignment(actions, obj)
|
20
9
|
end
|
21
10
|
|
22
11
|
alias has_permission can
|
23
12
|
|
24
|
-
def
|
25
|
-
|
26
|
-
self.class.have_permissions *preds, obj: obj, save: false if auto_define_before
|
27
|
-
not_defined_items, covered_items = [ ], [ ]
|
28
|
-
|
29
|
-
preds.each do |pred|
|
30
|
-
pms_name = pms_naming(pred, obj)
|
31
|
-
next not_defined_items << pms_name unless pms_name.in?(defined_permissions.keys)
|
32
|
-
covered_items << pms_name if pms_matched?(pms_name, in: pms_of_defined_local_role(self.name))
|
33
|
-
pms_of_defined_local_role(self.name) << pms_name
|
34
|
-
end
|
35
|
-
|
36
|
-
_pms_assignment_result(preds, obj, not_defined_items, covered_items, strict_mode)
|
37
|
-
end
|
38
|
-
|
39
|
-
alias locally_can temporarily_can
|
40
|
-
|
41
|
-
def cannot *preds, obj: nil, saved: true
|
42
|
-
not_defined_items = [ ]
|
43
|
-
|
44
|
-
preds.each do |pred|
|
45
|
-
pms_name = pms_naming(pred, obj)
|
46
|
-
if saved
|
47
|
-
next if stored_permissions_rmv(pred: pred, **deconstruct_obj(obj))
|
48
|
-
not_defined_items << pms_name
|
49
|
-
else
|
50
|
-
next not_defined_items << pms_name unless pms_name.in?(defined_permissions.keys)
|
51
|
-
pms_of_defined_local_role(self.name).delete(pms_name)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
_pms_assignment_result(preds, obj, not_defined_items)
|
13
|
+
def cannot *actions, obj: nil
|
14
|
+
_permissions_assignment(:cancel, actions, obj)
|
56
15
|
end
|
57
16
|
|
58
17
|
alias is_not_allowed_to cannot
|
59
18
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
19
|
+
def _permissions_assignment(action = :assignment, actions, obj)
|
20
|
+
permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o) } }
|
21
|
+
assignment = _stored_permissions_exec(action,
|
22
|
+
permissions.reduce({ }) { |a, b| a.merge(b) { |_, x, y| [x, y] } })
|
23
|
+
ResultOf.permission assignment, i_am_i_can, given: [[], permissions.map { |pms| pms.values.compact.join('_').to_sym }]
|
65
24
|
end
|
66
|
-
|
67
|
-
def temporarily_can? pred, obj
|
68
|
-
pms_name = pms_naming(pred, obj)
|
69
|
-
pms_matched?(pms_name, in: pms_of_defined_local_role(self.name))
|
70
|
-
end
|
71
|
-
|
72
|
-
alias locally_can? temporarily_can?
|
73
25
|
end
|
74
26
|
end
|
75
27
|
end
|
@@ -1,40 +1,20 @@
|
|
1
|
-
require 'i_am_i_can/permission/helpers'
|
2
|
-
require 'i_am_i_can/permission/p_array'
|
3
|
-
|
4
1
|
module IAmICan
|
5
2
|
module Permission
|
6
3
|
module Definition
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
preds.each do |pred|
|
13
|
-
pms_name = pms_naming(pred, obj)
|
14
|
-
description = desc || pms_name.to_s.tr('_', ' ')
|
15
|
-
if save
|
16
|
-
failed_items << pms_name unless _to_store_permission(pred, obj, desc: description)
|
17
|
-
else
|
18
|
-
failed_items << pms_name if pms_name.in?(defined_local_permissions.keys)
|
19
|
-
defined_local_permissions[pms_name] ||= { desc: description }
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
_pms_definition_result(preds, obj, failed_items)
|
4
|
+
def have_permission *actions, obj: nil
|
5
|
+
permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o) } }
|
6
|
+
definition = _create_permissions(permissions)
|
7
|
+
ResultOf.roles definition, i_am_i_can, given: permissions.map { |pms| pms.values.compact.join('_').to_sym }
|
24
8
|
end
|
25
9
|
|
26
|
-
|
27
|
-
alias has_permission have_permission
|
28
|
-
alias has_permissions have_permission
|
10
|
+
%i[ have_permissions has_permission has_permissions ].each { |aname| alias_method aname, :have_permission }
|
29
11
|
|
30
|
-
def
|
31
|
-
|
12
|
+
def deconstruct_obj(obj)
|
13
|
+
i_am_i_can.permission_model.deconstruct_obj(obj)
|
32
14
|
end
|
33
15
|
|
34
|
-
alias declare_permissions declare_permission
|
35
|
-
|
36
16
|
def self.extended(kls)
|
37
|
-
kls.delegate :
|
17
|
+
kls.delegate :deconstruct_obj, to: kls
|
38
18
|
end
|
39
19
|
end
|
40
20
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'i_am_i_can/permission/p_array'
|
2
1
|
require 'i_am_i_can/permission/definition'
|
3
2
|
require 'i_am_i_can/permission/assignment'
|
4
3
|
|
@@ -7,19 +6,23 @@ module IAmICan
|
|
7
6
|
extend ActiveSupport::Concern
|
8
7
|
|
9
8
|
class_methods do
|
10
|
-
def matched
|
11
|
-
|
9
|
+
def matched(actions, obj)
|
10
|
+
_ = deconstruct_obj(obj)
|
11
|
+
where(action: actions,
|
12
|
+
obj_type: [nil, _[:obj_type]],
|
13
|
+
obj_id: [nil, _[:obj_id]])
|
12
14
|
end
|
13
15
|
|
14
|
-
def
|
15
|
-
|
16
|
+
def matched?(actions, obj)
|
17
|
+
matched(actions, obj).present?
|
16
18
|
end
|
17
19
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
def matched_all?(actions, obj)
|
21
|
+
matched(actions, obj).count == Array(actions).count
|
22
|
+
end
|
23
|
+
|
24
|
+
def which(action:, obj: nil, **conditions)
|
25
|
+
find_by!(action: action, **deconstruct_obj(obj), **conditions)
|
23
26
|
end
|
24
27
|
|
25
28
|
def deconstruct_obj(obj)
|
@@ -34,32 +37,23 @@ module IAmICan
|
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
37
|
-
def
|
38
|
-
|
40
|
+
def names
|
41
|
+
all.map(&:name)
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
45
|
included do
|
43
46
|
# like: manage_User_1
|
44
47
|
def name
|
45
|
-
|
46
|
-
oid = "_#{obj_id}" if obj_id.present?
|
47
|
-
[pred, otp, oid].join.to_sym
|
48
|
+
[action, obj_type, obj_id].compact.join('_').to_sym
|
48
49
|
end
|
49
50
|
|
50
51
|
# def assign_to role: nil, group: nil
|
51
|
-
# obj = if role
|
52
|
-
# role.is_a?(Symbol) ? i_am_i_can.role_model.find(name: role) : role
|
53
|
-
# else
|
54
|
-
# group.is_a?(Symbol) ? i_am_i_can.role_group_model.find(name: role) : group
|
55
|
-
# end
|
56
|
-
# obj.have_permission self.pred, obj: self.obj
|
57
52
|
# end
|
58
|
-
#
|
59
|
-
# alias is_assigned_to assign_to
|
60
53
|
|
61
|
-
# :user, User, user
|
54
|
+
# returns :user, User, user
|
62
55
|
def obj
|
56
|
+
return if obj_type.blank?
|
63
57
|
return obj_type.constantize.find(obj_id) if obj_id.present?
|
64
58
|
obj_type[/[A-Z]/] ? obj_type.constantize : obj_type.to_sym
|
65
59
|
end
|
data/lib/i_am_i_can/resource.rb
CHANGED
@@ -2,28 +2,33 @@ module IAmICan
|
|
2
2
|
module Resource
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
|
6
|
-
# Book.that_allow(User.all
|
7
|
-
# Book.that_allow(User.last
|
8
|
-
|
9
|
-
|
5
|
+
included do
|
6
|
+
# Book.that_allow(User.all, to: :read)
|
7
|
+
# Book.that_allow(User.last, to: :write)
|
8
|
+
scope :that_allow, -> (subject, to:) do
|
9
|
+
tmp_role_ids = Array(subject).flat_map(&:temporary_roles).map(&:id).uniq
|
10
|
+
allowed_ids = subject.i_am_i_can.role_model.where(id: (subject._roles.ids + tmp_role_ids).uniq)
|
11
|
+
._permissions.where(action: to, obj_type: self.name).pluck(:obj_id).uniq
|
12
|
+
where(id: allowed_ids)
|
10
13
|
end
|
11
14
|
end
|
12
|
-
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
self.records = records
|
19
|
-
self.subject = subject
|
20
|
-
end
|
21
|
-
|
22
|
-
def to(pred)
|
23
|
-
roles = Configs.take.subject_model._roles
|
24
|
-
permissions = Configs.take.role_model._permissions
|
25
|
-
allowed_ids = subject.send(roles).send(permissions).where(pred: pred, obj_type: records.name).pluck(:obj_id).uniq
|
26
|
-
records.where(id: allowed_ids)
|
16
|
+
class_methods do
|
17
|
+
# def that_allow(subject)
|
18
|
+
# ThatAllow.new(self, subject)
|
19
|
+
# end
|
27
20
|
end
|
28
21
|
end
|
22
|
+
|
23
|
+
# class ThatAllow
|
24
|
+
# attr_accessor :records, :subject
|
25
|
+
#
|
26
|
+
# def initialize(records, subject)
|
27
|
+
# self.records = records
|
28
|
+
# self.subject = subject
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def to(action)
|
32
|
+
# end
|
33
|
+
# end
|
29
34
|
end
|
@@ -1,62 +1,41 @@
|
|
1
|
-
require 'i_am_i_can/role/helpers'
|
2
|
-
|
3
1
|
module IAmICan
|
4
2
|
module Role
|
5
3
|
module Assignment
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
self.class.have_roles *roles, which_can: which_can, obj: obj
|
11
|
-
|
12
|
-
|
13
|
-
roles.map(&__role).each do |role|
|
14
|
-
if save
|
15
|
-
failed_items << role unless stored_roles_add(role)
|
16
|
-
else
|
17
|
-
next failed_items << role unless role.in?(defined_roles.keys)
|
18
|
-
local_role_names << role unless role.in?(local_role_names)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
_role_assignment_result(roles, failed_items)
|
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
|
8
|
+
self.class.have_roles *roles, which_can: which_can, obj: obj if auto_definition
|
9
|
+
_roles_assignment(roles, save)
|
23
10
|
end
|
24
11
|
|
25
|
-
|
26
|
-
alias is_a_role becomes_a
|
27
|
-
alias is_roles becomes_a
|
28
|
-
alias has_role becomes_a
|
29
|
-
alias has_roles becomes_a
|
30
|
-
alias role_is becomes_a
|
31
|
-
alias roles_are becomes_a
|
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 }
|
32
13
|
|
33
|
-
def
|
14
|
+
def is_a_temporary *roles, **options
|
34
15
|
becomes_a *roles, save: false, **options
|
35
16
|
end
|
36
17
|
|
37
|
-
|
18
|
+
def falls_from *roles, saved: true
|
19
|
+
_roles_assignment(:cancel, roles, saved)
|
20
|
+
end
|
21
|
+
|
22
|
+
%i[ is_not_a will_not_be removes_role leaves has_not_role has_not_roles ].each { |aname| alias_method aname, :falls_from }
|
38
23
|
|
39
|
-
def
|
40
|
-
|
24
|
+
def is_not_a_temporary *roles
|
25
|
+
falls_from *roles, saved: false
|
26
|
+
end
|
41
27
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
28
|
+
def _roles_assignment(action = :assignment, roles, save)
|
29
|
+
instances, names = Role.extract(roles, i_am_i_can)
|
30
|
+
if save
|
31
|
+
assignment = _stored_roles_exec(action, instances, name: names)
|
32
|
+
else
|
33
|
+
to_be_assigned_names = (instances.map(&:name).map(&:to_sym) + names).uniq
|
34
|
+
assignment = _temporary_roles_exec(action, to_be_assigned_names)
|
49
35
|
end
|
50
36
|
|
51
|
-
|
37
|
+
ResultOf.role assignment, i_am_i_can, given: [instances, names]
|
52
38
|
end
|
53
|
-
|
54
|
-
alias is_not_a falls_from
|
55
|
-
alias will_not_be falls_from
|
56
|
-
alias removes_role falls_from
|
57
|
-
alias leaves falls_from
|
58
|
-
alias has_not_role falls_from
|
59
|
-
alias has_not_roles falls_from
|
60
39
|
end
|
61
40
|
end
|
62
41
|
end
|