i_am_i_can 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG.md +17 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +116 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +442 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/i_am_i_can.gemspec +36 -0
  15. data/lib/generators/i_am_i_can/setup_generator.rb +56 -0
  16. data/lib/generators/i_am_i_can/templates/migrations/add_to_subject.erb +5 -0
  17. data/lib/generators/i_am_i_can/templates/migrations/permission.erb +15 -0
  18. data/lib/generators/i_am_i_can/templates/migrations/role.erb +13 -0
  19. data/lib/generators/i_am_i_can/templates/migrations/role_group.erb +14 -0
  20. data/lib/generators/i_am_i_can/templates/models/permission.erb +11 -0
  21. data/lib/generators/i_am_i_can/templates/models/role.erb +10 -0
  22. data/lib/generators/i_am_i_can/templates/models/role_group.erb +11 -0
  23. data/lib/i_am_i_can/config.rb +14 -0
  24. data/lib/i_am_i_can/has_an_array_of.rb +75 -0
  25. data/lib/i_am_i_can/permission/assignment.rb +90 -0
  26. data/lib/i_am_i_can/permission/definition.rb +61 -0
  27. data/lib/i_am_i_can/permission/helpers.rb +46 -0
  28. data/lib/i_am_i_can/permission/p_array.rb +22 -0
  29. data/lib/i_am_i_can/permission.rb +68 -0
  30. data/lib/i_am_i_can/role/assignment.rb +76 -0
  31. data/lib/i_am_i_can/role/definition.rb +100 -0
  32. data/lib/i_am_i_can/role/helpers.rb +28 -0
  33. data/lib/i_am_i_can/subject/permission_querying.rb +69 -0
  34. data/lib/i_am_i_can/subject/role_querying.rb +66 -0
  35. data/lib/i_am_i_can/version.rb +3 -0
  36. data/lib/i_am_i_can.rb +61 -0
  37. metadata +220 -0
@@ -0,0 +1,75 @@
1
+ module IAmICan
2
+ module HasAnArrayOf
3
+ def has_an_array_of obj, model: nil, field: nil,
4
+ prefix: nil, attrs: [ ], located_by: nil, cache_expires_in: nil, for_related_name: nil
5
+ obj_model = model.constantize || obj.to_s.singularize.camelize.constantize
6
+ field = field || :"#{obj.to_s.singularize}_ids"
7
+ prefix = "#{prefix}_" if prefix
8
+
9
+ # User.where(..).stored_roles
10
+ define_singleton_method "#{prefix}#{obj}" do
11
+ obj_ids = self.all.map(&field).flatten.uniq
12
+ obj_model.where(id: obj_ids)
13
+ end
14
+
15
+ # user.stored_roles
16
+ define_method "#{prefix}#{obj}" do
17
+ obj_model.where(id: send(field))
18
+ end
19
+
20
+ # cached_stored_roles
21
+ define_method "cached_#{prefix}#{obj}" do |**options|
22
+ Rails.cache.fetch("#{self.class.name}/#{id}/#{obj}", expires_in: cache_expires_in, **options) do
23
+ obj_model.where(id: send(field))
24
+ end
25
+ end
26
+
27
+ # stored_roles_add
28
+ define_method "#{prefix}#{obj}_add" do |locate_vals = nil, check_size: nil, **condition|
29
+ condition = { located_by => locate_vals } if locate_vals
30
+ obj_ids = obj_model.where(condition)&.pluck(:id)
31
+ # will return false if it does nothing
32
+ return false if obj_ids.blank? || (check_size && obj_ids != check_size)
33
+ (send(field).concat(obj_ids)).uniq!
34
+ save!
35
+ end
36
+
37
+ # stored_roles_rmv
38
+ define_method "#{prefix}#{obj}_rmv" do |locate_vals = nil, check_size: nil, **condition|
39
+ condition = { located_by => locate_vals } if locate_vals
40
+ obj_ids = obj_model.where(condition)&.pluck(:id)
41
+ # will return false if it does nothing
42
+ return false if obj_ids.blank? || (check_size && obj_ids != check_size)
43
+ send("#{field}=", send(field) - obj_ids)
44
+ save!
45
+ end
46
+
47
+ attrs.each do |(attr_name, attr_type)|
48
+ # User.where(..).stored_role_names
49
+ define_singleton_method "#{prefix}#{obj.to_s.singularize}_#{attr_name.to_s.pluralize}" do
50
+ res = send("#{prefix}#{obj}").pluck(attr_name)
51
+ attr_type ? res.map(&attr_type) : res
52
+ end
53
+
54
+ # user.stored_role_names
55
+ define_method "#{prefix}#{obj.to_s.singularize}_#{attr_name.to_s.pluralize}" do
56
+ res = send("#{prefix}#{obj}").pluck(attr_name)
57
+ attr_type ? res.map(&attr_type) : res
58
+ end
59
+ end
60
+
61
+ # === actions for object model ===
62
+ obj_model.class_exec(for_related_name, self, field) do |subject_name, subject_model, related_field|
63
+ # roles.related_users
64
+ define_singleton_method "related_#{(subject_name || subject_model.name).underscore.pluralize}" do
65
+ subject_model.where("#{related_field} @> ARRAY[?]::integer[]", ids)
66
+ end
67
+
68
+ # role.related_users
69
+ define_method "related_#{(subject_name || subject_model.name).underscore.pluralize}" do
70
+ subject_model.where("? = ANY (#{related_field})", self.id)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,90 @@
1
+ require 'i_am_i_can/permission/helpers'
2
+
3
+ module IAmICan
4
+ module Permission
5
+ module Assignment
6
+ include Helpers::Ins
7
+
8
+ # permission assignment for stored role
9
+ def can *preds, obj: nil, strict_mode: false, auto_define_before: config.auto_define_before
10
+ self.class.have_permissions *preds, obj: obj if auto_define_before
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)
20
+ end
21
+
22
+ alias has_permission can
23
+
24
+ def temporarily_can *preds, obj: nil, strict_mode: false, auto_define_before: config.auto_define_before
25
+ raise Error, "Permission Assignment: local role `#{name}` was not defined" unless config.subject_model.defined_local_roles.key?(self.name.to_sym)
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)
56
+ end
57
+
58
+ alias is_not_allowed_to cannot
59
+
60
+ # `can? :manage, User` / `can? :manage, obj: User`
61
+ def can? pred, obj0 = nil, obj: nil
62
+ obj = obj0 || obj
63
+ pms_name = pms_naming(pred, obj)
64
+ temporarily_can?(pred, obj) || pms_matched?(pms_name, in: stored_permission_names)
65
+ 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
+
74
+ def local_permissions
75
+ @local_permissions ||= [ ]
76
+ end
77
+
78
+ alias local_permission_names local_permissions
79
+
80
+ def stored_permission_names
81
+ stored_permissions.map(&:name)
82
+ end
83
+
84
+ # TODO: show by hash
85
+ def permissions
86
+ local_permission_names + stored_permission_names
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,61 @@
1
+ require 'i_am_i_can/permission/helpers'
2
+ require 'i_am_i_can/permission/p_array'
3
+
4
+ module IAmICan
5
+ module Permission
6
+ module Definition
7
+ include Helpers::Cls
8
+
9
+ def which(name:)
10
+ find_by!(name: name)
11
+ end
12
+
13
+ def have_permission *preds, obj: nil, desc: nil, save: config.default_save
14
+ failed_items = [ ]
15
+
16
+ preds.each do |pred|
17
+ pms_name = pms_naming(pred, obj)
18
+ description = desc || pms_name.to_s.tr('_', ' ')
19
+ if save
20
+ failed_items << pms_name unless _to_store_permission(pred, obj, desc: description)
21
+ else
22
+ failed_items << pms_name if pms_name.in?(defined_local_permissions.keys)
23
+ defined_local_permissions[pms_name] ||= { desc: description }
24
+ end
25
+ end
26
+
27
+ _pms_definition_result(preds, obj, failed_items)
28
+ end
29
+
30
+ alias have_permissions have_permission
31
+ alias has_permission have_permission
32
+ alias has_permissions have_permission
33
+
34
+ def declare_permission *preds, **options
35
+ have_permission *preds, **options, save: false
36
+ end
37
+
38
+ alias declare_permissions declare_permission
39
+
40
+ def defined_local_permissions
41
+ @defined_local_permissions ||= { }
42
+ end
43
+
44
+ def defined_stored_pms_names
45
+ config.permission_model.all.map(&:name)
46
+ end
47
+
48
+ def defined_stored_permissions
49
+ config.permission_model.all.map { |pms| [ pms.name, pms.desc ] }.to_h
50
+ end
51
+
52
+ def defined_permissions
53
+ defined_local_permissions.deep_merge(defined_stored_permissions)
54
+ end
55
+
56
+ def self.extended(kls)
57
+ kls.delegate :defined_permissions, :pms_naming, :deconstruct_obj, :pms_of_defined_local_role, to: kls
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,46 @@
1
+ module IAmICan
2
+ module Permission
3
+ module Helpers
4
+ module Cls
5
+ def _pms_definition_result(preds, obj, failed_items)
6
+ prefix = 'Permission Definition Done'
7
+ fail_msg = prefix + ", but #{failed_items} have been defined" if failed_items.present?
8
+ raise Error, fail_msg if config.strict_mode && fail_msg
9
+ fail_msg ? fail_msg : prefix
10
+ end
11
+
12
+ def _to_store_permission(pred, obj, **options)
13
+ return false if config.permission_model.exists?(pred, obj)
14
+ config.permission_model.create!(pred: pred, **deconstruct_obj(obj), **options)
15
+ end
16
+
17
+ def pms_naming(pred, obj)
18
+ config.permission_model.naming(pred, obj)
19
+ end
20
+
21
+ def deconstruct_obj(obj)
22
+ config.permission_model.deconstruct_obj(obj)
23
+ end
24
+
25
+ def pms_of_defined_local_role(role_name)
26
+ config.subject_model.defined_local_roles[role_name.to_sym]&.[](:permissions) || []
27
+ end
28
+ end
29
+
30
+ module Ins
31
+ def _pms_assignment_result(preds, obj, not_defined_items, covered_items = nil, strict_mode = false)
32
+ prefix = 'Permission Assignment Done'
33
+ msg1 = "#{not_defined_items} have not been defined" if not_defined_items.present?
34
+ msg2 = "#{covered_items} have been covered" if covered_items.present?
35
+ fail_msg = prefix + ', but ' + [msg1, msg2].compact.join(', ') if msg1 || msg2
36
+ raise Error, fail_msg if (strict_mode || config.strict_mode) && fail_msg
37
+ fail_msg ? fail_msg : prefix
38
+ end
39
+
40
+ def pms_matched?(pms_name, plist)
41
+ config.permission_model.matched?(pms_name, in: plist[:in])
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,22 @@
1
+ module IAmICan
2
+ module Permission
3
+ class PArray < ::Array
4
+ attr_accessor :pms
5
+
6
+ def matched?(pms_name)
7
+ return false if self.blank?
8
+ self.pms = pms_name.to_sym
9
+ found? || covered?
10
+ end
11
+
12
+ def found?
13
+ pms.in? self
14
+ end
15
+
16
+ def covered?
17
+ pred, obj_type, obj_id = pms.to_s.split('_')
18
+ pred.to_sym.in?(self) || :"#{pred}_#{obj_type}".in?(self)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,68 @@
1
+ require 'i_am_i_can/permission/p_array'
2
+
3
+ module IAmICan
4
+ module Permission
5
+ def matched?(pms_name = nil, pred: nil, obj: nil, **options)
6
+ PArray.new(options[:in]).matched?(pms_name || naming(pred, obj))
7
+ end
8
+
9
+ def which(pred:, obj: nil)
10
+ find_by!(pred: pred, **deconstruct_obj(obj))
11
+ end
12
+
13
+ def naming(pred, obj)
14
+ obj_type, obj_id = deconstruct_obj(obj).values
15
+ otp = "_#{obj_type}" if obj_type.present?
16
+ oid = "_#{obj_id}" if obj_id.present?
17
+ [pred, otp, oid].join.to_sym
18
+ end
19
+
20
+ def deconstruct_obj(obj)
21
+ return { } unless obj
22
+
23
+ if obj.is_a?(String) || obj.is_a?(Symbol)
24
+ { obj_type: obj }
25
+ elsif obj.respond_to?(:attributes)
26
+ { obj_type: obj.class.name, obj_id: obj.id }
27
+ else
28
+ { obj_type: obj.to_s }
29
+ end
30
+ end
31
+
32
+ def exists?(pred, obj)
33
+ super(pred: pred, **deconstruct_obj(obj))
34
+ end
35
+
36
+ def self.extended(kls)
37
+ kls.include InstanceMethods
38
+ end
39
+ end
40
+
41
+ # === End of ClassMethods ===
42
+
43
+ module Permission::InstanceMethods
44
+ # like: manage_User_1
45
+ def name
46
+ otp = "_#{obj_type}" if obj_type.present?
47
+ oid = "_#{obj_id}" if obj_id.present?
48
+ [pred, otp, oid].join.to_sym
49
+ end
50
+
51
+ def assign_to role: nil, group: nil
52
+ obj = if role
53
+ role.is_a?(Symbol) ? ii_config.role_model.find(name: role) : role
54
+ else
55
+ group.is_a?(Symbol) ? ii_config.role_group_model.find(name: role) : group
56
+ end
57
+ obj.have_permission self.pred, obj: self.obj
58
+ end
59
+
60
+ alias is_assigned_to assign_to
61
+
62
+ # :user, User, user
63
+ def obj
64
+ return obj_type.constantize.find(obj_id) if obj_id.present?
65
+ obj_type[/[A-Z]/] ? obj_type.constantize : obj_type.to_sym
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,76 @@
1
+ require 'i_am_i_can/role/helpers'
2
+
3
+ module IAmICan
4
+ module Role
5
+ module Assignment
6
+ include Helpers::Ins
7
+
8
+ def becomes_a *roles, which_can: [ ], obj: nil, auto_define_before: ii_config.auto_define_before, save: ii_config.default_save
9
+ should_define_role = which_can.present? || auto_define_before
10
+ self.class.have_roles *roles, which_can: which_can, obj: obj, save: save if should_define_role
11
+ failed_items = [ ]
12
+
13
+ roles.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)
23
+ end
24
+
25
+ alias is becomes_a
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
32
+
33
+ def temporarily_is *roles, **options
34
+ becomes_a *roles, save: false, **options
35
+ end
36
+
37
+ alias locally_is temporarily_is
38
+
39
+ def falls_from *roles, saved: ii_config.default_save
40
+ failed_items = [ ]
41
+
42
+ roles.each do |role|
43
+ if saved
44
+ failed_items << role unless stored_roles_rmv(role)
45
+ else
46
+ next failed_items << role unless role.in?(defined_roles.keys)
47
+ local_role_names.delete(role)
48
+ end
49
+ end
50
+
51
+ _role_assignment_result(roles, failed_items)
52
+ 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
+
61
+ def local_role_names
62
+ @local_role_names ||= [ ]
63
+ end
64
+
65
+ def local_roles
66
+ defined_local_roles.slice(*local_role_names)
67
+ end
68
+
69
+ def roles
70
+ local_role_names + stored_role_names
71
+ end
72
+
73
+ alias role_names roles
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,100 @@
1
+ require 'i_am_i_can/role/helpers'
2
+
3
+ module IAmICan
4
+ module Role
5
+ module Definition
6
+ include Helpers::Cls
7
+
8
+ def have_role *names, desc: nil, save: ii_config.default_save, which_can: [ ], obj: nil
9
+ failed_items, preds = [ ], which_can
10
+
11
+ names.each do |name|
12
+ description = desc || name.to_s.humanize
13
+ if save
14
+ next failed_items << name unless _to_store_role(name, desc: description)
15
+ ii_config.role_model.which(name: name).can *preds, obj: obj, auto_define_before: true, strict_mode: true if which_can.present?
16
+ else
17
+ next failed_items << name if defined_local_roles.key?(name)
18
+ defined_local_roles[name] ||= { desc: description, permissions: [ ] }
19
+ local_role_which(name: name, can: preds, obj: obj, auto_define_before: true, strict_mode: true) if which_can.present?
20
+ end
21
+ end
22
+
23
+ _role_definition_result(names, failed_items)
24
+ end
25
+
26
+ alias have_roles have_role
27
+ alias has_role have_role
28
+ alias has_roles have_role
29
+
30
+ def declare_role *names, **options
31
+ have_role *names, save: false, **options
32
+ end
33
+
34
+ alias declare_roles has_role
35
+
36
+ def group_roles *members, by_name:, which_can: [ ], obj: nil
37
+ raise Error, 'Some of members have not been defined' unless (members - defined_stored_role_names).empty?
38
+ raise Error, "Given name #{by_name} has been used by a role" if ii_config.role_model.exists?(name: by_name)
39
+ ii_config.role_group_model.find_or_create_by!(name: by_name).members_add(members)
40
+ end
41
+
42
+ alias group_role group_roles
43
+ alias groups_role group_roles
44
+ alias groups_roles group_roles
45
+
46
+ def have_and_group_roles *members, by_name:
47
+ has_roles *members
48
+ group_roles *members, by_name: by_name
49
+ end
50
+
51
+ alias has_and_groups_roles have_and_group_roles
52
+
53
+ # permission assignment locally for local role
54
+ # User.local_role_which(name: :admin, can: :fly)
55
+ # same effect to: UserRole.new(name: :admin).temporarily_can :fly
56
+ def local_role_which(name:, can:, obj: nil, **options)
57
+ ii_config.role_model.new(name: name).temporarily_can *Array(can), obj: obj, **options
58
+ end
59
+
60
+ def self.extended(kls)
61
+ kls.delegate :defined_local_roles, :defined_stored_roles, :defined_roles, to: kls
62
+ end
63
+ end
64
+
65
+ # === End of MainMethods ===
66
+
67
+ module Definition::SecondaryMethods
68
+ def defined_local_roles
69
+ @local_roles ||= { }
70
+ end
71
+
72
+ def defined_stored_role_names
73
+ ii_config.role_model.pluck(:name).map(&:to_sym)
74
+ end
75
+
76
+ def defined_stored_roles
77
+ ii_config.role_model.all.map { |role| [ role.name.to_sym, role.desc ] }.to_h
78
+ end
79
+
80
+ def defined_roles
81
+ defined_local_roles.deep_merge(defined_stored_roles)
82
+ end
83
+
84
+ def defined_role_group_names
85
+ ii_config.role_group_model.pluck(:name).map(&:to_sym)
86
+
87
+ end
88
+
89
+ def defined_role_groups
90
+ ii_config.role_group_model.all.map { |group| [ group.name.to_sym, group.member_names.map(&:to_sym) ] }.to_h
91
+ end
92
+
93
+ def members_of_role_group name
94
+ ii_config.role_group_model.find_by!(name: name).member_names
95
+ end
96
+
97
+ Definition.include self
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,28 @@
1
+ module IAmICan
2
+ module Role
3
+ module Helpers
4
+ module Cls
5
+ def _to_store_role name, **options
6
+ return false if ii_config.role_model.exists?(name: name) || ii_config.role_group_model.exists?(name: name)
7
+ ii_config.role_model.create!(name: name, **options)
8
+ end
9
+
10
+ def _role_definition_result(names, failed_items)
11
+ prefix = 'Role Definition Done'
12
+ fail_msg = prefix + ", but name #{failed_items} have been used by other role or group" if failed_items.present?
13
+ raise Error, fail_msg if ii_config.strict_mode && fail_msg
14
+ fail_msg ? fail_msg : prefix
15
+ end
16
+ end
17
+
18
+ module Ins
19
+ def _role_assignment_result(names, failed_items)
20
+ prefix = 'Role Assignment Done'
21
+ fail_msg = prefix + ", but #{failed_items} have not been defined" if failed_items.present?
22
+ raise Error, fail_msg if ii_config.strict_mode && fail_msg
23
+ fail_msg ? fail_msg : prefix
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,69 @@
1
+ module IAmICan
2
+ module Subject
3
+ module PermissionQuerying
4
+ def can? pred, obj0 = nil, obj: nil, without_group: false
5
+ obj = obj0 || obj
6
+ return true if temporarily_can?(pred, obj)
7
+ return true if stored_can?(pred, obj)
8
+ group_can?(pred, obj, without_group)
9
+ end
10
+
11
+ def cannot? pred, obj0 = nil, obj: nil
12
+ !can? pred, obj0, obj: obj
13
+ end
14
+
15
+ def can! pred, obj0 = nil, obj: nil
16
+ raise InsufficientPermission if cannot? pred, obj0, obj: obj
17
+ true
18
+ end
19
+
20
+ def can_each? preds, obj0 = nil, obj: nil
21
+ preds.each { |pred| return false if cannot? pred, obj0, obj: obj } && true
22
+ end
23
+
24
+ alias can_every? can_each?
25
+
26
+ def can_each! preds, obj0 = nil, obj: nil
27
+ preds.each { |pred| can! pred, obj0, obj: obj } && true
28
+ end
29
+
30
+ alias can_every! can_each!
31
+
32
+ def can_one_of? preds, obj0 = nil, obj: nil
33
+ preds.each { |pred| return true if can? pred, obj0, obj: obj } && false
34
+ end
35
+
36
+ def can_one_of! preds, obj0 = nil, obj: nil
37
+ raise InsufficientPermission unless can_one_of? preds, obj0, obj: obj
38
+ true
39
+ end
40
+
41
+ def temporarily_can? pred, obj
42
+ ii_config.permission_model.matched?(pred: pred, obj: obj, in: permissions_of_local_roles)
43
+ end
44
+
45
+ alias locally_can? temporarily_can?
46
+
47
+ def stored_can? pred, obj
48
+ ii_config.permission_model.matched?(pred: pred, obj: obj, in: permissions_of_stored_roles)
49
+ end
50
+
51
+ def group_can? pred, obj, without_group = false
52
+ return false if without_group || ii_config.without_group
53
+ ii_config.permission_model.matched?(pred: pred, obj: obj, in: permissions_of_role_groups)
54
+ end
55
+
56
+ def permissions_of_stored_roles
57
+ stored_roles.stored_permissions.map(&:name)
58
+ end
59
+
60
+ def permissions_of_role_groups
61
+ stored_roles.related_role_groups.stored_permissions.map(&:name)
62
+ end
63
+
64
+ def permissions_of_local_roles
65
+ local_roles.map { |(name, info)| info[:permissions] }.flatten.uniq
66
+ end
67
+ end
68
+ end
69
+ end