isomorfeus-policy 1.0.0.zeta25 → 2.0.0.rc4

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.
@@ -1,42 +1,42 @@
1
- module LucidAuthorization
2
- module Mixin
3
- def record_authorization_reason
4
- @_isomorfeus_record_authorization_reason = true
5
- end
6
-
7
- def stop_to_record_authorization_reason
8
- @_isomorfeus_record_authorization_reason = false
9
- @_isomorfeus_authorization_reason = nil
10
- end
11
-
12
- def authorization_reason
13
- @_isomorfeus_authorization_reason
14
- end
15
-
16
- def authorized?(target_class, target_method = nil, props = nil)
17
- begin
18
- class_name = self.class.name
19
- class_name = class_name.split('>::').last if class_name.start_with?('#<')
20
- policy_class = Isomorfeus.cached_policy_class("#{class_name}Policy")
21
- rescue ::NameError
22
- policy_class = nil
23
- end
24
- return false unless policy_class
25
- policy_instance = policy_class.new(self, @_isomorfeus_record_authorization_reason)
26
- result = policy_instance.authorized?(target_class, target_method, props)
27
- @_isomorfeus_authorization_reason = policy_instance.reason
28
- result
29
- end
30
-
31
- def authorized!(target_class, target_method = nil, props = nil)
32
- class_name = self.class.name
33
- class_name = class_name.split('>::').last if class_name.start_with?('#<')
34
- policy_class = Isomorfeus.cached_policy_class("#{class_name}Policy")
35
- Isomorfeus.raise_error(error_class: LucidPolicy::Exception, message: "#{self}: policy class #{class_name}Policy not found!") unless policy_class
36
- policy_instance = policy_class.new(self, @_isomorfeus_record_authorization_reason)
37
- result = policy_instance.authorized!(target_class, target_method, props)
38
- @_isomorfeus_authorization_reason = policy_instance.reason
39
- result
40
- end
41
- end
42
- end
1
+ module LucidAuthorization
2
+ module Mixin
3
+ def record_authorization_reason
4
+ @_isomorfeus_record_authorization_reason = true
5
+ end
6
+
7
+ def stop_to_record_authorization_reason
8
+ @_isomorfeus_record_authorization_reason = false
9
+ @_isomorfeus_authorization_reason = nil
10
+ end
11
+
12
+ def authorization_reason
13
+ @_isomorfeus_authorization_reason
14
+ end
15
+
16
+ def authorized?(target_class, target_method = nil, props = nil)
17
+ begin
18
+ class_name = self.class.name
19
+ class_name = class_name.split('>::').last if class_name.start_with?('#<')
20
+ policy_class = Isomorfeus.cached_policy_class("#{class_name}Policy")
21
+ rescue ::NameError
22
+ policy_class = nil
23
+ end
24
+ return false unless policy_class
25
+ policy_instance = policy_class.new(self, @_isomorfeus_record_authorization_reason)
26
+ result = policy_instance.authorized?(target_class, target_method, props)
27
+ @_isomorfeus_authorization_reason = policy_instance.reason
28
+ result
29
+ end
30
+
31
+ def authorized!(target_class, target_method = nil, props = nil)
32
+ class_name = self.class.name
33
+ class_name = class_name.split('>::').last if class_name.start_with?('#<')
34
+ policy_class = Isomorfeus.cached_policy_class("#{class_name}Policy")
35
+ Isomorfeus.raise_error(error_class: LucidPolicy::Exception, message: "#{self}: policy class #{class_name}Policy not found!") unless policy_class
36
+ policy_instance = policy_class.new(self, @_isomorfeus_record_authorization_reason)
37
+ result = policy_instance.authorized!(target_class, target_method, props)
38
+ @_isomorfeus_authorization_reason = policy_instance.reason
39
+ result
40
+ end
41
+ end
42
+ end
@@ -1,11 +1,10 @@
1
- module LucidPolicy
2
- class Base
3
- include LucidPolicy::Mixin
4
-
5
- if RUBY_ENGINE != 'opal'
6
- def self.inherited(base)
7
- Isomorfeus.add_valid_policy_class(base)
8
- end
9
- end
10
- end
11
- end
1
+ module LucidPolicy
2
+ class Base
3
+ def self.inherited(base)
4
+ base.include LucidPolicy::Mixin
5
+ if RUBY_ENGINE != 'opal'
6
+ Isomorfeus.add_valid_policy_class(base)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -1,4 +1,4 @@
1
- module LucidPolicy
2
- class Exception < ::Exception
3
- end
4
- end
1
+ module LucidPolicy
2
+ class Exception < ::Exception
3
+ end
4
+ end
@@ -1,18 +1,18 @@
1
- module LucidPolicy
2
- class Helper < BasicObject
3
- attr_reader :result
4
-
5
- def initialize
6
- @result = :deny
7
- end
8
-
9
- def allow
10
- @result = :allow
11
- nil
12
- end
13
-
14
- def deny
15
- nil
16
- end
17
- end
18
- end
1
+ module LucidPolicy
2
+ class Helper < BasicObject
3
+ attr_reader :result
4
+
5
+ def initialize
6
+ @result = :deny
7
+ end
8
+
9
+ def allow
10
+ @result = :allow
11
+ nil
12
+ end
13
+
14
+ def deny
15
+ nil
16
+ end
17
+ end
18
+ end
@@ -1,195 +1,191 @@
1
- module LucidPolicy
2
- module Mixin
3
- def self.included(base)
4
- base.instance_exec do
5
- if RUBY_ENGINE != 'opal'
6
- Isomorfeus.add_valid_policy_class(base) unless base == LucidPolicy::Base
7
- end
8
-
9
- def authorization_rules
10
- @authorization_rules ||= { rules: {}.dup, policies: {}.dup, others: :deny }.dup
11
- end
12
-
13
- def all
14
- :others
15
- end
16
-
17
- def allow(*classes_and_methods_and_options)
18
- _allow_or_deny(:allow, *classes_and_methods_and_options)
19
- end
20
-
21
- def deny(*classes_and_methods_and_options)
22
- _allow_or_deny(:deny, *classes_and_methods_and_options)
23
- end
24
-
25
- def others
26
- :others
27
- end
28
-
29
- def rule(*classes_and_methods, &block)
30
- _allow_or_deny(:rule, *classes_and_methods, &block)
31
- end
32
-
33
- def combine_with(policy_class, **options)
34
- authorization_rules[:policies] = { policy_class => options }
35
- end
36
-
37
- private
38
-
39
- def _allow_or_deny(thing, *classes_methods_options, &block)
40
- rules = authorization_rules
41
-
42
- if %i[allow deny].include?(thing) && classes_methods_options.first == :others
43
- rules[:others] = thing
44
- return
45
- end
46
-
47
- target_classes = []
48
- target_methods = []
49
- target_options = {}
50
-
51
- classes_methods_options.each do |class_method_option|
52
- if class_method_option.class == Hash
53
- target_options = class_method_option
54
- else
55
- class_or_method_s = class_method_option.to_s
56
- if class_method_option.class == Symbol && class_or_method_s[0].downcase == class_or_method_s[0]
57
- target_methods << class_method_option
58
- else
59
- class_method_option = class_or_method_s unless class_method_option.class == String
60
- target_classes << class_method_option
61
- end
62
- end
63
- end
64
-
65
- thing_or_block = block_given? ? block : thing
66
-
67
- target_classes.each do |target_class|
68
- target_class = target_class.split('>::').last if target_class.start_with?('#<')
69
- rules[:rules][target_class] = {} unless rules[:rules].key?(target_class)
70
-
71
- if target_methods.empty?
72
- rules[:rules][target_class][:rule] = thing_or_block
73
- rules[:rules][target_class][:options] = target_options unless target_options.empty?
74
- else
75
- rules[:rules][target_class][:rule] = :deny unless rules[:rules][target_class].key?(:rule)
76
- rules[:rules][target_class][:methods] = {} unless rules[:rules][target_class].key?(:methods)
77
- target_methods.each do |target_method|
78
- rules[:rules][target_class][:methods][target_method] = { rule: thing_or_block }
79
- rules[:rules][target_class][:methods][target_method][:options] = target_options unless target_options.empty?
80
- end
81
- end
82
- end
83
- end
84
- end
85
-
86
- attr_reader :reason
87
-
88
- def initialize(object, record_reason = nil)
89
- @object = object
90
- @reason = nil
91
- @record_reason = record_reason
92
- if @record_reason
93
- @class_name = self.class.name
94
- @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
95
- end
96
- end
97
-
98
- def authorized?(target_class, target_method = nil, props = nil)
99
- Isomorfeus.raise_error(error_class: LucidPolicy::Exception, message: "#{self}: At least the class or class name must be given!") unless target_class
100
-
101
- target_class = target_class.to_s unless target_class.class == String
102
- target_class = target_class.split('>::').last if target_class.start_with?('#<')
103
-
104
- rules = self.class.authorization_rules
105
-
106
- result = if rules[:rules].key?(target_class)
107
- if target_method && rules[:rules][target_class].key?(:methods) && rules[:rules][target_class][:methods].key?(target_method)
108
- options = rules[:rules][target_class][:methods][target_method][:options]
109
- rule = rules[:rules][target_class][:methods][target_method][:rule]
110
- @reason = { policy_class: @class_name, class_name: target_class, method: target_method, rule: rule } if @record_reason
111
- else
112
- options = rules[:rules][target_class][:options]
113
- rule = rules[:rules][target_class][:rule]
114
- @reason = { policy_class: @class_name, class_name: target_class, rule: rule } if @record_reason
115
- end
116
-
117
- if rule.class == Symbol || rule.class == String
118
- if options
119
- condition, method_result = __get_condition_and_result(options)
120
- if @record_reason
121
- @reason[:condition] = condition
122
- @reason[:condition_result] = method_result
123
- end
124
- rule if (condition == :if && method_result == true) || (condition == :if_not && method_result == false)
125
- else
126
- rule
127
- end
128
- else
129
- props = LucidProps.new(props) unless props.class == LucidProps
130
- policy_helper = LucidPolicy::Helper.new
131
- policy_helper.instance_exec(@object, target_class, target_method, props, &rule)
132
- r = policy_helper.result
133
- @reason[:rule_result] = r if @record_reason
134
- r
135
- end
136
- else
137
- r = rules[:others]
138
- @reason = { policy_class: @class_name, class_name: target_class, others: r } if @record_reason
139
- r
140
- end
141
-
142
- return true if result == :allow
143
-
144
- rules[:policies].each do |policy_class, options|
145
- combined_policy_result = nil
146
- if options.empty?
147
- policy_instance = policy_class.new(@object, @record_reason)
148
- combined_policy_result = policy_instance.authorized?(target_class, target_method, props)
149
- @reason = @reason = { policy_class: @class_name, combined: policy_instance.reason } if @record_reason
150
- else
151
- condition, method_result = __get_condition_and_result(options)
152
- if (condition == :if && method_result == true) || (condition == :if_not && method_result == false)
153
- policy_instance = policy_class.new(@object, @record_reason)
154
- combined_policy_result = policy_instance.authorized?(target_class, target_method, props)
155
- @reason = { policy_class: @class_name, combined: policy_instance.reason, condition: condition, condition_result: method_result } if @record_reason
156
- end
157
- end
158
- return true if combined_policy_result == true
159
- end
160
-
161
- result == :allow ? true : false
162
- end
163
-
164
- def authorized!(target_class, target_method = nil, props = nil)
165
- result = authorized?(target_class, target_method, props)
166
- reason_message = reason ? ", reason: #{reason}" : ''
167
- return true if result
168
- Isomorfeus.raise_error(error_class: LucidPolicy::Exception, message: "#{@object}: not authorized to call #{target_class}#{}#{target_method} #{props} #{reason_message}!")
169
- end
170
-
171
- private
172
-
173
- def __get_condition_and_result(options)
174
- condition = nil
175
- method_name_or_block = if options.key?(:if)
176
- condition = :if
177
- options[:if]
178
- elsif options.key?(:if_not)
179
- condition = :if_not
180
- options[:if_not]
181
- elsif options.key?(:unless)
182
- condition = :if_not
183
- options[:unless]
184
- end
185
- method_result = if method_name_or_block && method_name_or_block.class == Symbol
186
- @object.__send__(method_name_or_block)
187
- else
188
- props = LucidProps.new(props) unless props.class == LucidProps
189
- method_name_or_block.call(@object, props)
190
- end
191
- [condition, method_result]
192
- end
193
- end
194
- end
195
- end
1
+ module LucidPolicy
2
+ module Mixin
3
+ def self.included(base)
4
+ base.instance_exec do
5
+ if RUBY_ENGINE != 'opal'
6
+ Isomorfeus.add_valid_policy_class(base) unless base == LucidPolicy::Base
7
+ end
8
+
9
+ def authorization_rules
10
+ @authorization_rules ||= { rules: {}.dup, policies: {}.dup, others: :deny }.dup
11
+ end
12
+
13
+ def all
14
+ :others
15
+ end
16
+
17
+ def allow(*classes_and_methods_and_options)
18
+ _allow_or_deny(:allow, *classes_and_methods_and_options)
19
+ end
20
+
21
+ def deny(*classes_and_methods_and_options)
22
+ _allow_or_deny(:deny, *classes_and_methods_and_options)
23
+ end
24
+
25
+ def others
26
+ :others
27
+ end
28
+
29
+ def rule(*classes_and_methods, &block)
30
+ _allow_or_deny(:rule, *classes_and_methods, &block)
31
+ end
32
+
33
+ def combine_with(policy_class, **options)
34
+ authorization_rules[:policies] = { policy_class => options }
35
+ end
36
+
37
+ def _allow_or_deny(thing, *classes_methods_options, &block)
38
+ rules = authorization_rules
39
+
40
+ if %i[allow deny].include?(thing) && classes_methods_options.first == :others
41
+ rules[:others] = thing
42
+ return
43
+ end
44
+
45
+ target_classes = []
46
+ target_methods = []
47
+ target_options = {}
48
+
49
+ classes_methods_options.each do |class_method_option|
50
+ if class_method_option.class == Hash
51
+ target_options = class_method_option
52
+ else
53
+ class_or_method_s = class_method_option.to_s
54
+ if class_method_option.class == Symbol && class_or_method_s[0].downcase == class_or_method_s[0]
55
+ target_methods << class_method_option
56
+ else
57
+ class_method_option = class_or_method_s unless class_method_option.class == String
58
+ target_classes << class_method_option
59
+ end
60
+ end
61
+ end
62
+
63
+ thing_or_block = block_given? ? block : thing
64
+
65
+ target_classes.each do |target_class|
66
+ target_class = target_class.split('>::').last if target_class.start_with?('#<')
67
+ rules[:rules][target_class] = {} unless rules[:rules].key?(target_class)
68
+
69
+ if target_methods.empty?
70
+ rules[:rules][target_class][:rule] = thing_or_block
71
+ rules[:rules][target_class][:options] = target_options unless target_options.empty?
72
+ else
73
+ rules[:rules][target_class][:rule] = :deny unless rules[:rules][target_class].key?(:rule)
74
+ rules[:rules][target_class][:methods] = {} unless rules[:rules][target_class].key?(:methods)
75
+ target_methods.each do |target_method|
76
+ rules[:rules][target_class][:methods][target_method] = { rule: thing_or_block }
77
+ rules[:rules][target_class][:methods][target_method][:options] = target_options unless target_options.empty?
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ attr_reader :reason
85
+
86
+ def initialize(object, record_reason = nil)
87
+ @object = object
88
+ @reason = nil
89
+ @record_reason = record_reason
90
+ if @record_reason
91
+ @class_name = self.class.name
92
+ @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
93
+ end
94
+ end
95
+
96
+ def authorized?(target_class, target_method = nil, props = nil)
97
+ Isomorfeus.raise_error(error_class: LucidPolicy::Exception, message: "#{self}: At least the class or class name must be given!") unless target_class
98
+
99
+ target_class = target_class.to_s unless target_class.class == String
100
+ target_class = target_class.split('>::').last if target_class.start_with?('#<')
101
+
102
+ rules = self.class.authorization_rules
103
+
104
+ result = if rules[:rules].key?(target_class)
105
+ if target_method && rules[:rules][target_class].key?(:methods) && rules[:rules][target_class][:methods].key?(target_method)
106
+ options = rules[:rules][target_class][:methods][target_method][:options]
107
+ rule = rules[:rules][target_class][:methods][target_method][:rule]
108
+ @reason = { policy_class: @class_name, class_name: target_class, method: target_method, rule: rule } if @record_reason
109
+ else
110
+ options = rules[:rules][target_class][:options]
111
+ rule = rules[:rules][target_class][:rule]
112
+ @reason = { policy_class: @class_name, class_name: target_class, rule: rule } if @record_reason
113
+ end
114
+
115
+ if rule.class == Symbol || rule.class == String
116
+ if options
117
+ condition, method_result = _get_condition_and_result(options)
118
+ if @record_reason
119
+ @reason[:condition] = condition
120
+ @reason[:condition_result] = method_result
121
+ end
122
+ rule if (condition == :if && method_result == true) || (condition == :if_not && method_result == false)
123
+ else
124
+ rule
125
+ end
126
+ else
127
+ props = LucidProps.new(props) unless props.class == LucidProps
128
+ policy_helper = LucidPolicy::Helper.new
129
+ policy_helper.instance_exec(@object, target_class, target_method, props, &rule)
130
+ r = policy_helper.result
131
+ @reason[:rule_result] = r if @record_reason
132
+ r
133
+ end
134
+ else
135
+ r = rules[:others]
136
+ @reason = { policy_class: @class_name, class_name: target_class, others: r } if @record_reason
137
+ r
138
+ end
139
+
140
+ return true if result == :allow
141
+
142
+ rules[:policies].each do |policy_class, options|
143
+ combined_policy_result = nil
144
+ if options.empty?
145
+ policy_instance = policy_class.new(@object, @record_reason)
146
+ combined_policy_result = policy_instance.authorized?(target_class, target_method, props)
147
+ @reason = @reason = { policy_class: @class_name, combined: policy_instance.reason } if @record_reason
148
+ else
149
+ condition, method_result = _get_condition_and_result(options)
150
+ if (condition == :if && method_result == true) || (condition == :if_not && method_result == false)
151
+ policy_instance = policy_class.new(@object, @record_reason)
152
+ combined_policy_result = policy_instance.authorized?(target_class, target_method, props)
153
+ @reason = { policy_class: @class_name, combined: policy_instance.reason, condition: condition, condition_result: method_result } if @record_reason
154
+ end
155
+ end
156
+ return true if combined_policy_result == true
157
+ end
158
+
159
+ result == :allow ? true : false
160
+ end
161
+
162
+ def authorized!(target_class, target_method = nil, props = nil)
163
+ result = authorized?(target_class, target_method, props)
164
+ reason_message = reason ? ", reason: #{reason}" : ''
165
+ return true if result
166
+ Isomorfeus.raise_error(error_class: LucidPolicy::Exception, message: "#{@object}: not authorized to call #{target_class}#{}#{target_method} #{props} #{reason_message}!")
167
+ end
168
+
169
+ def _get_condition_and_result(options)
170
+ condition = nil
171
+ method_name_or_block = if options.key?(:if)
172
+ condition = :if
173
+ options[:if]
174
+ elsif options.key?(:if_not)
175
+ condition = :if_not
176
+ options[:if_not]
177
+ elsif options.key?(:unless)
178
+ condition = :if_not
179
+ options[:unless]
180
+ end
181
+ method_result = if method_name_or_block && method_name_or_block.class == Symbol
182
+ @object.__send__(method_name_or_block)
183
+ else
184
+ props = LucidProps.new(props) unless props.class == LucidProps
185
+ method_name_or_block.call(@object, props)
186
+ end
187
+ [condition, method_result]
188
+ end
189
+ end
190
+ end
191
+ end