action_policy 0.4.4 → 0.5.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/CHANGELOG.md +203 -174
- data/README.md +5 -4
- 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 +10 -30
- data/lib/action_policy/i18n.rb +1 -1
- data/lib/action_policy/lookup_chain.rb +29 -15
- data/lib/action_policy/policy/aliases.rb +7 -12
- data/lib/action_policy/policy/authorization.rb +8 -7
- data/lib/action_policy/policy/cache.rb +11 -17
- 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 +29 -19
- data/lib/action_policy/policy/scoping.rb +5 -6
- data/lib/action_policy/rails/controller.rb +6 -1
- 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 +1 -1
- 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} +0 -0
- 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 +29 -119
- data/.gitattributes +0 -2
- data/.github/ISSUE_TEMPLATE.md +0 -21
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -29
- data/.github/bug_report_template.rb +0 -175
- 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 -74
- data/benchmarks/pre_checks.rb +0 -73
- 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 -79
- 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 -291
- 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 -22
- 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 -390
- data/docs/writing_policies.md +0 -107
- data/gemfiles/jruby.gemfile +0 -8
- data/gemfiles/rails42.gemfile +0 -9
- 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
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
[](https://badge.fury.io/rb/action_policy)
|
2
|
-
|
2
|
+

|
3
|
+

|
3
4
|
[](https://actionpolicy.evilmartians.io)
|
4
5
|
|
5
6
|
# Action Policy
|
@@ -21,7 +22,6 @@ Composable. Extensible. Performant.
|
|
21
22
|
|
22
23
|
- RailsConf, 2018 "Access Denied" talk ([video](https://www.youtube.com/watch?v=NVwx0DARDis), [slides](https://speakerdeck.com/palkan/railsconf-2018-access-denied-the-missing-guide-to-authorization-in-rails))
|
23
24
|
|
24
|
-
|
25
25
|
## Integrations
|
26
26
|
|
27
27
|
- GraphQL Ruby ([`action_policy-graphql`](https://github.com/palkan/action_policy-graphql))
|
@@ -36,7 +36,9 @@ gem "action_policy", "~> 0.4.0"
|
|
36
36
|
|
37
37
|
And then execute:
|
38
38
|
|
39
|
-
|
39
|
+
```sh
|
40
|
+
bundle install
|
41
|
+
```
|
40
42
|
|
41
43
|
## Usage
|
42
44
|
|
@@ -89,7 +91,6 @@ end
|
|
89
91
|
|
90
92
|
\* See [Non-Rails Usage](docs/non_rails.md) on how to add `authorize!` to any Ruby project.
|
91
93
|
|
92
|
-
|
93
94
|
When authorization is successful (i.e., the corresponding rule returns `true`), nothing happens, but in case of authorization failure `ActionPolicy::Unauthorized` error is raised.
|
94
95
|
|
95
96
|
There is also an `allowed_to?` method which returns `true` or `false`, and could be used, in views, for example:
|
data/lib/action_policy.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "ruby-next"
|
4
|
+
|
5
|
+
require "ruby-next/language/setup"
|
6
|
+
RubyNext::Language.setup_gem_load_path(transpile: true)
|
7
|
+
|
3
8
|
# ActionPolicy is an authorization framework for Ruby/Rails applications.
|
4
9
|
#
|
5
10
|
# It provides a way to write access policies and helpers to check these policies
|
@@ -30,8 +35,9 @@ module ActionPolicy
|
|
30
35
|
attr_accessor :cache_store
|
31
36
|
|
32
37
|
# Find a policy class for a target
|
33
|
-
def lookup(target, allow_nil: false, **options)
|
38
|
+
def lookup(target, allow_nil: false, default: nil, **options)
|
34
39
|
LookupChain.call(target, **options) ||
|
40
|
+
default ||
|
35
41
|
(allow_nil ? nil : raise(NotFound, target))
|
36
42
|
end
|
37
43
|
end
|
@@ -35,12 +35,7 @@ module ActionPolicy
|
|
35
35
|
#
|
36
36
|
# Raises `ActionPolicy::Unauthorized` if check failed.
|
37
37
|
def authorize!(record = :__undef__, to:, **options)
|
38
|
-
|
39
|
-
raise ArgumentError, "Record must be specified" if record.nil?
|
40
|
-
|
41
|
-
options[:context] && (options[:context] = authorization_context.merge(options[:context]))
|
42
|
-
|
43
|
-
policy = policy_for(record: record, **options)
|
38
|
+
policy = lookup_authorization_policy(record, **options)
|
44
39
|
|
45
40
|
Authorizer.call(policy, authorization_rule_for(policy, to))
|
46
41
|
end
|
@@ -49,14 +44,17 @@ module ActionPolicy
|
|
49
44
|
#
|
50
45
|
# Returns true of false.
|
51
46
|
def allowed_to?(rule, record = :__undef__, **options)
|
52
|
-
|
53
|
-
raise ArgumentError, "Record must be specified" if record.nil?
|
47
|
+
policy = lookup_authorization_policy(record, **options)
|
54
48
|
|
55
|
-
|
49
|
+
policy.apply(authorization_rule_for(policy, rule))
|
50
|
+
end
|
56
51
|
|
57
|
-
|
52
|
+
# Returns the authorization result object after applying a specified rule to a record.
|
53
|
+
def allowance_to(rule, record = :__undef__, **options)
|
54
|
+
policy = lookup_authorization_policy(record, **options)
|
58
55
|
|
59
56
|
policy.apply(authorization_rule_for(policy, rule))
|
57
|
+
policy.result
|
60
58
|
end
|
61
59
|
|
62
60
|
def authorization_context
|
@@ -75,6 +73,15 @@ module ActionPolicy
|
|
75
73
|
policy.resolve_rule(rule)
|
76
74
|
end
|
77
75
|
|
76
|
+
def lookup_authorization_policy(record, **options) # :nodoc:
|
77
|
+
record = implicit_authorization_target! if record == :__undef__
|
78
|
+
raise ArgumentError, "Record must be specified" if record.nil?
|
79
|
+
|
80
|
+
options[:context] && (options[:context] = authorization_context.merge(options[:context]))
|
81
|
+
|
82
|
+
policy_for(record: record, **options)
|
83
|
+
end
|
84
|
+
|
78
85
|
module ClassMethods # :nodoc:
|
79
86
|
# Configure authorization context.
|
80
87
|
#
|
@@ -97,12 +104,11 @@ module ActionPolicy
|
|
97
104
|
def authorization_targets
|
98
105
|
return @authorization_targets if instance_variable_defined?(:@authorization_targets)
|
99
106
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
107
|
+
if superclass.respond_to?(:authorization_targets)
|
108
|
+
superclass.authorization_targets.dup
|
109
|
+
else
|
110
|
+
{}
|
111
|
+
end => @authorization_targets
|
106
112
|
end
|
107
113
|
end
|
108
114
|
end
|
@@ -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
|
@@ -27,65 +27,45 @@ module ActionPolicy
|
|
27
27
|
end
|
28
28
|
|
29
29
|
refine NilClass do
|
30
|
-
def _policy_cache_key(*)
|
31
|
-
""
|
32
|
-
end
|
30
|
+
def _policy_cache_key(*) = ""
|
33
31
|
end
|
34
32
|
|
35
33
|
refine TrueClass do
|
36
|
-
def _policy_cache_key(*)
|
37
|
-
"t"
|
38
|
-
end
|
34
|
+
def _policy_cache_key(*) = "t"
|
39
35
|
end
|
40
36
|
|
41
37
|
refine FalseClass do
|
42
|
-
def _policy_cache_key(*)
|
43
|
-
"f"
|
44
|
-
end
|
38
|
+
def _policy_cache_key(*) = "f"
|
45
39
|
end
|
46
40
|
|
47
41
|
refine String do
|
48
|
-
def _policy_cache_key(*)
|
49
|
-
self
|
50
|
-
end
|
42
|
+
def _policy_cache_key(*) = self
|
51
43
|
end
|
52
44
|
|
53
45
|
refine Symbol do
|
54
|
-
def _policy_cache_key(*)
|
55
|
-
to_s
|
56
|
-
end
|
46
|
+
def _policy_cache_key(*) = to_s
|
57
47
|
end
|
58
48
|
|
59
49
|
if RUBY_PLATFORM.match?(/java/i)
|
60
50
|
refine Integer do
|
61
|
-
def _policy_cache_key(*)
|
62
|
-
to_s
|
63
|
-
end
|
51
|
+
def _policy_cache_key(*) = to_s
|
64
52
|
end
|
65
53
|
|
66
54
|
refine Float do
|
67
|
-
def _policy_cache_key(*)
|
68
|
-
to_s
|
69
|
-
end
|
55
|
+
def _policy_cache_key(*) = to_s
|
70
56
|
end
|
71
57
|
else
|
72
58
|
refine Numeric do
|
73
|
-
def _policy_cache_key(*)
|
74
|
-
to_s
|
75
|
-
end
|
59
|
+
def _policy_cache_key(*) = to_s
|
76
60
|
end
|
77
61
|
end
|
78
62
|
|
79
63
|
refine Time do
|
80
|
-
def _policy_cache_key(*)
|
81
|
-
to_s
|
82
|
-
end
|
64
|
+
def _policy_cache_key(*) = to_s
|
83
65
|
end
|
84
66
|
|
85
67
|
refine Module do
|
86
|
-
def _policy_cache_key(*)
|
87
|
-
name
|
88
|
-
end
|
68
|
+
def _policy_cache_key(*) = name
|
89
69
|
end
|
90
70
|
end
|
91
71
|
end
|
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}",
|
@@ -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,23 +65,23 @@ module ActionPolicy
|
|
53
65
|
|
54
66
|
private
|
55
67
|
|
56
|
-
def lookup_within_namespace(policy_name, namespace)
|
68
|
+
def lookup_within_namespace(policy_name, namespace, strict: false)
|
57
69
|
return unless namespace
|
58
|
-
NamespaceCache.fetch(namespace.name, policy_name) do
|
70
|
+
NamespaceCache.fetch(namespace.name, policy_name, strict: strict) do
|
59
71
|
mod = namespace
|
60
|
-
|
61
72
|
loop do
|
62
73
|
policy = "#{mod.name}::#{policy_name}".safe_constantize
|
63
|
-
|
64
74
|
break policy unless policy.nil?
|
65
|
-
|
66
75
|
mod = mod.namespace
|
67
|
-
|
68
|
-
break if mod.nil?
|
76
|
+
break if mod.nil? || strict
|
69
77
|
end
|
70
78
|
end
|
71
79
|
end
|
72
80
|
|
81
|
+
def objectify_policy(policy_name, strict: false)
|
82
|
+
policy_name.safe_constantize unless strict
|
83
|
+
end
|
84
|
+
|
73
85
|
def policy_class_name_for(record)
|
74
86
|
return record.policy_name.to_s if record.respond_to?(:policy_name)
|
75
87
|
|
@@ -112,19 +124,21 @@ module ActionPolicy
|
|
112
124
|
}
|
113
125
|
|
114
126
|
# Infer from passed symbol
|
115
|
-
SYMBOL_LOOKUP = ->(record, namespace: nil, **) {
|
127
|
+
SYMBOL_LOOKUP = ->(record, namespace: nil, strict_namespace: false, **) {
|
116
128
|
next unless record.is_a?(Symbol)
|
117
129
|
|
118
130
|
policy_name = "#{record.camelize}Policy"
|
119
|
-
lookup_within_namespace(policy_name, namespace) ||
|
131
|
+
lookup_within_namespace(policy_name, namespace, strict: strict_namespace) ||
|
132
|
+
objectify_policy(policy_name, strict: strict_namespace)
|
120
133
|
}
|
121
134
|
|
122
135
|
# (Optional) Infer using String#classify if available
|
123
|
-
CLASSIFY_SYMBOL_LOOKUP = ->(record, namespace: nil, **) {
|
136
|
+
CLASSIFY_SYMBOL_LOOKUP = ->(record, namespace: nil, strict_namespace: false, **) {
|
124
137
|
next unless record.is_a?(Symbol)
|
125
138
|
|
126
139
|
policy_name = "#{record.to_s.classify}Policy"
|
127
|
-
lookup_within_namespace(policy_name, namespace) ||
|
140
|
+
lookup_within_namespace(policy_name, namespace, strict: strict_namespace) ||
|
141
|
+
objectify_policy(policy_name, strict: strict_namespace)
|
128
142
|
}
|
129
143
|
|
130
144
|
self.chain = [
|
@@ -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)
|
@@ -63,8 +63,10 @@ module ActionPolicy
|
|
63
63
|
|
64
64
|
module ClassMethods # :nodoc:
|
65
65
|
def authorize(*ids, allow_nil: false, optional: false)
|
66
|
+
allow_nil ||= optional
|
67
|
+
|
66
68
|
ids.each do |id|
|
67
|
-
authorization_targets[id] = {allow_nil
|
69
|
+
authorization_targets[id] = {allow_nil, optional}
|
68
70
|
end
|
69
71
|
|
70
72
|
attr_reader(*ids)
|
@@ -73,12 +75,11 @@ module ActionPolicy
|
|
73
75
|
def authorization_targets
|
74
76
|
return @authorization_targets if instance_variable_defined?(:@authorization_targets)
|
75
77
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
78
|
+
if superclass.respond_to?(:authorization_targets)
|
79
|
+
superclass.authorization_targets.dup
|
80
|
+
else
|
81
|
+
{}
|
82
|
+
end => @authorization_targets
|
82
83
|
end
|
83
84
|
end
|
84
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,15 +23,13 @@ module ActionPolicy # :nodoc:
|
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
|
-
def cache_namespace
|
30
|
-
ActionPolicy::CACHE_NAMESPACE
|
31
|
-
end
|
26
|
+
def cache_namespace() = ActionPolicy::CACHE_NAMESPACE
|
32
27
|
|
33
28
|
def cache_key(*parts)
|
34
29
|
[
|
35
30
|
cache_namespace,
|
36
31
|
*parts
|
37
|
-
].map {
|
32
|
+
].map { _1._policy_cache_key }.join("/")
|
38
33
|
end
|
39
34
|
|
40
35
|
def rule_cache_key(rule)
|
@@ -47,7 +42,7 @@ module ActionPolicy # :nodoc:
|
|
47
42
|
end
|
48
43
|
|
49
44
|
def context_cache_key
|
50
|
-
authorization_context.map {
|
45
|
+
authorization_context.map { _2._policy_cache_key.to_s }.join("/")
|
51
46
|
end
|
52
47
|
|
53
48
|
def apply_with_cache(rule)
|
@@ -79,7 +74,7 @@ module ActionPolicy # :nodoc:
|
|
79
74
|
res = store.read(key)
|
80
75
|
next res unless res.nil?
|
81
76
|
res = yield
|
82
|
-
store.write(key, res,
|
77
|
+
store.write(key, res, options)
|
83
78
|
res
|
84
79
|
end
|
85
80
|
end
|
@@ -94,12 +89,11 @@ module ActionPolicy # :nodoc:
|
|
94
89
|
def cached_rules
|
95
90
|
return @cached_rules if instance_variable_defined?(:@cached_rules)
|
96
91
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
92
|
+
if superclass.respond_to?(:cached_rules)
|
93
|
+
superclass.cached_rules.dup
|
94
|
+
else
|
95
|
+
{}
|
96
|
+
end => @cached_rules
|
103
97
|
end
|
104
98
|
end
|
105
99
|
end
|