action_policy 0.4.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/action_policy.svg)](https://badge.fury.io/rb/action_policy)
|
2
|
-
|
2
|
+
![Build](https://github.com/palkan/action_policy/workflows/Build/badge.svg)
|
3
|
+
![JRuby Build](https://github.com/palkan/action_policy/workflows/JRuby%20Build/badge.svg)
|
3
4
|
[![Documentation](https://img.shields.io/badge/docs-link-brightgreen.svg)](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
|