u-authorization 1.4.0 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2d0d221c7afbf5307e6de989945f359e72432ecdff115f4da85a6d51df147f5
4
- data.tar.gz: 595029aef79e60b483373a3b7ad4eef586bc90944bc8533a1640575bccbe42c7
3
+ metadata.gz: 49ee3c29a92d117c33706e12939a2ced02597514586ae7cf06fe73622d15897f
4
+ data.tar.gz: b1991fa714603aa32a6288447796460287adcd6220a8485d6e82d6040c4e48cf
5
5
  SHA512:
6
- metadata.gz: b8c8d6e819e296f085c045af9c476941c9d3b2faf9269eb7ee7394321908257a1586b267c75dccb6a4b8d75c112ec35b31c3af26722c48dec2a6e99f77e74f05
7
- data.tar.gz: ef58ac9c0ff6b4aa1ed2ccf75fb67af13b9891e886f33a65a44bd64715ccbd49586adf2f9e12553fb17ec70374af5433aef69dccbcea1788a405a9c8ff41b080
6
+ metadata.gz: d480100a329ab41e4707cb124f46d85af1750fc35ee08e615b1cc488714cb8e817394b8b91acf6c965710faf7235a90c13827cf7369c920e974e39d77ad6446b
7
+ data.tar.gz: d427583d3e8c633138e018d2f2d5c339a615976622a6b224d1e0e370634cc09f08bc5ceb158caff480b9fabaa588aed85340282c58a44ca8bf509d857e181860
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'simplecov', require: false, group: :test
4
+
5
+ gem 'minitest', '~> 5.11', '>= 5.11.3'
6
+
7
+ # Specify your gem's dependencies in u-authorization.gemspec
8
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,29 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ u-authorization (1.4.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ docile (1.3.2)
10
+ json (2.2.0)
11
+ minitest (5.11.3)
12
+ rake (10.5.0)
13
+ simplecov (0.17.0)
14
+ docile (~> 1.1)
15
+ json (>= 1.8, < 3)
16
+ simplecov-html (~> 0.10.0)
17
+ simplecov-html (0.10.2)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ minitest (~> 5.11, >= 5.11.3)
24
+ rake (~> 10.0)
25
+ simplecov
26
+ u-authorization!
27
+
28
+ BUNDLED WITH
29
+ 1.17.2
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # µ-authorization
2
+
3
+ Simple authorization library and role managment for Ruby.
4
+
5
+ ## Prerequisites
6
+
7
+ > Ruby >= 2.2.0
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+ ```
13
+ gem 'u-authorization'
14
+ ```
15
+
16
+ And then execute:
17
+ ```
18
+ $ bundle
19
+ ```
20
+
21
+ Or install it yourself as:
22
+ ```
23
+ $ gem install u-authorization
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ```ruby
29
+ require 'ostruct'
30
+ require 'authorization'
31
+
32
+ role = OpenStruct.new(
33
+ name: 'user',
34
+ permissions: {
35
+ 'visit' => { 'except' => ['billings'] },
36
+ 'edit_users' => false, # Same as: 'edit_users' => { 'any' => false },
37
+ 'export_as_csv' => { 'except' => ['sales'] }
38
+ }
39
+ )
40
+
41
+ user = OpenStruct.new(id: 1, role: role)
42
+
43
+ class SalesPolicy < Micro::Authorization::Policy
44
+ def edit?(record)
45
+ user.id == record.user_id
46
+ end
47
+ end
48
+
49
+ authorization = Micro::Authorization::Model.build(
50
+ permissions: user.role.permissions,
51
+ policies: { default: :sales, sales: SalesPolicy }
52
+ context: {
53
+ user: user,
54
+ permissions: ['dashboard', 'controllers', 'sales', 'index']
55
+ }
56
+ )
57
+
58
+ # Verifying the permissions for the given context
59
+ authorization.permissions.to?('visit') #=> true
60
+ authorization.permissions.to?('export_as_csv') #=> false
61
+
62
+ # Verifying permission for a given feature in different contexts
63
+ has_permission_to = authorization.permissions.to('export_as_csv')
64
+ has_permission_to.context?('billings') #=> true
65
+ has_permission_to.context?('sales') #=> false
66
+
67
+ charge = OpenStruct.new(id: 2, user_id: user.id)
68
+
69
+ # The #to() method fetch and build a policy.
70
+ authorization.to(:sales).edit?(charge) #=> true
71
+
72
+ # :default is the only permitted key to receive
73
+ # another symbol as value (a policy reference).
74
+ authorization.to(:default).edit?(charge) #=> true
75
+
76
+ # #policy() method has a similar behavior of #to(),
77
+ # but if there is a policy named as ":default", it will be fetched and instantiated by default.
78
+ authorization.policy.edit?(charge) #=> true
79
+ authorization.policy(:sales).edit?(charge) #=> true
80
+
81
+
82
+ # Cloning the authorization changing only its context.
83
+ new_authorization = authorization.map(context: [
84
+ 'dashboard', 'controllers', 'billings', 'index'
85
+ ])
86
+
87
+ new_authorization.permissions.to?('visit') #=> false
88
+
89
+ authorization == new_authorization #=> false
90
+ ```
91
+
92
+ ## Original implementation
93
+
94
+ https://gist.github.com/serradura/7d51b979b90609d8601d0f416a9aa373
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Authorization
5
+ class Model
6
+ attr_reader :context, :permissions
7
+
8
+ def self.build(permissions:, context:, policies: {})
9
+ permissions_model =
10
+ Permissions.new(permissions, context: context.delete(:permissions))
11
+
12
+ self.new(context, permissions: permissions_model, policies: policies)
13
+ end
14
+
15
+ def initialize(context, permissions:, policies: {})
16
+ @context = context
17
+ @policies = {}
18
+ @policies_cache = {}
19
+ @permissions = Permissions[permissions]
20
+
21
+ add_policies(policies)
22
+ end
23
+
24
+ def map(context: nil, policies: nil)
25
+ if context.nil? && policies.nil?
26
+ raise ArgumentError, 'context or policies keywords args must be defined'
27
+ end
28
+
29
+ permissions_context = context || permissions.context
30
+
31
+ new_permissions =
32
+ Permissions.new(permissions.role, context: permissions_context)
33
+
34
+ self.class.new(context, permissions: new_permissions,
35
+ policies: policies || @policies)
36
+ end
37
+
38
+ def add_policy(key, policy_klass)
39
+ raise ArgumentError, 'key must be a Symbol' unless key.is_a?(Symbol)
40
+
41
+ default_ref = key == :default && policy_klass.is_a?(Symbol)
42
+
43
+ @policies[key] ||= default_ref ? policy_klass : Policy.type(policy_klass)
44
+
45
+ self
46
+ end
47
+
48
+ def add_policies(new_policies)
49
+ unless new_policies.is_a?(Hash)
50
+ raise ArgumentError, "policies must be a Hash (key => #{Policy.name})"
51
+ end
52
+
53
+ new_policies.each(&method(:add_policy))
54
+
55
+ self
56
+ end
57
+
58
+ def to(policy_key, subject: nil)
59
+ policy_klass = fetch_policy(policy_key)
60
+
61
+ return policy_klass.new(context, subject, permissions: permissions) if subject
62
+
63
+ return @policies_cache[policy_key] if @policies_cache[policy_key]
64
+
65
+ policy_klass.new(context, permissions: permissions).tap do |instance|
66
+ @policies_cache[policy_key] = instance if policy_klass != Policy
67
+ end
68
+ end
69
+
70
+ def policy(key = :default, subject: nil)
71
+ to(key, subject: subject)
72
+ end
73
+
74
+ private
75
+
76
+ def fetch_policy(policy_key)
77
+ data = @policies[policy_key]
78
+ value = data || @policies.fetch(:default, Policy)
79
+ value.is_a?(Symbol) ? fetch_policy(value) : value
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,53 @@
1
+ module Micro
2
+ module Authorization
3
+ module Permissions
4
+ module CheckRole
5
+ extend self
6
+
7
+ def call(context, role_permissions, required_features)
8
+ required_features
9
+ .all? { |feature| has_permission?(context, role_permissions[feature]) }
10
+ end
11
+
12
+ private
13
+
14
+ def has_permission?(context, role_permission)
15
+ return false if role_permission.nil?
16
+
17
+ if role_permission == false || role_permission == true
18
+ role_permission
19
+ elsif !(any = role_permission['any']).nil?
20
+ any
21
+ elsif only = role_permission['only']
22
+ check_feature_permission(only, context)
23
+ elsif except = role_permission['except']
24
+ !check_feature_permission(except, context)
25
+ else
26
+ raise NotImplementedError
27
+ end
28
+ end
29
+
30
+ def check_feature_permission(context_values, context)
31
+ Utils.values_as_downcased_strings(context_values).any? do |context_value|
32
+ Array(context_value.split('.')).all? { |permission| context.include?(permission) }
33
+ end
34
+ end
35
+ end
36
+
37
+ private_constant :CheckRole
38
+
39
+ class Checker
40
+ attr_reader :required_features
41
+
42
+ def initialize(role, features)
43
+ @role = role
44
+ @required_features = Utils.values_as_downcased_strings(features)
45
+ end
46
+
47
+ def context?(context)
48
+ CheckRole.call(context, @role, @required_features)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,33 @@
1
+ module Micro
2
+ module Authorization
3
+ module Permissions
4
+ class Model
5
+ attr_reader :role, :context
6
+
7
+ def initialize(role_permissions, context:)
8
+ @role = role_permissions.dup.freeze
9
+ @cache = {}
10
+ @context = Utils.values_as_downcased_strings(context).freeze
11
+ end
12
+
13
+ def to(features)
14
+ Permissions::Checker.new(@role, features)
15
+ end
16
+
17
+ def to?(features = nil)
18
+ has_permission_to = to(features)
19
+
20
+ cache_key = has_permission_to.required_features.inspect
21
+
22
+ return @cache[cache_key] unless @cache[cache_key].nil?
23
+
24
+ @cache[cache_key] = has_permission_to.context?(@context)
25
+ end
26
+
27
+ def to_not?(features = nil)
28
+ !to?(features)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'micro/authorization/permissions/checker'
4
+ require 'micro/authorization/permissions/model'
5
+
6
+ module Micro
7
+ module Authorization
8
+ module Permissions
9
+ def self.[](instance)
10
+ return instance if instance.is_a?(Permissions::Model)
11
+
12
+ raise ArgumentError, "#{instance.inspect} must be a #{self.name}"
13
+ end
14
+
15
+ def self.new(role_permissions, context: [])
16
+ Permissions::Model.new(role_permissions, context: context)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Authorization
5
+ class Policy
6
+ def self.type(klass)
7
+ return klass if klass < self
8
+
9
+ raise ArgumentError, "policy must be a #{self.name}"
10
+ end
11
+
12
+ def initialize(context, subject = nil, permissions: nil)
13
+ @context = context
14
+ @subject = subject
15
+ @permissions = permissions
16
+ end
17
+
18
+ def method_missing(method, *args, **keyargs, &block)
19
+ return false if method =~ /\?\z/
20
+ super(method)
21
+ end
22
+
23
+ private
24
+
25
+ def permissions; @permissions; end
26
+ def context; @context; end
27
+ def subject; @subject; end
28
+ def user
29
+ @user ||=
30
+ context.is_a?(Hash) ? context[:user] || context[:current_user] : context
31
+ end
32
+ alias_method :current_user, :user
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Authorization
5
+ module Utils
6
+ def self.values_as_downcased_strings(values)
7
+ Array(values).map { |value| String(value).downcase }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Authorization
5
+ VERSION = '2.0.0'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'micro/authorization/version'
4
+ require 'micro/authorization/utils'
5
+ require 'micro/authorization/permissions'
6
+ require 'micro/authorization/policy'
7
+ require 'micro/authorization/model'
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'authorization'
3
+ require 'micro/authorization'
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'micro/authorization/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'u-authorization'
7
+ spec.version = Micro::Authorization::VERSION
8
+ spec.authors = ['Rodrigo Serradura']
9
+ spec.email = ['rodrigo.serradura@gmail.com']
10
+
11
+ spec.summary = 'Authorization library and role managment'
12
+ spec.description = 'Simple authorization library and role managment for Ruby.'
13
+ spec.homepage = 'https://github.com/serradura/u-authorization'
14
+ spec.license = 'MIT'
15
+
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.bindir = 'exe'
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.required_ruby_version = '>= 2.2.0'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ end
metadata CHANGED
@@ -1,44 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-authorization
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-07 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2019-07-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '10.0'
13
27
  description: Simple authorization library and role managment for Ruby.
14
- email: rodrigo.serradura@gmail.com
28
+ email:
29
+ - rodrigo.serradura@gmail.com
15
30
  executables: []
16
31
  extensions: []
17
32
  extra_rdoc_files: []
18
33
  files:
19
- - authorization.rb
20
- - u-authorization.rb
21
- homepage: https://gist.github.com/serradura/7d51b979b90609d8601d0f416a9aa373
34
+ - ".gitignore"
35
+ - Gemfile
36
+ - Gemfile.lock
37
+ - README.md
38
+ - Rakefile
39
+ - lib/micro/authorization.rb
40
+ - lib/micro/authorization/model.rb
41
+ - lib/micro/authorization/permissions.rb
42
+ - lib/micro/authorization/permissions/checker.rb
43
+ - lib/micro/authorization/permissions/model.rb
44
+ - lib/micro/authorization/policy.rb
45
+ - lib/micro/authorization/utils.rb
46
+ - lib/micro/authorization/version.rb
47
+ - lib/u-authorization.rb
48
+ - u-authorization.gemspec
49
+ homepage: https://github.com/serradura/u-authorization
22
50
  licenses:
23
51
  - MIT
24
52
  metadata: {}
25
53
  post_install_message:
26
54
  rdoc_options: []
27
55
  require_paths:
28
- - "."
56
+ - lib
29
57
  required_ruby_version: !ruby/object:Gem::Requirement
30
58
  requirements:
31
59
  - - ">="
32
60
  - !ruby/object:Gem::Version
33
- version: 2.2.2
61
+ version: 2.2.0
34
62
  required_rubygems_version: !ruby/object:Gem::Requirement
35
63
  requirements:
36
64
  - - ">="
37
65
  - !ruby/object:Gem::Version
38
66
  version: '0'
39
67
  requirements: []
40
- rubyforge_project:
41
- rubygems_version: 2.7.7
68
+ rubygems_version: 3.0.1
42
69
  signing_key:
43
70
  specification_version: 4
44
71
  summary: Authorization library and role managment
data/authorization.rb DELETED
@@ -1,195 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Authorization
4
- VERSION = '1.4.0'
5
-
6
- MapValuesAsDowncasedStrings = -> (values) do
7
- Array(values).map { |value| String(value).downcase }
8
- end
9
-
10
- module CheckRolePermission
11
- extend self
12
-
13
- def call(context, role_permissions, required_features)
14
- required_features
15
- .all? { |feature| has_permission?(context, role_permissions[feature]) }
16
- end
17
-
18
- private
19
-
20
- def has_permission?(context, role_permission)
21
- return false if role_permission.nil?
22
-
23
- if role_permission == false || role_permission == true
24
- role_permission
25
- elsif !(any = role_permission['any']).nil?
26
- any
27
- elsif only = role_permission['only']
28
- check_feature_permission(only, context)
29
- elsif except = role_permission['except']
30
- !check_feature_permission(except, context)
31
- else
32
- raise NotImplementedError
33
- end
34
- end
35
-
36
- def check_feature_permission(context_values, context)
37
- MapValuesAsDowncasedStrings.(context_values).any? do |context_value|
38
- Array(context_value.split('.')).all? { |permission| context.include?(permission) }
39
- end
40
- end
41
- end
42
-
43
- class FeaturesPermissionChecker
44
- attr_reader :required_features
45
-
46
- def initialize(role, features)
47
- @role = role
48
- @required_features = MapValuesAsDowncasedStrings.(features)
49
- end
50
-
51
- def context?(context)
52
- CheckRolePermission.call(context, @role, @required_features)
53
- end
54
- end
55
-
56
- class Permissions
57
- attr_reader :role, :context
58
-
59
- def self.[](instance)
60
- return instance if instance.is_a?(Permissions)
61
-
62
- raise ArgumentError, "#{instance.inspect} must be a #{self.name}"
63
- end
64
-
65
- def initialize(role_permissions, context: [])
66
- @role = role_permissions.dup.freeze
67
- @cache = {}
68
- @context = MapValuesAsDowncasedStrings.(context).freeze
69
- end
70
-
71
- def to(features)
72
- FeaturesPermissionChecker.new(@role, features)
73
- end
74
-
75
- def to?(features = nil)
76
- has_permission_to = to(features)
77
-
78
- cache_key = has_permission_to.required_features.inspect
79
-
80
- return @cache[cache_key] unless @cache[cache_key].nil?
81
-
82
- @cache[cache_key] = has_permission_to.context?(@context)
83
- end
84
-
85
- def to_not?(features = nil)
86
- !to?(features)
87
- end
88
- end
89
-
90
- class Policy
91
- def self.type(klass)
92
- return klass if klass < self
93
-
94
- raise ArgumentError, "policy must be a #{self.name}"
95
- end
96
-
97
- def initialize(context, subject = nil, permissions: nil)
98
- @context = context
99
- @subject = subject
100
- @permissions = permissions
101
- end
102
-
103
- def method_missing(method, *args, **keyargs, &block)
104
- return false if method =~ /\?\z/
105
- super(method)
106
- end
107
-
108
- private
109
-
110
- def permissions; @permissions; end
111
- def context; @context; end
112
- def subject; @subject; end
113
- def user
114
- @user ||=
115
- context.is_a?(Hash) ? context[:user] || context[:current_user] : context
116
- end
117
- alias_method :current_user, :user
118
- end
119
-
120
- class Model
121
- attr_reader :user, :permissions
122
-
123
- def self.build(user, role, context: [], policies: {})
124
- permissions = Permissions.new(role, context: context)
125
-
126
- self.new(user, permissions: permissions, policies: policies)
127
- end
128
-
129
- def initialize(user, permissions:, policies: {})
130
- @user = user
131
- @policies = {}
132
- @policies_cache = {}
133
- @permissions = Permissions[permissions]
134
-
135
- add_policies(policies)
136
- end
137
-
138
- def map(context: nil, policies: nil)
139
- if context.nil? && policies.nil?
140
- raise ArgumentError, 'context or policies keywords args must be defined'
141
- end
142
-
143
- new_permissions =
144
- Permissions.new(permissions.role, context: context || @context)
145
-
146
- self.class.new(
147
- user, permissions: new_permissions, policies: policies || @policies
148
- )
149
- end
150
-
151
- def add_policy(key, policy_klass)
152
- raise ArgumentError, 'key must be a Symbol' unless key.is_a?(Symbol)
153
-
154
- default_ref = key == :default && policy_klass.is_a?(Symbol)
155
-
156
- @policies[key] ||= default_ref ? policy_klass : Policy.type(policy_klass)
157
-
158
- self
159
- end
160
-
161
- def add_policies(new_policies)
162
- unless new_policies.is_a?(Hash)
163
- raise ArgumentError, "policies must be a Hash (key => #{Policy.name})"
164
- end
165
-
166
- new_policies.each(&method(:add_policy))
167
-
168
- self
169
- end
170
-
171
- def to(policy_key, subject: nil)
172
- policy_klass = fetch_policy(policy_key)
173
-
174
- return policy_klass.new(user, subject, permissions: permissions) if subject
175
-
176
- return @policies_cache[policy_key] if @policies_cache[policy_key]
177
-
178
- policy_klass.new(user, permissions: permissions).tap do |instance|
179
- @policies_cache[policy_key] = instance if policy_klass != Policy
180
- end
181
- end
182
-
183
- def policy(key = :default, subject: nil)
184
- to(key, subject: subject)
185
- end
186
-
187
- private
188
-
189
- def fetch_policy(policy_key)
190
- data = @policies[policy_key]
191
- value = data || @policies.fetch(:default, Policy)
192
- value.is_a?(Symbol) ? fetch_policy(value) : value
193
- end
194
- end
195
- end