active_security 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.
@@ -0,0 +1,100 @@
1
+ module ActiveSecurity
2
+ # @guide begin
3
+ #
4
+ # ## Required Scope
5
+ #
6
+ # The {ActiveSecurity::Scoped} module allows ActiveSecurity to enforce querying
7
+ # within a scope.
8
+ #
9
+ # This allows, for example:
10
+ #
11
+ # class Restaurant < ActiveRecord::Base
12
+ # extend ActiveSecurity
13
+ # belongs_to :city
14
+ # active_security use: :scoped, scope: :city
15
+ # end
16
+ #
17
+ # class City < ActiveRecord::Base
18
+ # extend ActiveSecurity
19
+ # has_many :restaurants
20
+ # end
21
+ #
22
+ # City.find_by(name: "seattle").restaurants.restricted.find(23)
23
+ # City.find_by(name: "chicago").restaurants.restricted.find(23)
24
+ #
25
+ # The value for the `:scope` option can be the name of a `belongs_to` relation, or
26
+ # a column.
27
+ #
28
+ # Additionally, the `:scope` option can receive an array of scope values:
29
+ #
30
+ # class Cuisine < ActiveRecord::Base
31
+ # extend ActiveSecurity
32
+ # has_many :restaurants
33
+ # end
34
+ #
35
+ # class City < ActiveRecord::Base
36
+ # extend ActiveSecurity
37
+ # has_many :restaurants
38
+ # end
39
+ #
40
+ # class Restaurant < ActiveRecord::Base
41
+ # extend ActiveSecurity
42
+ # belongs_to :city
43
+ # active_security use: :scoped, scope: [:city, :cuisine]
44
+ # end
45
+ #
46
+ # All supplied values will be used to determine scope.
47
+ #
48
+ # ### Finding Records
49
+ #
50
+ # It's best to query through the relation:
51
+ #
52
+ # @city.restaurants.restricted.find(23)
53
+ #
54
+ # Alternatively, you could pass the scope value as a query parameter:
55
+ #
56
+ # Restaurant.where(city_id: @city.id).restricted.find(23)
57
+ #
58
+ # @guide end
59
+ module Scoped
60
+ class << self
61
+ # Sets up behavior and configuration options for scoped feature.
62
+ def included(model_class)
63
+ model_class.class_eval do
64
+ active_security_config.class.send(:include, Configuration)
65
+ end
66
+ end
67
+ end
68
+
69
+ # This module adds the `:scope` configuration option to
70
+ # {ActiveSecurity::Configuration ActiveSecurity::Configuration}.
71
+ module Configuration
72
+ # Gets the scope value.
73
+ #
74
+ # When setting this value, the argument should be a symbol referencing a
75
+ # `belongs_to` relation, or a column.
76
+ #
77
+ # @return Symbol The scope value
78
+ attr_accessor :scope
79
+
80
+ # Gets the scope columns.
81
+ #
82
+ # Checks to see if the `:scope` option passed to
83
+ # {ActiveSecurity::Base#active_security} refers to a relation, and if so, returns
84
+ # the relation's foreign key. Otherwise it assumes the option value was
85
+ # the name of column and returns it cast to a String.
86
+ #
87
+ # @return String The scope column
88
+ def scope_columns
89
+ [@scope].flatten.map { |s| (reflection_foreign_key(s) or s).to_s }
90
+ end
91
+
92
+ private
93
+
94
+ def reflection_foreign_key(scope)
95
+ reflection = model_class.reflections[scope] || model_class.reflections[scope.to_s]
96
+ reflection.try(:foreign_key)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSecurity
4
+ module Version
5
+ VERSION = "1.0.0"
6
+ end
7
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ # External Libraries
4
+ require "version_gem"
5
+ require "active_record"
6
+ require "active_support"
7
+
8
+ # This library
9
+ require_relative "active_security/version"
10
+ require_relative "active_security/base"
11
+ require_relative "active_security/configuration"
12
+ require_relative "active_security/finder_methods"
13
+ require_relative "active_security/privileged_hooks"
14
+ require_relative "active_security/restricted_hooks"
15
+
16
+ module ActiveSecurity
17
+ class RestrictedAccessError < RuntimeError; end
18
+
19
+ class UnhandledArelPredicateError < RuntimeError; end
20
+
21
+ class InvalidConfig < ArgumentError; end
22
+
23
+ autoload :Finders, "active_security/finders"
24
+ autoload :Privileged, "active_security/privileged"
25
+ autoload :Restricted, "active_security/restricted"
26
+ autoload :Scoped, "active_security/scoped"
27
+
28
+ class << self
29
+ # ActiveSecurity takes advantage of `extended` to do basic model setup, primarily
30
+ # extending {ActiveSecurity::Base} to add {ActiveSecurity::Base#active_security
31
+ # active_security} as a class method.
32
+ #
33
+ # In addition to adding {ActiveSecurity::Base#active_security active_security}, the class
34
+ # instance variable +@active_security_config+ is added. This variable is an
35
+ # instance of an anonymous subclass of {ActiveSecurity::Configuration}. This
36
+ # allows subsequently loaded modules like {ActiveSecurity::Scoped} to add
37
+ # functionality to the configuration class only for the current class,
38
+ # rather than monkey patching {ActiveSecurity::Configuration} directly.
39
+ # This isolates other models from large feature changes an addon to
40
+ # ActiveSecurity could potentially introduce.
41
+ #
42
+ # The upshot of this is, you can have two Active Record models that both have
43
+ # a @active_security_config, but each config object can have different methods
44
+ # and behaviors depending on what modules have been loaded, without
45
+ # conflicts. Keep this in mind if you're hacking on ActiveSecurity.
46
+ #
47
+ # For examples of this, see the source for {Scoped.included}.
48
+ def extended(model_class)
49
+ return if model_class.respond_to?(:active_security)
50
+ class << model_class
51
+ alias_method :relation_without_active_security, :relation
52
+ end
53
+ model_class.class_eval do
54
+ extend(Base)
55
+ @active_security_config = Class.new(Configuration).new(self) # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
56
+ ActiveSecurity.defaults.call(@active_security_config) # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
57
+ end
58
+ end
59
+
60
+ # Allow developers to `include` ActiveSecurity or `extend` it.
61
+ def included(model_class)
62
+ model_class.extend(self)
63
+ end
64
+
65
+ # Set global defaults for all models using ActiveSecurity.
66
+ #
67
+ # The default defaults are to use the `:restricted` module and nothing else.
68
+ #
69
+ # @example
70
+ # ActiveSecurity.defaults do |config|
71
+ # config.base :name
72
+ # config.use :something_else
73
+ # end
74
+ def defaults(&block)
75
+ @defaults = block if block # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
76
+ @defaults ||= ->(config) { config.use(:restricted) } # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
77
+ end
78
+
79
+ # If you need to reset the defaults to original defaults, just call without a block:
80
+ #
81
+ # ActiveSecurity.reset_defaults
82
+ #
83
+ def reset_defaults
84
+ @defaults = nil # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
85
+ end
86
+ end
87
+ end
88
+
89
+ ActiveSecurity::Version.class_eval do
90
+ extend VersionGem::Basic
91
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,394 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_security
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Boling
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
14
+ ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
15
+ A2NvbTAeFw0yMzA5MjAxNzMwMjhaFw0yNDA5MTkxNzMwMjhaMEMxFTATBgNVBAMM
16
+ DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
17
+ LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA+a9UvHo3
18
+ 84k96WgU5Kk5HB+cLZs/modjorsTfqY67MJF5nNvAoqcKTUBW4uG+Zpfnm3jaDO5
19
+ GxhJEIZWfndYzycHT2KMVQ1uTP82ba8ZaKrPlPIafkbui3mdds47qsmqHiblKERg
20
+ U532lkwfqHDlJwE7OBZQ59EwWWLynlT/yAUHpOBbqIuHKUxdpmBI+sIjrZcD1e05
21
+ WmjkO6fwIdC5oM757aoPxIgXD587VOViH11Vkm2doskj4T8yONtwVHlcrrhJ9Bzd
22
+ /zdp6vEn7GZQrABvpOlqwWxQ72ZnFhJe/RJZf6CXOPOh69Ai0QKYl2a1sYuCJKS3
23
+ nsBnxXJINEEznjR7rZjNUmYD+CZqfjzgPqedRxTlASe7iA4w7xZOqMDzcuhNwcUQ
24
+ tMEH6BTktxKP3jXZPXRfHCf6s+HRVb6vezAonTBVyydf5Xp5VwWkd6cwm+2BzHl5
25
+ 7kc/3lLxKMcsyEUprAsk8LdHohwZdC267l+RS++AP6Cz6x+nB3oGob19AgMBAAGj
26
+ fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQCSSas60GqqMjt
27
+ xR7LoY1gucEvtzAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
28
+ A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
29
+ ggGBAMl9ifcw5p+PdvB7dCPoNKoVdp/2LbC9ztETHuYL2gUMJB6UoS3o9c/piSuR
30
+ V3ZMQaijmNu6ms1bWAtJ66LjmYrVflJtf9yp31Kierr9LpisMSUx2qbMOHGa8d2Z
31
+ vCUWPF8E9Cg0mP3GAyZ6qql8jDh/anUKeksPXqJvNxNPDu2DVYsa/IWdl96whzS4
32
+ Bl7SwB1E7agps40UcshCSKaVDOU0M+XN6SrnJMElnBic+KSAkBkVFbzS0BE4ODZM
33
+ BgE6nYzQ05qhuvbE+oGdACTlemNtDDWCh0uw+7x0q2PocGIDU5zsPn/WNTkCXPmB
34
+ CHGvqDNWq4M7ncTKAaS2XExgyb7uPdq9fKiOW8nmH+zCiGzJXzBWwZlKf7L4Ht9E
35
+ a3f0e5C+zvee9Z5Ng9ciyfav9/fcXgYt5MjoBv27THr5XfBhgOCIHSYW2tqJmWKi
36
+ KuxrfYrN+9HvMdm+nZ6TypmKftHY3Gj+/uu+g8Icm/zrvTWAEE0mcJOkfrIoNPJb
37
+ pF8dMA==
38
+ -----END CERTIFICATE-----
39
+ date: 2024-07-05 00:00:00.000000000 Z
40
+ dependencies:
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '7.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '7.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '7.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '7.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: version_gem
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.1'
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 1.1.4
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '1.1'
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 1.1.4
89
+ - !ruby/object:Gem::Dependency
90
+ name: rake
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '13'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '13'
103
+ - !ruby/object:Gem::Dependency
104
+ name: anonymous_active_record
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.0'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 1.0.8
113
+ type: :development
114
+ prerelease: false
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '1.0'
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 1.0.8
123
+ - !ruby/object:Gem::Dependency
124
+ name: appraisal
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '2.5'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '2.5'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rspec
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '3'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '3'
151
+ - !ruby/object:Gem::Dependency
152
+ name: rspec-block_is_expected
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '1.0'
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: 1.0.5
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: '1.0'
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: 1.0.5
171
+ - !ruby/object:Gem::Dependency
172
+ name: rspec-pending_for
173
+ requirement: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - "~>"
176
+ - !ruby/object:Gem::Version
177
+ version: '0.1'
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: 0.1.16
181
+ type: :development
182
+ prerelease: false
183
+ version_requirements: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '0.1'
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: 0.1.16
191
+ - !ruby/object:Gem::Dependency
192
+ name: silent_stream
193
+ requirement: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - "~>"
196
+ - !ruby/object:Gem::Version
197
+ version: '1.0'
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: 1.0.8
201
+ type: :development
202
+ prerelease: false
203
+ version_requirements: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: '1.0'
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: 1.0.8
211
+ - !ruby/object:Gem::Dependency
212
+ name: sqlite3
213
+ requirement: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: 1.6.9
218
+ - - "<"
219
+ - !ruby/object:Gem::Version
220
+ version: '2'
221
+ type: :development
222
+ prerelease: false
223
+ version_requirements: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - ">="
226
+ - !ruby/object:Gem::Version
227
+ version: 1.6.9
228
+ - - "<"
229
+ - !ruby/object:Gem::Version
230
+ version: '2'
231
+ - !ruby/object:Gem::Dependency
232
+ name: kettle-soup-cover
233
+ requirement: !ruby/object:Gem::Requirement
234
+ requirements:
235
+ - - "~>"
236
+ - !ruby/object:Gem::Version
237
+ version: '1.0'
238
+ - - ">="
239
+ - !ruby/object:Gem::Version
240
+ version: 1.0.2
241
+ type: :development
242
+ prerelease: false
243
+ version_requirements: !ruby/object:Gem::Requirement
244
+ requirements:
245
+ - - "~>"
246
+ - !ruby/object:Gem::Version
247
+ version: '1.0'
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: 1.0.2
251
+ - !ruby/object:Gem::Dependency
252
+ name: rubocop-lts
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - "~>"
256
+ - !ruby/object:Gem::Version
257
+ version: '18.2'
258
+ - - ">="
259
+ - !ruby/object:Gem::Version
260
+ version: 18.2.1
261
+ type: :development
262
+ prerelease: false
263
+ version_requirements: !ruby/object:Gem::Requirement
264
+ requirements:
265
+ - - "~>"
266
+ - !ruby/object:Gem::Version
267
+ version: '18.2'
268
+ - - ">="
269
+ - !ruby/object:Gem::Version
270
+ version: 18.2.1
271
+ - !ruby/object:Gem::Dependency
272
+ name: rubocop-packaging
273
+ requirement: !ruby/object:Gem::Requirement
274
+ requirements:
275
+ - - "~>"
276
+ - !ruby/object:Gem::Version
277
+ version: '0.5'
278
+ - - ">="
279
+ - !ruby/object:Gem::Version
280
+ version: 0.5.2
281
+ type: :development
282
+ prerelease: false
283
+ version_requirements: !ruby/object:Gem::Requirement
284
+ requirements:
285
+ - - "~>"
286
+ - !ruby/object:Gem::Version
287
+ version: '0.5'
288
+ - - ">="
289
+ - !ruby/object:Gem::Version
290
+ version: 0.5.2
291
+ - !ruby/object:Gem::Dependency
292
+ name: rubocop-rspec
293
+ requirement: !ruby/object:Gem::Requirement
294
+ requirements:
295
+ - - "~>"
296
+ - !ruby/object:Gem::Version
297
+ version: '2.10'
298
+ type: :development
299
+ prerelease: false
300
+ version_requirements: !ruby/object:Gem::Requirement
301
+ requirements:
302
+ - - "~>"
303
+ - !ruby/object:Gem::Version
304
+ version: '2.10'
305
+ - !ruby/object:Gem::Dependency
306
+ name: yard
307
+ requirement: !ruby/object:Gem::Requirement
308
+ requirements:
309
+ - - "~>"
310
+ - !ruby/object:Gem::Version
311
+ version: '0.9'
312
+ - - ">="
313
+ - !ruby/object:Gem::Version
314
+ version: 0.9.34
315
+ type: :development
316
+ prerelease: false
317
+ version_requirements: !ruby/object:Gem::Requirement
318
+ requirements:
319
+ - - "~>"
320
+ - !ruby/object:Gem::Version
321
+ version: '0.9'
322
+ - - ">="
323
+ - !ruby/object:Gem::Version
324
+ version: 0.9.34
325
+ - !ruby/object:Gem::Dependency
326
+ name: yard-junk
327
+ requirement: !ruby/object:Gem::Requirement
328
+ requirements:
329
+ - - "~>"
330
+ - !ruby/object:Gem::Version
331
+ version: '0.0'
332
+ type: :development
333
+ prerelease: false
334
+ version_requirements: !ruby/object:Gem::Requirement
335
+ requirements:
336
+ - - "~>"
337
+ - !ruby/object:Gem::Version
338
+ version: '0.0'
339
+ description: Disallow insecure, unscoped, finds
340
+ email:
341
+ - peter.boling@gmail.com
342
+ executables: []
343
+ extensions: []
344
+ extra_rdoc_files: []
345
+ files:
346
+ - CHANGELOG.md
347
+ - CODE_OF_CONDUCT.md
348
+ - CONTRIBUTING.md
349
+ - LICENSE.txt
350
+ - README.md
351
+ - SECURITY.md
352
+ - lib/active_security.rb
353
+ - lib/active_security/base.rb
354
+ - lib/active_security/configuration.rb
355
+ - lib/active_security/finder_methods.rb
356
+ - lib/active_security/finders.rb
357
+ - lib/active_security/privileged.rb
358
+ - lib/active_security/privileged_hooks.rb
359
+ - lib/active_security/restricted.rb
360
+ - lib/active_security/restricted_hooks.rb
361
+ - lib/active_security/scoped.rb
362
+ - lib/active_security/version.rb
363
+ homepage: https://github.com/pboling/active_security
364
+ licenses:
365
+ - MIT
366
+ metadata:
367
+ homepage_uri: https://github.com/pboling/active_security
368
+ source_code_uri: https://github.com/pboling/active_security/tree/v1.0.0
369
+ changelog_uri: https://github.com/pboling/active_security/blob/v1.0.0/CHANGELOG.md
370
+ bug_tracker_uri: https://github.com/pboling/active_security/issues
371
+ documentation_uri: https://www.rubydoc.info/gems/active_security/1.0.0
372
+ wiki_uri: https://github.com/pboling/active_security/wiki
373
+ funding_uri: https://liberapay.com/pboling
374
+ rubygems_mfa_required: 'true'
375
+ post_install_message:
376
+ rdoc_options: []
377
+ require_paths:
378
+ - lib
379
+ required_ruby_version: !ruby/object:Gem::Requirement
380
+ requirements:
381
+ - - ">="
382
+ - !ruby/object:Gem::Version
383
+ version: 2.7.0
384
+ required_rubygems_version: !ruby/object:Gem::Requirement
385
+ requirements:
386
+ - - ">="
387
+ - !ruby/object:Gem::Version
388
+ version: '0'
389
+ requirements: []
390
+ rubygems_version: 3.5.14
391
+ signing_key:
392
+ specification_version: 4
393
+ summary: Prevent insecure, unscoped, finds
394
+ test_files: []
metadata.gz.sig ADDED
Binary file