i_am_i_can 2.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.
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