resource_policy 1.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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +20 -0
  3. data/.gitignore +15 -0
  4. data/.hound.yml +3 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +43 -0
  7. data/.ruby-version +1 -0
  8. data/.travis.yml +7 -0
  9. data/CHANGELOG.md +19 -0
  10. data/CODE_OF_CONDUCT.md +74 -0
  11. data/Gemfile +11 -0
  12. data/Gemfile.lock +232 -0
  13. data/LICENSE.txt +21 -0
  14. data/Rakefile +6 -0
  15. data/bin/console +14 -0
  16. data/bin/setup +8 -0
  17. data/docs/.nojekyll +0 -0
  18. data/docs/README.md +163 -0
  19. data/docs/_sidebar.md +6 -0
  20. data/docs/components/action_validator.md +34 -0
  21. data/docs/components/actions_policy.md +68 -0
  22. data/docs/components/attributes_policy.md +68 -0
  23. data/docs/components/policy.md +202 -0
  24. data/docs/index.html +70 -0
  25. data/lib/resource_policy/policy/action_policy_configuration.rb +37 -0
  26. data/lib/resource_policy/policy/actions_policy/action_policy.rb +32 -0
  27. data/lib/resource_policy/policy/actions_policy/actions_policy_model.rb +39 -0
  28. data/lib/resource_policy/policy/actions_policy.rb +35 -0
  29. data/lib/resource_policy/policy/attributes_policy/attribute_configuration.rb +72 -0
  30. data/lib/resource_policy/policy/attributes_policy/attribute_policy.rb +49 -0
  31. data/lib/resource_policy/policy/attributes_policy/attributes_policy_model.rb +52 -0
  32. data/lib/resource_policy/policy/attributes_policy.rb +58 -0
  33. data/lib/resource_policy/policy/merge_policies.rb +44 -0
  34. data/lib/resource_policy/policy/policy_configuration.rb +87 -0
  35. data/lib/resource_policy/policy.rb +31 -0
  36. data/lib/resource_policy/protected_resource.rb +43 -0
  37. data/lib/resource_policy/rails.rb +5 -0
  38. data/lib/resource_policy/validators/action_policy_validator.rb +54 -0
  39. data/lib/resource_policy/version.rb +5 -0
  40. data/lib/resource_policy.rb +11 -0
  41. data/resource_policy.gemspec +47 -0
  42. metadata +212 -0
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourcePolicy
4
+ module Policy
5
+ module AttributesPolicy
6
+ # Class which isolates methods defined via attributes_policy config
7
+ class AttributesPolicyModel
8
+ require 'resource_policy/policy/attributes_policy/attribute_policy'
9
+
10
+ def initialize(policy)
11
+ @policy = policy
12
+ @policy_item_by_name ||= {}
13
+ end
14
+
15
+ def all
16
+ @all ||= config.attributes.keys.map do |attribute_name|
17
+ policy_item(attribute_name)
18
+ end
19
+ end
20
+
21
+ def all_allowed_to(status)
22
+ all.select { |attribute| attribute.allowed_to?(status) }
23
+ end
24
+
25
+ def method_missing(method_name)
26
+ return super unless config.attributes.key?(method_name.to_sym)
27
+
28
+ policy_item(method_name.to_sym)
29
+ end
30
+
31
+ def respond_to_missing?(method_name, *args)
32
+ config.attributes.key?(method_name.to_sym) || super
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :policy
38
+
39
+ def config
40
+ policy.class.policy
41
+ end
42
+
43
+ def policy_item(name)
44
+ @policy_item_by_name[name] ||= begin
45
+ attribute = config.attributes.fetch(name)
46
+ AttributePolicy.new(attribute, policy: policy)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourcePolicy
4
+ module Policy
5
+ # Allows to define fields policy using configuration block.
6
+ #
7
+ # Usage example:
8
+ #
9
+ # class SomeModelPolicy
10
+ # include ResourcePolicy::AttributesPolicy
11
+ #
12
+ # policy do |c|
13
+ # c.attribute(:some_name)
14
+ # .allowed(:read, if: :readable?)
15
+ # .allowed(:write, if: :writable?)
16
+ #
17
+ # c.group(:current_user_is_admin?) do |g|
18
+ # g.attribute(:password).allowed(:write)
19
+ # end
20
+ # end
21
+ #
22
+ # def current_user_is_admin?
23
+ # current_user.admin?
24
+ # end
25
+ # ...
26
+ # end
27
+ #
28
+ module AttributesPolicy
29
+ require 'resource_policy/policy/attributes_policy/attributes_policy_model'
30
+
31
+ def protected_resource
32
+ @protected_resource ||= ProtectedResource.new(self)
33
+ end
34
+
35
+ def action(name)
36
+ actions_policy.public_send(name) if actions_policy.respond_to?(name)
37
+ end
38
+
39
+ def attribute(name)
40
+ attributes_policy.public_send(name) if attributes_policy.respond_to?(name)
41
+ end
42
+
43
+ def policy_target
44
+ send(self.class.policy.policy_target)
45
+ end
46
+
47
+ def attributes_policy
48
+ @attributes_policy ||= AttributesPolicyModel.new(self)
49
+ end
50
+
51
+ private
52
+
53
+ def resource_policy_initialize(*args)
54
+ @policy_target = args.first
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourcePolicy
4
+ module Policy
5
+ # Service object using for merging two policy configurations
6
+ class MergePolicies
7
+ class OverlappingActionError < ResourcePolicy::Error; end
8
+
9
+ def self.call(*args)
10
+ new(*args).call
11
+ end
12
+
13
+ def initialize(policy, other_policy)
14
+ @policy = policy
15
+ @other_policy = other_policy
16
+ end
17
+
18
+ def call
19
+ merge_actions
20
+ merge_attributes
21
+ policy
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :policy, :other_policy
27
+
28
+ def merge_actions
29
+ other_policy.actions.values.each do |action|
30
+ policy.action(action.name).allowed(if: action.conditions)
31
+ end
32
+ end
33
+
34
+ def merge_attributes
35
+ other_policy.attributes.values.each do |attribute|
36
+ attribute.defined_actions.each do |action_name|
37
+ conditions = attribute.conditions_for(action_name)
38
+ policy.attribute(attribute.name).allowed(action_name, if: conditions)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourcePolicy
4
+ module Policy
5
+ # Stores all configuration about policy
6
+ class PolicyConfiguration
7
+ require 'resource_policy/policy/action_policy_configuration'
8
+
9
+ require 'resource_policy/policy/attributes_policy/attribute_configuration'
10
+ require 'resource_policy/policy/merge_policies'
11
+
12
+ EmptyConfiguration = Class.new do
13
+ def group_conditions
14
+ []
15
+ end
16
+ end
17
+
18
+ EMPTY_CONFIGURATION = EmptyConfiguration.new
19
+
20
+ def initialize(parent_configuration: EMPTY_CONFIGURATION, extra_group_conditions: [])
21
+ @actions = {}
22
+ @attributes = {}
23
+ @parent_configuration = parent_configuration
24
+ @extra_group_conditions = extra_group_conditions
25
+ end
26
+
27
+ def initialize_copy(_other)
28
+ @actions = @actions.dup.each.with_object({}) { |(key, value), result| result[key] = value.dup }
29
+ @attributes = @attributes.dup.each.with_object({}) { |(key, value), result| result[key] = value.dup }
30
+ end
31
+
32
+ def policy_target(policy_target_name = nil)
33
+ @policy_target = policy_target_name if policy_target_name
34
+ @policy_target
35
+ end
36
+
37
+ def attribute(attribute_name)
38
+ symbolized_name = attribute_name.to_sym
39
+
40
+ @attributes[symbolized_name] ||= AttributesPolicy::AttributeConfiguration.new(
41
+ symbolized_name, policy_configuration: self
42
+ )
43
+ end
44
+
45
+ def attributes
46
+ @attributes.select { |_name, action| action.configured? }
47
+ end
48
+
49
+ def actions
50
+ @actions.select { |_name, action| action.configured? }
51
+ end
52
+
53
+ def action(attribute_name)
54
+ symbolized_name = attribute_name.to_sym
55
+
56
+ @actions[symbolized_name] ||= ActionPolicyConfiguration.new(
57
+ symbolized_name, policy_configuration: self
58
+ )
59
+ end
60
+
61
+ def group(*new_conditions)
62
+ return @group if new_conditions.empty?
63
+
64
+ unique_new_conditions = new_conditions.map(&:to_sym).uniq
65
+ group_config = self.class.new(
66
+ parent_configuration: self,
67
+ extra_group_conditions: unique_new_conditions
68
+ )
69
+
70
+ yield(group_config)
71
+ tap { |config| config.merge(group_config) }
72
+ end
73
+
74
+ def group_conditions
75
+ (parent_configuration.group_conditions + extra_group_conditions).uniq
76
+ end
77
+
78
+ def merge(other)
79
+ MergePolicies.call(self, other)
80
+ end
81
+
82
+ protected
83
+
84
+ attr_reader :extra_group_conditions, :parent_configuration
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourcePolicy
4
+ # Gives policy configuration methods for any policy class
5
+ module Policy
6
+ require 'resource_policy/protected_resource'
7
+ require 'resource_policy/policy/policy_configuration'
8
+ require 'resource_policy/policy/attributes_policy'
9
+ require 'resource_policy/policy/actions_policy'
10
+
11
+ # Class methods.
12
+ module ClassMethods
13
+ def policy
14
+ @policy ||= Policy::PolicyConfiguration.new
15
+ yield(@policy) if block_given?
16
+ @policy
17
+ end
18
+
19
+ def inherited(subclass)
20
+ super
21
+ subclass.instance_variable_set(:@policy, policy.dup)
22
+ end
23
+ end
24
+
25
+ def self.included(receiver)
26
+ receiver.send(:extend, ClassMethods)
27
+ receiver.send(:include, ::ResourcePolicy::Policy::ActionsPolicy)
28
+ receiver.send(:include, ::ResourcePolicy::Policy::AttributesPolicy)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourcePolicy
4
+ # Generates resource which has same attributes as policy target,
5
+ # but returns `nil` when attribute in not readable according to policy
6
+ class ProtectedResource
7
+ def initialize(policy)
8
+ @policy = policy
9
+ end
10
+
11
+ def method_missing(method_name, *args)
12
+ return super unless target_respond_to?(method_name, *args)
13
+ return nil unless policy.attribute(method_name).readable?
14
+
15
+ policy_target.public_send(method_name, *args)
16
+ end
17
+
18
+ def respond_to_missing?(*args)
19
+ target_respond_to?(*args) || super
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :policy
25
+
26
+ def target_respond_to?(method_name, *args)
27
+ accessible_attributes.include?(method_name.to_sym) &&
28
+ policy_target.respond_to?(method_name, *args)
29
+ end
30
+
31
+ def accessible_attributes
32
+ attributes = policy.class.policy.attributes.values.select do |attribute|
33
+ attribute.defined_action?(:read)
34
+ end
35
+
36
+ attributes.map(&:name)
37
+ end
38
+
39
+ def policy_target
40
+ policy.policy_target
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Incudes resource policy and rails specific helpers
4
+ require 'resource_policy'
5
+ require 'resource_policy/validators/action_policy_validator'
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Available options:
4
+ #
5
+ # * `:allowed_to` (required) - action type which we need to check.
6
+ # * `:as` (optional) - key which will be used to display errors.
7
+ #
8
+ # Usage example:
9
+ #
10
+ # class SomeClass
11
+ # validates :some_policy, 'resource_policy/action': { allowed_to: :create, as: :some_item }
12
+ #
13
+ # def some_policy
14
+ # SomePolicy.new
15
+ # end
16
+ # end
17
+ #
18
+ module ResourcePolicy
19
+ class ActionValidator < ActiveModel::EachValidator
20
+ def validate_each(record, default_attribute, policy)
21
+ attribute = options.fetch(:as, default_attribute)
22
+ action_policy = policy.action(action_name)
23
+ validate_action_policy(action_policy, record:, attribute:)
24
+ end
25
+
26
+ private
27
+
28
+ def validate_action_policy(policy, record:, attribute:)
29
+ if policy.nil?
30
+ add_missing_policy_error_for(record, attribute:)
31
+ elsif !policy.allowed?
32
+ add_not_permitted_error_for(record, attribute:)
33
+ end
34
+ end
35
+
36
+ def action_name
37
+ @action_name ||= options.fetch(:allowed_to)
38
+ end
39
+
40
+ def add_missing_policy_error_for(record, attribute:)
41
+ record.errors.add(
42
+ attribute,
43
+ "does not have #{action_name.to_s.inspect} action policy defined"
44
+ )
45
+ end
46
+
47
+ def add_not_permitted_error_for(record, attribute:)
48
+ record.errors.add(
49
+ attribute,
50
+ "action #{action_name.to_s.inspect} is not allowed"
51
+ )
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourcePolicy
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'resource_policy/version'
4
+
5
+ # Root namespace
6
+ module ResourcePolicy
7
+ class Error < StandardError; end
8
+
9
+ require 'resource_policy/policy'
10
+ # Your code goes here...
11
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'resource_policy/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'resource_policy'
9
+ spec.version = ResourcePolicy::VERSION
10
+ spec.authors = ['Povilas Jurcys']
11
+ spec.email = ['po.jurcys@gmail.com']
12
+
13
+ spec.summary = "Access control for single resource and it's methods"
14
+ spec.homepage = 'https://github.com/samesystem/resource_policy'
15
+ spec.license = 'MIT'
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] = 'https://github.com/samesystem/resource_policy'
22
+ spec.metadata['changelog_uri'] = \
23
+ "https://github.com/samesystem/resource_policy/blob/v#{ResourcePolicy::VERSION}/CHANGELOG.md"
24
+ else
25
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
26
+ 'public gem pushes.'
27
+ end
28
+
29
+ # Specify which files should be added to the gem when it is released.
30
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
31
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
32
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
33
+ end
34
+ spec.bindir = 'exe'
35
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ['lib']
37
+
38
+ spec.add_development_dependency 'bundler', '~> 2.0'
39
+ spec.add_development_dependency 'pry-byebug'
40
+ spec.add_development_dependency 'rake', '~> 13.0'
41
+ spec.add_development_dependency 'rspec', '~> 3.0'
42
+ spec.add_development_dependency 'rubocop'
43
+ spec.add_development_dependency 'rubocop-performance'
44
+ spec.add_development_dependency 'rubocop-rails'
45
+ spec.add_development_dependency 'rubocop-rspec'
46
+ spec.add_development_dependency 'rails', '~> 7.0.0'
47
+ end
metadata ADDED
@@ -0,0 +1,212 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resource_policy
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Povilas Jurcys
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-02-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry-byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-performance
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 7.0.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 7.0.0
139
+ description:
140
+ email:
141
+ - po.jurcys@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".github/workflows/ruby.yml"
147
+ - ".gitignore"
148
+ - ".hound.yml"
149
+ - ".rspec"
150
+ - ".rubocop.yml"
151
+ - ".ruby-version"
152
+ - ".travis.yml"
153
+ - CHANGELOG.md
154
+ - CODE_OF_CONDUCT.md
155
+ - Gemfile
156
+ - Gemfile.lock
157
+ - LICENSE.txt
158
+ - Rakefile
159
+ - bin/console
160
+ - bin/setup
161
+ - docs/.nojekyll
162
+ - docs/README.md
163
+ - docs/_sidebar.md
164
+ - docs/components/action_validator.md
165
+ - docs/components/actions_policy.md
166
+ - docs/components/attributes_policy.md
167
+ - docs/components/policy.md
168
+ - docs/index.html
169
+ - lib/resource_policy.rb
170
+ - lib/resource_policy/policy.rb
171
+ - lib/resource_policy/policy/action_policy_configuration.rb
172
+ - lib/resource_policy/policy/actions_policy.rb
173
+ - lib/resource_policy/policy/actions_policy/action_policy.rb
174
+ - lib/resource_policy/policy/actions_policy/actions_policy_model.rb
175
+ - lib/resource_policy/policy/attributes_policy.rb
176
+ - lib/resource_policy/policy/attributes_policy/attribute_configuration.rb
177
+ - lib/resource_policy/policy/attributes_policy/attribute_policy.rb
178
+ - lib/resource_policy/policy/attributes_policy/attributes_policy_model.rb
179
+ - lib/resource_policy/policy/merge_policies.rb
180
+ - lib/resource_policy/policy/policy_configuration.rb
181
+ - lib/resource_policy/protected_resource.rb
182
+ - lib/resource_policy/rails.rb
183
+ - lib/resource_policy/validators/action_policy_validator.rb
184
+ - lib/resource_policy/version.rb
185
+ - resource_policy.gemspec
186
+ homepage: https://github.com/samesystem/resource_policy
187
+ licenses:
188
+ - MIT
189
+ metadata:
190
+ homepage_uri: https://github.com/samesystem/resource_policy
191
+ source_code_uri: https://github.com/samesystem/resource_policy
192
+ changelog_uri: https://github.com/samesystem/resource_policy/blob/v1.0.0/CHANGELOG.md
193
+ post_install_message:
194
+ rdoc_options: []
195
+ require_paths:
196
+ - lib
197
+ required_ruby_version: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ required_rubygems_version: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ requirements: []
208
+ rubygems_version: 3.3.7
209
+ signing_key:
210
+ specification_version: 4
211
+ summary: Access control for single resource and it's methods
212
+ test_files: []