i_am_i_can 3.0.1 → 4.0.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/.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
@@ -1,95 +0,0 @@
|
|
1
|
-
module IAmICan
|
2
|
-
module DynamicGenerate
|
3
|
-
extend self
|
4
|
-
|
5
|
-
def scopes
|
6
|
-
# Generate scopes of each specified i_am_i_can association
|
7
|
-
#
|
8
|
-
# scope :with_stored_roles, -> { includes(:stored_roles) }
|
9
|
-
#
|
10
|
-
proc do |keys|
|
11
|
-
keys.each do |k|
|
12
|
-
scope :"with_#{_reflect_of(k)}", -> { includes(_reflect_of(k)) }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def class_reflections
|
18
|
-
# Extend each associated querying to a class method that returns ActiveRecord::Relation
|
19
|
-
#
|
20
|
-
# Suppose: in UserRole model,
|
21
|
-
# has_and_belongs_to_many :related_users
|
22
|
-
#
|
23
|
-
# It will do like this:
|
24
|
-
# def self.related_users
|
25
|
-
# i_am_i_can.subject_model.with_stored_roles.where(user_roles: { id: self.ids })
|
26
|
-
# end
|
27
|
-
#
|
28
|
-
# Usage:
|
29
|
-
# UserRole.all.related_users
|
30
|
-
#
|
31
|
-
proc do
|
32
|
-
%w[ subject role role_group permission ].each do |k|
|
33
|
-
next unless _reflect_of(k)
|
34
|
-
define_singleton_method _reflect_of(k) do
|
35
|
-
model = i_am_i_can.send("#{k}_model")
|
36
|
-
raise NoMethodError unless (reflect_name = model._reflect_of(i_am_i_can.act))
|
37
|
-
model.send("with_#{reflect_name}").where(
|
38
|
-
self.name.underscore.pluralize => { id: self.ids }
|
39
|
-
)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def assignment_helpers
|
46
|
-
# Generate 4 methods for each Content of Assignment
|
47
|
-
#
|
48
|
-
# Example for a subject model called User, which `has_and_belongs_to_many :stored_roles`.
|
49
|
-
# You call this proc by given contents [:role], then:
|
50
|
-
#
|
51
|
-
# 1. stored_roles_add
|
52
|
-
# Add roles to a user instance
|
53
|
-
#
|
54
|
-
# 2. stored_roles_add
|
55
|
-
# Remove roles to a user instance
|
56
|
-
#
|
57
|
-
# 3. stored_role_names
|
58
|
-
# Get names of stored_roles of a user instance
|
59
|
-
#
|
60
|
-
# 4. self.stored_role_names
|
61
|
-
# Get names of stored_roles of User ActiveRecord::Relation
|
62
|
-
#
|
63
|
-
proc do |contents|
|
64
|
-
contents.each do |content|
|
65
|
-
# TODO: refactoring
|
66
|
-
define_method "#{_reflect_of(content)}_add" do |locate_vals = nil, check_size: nil, **condition|
|
67
|
-
condition = { name: locate_vals } if locate_vals
|
68
|
-
assoc = send("_#{content.to_s.pluralize}")
|
69
|
-
records = i_am_i_can.send("#{content}_model").where(condition).where.not(id: assoc.ids)
|
70
|
-
# will return false if it does nothing
|
71
|
-
return false if records.blank? || (check_size && records.count != check_size)
|
72
|
-
assoc << records
|
73
|
-
end
|
74
|
-
|
75
|
-
define_method "#{_reflect_of(content)}_rmv" do |locate_vals = nil, check_size: nil, **condition|
|
76
|
-
condition = { name: locate_vals } if locate_vals
|
77
|
-
assoc = send("_#{content.to_s.pluralize}")
|
78
|
-
records = i_am_i_can.send("#{content}_model").where(id: assoc.ids, **condition)
|
79
|
-
# will return false if it does nothing
|
80
|
-
return false if records.blank? || (check_size && records.count != check_size)
|
81
|
-
assoc.destroy(records)
|
82
|
-
end
|
83
|
-
|
84
|
-
define_method "#{_reflect_of(content).to_s.singularize}_names" do
|
85
|
-
send("_#{content.to_s.pluralize}").map(&:name).map(&:to_sym)
|
86
|
-
end
|
87
|
-
|
88
|
-
define_singleton_method "#{_reflect_of(content).to_s.singularize}_names" do
|
89
|
-
all.flat_map { |user| user.send("#{_reflect_of(content).to_s.singularize}_name") }.uniq
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
@@ -1,75 +0,0 @@
|
|
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 i_am_i_can.strict_mode && fail_msg
|
9
|
-
puts fail_msg || prefix unless ENV['ITEST']
|
10
|
-
prefix.present?
|
11
|
-
end
|
12
|
-
|
13
|
-
def _to_store_permission(pred, obj, **options)
|
14
|
-
return false if i_am_i_can.permission_model.exists?(pred, obj)
|
15
|
-
i_am_i_can.permission_model.create!(pred: pred, **deconstruct_obj(obj), **options)
|
16
|
-
end
|
17
|
-
|
18
|
-
def pms_naming(pred, obj)
|
19
|
-
i_am_i_can.permission_model.naming(pred, obj)
|
20
|
-
end
|
21
|
-
|
22
|
-
def deconstruct_obj(obj)
|
23
|
-
i_am_i_can.permission_model.deconstruct_obj(obj)
|
24
|
-
end
|
25
|
-
|
26
|
-
def defined_local_permissions
|
27
|
-
@defined_local_permissions ||= { }
|
28
|
-
end
|
29
|
-
|
30
|
-
def defined_stored_pms_names
|
31
|
-
i_am_i_can.permission_model.all.map(&:name)
|
32
|
-
end
|
33
|
-
|
34
|
-
def defined_stored_permissions
|
35
|
-
i_am_i_can.permission_model.all.map { |pms| [ pms.name, pms.desc ] }.to_h
|
36
|
-
end
|
37
|
-
|
38
|
-
def defined_permissions
|
39
|
-
defined_local_permissions.deep_merge(defined_stored_permissions)
|
40
|
-
end
|
41
|
-
|
42
|
-
def pms_of_defined_local_role(role_name)
|
43
|
-
i_am_i_can.subject_model.defined_local_roles[role_name.to_sym]&.[](:permissions) || []
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
module Ins
|
48
|
-
def _pms_assignment_result(preds, obj, not_defined_items, covered_items = nil, strict_mode = false)
|
49
|
-
prefix = 'Permission Assignment Done'
|
50
|
-
msg1 = "#{not_defined_items} have not been defined or have been repeatedly assigned" if not_defined_items.present?
|
51
|
-
msg2 = "#{covered_items} have been covered" if covered_items.present?
|
52
|
-
fail_msg = prefix + ', but ' + [msg1, msg2].compact.join(', ') if msg1 || msg2
|
53
|
-
raise Error, fail_msg if (strict_mode || i_am_i_can.strict_mode) && fail_msg
|
54
|
-
puts fail_msg || prefix unless ENV['ITEST']
|
55
|
-
prefix.present?
|
56
|
-
end
|
57
|
-
|
58
|
-
def pms_matched?(pms_name, plist)
|
59
|
-
i_am_i_can.permission_model.matched?(pms_name, in: plist[:in])
|
60
|
-
end
|
61
|
-
|
62
|
-
def local_permissions
|
63
|
-
@local_permissions ||= [ ]
|
64
|
-
end
|
65
|
-
|
66
|
-
alias local_permission_names local_permissions
|
67
|
-
|
68
|
-
# TODO: show by hash
|
69
|
-
def permissions
|
70
|
-
local_permission_names + stored_permission_names
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,22 +0,0 @@
|
|
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
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module IAmICan
|
2
|
-
module Reflection
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
class_methods do
|
6
|
-
# User._roles => 'stored_roles'
|
7
|
-
%w[ subjects roles role_groups permissions ].each do |k|
|
8
|
-
define_method "_#{k}" do
|
9
|
-
v = instance_variable_get("@_#{k}")
|
10
|
-
return v if v.present?
|
11
|
-
instance_variable_set("@_#{k}", _reflect_of(k.singularize))
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
included do
|
17
|
-
# user._roles => Association CollectionProxy, same as: `user.stored_roles`
|
18
|
-
%w[ subjects roles role_groups permissions ].each do |k|
|
19
|
-
define_method "_#{k}" do
|
20
|
-
send(self.class.send("_#{k}")) if self.class.send("_#{k}")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
module IAmICan
|
2
|
-
module Role
|
3
|
-
module Helpers
|
4
|
-
module Cls
|
5
|
-
def _to_store_role name, **options
|
6
|
-
return false if i_am_i_can.role_model.exists?(name: name) || i_am_i_can.role_group_model&.exists?(name: name)
|
7
|
-
i_am_i_can.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 i_am_i_can.strict_mode && fail_msg
|
14
|
-
puts fail_msg || prefix unless ENV['ITEST']
|
15
|
-
prefix.present?
|
16
|
-
end
|
17
|
-
|
18
|
-
def defined_local_roles
|
19
|
-
@local_roles ||= { }
|
20
|
-
end
|
21
|
-
|
22
|
-
def defined_stored_role_names
|
23
|
-
i_am_i_can.role_model.pluck(:name).map(&:to_sym)
|
24
|
-
end
|
25
|
-
|
26
|
-
def defined_stored_roles
|
27
|
-
i_am_i_can.role_model.all.map { |role| [ role.name.to_sym, role.desc ] }.to_h
|
28
|
-
end
|
29
|
-
|
30
|
-
def defined_roles
|
31
|
-
defined_local_roles.deep_merge(defined_stored_roles)
|
32
|
-
end
|
33
|
-
|
34
|
-
def defined_role_group_names
|
35
|
-
i_am_i_can.role_group_model.pluck(:name).map(&:to_sym)
|
36
|
-
end
|
37
|
-
|
38
|
-
def defined_role_groups
|
39
|
-
i_am_i_can.role_group_model.all.map { |group| [ group.name.to_sym, group.member_names.map(&:to_sym).sort ] }.to_h
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
module Ins
|
44
|
-
def _role_assignment_result(names, failed_items)
|
45
|
-
prefix = 'Role Assignment Done'
|
46
|
-
fail_msg = prefix + ", but #{failed_items} have not been defined or have been repeatedly assigned" if failed_items.present?
|
47
|
-
raise Error, fail_msg if i_am_i_can.strict_mode && fail_msg
|
48
|
-
puts fail_msg || prefix unless ENV['ITEST']
|
49
|
-
prefix.present?
|
50
|
-
end
|
51
|
-
|
52
|
-
def __role
|
53
|
-
proc do |role|
|
54
|
-
next role.to_sym if role.is_a?(String) || role.is_a?(Symbol)
|
55
|
-
next role.name if role.is_a?(i_am_i_can.role_model)
|
56
|
-
# raise error
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def local_role_names
|
61
|
-
@local_role_names ||= [ ]
|
62
|
-
end
|
63
|
-
|
64
|
-
def local_roles
|
65
|
-
defined_local_roles.slice(*local_role_names)
|
66
|
-
end
|
67
|
-
|
68
|
-
def roles
|
69
|
-
local_role_names + stored_role_names
|
70
|
-
end
|
71
|
-
|
72
|
-
alias role_names roles
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|