declarative_policy 1.1.0 → 2.0.1
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 +12 -0
- data/README.md +75 -8
- data/{declarative_policy.gemspec → declarative-policy.gemspec} +23 -8
- data/doc/caching.md +7 -7
- data/doc/defining-policies.md +47 -9
- data/doc/optimization.md +1 -1
- data/lib/declarative_policy/base.rb +1 -1
- data/lib/declarative_policy/condition.rb +22 -5
- data/lib/declarative_policy/configuration.rb +1 -1
- data/lib/declarative_policy/delegate_dsl.rb +1 -1
- data/lib/declarative_policy/policy_dsl.rb +2 -2
- data/lib/declarative_policy/preferred_scope.rb +1 -1
- data/lib/declarative_policy/rule_dsl.rb +1 -1
- data/lib/declarative_policy/runner.rb +1 -1
- data/lib/declarative_policy/version.rb +1 -1
- metadata +111 -24
- data/.gitignore +0 -12
- data/.gitlab-ci.yml +0 -91
- data/.rspec +0 -4
- data/.rubocop.yml +0 -13
- data/Dangerfile +0 -16
- data/Gemfile +0 -23
- data/Gemfile.lock +0 -214
- data/Rakefile +0 -8
- data/benchmarks/repeated_invocation.rb +0 -37
- data/danger/plugins/project_helper.rb +0 -58
- data/danger/roulette/Dangerfile +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 704af6c0500c00a0e6c6797dd5b496c098db86f33ccc1ef2496be37e43b33e03
|
4
|
+
data.tar.gz: 2236adb02dbee28b6565fc72541fe2fbee5a087ef15cc2fe1f0d060ce1eece13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3841495e1922ae72f704524e40ca080da4838cfe075d401350212f5b31f116f6003aa3e371d2a0084a11986b4745bb82946ad84b61247a19b59470a26e24755
|
7
|
+
data.tar.gz: f3f0d97ba2b9e56079d5307c135ec2b15c73759661f32e6cda2db44ab0fa21002598725cf0c762ca85c0580ae1c5b7c397115f185ec94c9da600cfaf19f6e590
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
2.0.0:
|
2
|
+
|
3
|
+
- Drop explicit support for Ruby 2.6 and 2.7 by removing those versions from
|
4
|
+
the CI matrix. These Ruby versions are now past EOL.
|
5
|
+
- Rename default condition scope name to `:user_and_subject`
|
6
|
+
- Clarify the use of `User` and `Subject` in README and documentation
|
7
|
+
- Update `ruby-git` in Gemfile.lock
|
8
|
+
|
9
|
+
1.1.1:
|
10
|
+
|
11
|
+
- Define development dependencies
|
12
|
+
|
1
13
|
1.1.0:
|
2
14
|
|
3
15
|
- Add cache invalidation API: `DeclarativePolicy.invalidate(cache, keys)`
|
data/README.md
CHANGED
@@ -20,14 +20,72 @@ gem 'declarative_policy'
|
|
20
20
|
|
21
21
|
And then execute:
|
22
22
|
|
23
|
-
|
23
|
+
```plain
|
24
|
+
$ bundle install
|
25
|
+
```
|
24
26
|
|
25
27
|
Or install it yourself as:
|
26
28
|
|
27
|
-
|
29
|
+
```plain
|
30
|
+
$ gem install declarative_policy
|
31
|
+
```
|
32
|
+
|
33
|
+
## Example
|
28
34
|
|
29
|
-
|
35
|
+
```ruby
|
36
|
+
require 'declarative_policy'
|
37
|
+
|
38
|
+
class User
|
39
|
+
attr_reader :name
|
40
|
+
|
41
|
+
def initialize(name:)
|
42
|
+
@name = name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Vehicle
|
47
|
+
def initialize(owner:, trusted: [])
|
48
|
+
@owner = owner
|
49
|
+
@trusted = trusted
|
50
|
+
end
|
51
|
+
|
52
|
+
def owner?(user)
|
53
|
+
@owner.name == user.name
|
54
|
+
end
|
55
|
+
|
56
|
+
def trusted?(user)
|
57
|
+
@owner.name == user.name || @trusted.detect { |t| t.name == user.name }
|
58
|
+
end
|
59
|
+
end
|
30
60
|
|
61
|
+
class VehiclePolicy < DeclarativePolicy::Base
|
62
|
+
condition(:owns) { @subject.owner?(@user) }
|
63
|
+
condition(:trusted) { @subject.trusted?(@user) }
|
64
|
+
|
65
|
+
rule { owns }.enable :sell_vehicle
|
66
|
+
rule { trusted }.enable :drive_vehicle
|
67
|
+
end
|
68
|
+
|
69
|
+
jack = User.new(name: 'jack')
|
70
|
+
jill = User.new(name: 'jill')
|
71
|
+
jacks_vehicle = Vehicle.new(owner: jack, trusted: [jill])
|
72
|
+
jills_vehicle = Vehicle.new(owner: jill, trusted: [jack])
|
73
|
+
|
74
|
+
puts "Jack can drive Jack's vehicle? -> #{DeclarativePolicy.policy_for(jack, jacks_vehicle).can?(:drive_vehicle)}"
|
75
|
+
puts "Jack can drive Jill's vehicle? -> #{DeclarativePolicy.policy_for(jack, jills_vehicle).can?(:drive_vehicle)}"
|
76
|
+
puts "Jack can sell Jack's vehicle? -> #{DeclarativePolicy.policy_for(jack, jacks_vehicle).can?(:sell_vehicle)}"
|
77
|
+
puts "Jack can sell Jill's vehicle? -> #{DeclarativePolicy.policy_for(jack, jills_vehicle).can?(:sell_vehicle)}"
|
78
|
+
```
|
79
|
+
|
80
|
+
```plain
|
81
|
+
$ ruby example.rb
|
82
|
+
Jack can drive Jack's vehicle? -> true
|
83
|
+
Jack can drive Jill's vehicle? -> true
|
84
|
+
Jack can sell Jack's vehicle? -> true
|
85
|
+
Jack can sell Jill's vehicle? -> false
|
86
|
+
```
|
87
|
+
|
88
|
+
## Usage
|
31
89
|
|
32
90
|
The core abstraction of this library is a `Policy`. Policies combine:
|
33
91
|
|
@@ -36,9 +94,12 @@ The core abstraction of this library is a `Policy`. Policies combine:
|
|
36
94
|
|
37
95
|
This library exists to determine the truth value of statements of the form:
|
38
96
|
|
97
|
+
```plain
|
98
|
+
User Predicate [Subject]
|
39
99
|
```
|
40
|
-
|
41
|
-
|
100
|
+
|
101
|
+
Renaming `User` to `Actor` and `Subject` to `Resource` is discussed in
|
102
|
+
[this issue](https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/-/issues/6).
|
42
103
|
|
43
104
|
For example:
|
44
105
|
|
@@ -64,14 +125,14 @@ class VehiclePolicy < DeclarativePolicy::Base
|
|
64
125
|
condition(:owns, score: 0) { @subject.owner == @user }
|
65
126
|
condition(:has_access_to, score: 3) { @subject.owner.trusts?(@user) }
|
66
127
|
condition(:intoxicated, score: 5) { @user.blood_alcohol > laws.max_blood_alcohol }
|
67
|
-
|
128
|
+
|
68
129
|
# conclusions we can draw:
|
69
130
|
rule { owns }.enable :drive_vehicle
|
70
131
|
rule { has_access_to }.enable :drive_vehicle
|
71
132
|
rule { ~old_enough_to_drive }.prevent :drive_vehicle
|
72
133
|
rule { intoxicated }.prevent :drive_vehicle
|
73
134
|
rule { ~has_driving_license }.prevent :drive_vehicle
|
74
|
-
|
135
|
+
|
75
136
|
# we can use methods to abstract common logic
|
76
137
|
def laws
|
77
138
|
@subject.registration.country.driving_laws
|
@@ -128,10 +189,16 @@ interactive prompt that will allow you to experiment.
|
|
128
189
|
|
129
190
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
130
191
|
|
192
|
+
## Additional Reading Material
|
193
|
+
|
194
|
+
More details on policies and custom roles can be found in the following pages:
|
195
|
+
- [Development Process for the DeclarativePolicy framework](https://docs.gitlab.com/ee/development/policies.html)
|
196
|
+
- [Custom Roles docs](https://docs.gitlab.com/ee/development/permissions/custom_roles.html)
|
197
|
+
|
131
198
|
## Contributing
|
132
199
|
|
133
200
|
Bug reports and merge requests are welcome on GitLab at
|
134
|
-
https://gitlab.com/gitlab-org/declarative-policy. This project is intended to be
|
201
|
+
https://gitlab.com/gitlab-org/ruby/gems/declarative-policy. This project is intended to be
|
135
202
|
a safe, welcoming space for collaboration, and contributors are expected to
|
136
203
|
adhere to the [GitLab code of conduct](https://about.gitlab.com/community/contribute/code-of-conduct/).
|
137
204
|
|
@@ -5,8 +5,8 @@ require_relative 'lib/declarative_policy/version'
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'declarative_policy'
|
7
7
|
spec.version = DeclarativePolicy::VERSION
|
8
|
-
spec.authors = ['
|
9
|
-
spec.email = ['
|
8
|
+
spec.authors = ['group::authorization']
|
9
|
+
spec.email = ['engineering@gitlab.com']
|
10
10
|
|
11
11
|
spec.summary = 'An authorization library with a focus on declarative policy definitions.'
|
12
12
|
spec.description = <<~DESC
|
@@ -17,20 +17,35 @@ Gem::Specification.new do |spec|
|
|
17
17
|
|
18
18
|
This library is in production use at GitLab.com
|
19
19
|
DESC
|
20
|
-
spec.homepage = 'https://gitlab.com/gitlab-org/declarative-policy'
|
20
|
+
spec.homepage = 'https://gitlab.com/gitlab-org/ruby/gems/declarative-policy'
|
21
21
|
spec.license = 'MIT'
|
22
|
-
spec.required_ruby_version = Gem::Requirement.new('>=
|
22
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
|
23
23
|
|
24
24
|
spec.metadata['homepage_uri'] = spec.homepage
|
25
|
-
spec.metadata['source_code_uri'] = 'https://gitlab.com/gitlab-org/declarative-policy'
|
26
|
-
spec.metadata['changelog_uri'] = 'https://gitlab.com/gitlab-org/declarative-policy/-/
|
25
|
+
spec.metadata['source_code_uri'] = 'https://gitlab.com/gitlab-org/ruby/gems/declarative-policy'
|
26
|
+
spec.metadata['changelog_uri'] = 'https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/-/blob/main/CHANGELOG.md'
|
27
|
+
|
28
|
+
spec.metadata['rubygems_mfa_required'] = 'false'
|
27
29
|
|
28
30
|
# Specify which files should be added to the gem when it is released.
|
29
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
30
31
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
31
|
-
|
32
|
+
%w[
|
33
|
+
*.gemspec
|
34
|
+
lib/**/*.rb
|
35
|
+
*.{md,txt}
|
36
|
+
doc/**/*
|
37
|
+
].flat_map { |pattern| Dir.glob(pattern) }
|
32
38
|
end
|
33
39
|
spec.bindir = 'exe'
|
34
40
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
35
41
|
spec.require_paths = ['lib']
|
42
|
+
|
43
|
+
# Development dependencies:
|
44
|
+
spec.add_development_dependency 'benchmark-ips', '~> 2.12'
|
45
|
+
spec.add_development_dependency 'gitlab-dangerfiles', '~> 3.8'
|
46
|
+
spec.add_development_dependency 'gitlab-styles', '~> 12.0'
|
47
|
+
spec.add_development_dependency 'pry-byebug'
|
48
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
49
|
+
spec.add_development_dependency 'rspec', '~> 3.10'
|
50
|
+
spec.add_development_dependency 'rspec-parameterized', '~> 1.0'
|
36
51
|
end
|
data/doc/caching.md
CHANGED
@@ -122,8 +122,8 @@ policy itself.
|
|
122
122
|
|
123
123
|
The best approach here is to use normal Ruby methods and instance variables for
|
124
124
|
such values. The policy instances themselves are cached, so that any two
|
125
|
-
invocations of `DeclarativePolicy.policy_for(user,
|
126
|
-
`user` and `
|
125
|
+
invocations of `DeclarativePolicy.policy_for(user, subject)` with identical
|
126
|
+
`user` and `subject` arguments will always return the same policy object. This
|
127
127
|
means instance variables stored on the policy will be available for the lifetime
|
128
128
|
of the cache.
|
129
129
|
|
@@ -209,18 +209,18 @@ In this case, it doesn't matter who the user is or even where they are going:
|
|
209
209
|
the condition will be computed once (per cache lifetime) for all combinations.
|
210
210
|
|
211
211
|
Because of the implications for sharing, the scope determines the
|
212
|
-
[`#score`](https://gitlab.com/gitlab-org/declarative-policy/blob/2ab9dbdf44fb37beb8d0f7c131742d47ae9ef5d0/lib/declarative_policy/condition.rb#L58-77) of
|
212
|
+
[`#score`](https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/blob/2ab9dbdf44fb37beb8d0f7c131742d47ae9ef5d0/lib/declarative_policy/condition.rb#L58-77) of
|
213
213
|
the condition (if not provided explicitly). The intention is to prefer values we
|
214
214
|
are more likely (all other things being equal) to re-use:
|
215
215
|
|
216
216
|
- Conditions we have already cached get a score of `0`.
|
217
217
|
- Conditions that are in the `:global` scope get a score of `2`.
|
218
218
|
- Conditions that are in the `:user` or `:subject` scopes get a score of `8`.
|
219
|
-
- Conditions that are in the `:
|
219
|
+
- Conditions that are in the `:user_and_subject` scope get a score of `16`.
|
220
220
|
|
221
221
|
Bear helper-methods in mind when defining scopes. While the instance level cache
|
222
222
|
for non-boolean values would not be shared, as long as the derived condition is
|
223
|
-
shared (for example by being in the `:user` scope, rather than the `:
|
223
|
+
shared (for example by being in the `:user` scope, rather than the `:user_and_subject`
|
224
224
|
scope), helper-methods will also benefit from improved cache hits.
|
225
225
|
|
226
226
|
### Preferred scope
|
@@ -231,7 +231,7 @@ the `:subject` or the `:user` scope. We can inform the optimizer of this
|
|
231
231
|
by setting `DeclarativePolicy.preferred_scope`.
|
232
232
|
|
233
233
|
To do this, check the abilities within a block bounded
|
234
|
-
by [`DeclarativePolicy.with_preferred_scope`](https://gitlab.com/gitlab-org/declarative-policy/blob/481c322a74f76c325d3ccab7f2f3cc2773e8168b/lib/declarative_policy/preferred_scope.rb#L7-13).
|
234
|
+
by [`DeclarativePolicy.with_preferred_scope`](https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/blob/481c322a74f76c325d3ccab7f2f3cc2773e8168b/lib/declarative_policy/preferred_scope.rb#L7-13).
|
235
235
|
For example:
|
236
236
|
|
237
237
|
```ruby
|
@@ -270,7 +270,7 @@ have different `object_id` values, and using `object_id` will not get optimal ca
|
|
270
270
|
policy subjects should implement `#id` for this reason. `ActiveRecord` models
|
271
271
|
with an `id` primary ID attribute do not need any extra configuration.
|
272
272
|
|
273
|
-
Please see: [`DeclarativePolicy::Cache`](https://gitlab.com/gitlab-org/declarative-policy/blob/
|
273
|
+
Please see: [`DeclarativePolicy::Cache`](https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/blob/main/lib/declarative_policy/cache.rb).
|
274
274
|
|
275
275
|
## Cache invalidation
|
276
276
|
|
data/doc/defining-policies.md
CHANGED
@@ -22,9 +22,9 @@ and then evaluating them with `DeclarativePolicy::Base#allowed?`.
|
|
22
22
|
You may wish to define a method to abstract policy evaluation. Something like:
|
23
23
|
|
24
24
|
```ruby
|
25
|
-
def allowed?(user, ability,
|
25
|
+
def allowed?(user, ability, subject)
|
26
26
|
opts = { cache: Cache.current_cache } # re-using a cache between checks eliminates duplication of work
|
27
|
-
policy = DeclarativePolicy.policy_for(user,
|
27
|
+
policy = DeclarativePolicy.policy_for(user, subject, opts)
|
28
28
|
policy.allowed?(ability)
|
29
29
|
end
|
30
30
|
```
|
@@ -41,9 +41,9 @@ want to know if a user can drive a vehicle. We need a `VehiclePolicy`:
|
|
41
41
|
```ruby
|
42
42
|
class VehiclePolicy < DeclarativePolicy::Base
|
43
43
|
# conditions go here by convention
|
44
|
-
|
44
|
+
|
45
45
|
# rules go here by convention
|
46
|
-
|
46
|
+
|
47
47
|
# helper methods go last
|
48
48
|
end
|
49
49
|
```
|
@@ -55,14 +55,14 @@ Conditions are facts about the state of the system.
|
|
55
55
|
They have access to two elements of the proposition:
|
56
56
|
|
57
57
|
- `@user` - the representation of a user in your system: the *subject* of the proposition.
|
58
|
-
`user` in `allowed?(user, ability,
|
58
|
+
`user` in `allowed?(user, ability, subject)`. `@user` may be `nil`, which means
|
59
59
|
that the current user is anonymous (for example this may reflect an
|
60
60
|
unauthenticated request in your system).
|
61
61
|
- `@subject` - any domain object that has an associated policy: the *object* of
|
62
|
-
the predicate of the proposition. `
|
62
|
+
the predicate of the proposition. `subject` in `allowed?(user, ability, subject)`.
|
63
63
|
`@subject` is never `nil`. See [handling `nil` values](./configuration.md#handling-nil-values)
|
64
64
|
for details of how to apply policies to `nil` values.
|
65
|
-
|
65
|
+
|
66
66
|
|
67
67
|
They are defined as `condition(name, **options, &block)`, where the block is
|
68
68
|
evaluated in the context of an instance of the policy.
|
@@ -184,7 +184,7 @@ like:
|
|
184
184
|
```ruby
|
185
185
|
class DrivingLicensePolicy < DeclarativePolicy::Base
|
186
186
|
condition(:expired) { @subject.expires_at <= Time.current }
|
187
|
-
|
187
|
+
|
188
188
|
rule { expired }.prevent :drive_vehicle
|
189
189
|
end
|
190
190
|
```
|
@@ -194,7 +194,7 @@ And a registration policy:
|
|
194
194
|
```ruby
|
195
195
|
class RegistrationPolicy < DeclarativePolicy::Base
|
196
196
|
condition(:valid) { @subject.valid_for?(@user.current_location) }
|
197
|
-
|
197
|
+
|
198
198
|
rule { ~valid }.prevent :drive_vehicle
|
199
199
|
end
|
200
200
|
```
|
@@ -209,3 +209,41 @@ delegate { @subject.registration }
|
|
209
209
|
|
210
210
|
This is a powerful mechanism for inferring rules based on relationships between
|
211
211
|
objects.
|
212
|
+
|
213
|
+
#### Overrides
|
214
|
+
|
215
|
+
It can be useful to declare that the given abilities should not be read
|
216
|
+
from delegates. This declaration is useful if you have an ability you want
|
217
|
+
to define differently in a policy than in a delegated policy, but you still
|
218
|
+
want to delegate all other abilities.
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
delegate { @subject.parent }
|
222
|
+
|
223
|
+
overrides :drive_car, :watch_tv
|
224
|
+
```
|
225
|
+
|
226
|
+
NOTE:
|
227
|
+
Rules with `prevent_all` present in the delegated policy are properly
|
228
|
+
not used during overridden abilities evaluation.
|
229
|
+
|
230
|
+
#### Delegated conditions
|
231
|
+
|
232
|
+
When named delegates are defined, their [conditions](#conditions) can be
|
233
|
+
referenced in [rules](#rules) using bare words.
|
234
|
+
|
235
|
+
Given a registration policy:
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
class RegistrationPolicy < DeclarativePolicy::Base
|
239
|
+
condition(:valid) { @subject.valid_for?(@user.current_location) }
|
240
|
+
end
|
241
|
+
```
|
242
|
+
|
243
|
+
The vehicle policy can reference the `:valid` condition as follows:
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
delegate(:registration) { @subject.registration }
|
247
|
+
|
248
|
+
rule { registration.valid }.enable :drive_vehicle
|
249
|
+
```
|
data/doc/optimization.md
CHANGED
@@ -97,7 +97,7 @@ They aren't necessarily run in this order, however. Instead, we try to order
|
|
97
97
|
the list to minimize unnecessary work.
|
98
98
|
|
99
99
|
The
|
100
|
-
[logic](https://gitlab.com/gitlab-org/declarative-policy/blob/659ac0525773a76cf8712d47b3c2dadd03b758c9/lib/declarative_policy/runner.rb#L80-112)
|
100
|
+
[logic](https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/blob/659ac0525773a76cf8712d47b3c2dadd03b758c9/lib/declarative_policy/runner.rb#L80-112)
|
101
101
|
to process this list is (in pseudo-code):
|
102
102
|
|
103
103
|
```pseudo
|
@@ -9,10 +9,14 @@ module DeclarativePolicy
|
|
9
9
|
class Condition
|
10
10
|
attr_reader :name, :description, :scope, :manual_score, :context_key
|
11
11
|
|
12
|
+
VALID_SCOPES = %i[user_and_subject user subject global].freeze
|
13
|
+
ALLOWED_SCOPES = VALID_SCOPES + %i[normal]
|
14
|
+
|
12
15
|
def initialize(name, opts = {}, &compute)
|
13
16
|
@name = name
|
14
17
|
@compute = compute
|
15
|
-
@scope = opts
|
18
|
+
@scope = fetch_scope(opts)
|
19
|
+
|
16
20
|
@description = opts.delete(:description)
|
17
21
|
@context_key = opts[:context_key]
|
18
22
|
@manual_score = opts.fetch(:score, nil)
|
@@ -25,6 +29,20 @@ module DeclarativePolicy
|
|
25
29
|
def key
|
26
30
|
"#{@context_key}/#{@name}"
|
27
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def fetch_scope(options)
|
36
|
+
result = options.fetch(:scope, :user_and_subject)
|
37
|
+
if result == :normal
|
38
|
+
warn "[DEPRECATION] `:normal` is deprecated and will be removed in 2.0. Please use new name `:user_and_subject`"
|
39
|
+
result = :user_and_subject
|
40
|
+
end
|
41
|
+
|
42
|
+
raise "Invalid scope #{result}. Allowed values: #{VALID_SCOPES.inspect}" unless ALLOWED_SCOPES.include?(result)
|
43
|
+
|
44
|
+
result
|
45
|
+
end
|
28
46
|
end
|
29
47
|
|
30
48
|
# In contrast to a Condition, a ManifestCondition contains
|
@@ -68,7 +86,7 @@ module DeclarativePolicy
|
|
68
86
|
return 2 if @condition.scope == :global
|
69
87
|
|
70
88
|
# "Normal" rules can't share caches with any other policies
|
71
|
-
return 16 if @condition.scope == :
|
89
|
+
return 16 if @condition.scope == :user_and_subject
|
72
90
|
|
73
91
|
# otherwise, we're :user or :subject scope, so it's 4 if
|
74
92
|
# the caller has declared a preference
|
@@ -85,11 +103,10 @@ module DeclarativePolicy
|
|
85
103
|
def cache_key
|
86
104
|
@cache_key ||=
|
87
105
|
case @condition.scope
|
88
|
-
when :
|
106
|
+
when :global then "/dp/condition/#{@condition.key}"
|
89
107
|
when :user then "/dp/condition/#{@condition.key}/#{user_key}"
|
90
108
|
when :subject then "/dp/condition/#{@condition.key}/#{subject_key}"
|
91
|
-
|
92
|
-
else raise 'invalid scope'
|
109
|
+
else "/dp/condition/#{@condition.key}/#{user_key},#{subject_key}"
|
93
110
|
end
|
94
111
|
end
|
95
112
|
|
@@ -35,7 +35,7 @@ module DeclarativePolicy
|
|
35
35
|
def policy_class(domain_class_name)
|
36
36
|
return unless domain_class_name
|
37
37
|
|
38
|
-
@class_for.call(
|
38
|
+
@class_for.call(@name_transformation.call(domain_class_name))
|
39
39
|
rescue NameError
|
40
40
|
nil
|
41
41
|
end
|
@@ -33,10 +33,10 @@ module DeclarativePolicy
|
|
33
33
|
@context_class.prevent_all_when(@rule)
|
34
34
|
end
|
35
35
|
|
36
|
-
def method_missing(msg,
|
36
|
+
def method_missing(msg, ...)
|
37
37
|
return super unless @context_class.respond_to?(msg)
|
38
38
|
|
39
|
-
@context_class.__send__(msg,
|
39
|
+
@context_class.__send__(msg, ...) # rubocop: disable GitlabSecurity/PublicSend
|
40
40
|
end
|
41
41
|
|
42
42
|
def respond_to_missing?(msg)
|
metadata
CHANGED
@@ -1,16 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: declarative_policy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
- Alexis Kalderimis
|
7
|
+
- group::authorization
|
9
8
|
autorequire:
|
10
9
|
bindir: exe
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
11
|
+
date: 2025-08-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: benchmark-ips
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: gitlab-dangerfiles
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.8'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.8'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: gitlab-styles
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '12.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '12.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry-byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '12.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '12.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.10'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.10'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-parameterized
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
14
111
|
description: |
|
15
112
|
This library provides an authorization framework with a declarative DSL
|
16
113
|
|
@@ -19,28 +116,17 @@ description: |
|
|
19
116
|
|
20
117
|
This library is in production use at GitLab.com
|
21
118
|
email:
|
22
|
-
-
|
119
|
+
- engineering@gitlab.com
|
23
120
|
executables: []
|
24
121
|
extensions: []
|
25
122
|
extra_rdoc_files: []
|
26
123
|
files:
|
27
|
-
- ".gitignore"
|
28
|
-
- ".gitlab-ci.yml"
|
29
|
-
- ".rspec"
|
30
|
-
- ".rubocop.yml"
|
31
124
|
- CHANGELOG.md
|
32
125
|
- CODE_OF_CONDUCT.md
|
33
126
|
- CONTRIBUTING.md
|
34
|
-
- Dangerfile
|
35
|
-
- Gemfile
|
36
|
-
- Gemfile.lock
|
37
127
|
- LICENSE.txt
|
38
128
|
- README.md
|
39
|
-
-
|
40
|
-
- benchmarks/repeated_invocation.rb
|
41
|
-
- danger/plugins/project_helper.rb
|
42
|
-
- danger/roulette/Dangerfile
|
43
|
-
- declarative_policy.gemspec
|
129
|
+
- declarative-policy.gemspec
|
44
130
|
- doc/caching.md
|
45
131
|
- doc/configuration.md
|
46
132
|
- doc/defining-policies.md
|
@@ -59,13 +145,14 @@ files:
|
|
59
145
|
- lib/declarative_policy/runner.rb
|
60
146
|
- lib/declarative_policy/step.rb
|
61
147
|
- lib/declarative_policy/version.rb
|
62
|
-
homepage: https://gitlab.com/gitlab-org/declarative-policy
|
148
|
+
homepage: https://gitlab.com/gitlab-org/ruby/gems/declarative-policy
|
63
149
|
licenses:
|
64
150
|
- MIT
|
65
151
|
metadata:
|
66
|
-
homepage_uri: https://gitlab.com/gitlab-org/declarative-policy
|
67
|
-
source_code_uri: https://gitlab.com/gitlab-org/declarative-policy
|
68
|
-
changelog_uri: https://gitlab.com/gitlab-org/declarative-policy/-/
|
152
|
+
homepage_uri: https://gitlab.com/gitlab-org/ruby/gems/declarative-policy
|
153
|
+
source_code_uri: https://gitlab.com/gitlab-org/ruby/gems/declarative-policy
|
154
|
+
changelog_uri: https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/-/blob/main/CHANGELOG.md
|
155
|
+
rubygems_mfa_required: 'false'
|
69
156
|
post_install_message:
|
70
157
|
rdoc_options: []
|
71
158
|
require_paths:
|
@@ -74,14 +161,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
161
|
requirements:
|
75
162
|
- - ">="
|
76
163
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
164
|
+
version: 3.0.0
|
78
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
166
|
requirements:
|
80
167
|
- - ">="
|
81
168
|
- !ruby/object:Gem::Version
|
82
169
|
version: '0'
|
83
170
|
requirements: []
|
84
|
-
rubygems_version: 3.
|
171
|
+
rubygems_version: 3.5.22
|
85
172
|
signing_key:
|
86
173
|
specification_version: 4
|
87
174
|
summary: An authorization library with a focus on declarative policy definitions.
|
data/.gitignore
DELETED
data/.gitlab-ci.yml
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
image: "ruby:2.7"
|
2
|
-
|
3
|
-
include:
|
4
|
-
- template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
|
5
|
-
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
6
|
-
- template: Security/License-Scanning.gitlab-ci.yml
|
7
|
-
- template: Security/SAST.gitlab-ci.yml
|
8
|
-
- template: Security/Secret-Detection.gitlab-ci.yml
|
9
|
-
|
10
|
-
.tests:
|
11
|
-
stage: test
|
12
|
-
cache:
|
13
|
-
paths:
|
14
|
-
- vendor/ruby
|
15
|
-
before_script:
|
16
|
-
- ruby -v # Print out ruby version for debugging
|
17
|
-
- bundle install -j $(nproc) --path vendor/ruby/$RUBY_VERSION
|
18
|
-
|
19
|
-
rubocop:
|
20
|
-
extends: .tests
|
21
|
-
script:
|
22
|
-
- bundle exec rubocop
|
23
|
-
|
24
|
-
.rspec:
|
25
|
-
extends: .tests
|
26
|
-
script:
|
27
|
-
- bundle exec rspec
|
28
|
-
|
29
|
-
rspec:mri:
|
30
|
-
extends: .rspec
|
31
|
-
image: "ruby:$RUBY_VERSION"
|
32
|
-
parallel:
|
33
|
-
matrix:
|
34
|
-
- RUBY_VERSION:
|
35
|
-
- "2.7"
|
36
|
-
- "3.0"
|
37
|
-
|
38
|
-
rspec:jruby:
|
39
|
-
extends: .rspec
|
40
|
-
image: "bitnami/jruby:latest"
|
41
|
-
variables:
|
42
|
-
RUBY_VERSION: jruby
|
43
|
-
|
44
|
-
rspec:truffleruby:
|
45
|
-
extends: .rspec
|
46
|
-
image: "flavorjones/truffleruby:latest"
|
47
|
-
variables:
|
48
|
-
RUBY_VERSION: truffleruby
|
49
|
-
|
50
|
-
danger-review:
|
51
|
-
extends: .tests
|
52
|
-
needs: []
|
53
|
-
script:
|
54
|
-
- >
|
55
|
-
if [ -z "$DANGER_GITLAB_API_TOKEN" ]; then
|
56
|
-
# Force danger to skip CI source GitLab and fallback to "local only git repo".
|
57
|
-
unset GITLAB_CI
|
58
|
-
# We need to base SHA to help danger determine the base commit for this shallow clone.
|
59
|
-
bundle exec danger dry_run --fail-on-errors=true --verbose --base="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
|
60
|
-
else
|
61
|
-
bundle exec danger --fail-on-errors=true --verbose
|
62
|
-
fi
|
63
|
-
|
64
|
-
# run security jobs on MRs
|
65
|
-
# see: https://gitlab.com/gitlab-org/gitlab/-/issues/218444#note_478761991
|
66
|
-
|
67
|
-
brakeman-sast:
|
68
|
-
rules:
|
69
|
-
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
70
|
-
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
71
|
-
|
72
|
-
gemnasium-dependency_scanning:
|
73
|
-
rules:
|
74
|
-
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
75
|
-
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
76
|
-
|
77
|
-
bundler-audit-dependency_scanning:
|
78
|
-
rules:
|
79
|
-
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
80
|
-
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
81
|
-
|
82
|
-
license_scanning:
|
83
|
-
rules:
|
84
|
-
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
85
|
-
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
86
|
-
|
87
|
-
secret_detection:
|
88
|
-
rules:
|
89
|
-
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
90
|
-
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
91
|
-
|
data/.rspec
DELETED
data/.rubocop.yml
DELETED
data/Dangerfile
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'gitlab-dangerfiles'
|
4
|
-
|
5
|
-
Gitlab::Dangerfiles.import_plugins(danger)
|
6
|
-
danger.import_plugin('danger/plugins/*.rb')
|
7
|
-
|
8
|
-
return if helper.release_automation?
|
9
|
-
|
10
|
-
danger.import_dangerfile(path: File.join('danger', 'roulette'))
|
11
|
-
|
12
|
-
anything_to_post = status_report.values.any?(&:any?)
|
13
|
-
|
14
|
-
if helper.ci? && anything_to_post
|
15
|
-
markdown("**If needed, you can retry the [`danger-review` job](#{ENV['CI_JOB_URL']}) that generated this comment.**")
|
16
|
-
end
|
data/Gemfile
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
source 'https://rubygems.org'
|
4
|
-
|
5
|
-
# Specify your gem's dependencies in declarative-policy.gemspec
|
6
|
-
gemspec
|
7
|
-
|
8
|
-
group :test do
|
9
|
-
gem 'rspec', '~> 3.10'
|
10
|
-
gem 'rspec-parameterized', require: false
|
11
|
-
gem 'pry-byebug', platforms: [:ruby]
|
12
|
-
end
|
13
|
-
|
14
|
-
group :development, :test do
|
15
|
-
gem 'gitlab-styles', '~> 6.1.0', require: false, platforms: [:ruby]
|
16
|
-
gem 'rake', '~> 12.0'
|
17
|
-
gem 'benchmark', require: false
|
18
|
-
gem 'rubocop', require: false
|
19
|
-
end
|
20
|
-
|
21
|
-
group :development, :test, :danger do
|
22
|
-
gem 'gitlab-dangerfiles', '~> 1.1.0', require: false, platforms: [:ruby]
|
23
|
-
end
|
data/Gemfile.lock
DELETED
@@ -1,214 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
declarative_policy (1.1.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
abstract_type (0.0.7)
|
10
|
-
activesupport (6.1.3.2)
|
11
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
-
i18n (>= 1.6, < 2)
|
13
|
-
minitest (>= 5.1)
|
14
|
-
tzinfo (~> 2.0)
|
15
|
-
zeitwerk (~> 2.3)
|
16
|
-
adamantium (0.2.0)
|
17
|
-
ice_nine (~> 0.11.0)
|
18
|
-
memoizable (~> 0.4.0)
|
19
|
-
addressable (2.7.0)
|
20
|
-
public_suffix (>= 2.0.2, < 5.0)
|
21
|
-
ast (2.4.2)
|
22
|
-
benchmark (0.1.1)
|
23
|
-
binding_ninja (0.2.3)
|
24
|
-
binding_ninja (0.2.3-java)
|
25
|
-
byebug (11.1.3)
|
26
|
-
claide (1.0.3)
|
27
|
-
claide-plugins (0.9.2)
|
28
|
-
cork
|
29
|
-
nap
|
30
|
-
open4 (~> 1.3)
|
31
|
-
coderay (1.1.3)
|
32
|
-
colored2 (3.1.2)
|
33
|
-
concord (0.1.5)
|
34
|
-
adamantium (~> 0.2.0)
|
35
|
-
equalizer (~> 0.0.9)
|
36
|
-
concurrent-ruby (1.1.8)
|
37
|
-
cork (0.3.0)
|
38
|
-
colored2 (~> 3.1)
|
39
|
-
danger (8.2.3)
|
40
|
-
claide (~> 1.0)
|
41
|
-
claide-plugins (>= 0.9.2)
|
42
|
-
colored2 (~> 3.1)
|
43
|
-
cork (~> 0.1)
|
44
|
-
faraday (>= 0.9.0, < 2.0)
|
45
|
-
faraday-http-cache (~> 2.0)
|
46
|
-
git (~> 1.7)
|
47
|
-
kramdown (~> 2.3)
|
48
|
-
kramdown-parser-gfm (~> 1.0)
|
49
|
-
no_proxy_fix
|
50
|
-
octokit (~> 4.7)
|
51
|
-
terminal-table (>= 1, < 4)
|
52
|
-
danger-gitlab (8.0.0)
|
53
|
-
danger
|
54
|
-
gitlab (~> 4.2, >= 4.2.0)
|
55
|
-
diff-lcs (1.4.4)
|
56
|
-
equalizer (0.0.11)
|
57
|
-
faraday (1.4.1)
|
58
|
-
faraday-excon (~> 1.1)
|
59
|
-
faraday-net_http (~> 1.0)
|
60
|
-
faraday-net_http_persistent (~> 1.1)
|
61
|
-
multipart-post (>= 1.2, < 3)
|
62
|
-
ruby2_keywords (>= 0.0.4)
|
63
|
-
faraday-excon (1.1.0)
|
64
|
-
faraday-http-cache (2.2.0)
|
65
|
-
faraday (>= 0.8)
|
66
|
-
faraday-net_http (1.0.1)
|
67
|
-
faraday-net_http_persistent (1.1.0)
|
68
|
-
ffi (1.15.4-java)
|
69
|
-
git (1.8.1)
|
70
|
-
rchardet (~> 1.8)
|
71
|
-
gitlab (4.17.0)
|
72
|
-
httparty (~> 0.18)
|
73
|
-
terminal-table (~> 1.5, >= 1.5.1)
|
74
|
-
gitlab-dangerfiles (1.1.1)
|
75
|
-
danger-gitlab
|
76
|
-
gitlab-styles (6.1.0)
|
77
|
-
rubocop (~> 0.91, >= 0.91.1)
|
78
|
-
rubocop-gitlab-security (~> 0.1.1)
|
79
|
-
rubocop-performance (~> 1.9.2)
|
80
|
-
rubocop-rails (~> 2.9)
|
81
|
-
rubocop-rspec (~> 1.44)
|
82
|
-
httparty (0.18.1)
|
83
|
-
mime-types (~> 3.0)
|
84
|
-
multi_xml (>= 0.5.2)
|
85
|
-
i18n (1.8.10)
|
86
|
-
concurrent-ruby (~> 1.0)
|
87
|
-
ice_nine (0.11.2)
|
88
|
-
kramdown (2.3.1)
|
89
|
-
rexml
|
90
|
-
kramdown-parser-gfm (1.1.0)
|
91
|
-
kramdown (~> 2.0)
|
92
|
-
memoizable (0.4.2)
|
93
|
-
thread_safe (~> 0.3, >= 0.3.1)
|
94
|
-
method_source (1.0.0)
|
95
|
-
mime-types (3.3.1)
|
96
|
-
mime-types-data (~> 3.2015)
|
97
|
-
mime-types-data (3.2021.0225)
|
98
|
-
minitest (5.14.4)
|
99
|
-
multi_xml (0.6.0)
|
100
|
-
multipart-post (2.1.1)
|
101
|
-
nap (1.1.0)
|
102
|
-
no_proxy_fix (0.1.2)
|
103
|
-
octokit (4.21.0)
|
104
|
-
faraday (>= 0.9)
|
105
|
-
sawyer (~> 0.8.0, >= 0.5.3)
|
106
|
-
open4 (1.3.4)
|
107
|
-
parallel (1.20.1)
|
108
|
-
parser (3.0.0.0)
|
109
|
-
ast (~> 2.4.1)
|
110
|
-
proc_to_ast (0.1.0)
|
111
|
-
coderay
|
112
|
-
parser
|
113
|
-
unparser
|
114
|
-
procto (0.0.3)
|
115
|
-
pry (0.13.1)
|
116
|
-
coderay (~> 1.1)
|
117
|
-
method_source (~> 1.0)
|
118
|
-
pry (0.13.1-java)
|
119
|
-
coderay (~> 1.1)
|
120
|
-
method_source (~> 1.0)
|
121
|
-
spoon (~> 0.0)
|
122
|
-
pry-byebug (3.9.0)
|
123
|
-
byebug (~> 11.0)
|
124
|
-
pry (~> 0.13.0)
|
125
|
-
public_suffix (4.0.6)
|
126
|
-
rack (2.2.3)
|
127
|
-
rainbow (3.0.0)
|
128
|
-
rake (12.3.3)
|
129
|
-
rchardet (1.8.0)
|
130
|
-
regexp_parser (1.8.2)
|
131
|
-
rexml (3.2.4)
|
132
|
-
rspec (3.10.0)
|
133
|
-
rspec-core (~> 3.10.0)
|
134
|
-
rspec-expectations (~> 3.10.0)
|
135
|
-
rspec-mocks (~> 3.10.0)
|
136
|
-
rspec-core (3.10.1)
|
137
|
-
rspec-support (~> 3.10.0)
|
138
|
-
rspec-expectations (3.10.1)
|
139
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
140
|
-
rspec-support (~> 3.10.0)
|
141
|
-
rspec-mocks (3.10.2)
|
142
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
143
|
-
rspec-support (~> 3.10.0)
|
144
|
-
rspec-parameterized (0.4.2)
|
145
|
-
binding_ninja (>= 0.2.3)
|
146
|
-
parser
|
147
|
-
proc_to_ast
|
148
|
-
rspec (>= 2.13, < 4)
|
149
|
-
unparser
|
150
|
-
rspec-support (3.10.2)
|
151
|
-
rubocop (0.93.1)
|
152
|
-
parallel (~> 1.10)
|
153
|
-
parser (>= 2.7.1.5)
|
154
|
-
rainbow (>= 2.2.2, < 4.0)
|
155
|
-
regexp_parser (>= 1.8)
|
156
|
-
rexml
|
157
|
-
rubocop-ast (>= 0.6.0)
|
158
|
-
ruby-progressbar (~> 1.7)
|
159
|
-
unicode-display_width (>= 1.4.0, < 2.0)
|
160
|
-
rubocop-ast (1.4.1)
|
161
|
-
parser (>= 2.7.1.5)
|
162
|
-
rubocop-gitlab-security (0.1.1)
|
163
|
-
rubocop (>= 0.51)
|
164
|
-
rubocop-performance (1.9.2)
|
165
|
-
rubocop (>= 0.90.0, < 2.0)
|
166
|
-
rubocop-ast (>= 0.4.0)
|
167
|
-
rubocop-rails (2.9.1)
|
168
|
-
activesupport (>= 4.2.0)
|
169
|
-
rack (>= 1.1)
|
170
|
-
rubocop (>= 0.90.0, < 2.0)
|
171
|
-
rubocop-rspec (1.44.1)
|
172
|
-
rubocop (~> 0.87)
|
173
|
-
rubocop-ast (>= 0.7.1)
|
174
|
-
ruby-progressbar (1.11.0)
|
175
|
-
ruby2_keywords (0.0.4)
|
176
|
-
sawyer (0.8.2)
|
177
|
-
addressable (>= 2.3.5)
|
178
|
-
faraday (> 0.8, < 2.0)
|
179
|
-
spoon (0.0.6)
|
180
|
-
ffi
|
181
|
-
terminal-table (1.8.0)
|
182
|
-
unicode-display_width (~> 1.1, >= 1.1.1)
|
183
|
-
thread_safe (0.3.6)
|
184
|
-
thread_safe (0.3.6-java)
|
185
|
-
tzinfo (2.0.4)
|
186
|
-
concurrent-ruby (~> 1.0)
|
187
|
-
unicode-display_width (1.7.0)
|
188
|
-
unparser (0.4.7)
|
189
|
-
abstract_type (~> 0.0.7)
|
190
|
-
adamantium (~> 0.2.0)
|
191
|
-
concord (~> 0.1.5)
|
192
|
-
diff-lcs (~> 1.3)
|
193
|
-
equalizer (~> 0.0.9)
|
194
|
-
parser (>= 2.6.5)
|
195
|
-
procto (~> 0.0.2)
|
196
|
-
zeitwerk (2.4.2)
|
197
|
-
|
198
|
-
PLATFORMS
|
199
|
-
ruby
|
200
|
-
universal-java-1.8
|
201
|
-
|
202
|
-
DEPENDENCIES
|
203
|
-
benchmark
|
204
|
-
declarative_policy!
|
205
|
-
gitlab-dangerfiles (~> 1.1.0)
|
206
|
-
gitlab-styles (~> 6.1.0)
|
207
|
-
pry-byebug
|
208
|
-
rake (~> 12.0)
|
209
|
-
rspec (~> 3.10)
|
210
|
-
rspec-parameterized
|
211
|
-
rubocop
|
212
|
-
|
213
|
-
BUNDLED WITH
|
214
|
-
2.2.15
|
data/Rakefile
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -w
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'declarative_policy'
|
5
|
-
require 'benchmark'
|
6
|
-
|
7
|
-
Dir["./spec/support/policies/*.rb"].sort.each { |f| require f }
|
8
|
-
Dir["./spec/support/models/*.rb"].sort.each { |f| require f }
|
9
|
-
|
10
|
-
TIMES = 1_000_000
|
11
|
-
LABEL = 'allowed?(driver, :drive_vehicle, car)'
|
12
|
-
|
13
|
-
DeclarativePolicy.configure! do
|
14
|
-
named_policy :global, GlobalPolicy
|
15
|
-
|
16
|
-
name_transformation do |name|
|
17
|
-
'ReadmePolicy' if name == 'Vehicle'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
Benchmark.bm(LABEL.length) do |b|
|
22
|
-
cache = {}
|
23
|
-
valid_license = License.valid
|
24
|
-
country = Country.moderate
|
25
|
-
registration = Registration.new(number: 'xyz123', country: country)
|
26
|
-
driver = User.new(name: 'The driver', driving_license: valid_license)
|
27
|
-
owner = User.new(name: 'The Owner', trusted: [driver.name])
|
28
|
-
car = Vehicle.new(owner: owner, registration: registration)
|
29
|
-
|
30
|
-
raise 'Expected to drive' unless DeclarativePolicy.policy_for(driver, car).allowed?(:drive_vehicle)
|
31
|
-
|
32
|
-
b.report LABEL do
|
33
|
-
TIMES.times do
|
34
|
-
DeclarativePolicy.policy_for(driver, car, cache: cache).allowed?(:drive_vehicle)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Danger
|
4
|
-
# Project specific configuration
|
5
|
-
class ProjectHelper < ::Danger::Plugin
|
6
|
-
LOCAL_RULES ||= %w[
|
7
|
-
changelog
|
8
|
-
documentation
|
9
|
-
].freeze
|
10
|
-
|
11
|
-
CI_ONLY_RULES ||= %w[
|
12
|
-
roulette
|
13
|
-
].freeze
|
14
|
-
|
15
|
-
MESSAGE_PREFIX = '==>'
|
16
|
-
|
17
|
-
# First-match win, so be sure to put more specific regex at the top...
|
18
|
-
# rubocop: disable Style/RegexpLiteral
|
19
|
-
CATEGORIES = {
|
20
|
-
%r{\A(\.gitlab-ci\.yml\z|\.gitlab/ci)} => :engineering_productivity,
|
21
|
-
%r{\Alefthook.yml\z} => :engineering_productivity,
|
22
|
-
%r{\A\.editorconfig\z} => :engineering_productivity,
|
23
|
-
%r{Dangerfile\z} => :engineering_productivity,
|
24
|
-
%r{\A(danger/|tooling/danger/)} => :engineering_productivity,
|
25
|
-
%r{\A?scripts/} => :engineering_productivity,
|
26
|
-
%r{\Atooling/} => :engineering_productivity,
|
27
|
-
%r{(CODEOWNERS)} => :engineering_productivity,
|
28
|
-
%r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
|
29
|
-
%r{\A\.rubocop((_manual)?_todo)?\.yml\z} => :backend,
|
30
|
-
%r{\.rb\z} => :backend,
|
31
|
-
%r{(
|
32
|
-
\.(md|txt)\z |
|
33
|
-
\.markdownlint\.json
|
34
|
-
)}x => :docs
|
35
|
-
}.freeze
|
36
|
-
# rubocop: enable Style/RegexpLiteral
|
37
|
-
|
38
|
-
def changes_by_category
|
39
|
-
helper.changes_by_category(CATEGORIES)
|
40
|
-
end
|
41
|
-
|
42
|
-
def changes
|
43
|
-
helper.changes(CATEGORIES)
|
44
|
-
end
|
45
|
-
|
46
|
-
def rule_names
|
47
|
-
helper.ci? ? LOCAL_RULES | CI_ONLY_RULES : LOCAL_RULES
|
48
|
-
end
|
49
|
-
|
50
|
-
def project_name
|
51
|
-
# 'declarative-policy'
|
52
|
-
# TODO: roulette uses the project name to find reviewers, but the gitlab team
|
53
|
-
# directory currently does not have any team members assigned to the declarative-policy
|
54
|
-
# project. We thus are piggybacking on 'gitlab' for now.
|
55
|
-
'gitlab'
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
data/danger/roulette/Dangerfile
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'digest/md5'
|
4
|
-
|
5
|
-
MESSAGE = <<MARKDOWN
|
6
|
-
## Reviewer roulette
|
7
|
-
|
8
|
-
Changes that require review have been detected! A merge request is normally
|
9
|
-
reviewed by both a reviewer and a maintainer.
|
10
|
-
MARKDOWN
|
11
|
-
|
12
|
-
CATEGORY_TABLE_HEADER = <<MARKDOWN
|
13
|
-
|
14
|
-
To spread load more evenly across eligible reviewers, Danger has picked a
|
15
|
-
candidate for each review slot, based on their timezone. Feel free to
|
16
|
-
[override these selections](https://about.gitlab.com/handbook/engineering/projects/#gitlab) if
|
17
|
-
you think someone else would be better-suited or use the
|
18
|
-
[GitLab Review Workload Dashboard](https://gitlab-org.gitlab.io/gitlab-roulette/) to find other
|
19
|
-
available reviewers.
|
20
|
-
|
21
|
-
To read more on how to use the reviewer roulette, please take a look at the
|
22
|
-
[Engineering workflow](https://about.gitlab.com/handbook/engineering/workflow/#basics) and
|
23
|
-
[code review guidelines](https://docs.gitlab.com/ee/development/code_review.html). You may
|
24
|
-
consider assigning a reviewer or maintainer who is
|
25
|
-
a [domain expert](https://about.gitlab.com/handbook/engineering/projects/#gitlab) for
|
26
|
-
the `DeclarativePolicy` library.
|
27
|
-
|
28
|
-
Once you've decided who will review this merge request, assign them as a reviewer!
|
29
|
-
Danger does not automatically notify them for you.
|
30
|
-
|
31
|
-
| Category | Reviewer | Maintainer |
|
32
|
-
| -------- | -------- | ---------- |
|
33
|
-
MARKDOWN
|
34
|
-
|
35
|
-
UNKNOWN_FILES_MESSAGE = <<MARKDOWN
|
36
|
-
|
37
|
-
These files couldn't be categorised, so Danger was unable to suggest a reviewer.
|
38
|
-
Please consider creating a merge request
|
39
|
-
to [add support](https://gitlab.com/gitlab-org/gitlab/blob/master/tooling/danger/project_helper.rb)
|
40
|
-
for them.
|
41
|
-
MARKDOWN
|
42
|
-
|
43
|
-
OPTIONAL_REVIEW_TEMPLATE = '%{role} review is optional for %{category}'
|
44
|
-
NOT_AVAILABLE_TEMPLATE = 'No %{role} available'
|
45
|
-
|
46
|
-
def note_for_spins_role(spins, role)
|
47
|
-
spins.each do |spin|
|
48
|
-
note = note_for_spin_role(spin, role)
|
49
|
-
|
50
|
-
return note if note
|
51
|
-
end
|
52
|
-
|
53
|
-
format(NOT_AVAILABLE_TEMPLATE, role: role)
|
54
|
-
end
|
55
|
-
|
56
|
-
def note_for_spin_role(spin, role)
|
57
|
-
if spin.optional_role == role
|
58
|
-
return format(OPTIONAL_REVIEW_TEMPLATE, role: role.capitalize, category: helper.label_for_category(spin.category))
|
59
|
-
end
|
60
|
-
|
61
|
-
spin.public_send(role)&.markdown_name(author: roulette.team_mr_author) # rubocop:disable GitlabSecurity/PublicSend
|
62
|
-
end
|
63
|
-
|
64
|
-
def markdown_row_for_spins(category, spins_array)
|
65
|
-
reviewer_note = note_for_spins_role(spins_array, :reviewer)
|
66
|
-
maintainer_note = note_for_spins_role(spins_array, :maintainer)
|
67
|
-
|
68
|
-
"| #{helper.label_for_category(category)} | #{reviewer_note} | #{maintainer_note} |"
|
69
|
-
end
|
70
|
-
|
71
|
-
changes = project_helper.changes_by_category
|
72
|
-
|
73
|
-
# Ignore any files that are known but uncategorized. Prompt for any unknown files
|
74
|
-
changes.delete(:none)
|
75
|
-
# To reinstate roulette for documentation, remove this line.
|
76
|
-
changes.delete(:docs)
|
77
|
-
# No special review for changelog needed and changelog was never a label.
|
78
|
-
changes.delete(:changelog)
|
79
|
-
# No special review for feature flags needed.
|
80
|
-
changes.delete(:feature_flag)
|
81
|
-
categories = changes.keys.to_set.delete(:unknown)
|
82
|
-
|
83
|
-
if changes.any?
|
84
|
-
project = project_helper.project_name
|
85
|
-
|
86
|
-
random_roulette_spins = roulette.spin(project, categories, timezone_experiment: false)
|
87
|
-
|
88
|
-
rows = random_roulette_spins.map do |spin|
|
89
|
-
markdown_row_for_spins(spin.category, [spin])
|
90
|
-
end
|
91
|
-
|
92
|
-
markdown(MESSAGE)
|
93
|
-
markdown(CATEGORY_TABLE_HEADER + rows.join("\n")) unless rows.empty?
|
94
|
-
|
95
|
-
unknown = changes.fetch(:unknown, [])
|
96
|
-
markdown(UNKNOWN_FILES_MESSAGE + helper.markdown_list(unknown)) unless unknown.empty?
|
97
|
-
end
|