action_policy 0.4.2 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +229 -171
- data/LICENSE.txt +1 -1
- data/README.md +7 -11
- data/lib/.rbnext/2.7/action_policy/behaviours/policy_for.rb +62 -0
- data/lib/.rbnext/2.7/action_policy/i18n.rb +56 -0
- data/lib/.rbnext/2.7/action_policy/policy/cache.rb +101 -0
- data/lib/.rbnext/2.7/action_policy/policy/pre_check.rb +162 -0
- data/lib/.rbnext/2.7/action_policy/rspec/be_authorized_to.rb +89 -0
- data/lib/.rbnext/2.7/action_policy/rspec/have_authorized_scope.rb +124 -0
- data/lib/.rbnext/2.7/action_policy/utils/pretty_print.rb +159 -0
- data/lib/.rbnext/3.0/action_policy/behaviour.rb +115 -0
- data/lib/.rbnext/3.0/action_policy/behaviours/policy_for.rb +62 -0
- data/lib/.rbnext/3.0/action_policy/behaviours/scoping.rb +35 -0
- data/lib/.rbnext/3.0/action_policy/behaviours/thread_memoized.rb +59 -0
- data/lib/.rbnext/3.0/action_policy/ext/policy_cache_key.rb +72 -0
- data/lib/.rbnext/3.0/action_policy/policy/aliases.rb +69 -0
- data/lib/.rbnext/3.0/action_policy/policy/authorization.rb +87 -0
- data/lib/.rbnext/3.0/action_policy/policy/cache.rb +101 -0
- data/lib/.rbnext/3.0/action_policy/policy/core.rb +161 -0
- data/lib/.rbnext/3.0/action_policy/policy/defaults.rb +31 -0
- data/lib/.rbnext/3.0/action_policy/policy/execution_result.rb +37 -0
- data/lib/.rbnext/3.0/action_policy/policy/pre_check.rb +162 -0
- data/lib/.rbnext/3.0/action_policy/policy/reasons.rb +210 -0
- data/lib/.rbnext/3.0/action_policy/policy/scoping.rb +160 -0
- data/lib/.rbnext/3.0/action_policy/rspec/be_authorized_to.rb +89 -0
- data/lib/.rbnext/3.0/action_policy/rspec/have_authorized_scope.rb +124 -0
- data/lib/.rbnext/3.0/action_policy/utils/pretty_print.rb +159 -0
- data/lib/.rbnext/3.0/action_policy/utils/suggest_message.rb +19 -0
- data/lib/action_policy.rb +7 -1
- data/lib/action_policy/behaviour.rb +22 -16
- data/lib/action_policy/behaviours/policy_for.rb +10 -3
- data/lib/action_policy/behaviours/scoping.rb +2 -1
- data/lib/action_policy/behaviours/thread_memoized.rb +1 -3
- data/lib/action_policy/ext/module_namespace.rb +1 -6
- data/lib/action_policy/ext/policy_cache_key.rb +15 -33
- data/lib/action_policy/ext/{symbol_classify.rb → symbol_camelize.rb} +6 -6
- data/lib/action_policy/i18n.rb +1 -1
- data/lib/action_policy/lookup_chain.rb +41 -21
- data/lib/action_policy/policy/aliases.rb +7 -12
- data/lib/action_policy/policy/authorization.rb +14 -17
- data/lib/action_policy/policy/cache.rb +34 -18
- data/lib/action_policy/policy/core.rb +25 -12
- data/lib/action_policy/policy/defaults.rb +3 -9
- data/lib/action_policy/policy/execution_result.rb +3 -9
- data/lib/action_policy/policy/pre_check.rb +19 -58
- data/lib/action_policy/policy/reasons.rb +32 -20
- data/lib/action_policy/policy/scoping.rb +5 -6
- data/lib/action_policy/rails/controller.rb +6 -1
- data/lib/action_policy/rails/ext/active_record.rb +7 -0
- data/lib/action_policy/rails/policy/instrumentation.rb +1 -1
- data/lib/action_policy/rspec/be_authorized_to.rb +5 -9
- data/lib/action_policy/rspec/dsl.rb +3 -3
- data/lib/action_policy/rspec/have_authorized_scope.rb +5 -7
- data/lib/action_policy/utils/pretty_print.rb +21 -24
- data/lib/action_policy/utils/suggest_message.rb +1 -3
- data/lib/action_policy/version.rb +1 -1
- data/lib/generators/action_policy/install/templates/{application_policy.rb → application_policy.rb.tt} +1 -1
- data/lib/generators/action_policy/policy/policy_generator.rb +4 -1
- data/lib/generators/action_policy/policy/templates/{policy.rb → policy.rb.tt} +0 -0
- data/lib/generators/rspec/templates/{policy_spec.rb → policy_spec.rb.tt} +0 -0
- data/lib/generators/test_unit/templates/{policy_test.rb → policy_test.rb.tt} +0 -0
- metadata +55 -119
- data/.gitattributes +0 -2
- data/.github/FUNDING.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -18
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -29
- data/.gitignore +0 -15
- data/.rubocop.yml +0 -54
- data/.tidelift.yml +0 -6
- data/.travis.yml +0 -31
- data/Gemfile +0 -22
- data/Rakefile +0 -27
- data/action_policy.gemspec +0 -44
- data/benchmarks/namespaced_lookup_cache.rb +0 -71
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/docs/.nojekyll +0 -0
- data/docs/CNAME +0 -1
- data/docs/README.md +0 -77
- data/docs/_sidebar.md +0 -27
- data/docs/aliases.md +0 -122
- data/docs/assets/docsify-search.js +0 -364
- data/docs/assets/docsify.min.js +0 -3
- data/docs/assets/fonts/FiraCode-Medium.woff +0 -0
- data/docs/assets/fonts/FiraCode-Regular.woff +0 -0
- data/docs/assets/images/banner.png +0 -0
- data/docs/assets/images/cache.png +0 -0
- data/docs/assets/images/cache.svg +0 -70
- data/docs/assets/images/layer.png +0 -0
- data/docs/assets/images/layer.svg +0 -35
- data/docs/assets/prism-ruby.min.js +0 -1
- data/docs/assets/styles.css +0 -347
- data/docs/assets/vue.min.css +0 -1
- data/docs/authorization_context.md +0 -92
- data/docs/behaviour.md +0 -113
- data/docs/caching.md +0 -273
- data/docs/controller_action_aliases.md +0 -109
- data/docs/custom_lookup_chain.md +0 -48
- data/docs/custom_policy.md +0 -53
- data/docs/debugging.md +0 -55
- data/docs/decorators.md +0 -27
- data/docs/favicon.ico +0 -0
- data/docs/graphql.md +0 -302
- data/docs/i18n.md +0 -44
- data/docs/index.html +0 -43
- data/docs/instrumentation.md +0 -84
- data/docs/lookup_chain.md +0 -17
- data/docs/namespaces.md +0 -77
- data/docs/non_rails.md +0 -28
- data/docs/pre_checks.md +0 -57
- data/docs/pundit_migration.md +0 -80
- data/docs/quick_start.md +0 -118
- data/docs/rails.md +0 -120
- data/docs/reasons.md +0 -120
- data/docs/scoping.md +0 -255
- data/docs/testing.md +0 -333
- data/docs/writing_policies.md +0 -107
- data/gemfiles/jruby.gemfile +0 -8
- data/gemfiles/rails42.gemfile +0 -8
- data/gemfiles/rails6.gemfile +0 -8
- data/gemfiles/railsmaster.gemfile +0 -6
- data/lib/action_policy/ext/string_match.rb +0 -14
- data/lib/action_policy/ext/yield_self_then.rb +0 -25
@@ -8,8 +8,11 @@ module ActionPolicy
|
|
8
8
|
using ActionPolicy::Ext::PolicyCacheKey
|
9
9
|
|
10
10
|
# Returns policy instance for the record.
|
11
|
-
def policy_for(record:, with: nil, namespace: authorization_namespace, context: authorization_context, allow_nil: false)
|
12
|
-
policy_class = with || ::ActionPolicy.lookup(
|
11
|
+
def policy_for(record:, with: nil, namespace: authorization_namespace, context: authorization_context, allow_nil: false, default: default_authorization_policy_class)
|
12
|
+
policy_class = with || ::ActionPolicy.lookup(
|
13
|
+
record,
|
14
|
+
**{namespace, context, allow_nil, default}
|
15
|
+
)
|
13
16
|
policy_class&.new(record, **context)
|
14
17
|
end
|
15
18
|
|
@@ -21,6 +24,10 @@ module ActionPolicy
|
|
21
24
|
# override to provide specific authorization namespace
|
22
25
|
end
|
23
26
|
|
27
|
+
def default_authorization_policy_class
|
28
|
+
# override to provide a policy class use when no policy found
|
29
|
+
end
|
30
|
+
|
24
31
|
# Override this method to provide implicit authorization target
|
25
32
|
# that would be used in case `record` is not specified in
|
26
33
|
# `authorize!` and `allowed_to?` call.
|
@@ -46,7 +53,7 @@ module ActionPolicy
|
|
46
53
|
|
47
54
|
def policy_for_cache_key(record:, with: nil, namespace: nil, context: authorization_context, **)
|
48
55
|
record_key = record._policy_cache_key(use_object_id: true)
|
49
|
-
context_key = context.values.map {
|
56
|
+
context_key = context.values.map { _1._policy_cache_key(use_object_id: true) }.join(".")
|
50
57
|
|
51
58
|
"#{namespace}/#{with}/#{context_key}/#{record_key}"
|
52
59
|
end
|
@@ -17,8 +17,9 @@ module ActionPolicy
|
|
17
17
|
policy ||= policy_for(record: implicit_authorization_target!, **options)
|
18
18
|
|
19
19
|
type ||= authorization_scope_type_for(policy, target)
|
20
|
+
name = as
|
20
21
|
|
21
|
-
Authorizer.scopify(target, policy, type
|
22
|
+
Authorizer.scopify(target, policy, **{type, name, scope_options})
|
22
23
|
end
|
23
24
|
|
24
25
|
# For backward compatibility
|
@@ -9,11 +9,6 @@ module ActionPolicy
|
|
9
9
|
using ActionPolicy::Ext::StringConstantize
|
10
10
|
end
|
11
11
|
|
12
|
-
unless "".respond_to?(:match?)
|
13
|
-
require "action_policy/ext/string_match"
|
14
|
-
using ActionPolicy::Ext::StringMatch
|
15
|
-
end
|
16
|
-
|
17
12
|
module Ext
|
18
13
|
def namespace
|
19
14
|
return unless name&.match?(/[^^]::/)
|
@@ -23,7 +18,7 @@ module ActionPolicy
|
|
23
18
|
end
|
24
19
|
|
25
20
|
# See https://github.com/jruby/jruby/issues/5220
|
26
|
-
::Module.include(Ext) if RUBY_PLATFORM
|
21
|
+
::Module.include(Ext) if RUBY_PLATFORM.match?(/java/i)
|
27
22
|
|
28
23
|
refine Module do
|
29
24
|
include Ext
|
@@ -13,77 +13,59 @@ module ActionPolicy
|
|
13
13
|
module ObjectExt
|
14
14
|
def _policy_cache_key(use_object_id: false)
|
15
15
|
return policy_cache_key if respond_to?(:policy_cache_key)
|
16
|
+
return cache_key_with_version if respond_to?(:cache_key_with_version)
|
16
17
|
return cache_key if respond_to?(:cache_key)
|
17
18
|
|
18
|
-
return object_id if use_object_id == true
|
19
|
+
return object_id.to_s if use_object_id == true
|
19
20
|
|
20
21
|
raise ArgumentError, "object is not cacheable"
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
|
-
# JRuby doesn't support _global_ modules refinements (see https://github.com/jruby/jruby/issues/5220)
|
25
|
-
# Fallback to monkey-patching.
|
26
|
-
# TODO: remove after 9.2.7.0 (See https://github.com/jruby/jruby/pull/5627)
|
27
|
-
::Object.include(ObjectExt) if RUBY_PLATFORM =~ /java/i
|
28
|
-
|
29
25
|
refine Object do
|
30
26
|
include ObjectExt
|
31
27
|
end
|
32
28
|
|
33
29
|
refine NilClass do
|
34
|
-
def _policy_cache_key(*)
|
35
|
-
""
|
36
|
-
end
|
30
|
+
def _policy_cache_key(*) = ""
|
37
31
|
end
|
38
32
|
|
39
33
|
refine TrueClass do
|
40
|
-
def _policy_cache_key(*)
|
41
|
-
"t"
|
42
|
-
end
|
34
|
+
def _policy_cache_key(*) = "t"
|
43
35
|
end
|
44
36
|
|
45
37
|
refine FalseClass do
|
46
|
-
def _policy_cache_key(*)
|
47
|
-
"f"
|
48
|
-
end
|
38
|
+
def _policy_cache_key(*) = "f"
|
49
39
|
end
|
50
40
|
|
51
41
|
refine String do
|
52
|
-
def _policy_cache_key(*)
|
53
|
-
self
|
54
|
-
end
|
42
|
+
def _policy_cache_key(*) = self
|
55
43
|
end
|
56
44
|
|
57
45
|
refine Symbol do
|
58
|
-
def _policy_cache_key(*)
|
59
|
-
to_s
|
60
|
-
end
|
46
|
+
def _policy_cache_key(*) = to_s
|
61
47
|
end
|
62
48
|
|
63
49
|
if RUBY_PLATFORM.match?(/java/i)
|
64
50
|
refine Integer do
|
65
|
-
def _policy_cache_key(*)
|
66
|
-
to_s
|
67
|
-
end
|
51
|
+
def _policy_cache_key(*) = to_s
|
68
52
|
end
|
69
53
|
|
70
54
|
refine Float do
|
71
|
-
def _policy_cache_key(*)
|
72
|
-
to_s
|
73
|
-
end
|
55
|
+
def _policy_cache_key(*) = to_s
|
74
56
|
end
|
75
57
|
else
|
76
58
|
refine Numeric do
|
77
|
-
def _policy_cache_key(*)
|
78
|
-
to_s
|
79
|
-
end
|
59
|
+
def _policy_cache_key(*) = to_s
|
80
60
|
end
|
81
61
|
end
|
82
62
|
|
83
63
|
refine Time do
|
84
|
-
def _policy_cache_key(*)
|
85
|
-
|
86
|
-
|
64
|
+
def _policy_cache_key(*) = to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
refine Module do
|
68
|
+
def _policy_cache_key(*) = name
|
87
69
|
end
|
88
70
|
end
|
89
71
|
end
|
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
module ActionPolicy
|
4
4
|
module Ext
|
5
|
-
# Add `
|
6
|
-
module
|
5
|
+
# Add `camelize` to Symbol
|
6
|
+
module SymbolCamelize
|
7
7
|
refine Symbol do
|
8
|
-
if "".respond_to?(:
|
9
|
-
def
|
10
|
-
to_s.
|
8
|
+
if "".respond_to?(:camelize)
|
9
|
+
def camelize
|
10
|
+
to_s.camelize
|
11
11
|
end
|
12
12
|
else
|
13
|
-
def
|
13
|
+
def camelize
|
14
14
|
word = to_s.capitalize
|
15
15
|
word.gsub!(/(?:_)([a-z\d]*)/) { $1.capitalize }
|
16
16
|
word
|
data/lib/action_policy/i18n.rb
CHANGED
@@ -21,7 +21,7 @@ module ActionPolicy
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def candidates_for(policy_class, rule)
|
24
|
-
policy_hierarchy = policy_class.ancestors.select {
|
24
|
+
policy_hierarchy = policy_class.ancestors.select { _1.respond_to?(:identifier) }
|
25
25
|
[
|
26
26
|
*policy_hierarchy.map { |klass| :"policy.#{klass.identifier}.#{rule}" },
|
27
27
|
:"policy.#{rule}",
|
@@ -12,8 +12,8 @@ module ActionPolicy
|
|
12
12
|
using ActionPolicy::Ext::StringConstantize
|
13
13
|
end
|
14
14
|
|
15
|
-
require "action_policy/ext/
|
16
|
-
using ActionPolicy::Ext::
|
15
|
+
require "action_policy/ext/symbol_camelize"
|
16
|
+
using ActionPolicy::Ext::SymbolCamelize
|
17
17
|
|
18
18
|
require "action_policy/ext/module_namespace"
|
19
19
|
using ActionPolicy::Ext::ModuleNamespace
|
@@ -24,14 +24,26 @@ module ActionPolicy
|
|
24
24
|
class << self
|
25
25
|
attr_reader :store
|
26
26
|
|
27
|
-
def
|
27
|
+
def put_if_absent(scope, namespace, policy)
|
28
|
+
local_store = store[scope][namespace]
|
29
|
+
return local_store[policy] if local_store[policy]
|
30
|
+
local_store[policy] ||= yield
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch(namespace, policy, strict:, &block)
|
28
34
|
return yield unless LookupChain.namespace_cache_enabled?
|
29
|
-
|
30
|
-
|
35
|
+
|
36
|
+
if strict
|
37
|
+
put_if_absent(:strict, namespace, policy, &block)
|
38
|
+
else
|
39
|
+
cached_policy = put_if_absent(:strict, namespace, policy, &block)
|
40
|
+
put_if_absent(:flexible, namespace, policy) { cached_policy }
|
41
|
+
end
|
31
42
|
end
|
32
43
|
|
33
44
|
def clear
|
34
|
-
|
45
|
+
hash = Hash.new { |h, k| h[k] = {} }
|
46
|
+
@store = {strict: hash, flexible: hash.clone}
|
35
47
|
end
|
36
48
|
end
|
37
49
|
|
@@ -53,22 +65,23 @@ module ActionPolicy
|
|
53
65
|
|
54
66
|
private
|
55
67
|
|
56
|
-
def lookup_within_namespace(policy_name, namespace)
|
57
|
-
|
68
|
+
def lookup_within_namespace(policy_name, namespace, strict: false)
|
69
|
+
return unless namespace
|
70
|
+
NamespaceCache.fetch(namespace.name, policy_name, strict: strict) do
|
58
71
|
mod = namespace
|
59
|
-
|
60
72
|
loop do
|
61
73
|
policy = "#{mod.name}::#{policy_name}".safe_constantize
|
62
|
-
|
63
74
|
break policy unless policy.nil?
|
64
|
-
|
65
75
|
mod = mod.namespace
|
66
|
-
|
67
|
-
break if mod.nil?
|
76
|
+
break if mod.nil? || strict
|
68
77
|
end
|
69
78
|
end
|
70
79
|
end
|
71
80
|
|
81
|
+
def objectify_policy(policy_name, strict: false)
|
82
|
+
policy_name.safe_constantize unless strict
|
83
|
+
end
|
84
|
+
|
72
85
|
def policy_class_name_for(record)
|
73
86
|
return record.policy_name.to_s if record.respond_to?(:policy_name)
|
74
87
|
|
@@ -111,23 +124,30 @@ module ActionPolicy
|
|
111
124
|
}
|
112
125
|
|
113
126
|
# Infer from passed symbol
|
114
|
-
SYMBOL_LOOKUP = ->(record, namespace: nil, **) {
|
127
|
+
SYMBOL_LOOKUP = ->(record, namespace: nil, strict_namespace: false, **) {
|
115
128
|
next unless record.is_a?(Symbol)
|
116
129
|
|
117
|
-
policy_name = "#{record.
|
118
|
-
|
119
|
-
policy_name
|
120
|
-
|
121
|
-
|
122
|
-
|
130
|
+
policy_name = "#{record.camelize}Policy"
|
131
|
+
lookup_within_namespace(policy_name, namespace, strict: strict_namespace) ||
|
132
|
+
objectify_policy(policy_name, strict: strict_namespace)
|
133
|
+
}
|
134
|
+
|
135
|
+
# (Optional) Infer using String#classify if available
|
136
|
+
CLASSIFY_SYMBOL_LOOKUP = ->(record, namespace: nil, strict_namespace: false, **) {
|
137
|
+
next unless record.is_a?(Symbol)
|
138
|
+
|
139
|
+
policy_name = "#{record.to_s.classify}Policy"
|
140
|
+
lookup_within_namespace(policy_name, namespace, strict: strict_namespace) ||
|
141
|
+
objectify_policy(policy_name, strict: strict_namespace)
|
123
142
|
}
|
124
143
|
|
125
144
|
self.chain = [
|
126
145
|
SYMBOL_LOOKUP,
|
146
|
+
(CLASSIFY_SYMBOL_LOOKUP if String.method_defined?(:classify)),
|
127
147
|
INSTANCE_POLICY_CLASS,
|
128
148
|
CLASS_POLICY_CLASS,
|
129
149
|
NAMESPACE_LOOKUP,
|
130
150
|
INFER_FROM_CLASS
|
131
|
-
]
|
151
|
+
].compact
|
132
152
|
end
|
133
153
|
end
|
@@ -46,23 +46,18 @@ module ActionPolicy
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
def lookup_alias(rule)
|
50
|
-
rules_aliases[rule]
|
51
|
-
end
|
49
|
+
def lookup_alias(rule) = rules_aliases[rule]
|
52
50
|
|
53
|
-
def lookup_default_rule
|
54
|
-
rules_aliases[DEFAULT]
|
55
|
-
end
|
51
|
+
def lookup_default_rule() = rules_aliases[DEFAULT]
|
56
52
|
|
57
53
|
def rules_aliases
|
58
54
|
return @rules_aliases if instance_variable_defined?(:@rules_aliases)
|
59
55
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
56
|
+
if superclass.respond_to?(:rules_aliases)
|
57
|
+
superclass.rules_aliases.dup
|
58
|
+
else
|
59
|
+
{}
|
60
|
+
end => @rules_aliases
|
66
61
|
end
|
67
62
|
|
68
63
|
def method_added(name)
|
@@ -43,21 +43,17 @@ module ActionPolicy
|
|
43
43
|
|
44
44
|
attr_reader :authorization_context
|
45
45
|
|
46
|
-
def initialize(
|
47
|
-
super(
|
46
|
+
def initialize(record = nil, **params)
|
47
|
+
super(record)
|
48
48
|
|
49
49
|
@authorization_context = {}
|
50
50
|
|
51
51
|
self.class.authorization_targets.each do |id, opts|
|
52
|
-
|
53
|
-
val = params.fetch(id, nil)
|
54
|
-
else
|
55
|
-
raise AuthorizationContextMissing, id unless params.key?(id)
|
52
|
+
raise AuthorizationContextMissing, id unless params.key?(id) || opts[:optional]
|
56
53
|
|
57
|
-
|
54
|
+
val = params.fetch(id, nil)
|
58
55
|
|
59
|
-
|
60
|
-
end
|
56
|
+
raise AuthorizationContextMissing, id if val.nil? && opts[:allow_nil] != true
|
61
57
|
|
62
58
|
authorization_context[id] = instance_variable_set("@#{id}", val)
|
63
59
|
end
|
@@ -66,9 +62,11 @@ module ActionPolicy
|
|
66
62
|
end
|
67
63
|
|
68
64
|
module ClassMethods # :nodoc:
|
69
|
-
def authorize(*ids,
|
65
|
+
def authorize(*ids, allow_nil: false, optional: false)
|
66
|
+
allow_nil ||= optional
|
67
|
+
|
70
68
|
ids.each do |id|
|
71
|
-
authorization_targets[id] =
|
69
|
+
authorization_targets[id] = {allow_nil, optional}
|
72
70
|
end
|
73
71
|
|
74
72
|
attr_reader(*ids)
|
@@ -77,12 +75,11 @@ module ActionPolicy
|
|
77
75
|
def authorization_targets
|
78
76
|
return @authorization_targets if instance_variable_defined?(:@authorization_targets)
|
79
77
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
78
|
+
if superclass.respond_to?(:authorization_targets)
|
79
|
+
superclass.authorization_targets.dup
|
80
|
+
else
|
81
|
+
{}
|
82
|
+
end => @authorization_targets
|
86
83
|
end
|
87
84
|
end
|
88
85
|
end
|
@@ -3,16 +3,13 @@
|
|
3
3
|
require "action_policy/version"
|
4
4
|
|
5
5
|
module ActionPolicy # :nodoc:
|
6
|
+
using RubyNext
|
7
|
+
|
6
8
|
# By default cache namespace (or prefix) contains major and minor version of the gem
|
7
9
|
CACHE_NAMESPACE = "acp:#{ActionPolicy::VERSION.split(".").take(2).join(".")}"
|
8
10
|
|
9
|
-
require "action_policy/ext/yield_self_then"
|
10
11
|
require "action_policy/ext/policy_cache_key"
|
11
12
|
|
12
|
-
unless "".respond_to?(:then)
|
13
|
-
require "action_policy/ext/yield_self_then"
|
14
|
-
using ActionPolicy::Ext::YieldSelfThen
|
15
|
-
end
|
16
13
|
using ActionPolicy::Ext::PolicyCacheKey
|
17
14
|
|
18
15
|
module Policy
|
@@ -26,22 +23,31 @@ module ActionPolicy # :nodoc:
|
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
|
-
def cache_namespace
|
30
|
-
|
26
|
+
def cache_namespace() = ActionPolicy::CACHE_NAMESPACE
|
27
|
+
|
28
|
+
def cache_key(*parts)
|
29
|
+
[
|
30
|
+
cache_namespace,
|
31
|
+
*parts
|
32
|
+
].map { _1._policy_cache_key }.join("/")
|
31
33
|
end
|
32
34
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
35
|
+
def rule_cache_key(rule)
|
36
|
+
cache_key(
|
37
|
+
context_cache_key,
|
38
|
+
record,
|
39
|
+
self.class,
|
40
|
+
rule
|
41
|
+
)
|
36
42
|
end
|
37
43
|
|
38
44
|
def context_cache_key
|
39
|
-
authorization_context.map {
|
45
|
+
authorization_context.map { _2._policy_cache_key.to_s }.join("/")
|
40
46
|
end
|
41
47
|
|
42
48
|
def apply_with_cache(rule)
|
43
49
|
options = self.class.cached_rules.fetch(rule)
|
44
|
-
key =
|
50
|
+
key = rule_cache_key(rule)
|
45
51
|
|
46
52
|
ActionPolicy.cache_store.then do |store|
|
47
53
|
@result = store.read(key)
|
@@ -62,6 +68,17 @@ module ActionPolicy # :nodoc:
|
|
62
68
|
apply_with_cache(rule) { super }
|
63
69
|
end
|
64
70
|
|
71
|
+
def cache(*parts, **options)
|
72
|
+
key = cache_key(*parts)
|
73
|
+
ActionPolicy.cache_store.then do |store|
|
74
|
+
res = store.read(key)
|
75
|
+
next res unless res.nil?
|
76
|
+
res = yield
|
77
|
+
store.write(key, res, options)
|
78
|
+
res
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
65
82
|
module ClassMethods # :nodoc:
|
66
83
|
def cache(*rules, **options)
|
67
84
|
rules.each do |rule|
|
@@ -72,12 +89,11 @@ module ActionPolicy # :nodoc:
|
|
72
89
|
def cached_rules
|
73
90
|
return @cached_rules if instance_variable_defined?(:@cached_rules)
|
74
91
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
92
|
+
if superclass.respond_to?(:cached_rules)
|
93
|
+
superclass.cached_rules.dup
|
94
|
+
else
|
95
|
+
{}
|
96
|
+
end => @cached_rules
|
81
97
|
end
|
82
98
|
end
|
83
99
|
end
|