Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile8
-rw-r--r--Gemfile.checksum26
-rw-r--r--Gemfile.lock21
-rw-r--r--app/controllers/passwords_controller.rb4
-rw-r--r--app/policies/ci/pipeline_policy.rb8
-rw-r--r--doc/administration/audit_event_streaming/audit_event_types.md1
-rw-r--r--doc/administration/gitaly/reference.md36
-rw-r--r--doc/install/requirements.md12
-rw-r--r--doc/update/versions/gitlab_16_changes.md6
-rw-r--r--lib/api/entities/feature.rb6
-rw-r--r--lib/api/helpers.rb24
-rw-r--r--locale/gitlab.pot12
-rw-r--r--spec/lib/api/helpers_spec.rb159
-rw-r--r--spec/policies/ci/pipeline_policy_spec.rb25
14 files changed, 302 insertions, 46 deletions
diff --git a/Gemfile b/Gemfile
index fea4a83e085..0a83dc69e97 100644
--- a/Gemfile
+++ b/Gemfile
@@ -536,14 +536,14 @@ gem 'kas-grpc', '~> 0.2.0'
gem 'grpc', '~> 1.55.0'
-gem 'google-protobuf', '~> 3.24', '>= 3.24.2'
+gem 'google-protobuf', '~> 3.24', '>= 3.24.3'
gem 'toml-rb', '~> 2.2.0'
# Feature toggles
-gem 'flipper', '~> 0.25.0'
-gem 'flipper-active_record', '~> 0.25.0'
-gem 'flipper-active_support_cache_store', '~> 0.25.0'
+gem 'flipper', '~> 0.26.2'
+gem 'flipper-active_record', '~> 0.26.2'
+gem 'flipper-active_support_cache_store', '~> 0.26.2'
gem 'unleash', '~> 3.2.2'
gem 'gitlab-experiment', '~> 0.7.1'
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 920b5cb24b6..583a2a26ec6 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -184,9 +184,9 @@
{"name":"ffi-yajl","version":"2.6.0","platform":"universal-java","checksum":"1159a093c51d75d67578e31d2ed429f2481ef7e73021c5d667ebf6ab481a0d21"},
{"name":"filelock","version":"1.1.1","platform":"ruby","checksum":"5207258374370a75d5927b2eaf9b831732d224e48ce56c318e8308c7cdcabb20"},
{"name":"find_a_port","version":"1.0.1","platform":"ruby","checksum":"605d6a84b5e6f138da2b06c87c5a4a0231e4fdc9b9a92022d9caa361f77d5ceb"},
-{"name":"flipper","version":"0.25.0","platform":"ruby","checksum":"ccb2776752b8378bc994c9d873ccde290c090341940761b873494695ee697add"},
-{"name":"flipper-active_record","version":"0.25.0","platform":"ruby","checksum":"85a5c99465e2cc6a09e91931a9998b0dbd463cd6c80dd513129377132e3eb67f"},
-{"name":"flipper-active_support_cache_store","version":"0.25.0","platform":"ruby","checksum":"7282bf994b08d1a076b65c6f3b51e3dc04fcb00fa6e7b20089e60db25c7b531b"},
+{"name":"flipper","version":"0.26.2","platform":"ruby","checksum":"6d577208d971b2d53b7c090ef19765685c31bb43c3cc345d4ee11c1052f6f988"},
+{"name":"flipper-active_record","version":"0.26.2","platform":"ruby","checksum":"61deaeef8ce2f775e67d7095f40fd95fc2d07241e143dd4436e78c7b26a320bc"},
+{"name":"flipper-active_support_cache_store","version":"0.26.2","platform":"ruby","checksum":"c2d3883ad1e5c7de827c37df455ffe6e175bc0be93f2a260c54efdabb313d2b0"},
{"name":"fog-aliyun","version":"0.4.0","platform":"ruby","checksum":"8f2334604beb781eafbb9cd5f50141fbb2c7eb77c7f2b01f45c2e04db0e5cc38"},
{"name":"fog-aws","version":"3.18.0","platform":"ruby","checksum":"f4c5880ecfbc4edbf711dfd41140f9f17dfc68b519546d121448d2d3a5584704"},
{"name":"fog-core","version":"2.1.0","platform":"ruby","checksum":"53e5d793554d7080d015ef13cd44b54027e421d924d9dba4ce3d83f95f37eda9"},
@@ -242,16 +242,16 @@
{"name":"google-cloud-errors","version":"1.3.0","platform":"ruby","checksum":"450b681e24c089a20721a01acc4408bb4a7b0df28c175aaab488da917480d64b"},
{"name":"google-cloud-profiler-v2","version":"0.4.0","platform":"ruby","checksum":"53fc2ab175d08f54233c644310d47798feac996220916815c4fb44c937b5d3e3"},
{"name":"google-cloud-storage","version":"1.44.0","platform":"ruby","checksum":"299a1e055c9277c8120f7c10d21d37e4d8c17c7b963350c0e0bff7e9d9a570ea"},
-{"name":"google-protobuf","version":"3.24.2","platform":"aarch64-linux","checksum":"acd4be32962a648bc76cd44131bb8fd0ed18116e3774a8eb55d4cb8d3b7c3ce2"},
-{"name":"google-protobuf","version":"3.24.2","platform":"arm64-darwin","checksum":"743d50a21e3f1dc3152d38733948b2b680afb5b6095b0853e091deeb899fcf5a"},
-{"name":"google-protobuf","version":"3.24.2","platform":"java","checksum":"a2981147d7ef8a4fb751f6f53872159800f7e2db296ba1495f18905820785c3a"},
-{"name":"google-protobuf","version":"3.24.2","platform":"ruby","checksum":"0e5cbb7ff14d2fceedb69a7f5912f521fe6f0c7337e04a80b516a19fb70ec338"},
-{"name":"google-protobuf","version":"3.24.2","platform":"x64-mingw-ucrt","checksum":"88a5cae186ebd211243365e60d302f14b59394afd2913aa8e3b329b19b928477"},
-{"name":"google-protobuf","version":"3.24.2","platform":"x64-mingw32","checksum":"80787c24e244a0186efafbf3e17f5d6d02de7c3ebd63dc0129bc7d42aacf0022"},
-{"name":"google-protobuf","version":"3.24.2","platform":"x86-linux","checksum":"4e853ac257336e1cbbdef0bd3d8590e9f2e744e6dbdef4e3105d012f56a279b0"},
-{"name":"google-protobuf","version":"3.24.2","platform":"x86-mingw32","checksum":"7143a8ffcb831624c5d368bde73d2449737c89c9947d289495f887b4ce62a122"},
-{"name":"google-protobuf","version":"3.24.2","platform":"x86_64-darwin","checksum":"3dae4616b312e733cd32d4d63cd4bd96d5d1aed6d4e69917f073c45bfe037c96"},
-{"name":"google-protobuf","version":"3.24.2","platform":"x86_64-linux","checksum":"915d37758f7aaea497db7087d7cf92709529370a37fc4b77d14ddaa3f900c21d"},
+{"name":"google-protobuf","version":"3.24.3","platform":"aarch64-linux","checksum":"02591f0bb6a7b34da7f4451b3e9b684787eae6fab5c9283ff09be993830683cd"},
+{"name":"google-protobuf","version":"3.24.3","platform":"arm64-darwin","checksum":"34919ce25e3260954a509a7fb4ff4767e438c1d09cffe0998fa97aa7f547c50c"},
+{"name":"google-protobuf","version":"3.24.3","platform":"java","checksum":"f1582bd2665df61a363501b2a51bea61e2c8466bd1f8823a22b53cbea5aa7401"},
+{"name":"google-protobuf","version":"3.24.3","platform":"ruby","checksum":"63f3cceb398b5f3258760da95037d26ef65405aa3425fd7ba1560fce4827945d"},
+{"name":"google-protobuf","version":"3.24.3","platform":"x64-mingw-ucrt","checksum":"381f16aeda20d23465b9d9efffaa660367cda951299df0d5fd5662e9a119a36c"},
+{"name":"google-protobuf","version":"3.24.3","platform":"x64-mingw32","checksum":"5a687545a4a9deb93375107600aee43edfc495979ec8b88fff39d8c139e49330"},
+{"name":"google-protobuf","version":"3.24.3","platform":"x86-linux","checksum":"d7f556d618b83629a49f831a9358122a22c3a3ebd65f59c10f690c4ec95ad321"},
+{"name":"google-protobuf","version":"3.24.3","platform":"x86-mingw32","checksum":"05711b1c8cdf77fdbe8eabbe477b2b792758b6e2c5a72add222ac6f4c5626119"},
+{"name":"google-protobuf","version":"3.24.3","platform":"x86_64-darwin","checksum":"10d9645ebe89758fd81fcbcd678aaaa30c34ca2b2a2182e8dfc90e29df9cafb4"},
+{"name":"google-protobuf","version":"3.24.3","platform":"x86_64-linux","checksum":"e081a8345680b7883b48823a4123acdf45ebd169e3d5a3c2e0cb9ac47fc896eb"},
{"name":"googleapis-common-protos","version":"1.4.0","platform":"ruby","checksum":"da2380fb5ab1563580816c74e8d684ac17512c3654c829a3ee84f6d6139de382"},
{"name":"googleapis-common-protos-types","version":"1.5.0","platform":"ruby","checksum":"5769cf7376abc86ef7f5897a4aaca1d5c5a3c49ddabeddd2c251fcf8155f858b"},
{"name":"googleauth","version":"1.3.0","platform":"ruby","checksum":"51dd7362353cf1e90a2d01e1fb94321ae3926c776d4dc4a79db65230217ffcc2"},
diff --git a/Gemfile.lock b/Gemfile.lock
index c3115e0b0cc..795baf146d8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -561,13 +561,14 @@ GEM
libyajl2 (>= 1.2)
filelock (1.1.1)
find_a_port (1.0.1)
- flipper (0.25.0)
- flipper-active_record (0.25.0)
+ flipper (0.26.2)
+ concurrent-ruby (< 2)
+ flipper-active_record (0.26.2)
activerecord (>= 4.2, < 8)
- flipper (~> 0.25.0)
- flipper-active_support_cache_store (0.25.0)
+ flipper (~> 0.26.2)
+ flipper-active_support_cache_store (0.26.2)
activesupport (>= 4.2, < 8)
- flipper (~> 0.25.0)
+ flipper (~> 0.26.2)
fog-aliyun (0.4.0)
addressable (~> 2.8.0)
aliyun-sdk (~> 0.8.0)
@@ -753,7 +754,7 @@ GEM
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
- google-protobuf (3.24.2)
+ google-protobuf (3.24.3)
googleapis-common-protos (1.4.0)
google-protobuf (~> 3.14)
googleapis-common-protos-types (~> 1.2)
@@ -1803,9 +1804,9 @@ DEPENDENCIES
faraday_middleware-aws-sigv4 (~> 0.3.0)
fast_blank (~> 1.0.1)
ffaker (~> 2.10)
- flipper (~> 0.25.0)
- flipper-active_record (~> 0.25.0)
- flipper-active_support_cache_store (~> 0.25.0)
+ flipper (~> 0.26.2)
+ flipper-active_record (~> 0.26.2)
+ flipper-active_support_cache_store (~> 0.26.2)
fog-aliyun (~> 0.4)
fog-aws (~> 3.18)
fog-core (= 2.1.0)
@@ -1847,7 +1848,7 @@ DEPENDENCIES
google-apis-serviceusage_v1 (~> 0.28.0)
google-apis-sqladmin_v1beta4 (~> 0.41.0)
google-cloud-storage (~> 1.44.0)
- google-protobuf (~> 3.24, >= 3.24.2)
+ google-protobuf (~> 3.24, >= 3.24.3)
gpgme (~> 2.0.22)
grape (~> 1.7.1)
grape-entity (~> 0.10.0)
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index 38839497fb6..d1ca16bd8fb 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -43,6 +43,7 @@ class PasswordsController < Devise::PasswordsController
resource.password_expires_at = nil
resource.save(validate: false) if resource.changed?
else
+ log_audit_reset_failure(@user)
track_weak_password_error(@user, self.class.name, 'create')
end
end
@@ -50,6 +51,9 @@ class PasswordsController < Devise::PasswordsController
protected
+ # overriden in EE
+ def log_audit_reset_failure(_user); end
+
def resource_from_email
email = resource_params[:email]
self.resource = resource_class.find_by_email(email)
diff --git a/app/policies/ci/pipeline_policy.rb b/app/policies/ci/pipeline_policy.rb
index 4d21da0226b..1d60b1e79de 100644
--- a/app/policies/ci/pipeline_policy.rb
+++ b/app/policies/ci/pipeline_policy.rb
@@ -18,6 +18,10 @@ module Ci
@subject.triggered_by?(@user)
end
+ condition(:project_allows_read_dependency) do
+ can?(:read_dependency, @subject.project)
+ end
+
# Disallow users without permissions from accessing internal pipelines
rule { ~can?(:read_build) & ~external_pipeline }.policy do
prevent :read_pipeline
@@ -41,6 +45,10 @@ module Ci
enable :read_pipeline_variable
end
+ rule { project_allows_read_dependency }.policy do
+ enable :read_dependency
+ end
+
def ref_protected?(user, project, tag, ref)
access = ::Gitlab::UserAccess.new(user, container: project)
diff --git a/doc/administration/audit_event_streaming/audit_event_types.md b/doc/administration/audit_event_streaming/audit_event_types.md
index 2a7c3367f6a..331e991aeb3 100644
--- a/doc/administration/audit_event_streaming/audit_event_types.md
+++ b/doc/administration/audit_event_streaming/audit_event_types.md
@@ -170,6 +170,7 @@ Every audit event is associated with an event type. The association with the eve
| [`merged_merge_request_deleted`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118793) | Audit event triggered when a merged merge request is deleted | **{dotted-circle}** No | **{check-circle}** Yes | `source_code_management` | GitLab [16.0](https://gitlab.com/gitlab-org/gitlab/-/issues/408288) |
| [`merged_merge_request_deletion_started`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118793) | Audit event triggered when a merged merge request's deletion is started | **{dotted-circle}** No | **{check-circle}** Yes | `source_code_management` | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/408288) |
| [`omniauth_login_failed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123080) | Event triggered when an OmniAuth login fails | **{check-circle}** Yes | **{check-circle}** Yes | `compliance_management` | GitLab [16.3](https://gitlab.com/gitlab-org/gitlab/-/issues/374107) |
+| [`password_reset_failed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/129079) | Event triggered when a password reset fails for a user | **{dotted-circle}** No | **{check-circle}** Yes | `user_management` | GitLab [16.4](https://gitlab.com/gitlab-org/gitlab/-/issues/377762) |
| [`password_reset_requested`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114548) | Event triggered when a user requests a password reset using a registered email address | **{check-circle}** Yes | **{dotted-circle}** No | `compliance_management` | GitLab [15.11](https://gitlab.com/gitlab-org/gitlab/-/issues/374107) |
| [`personal_access_token_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108952) | Event triggered when a user creates a personal access token | **{check-circle}** Yes | **{check-circle}** Yes | `compliance_management` | GitLab [15.9](https://gitlab.com/gitlab-org/gitlab/-/issues/374113) |
| [`personal_access_token_revoked`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108952) | Event triggered when a personal access token is revoked | **{check-circle}** Yes | **{check-circle}** Yes | `compliance_management` | GitLab [15.9](https://gitlab.com/gitlab-org/gitlab/-/issues/374113) |
diff --git a/doc/administration/gitaly/reference.md b/doc/administration/gitaly/reference.md
index aa04c9a92c4..5b26c93cea8 100644
--- a/doc/administration/gitaly/reference.md
+++ b/doc/administration/gitaly/reference.md
@@ -155,25 +155,43 @@ Prometheus query to see the hit rate:
sum(rate(gitaly_catfile_cache_total{type="hit"}[5m])) / sum(rate(gitaly_catfile_cache_total{type=~"(hit)|(miss)"}[5m]))
```
-### GitLab Shell
+#### Custom Hooks
-For historical reasons
-[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) contains
-the Git hooks that allow GitLab to validate and react to Git pushes.
-Because Gitaly "owns" Git pushes, GitLab Shell must therefore be
-installed alongside Gitaly.
+> Method of configuring custom hooks directory documented here is preferred from GitLab 16.4. `[gitlab-shell] dir` configuration is no longer required.
+
+Gitaly supports [custom Git hooks](../server_hooks.md) that are
+used to perform tasks based on changes performed in any repository. The custom
+hooks directory is configured in the `[hooks]` section:
| Name | Type | Required | Description |
| ---- | ---- | -------- | ----------- |
-| `dir` | string | yes | The directory where GitLab Shell is installed.|
+| `custom_hooks_dir` | string | no | The directory where custom Git hooks are installed. |
Example:
```toml
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
+[hooks]
+custom_hooks_dir = "/home/git/custom-hooks"
```
+If left unset, no custom hooks are used.
+
+### GitLab
+
+> Method of configuring custom hooks directory documented here is preferred from GitLab 16.4. `[gitlab-shell] dir` configuration is no longer required.
+
+Gitaly must connect to the GitLab application to perform access
+checks when a user performs a change. The parameters to connect to GitLab must
+be configured in the `[gitlab]` section.
+
+| Name | Type | Required | Description |
+| ---- | ---- | -------- | ----------- |
+| `url` | string | yes | The URL of the GitLab server.
+| `secret` | string | no | The secret token used to authenticate with GitLab. |
+| `secret_file` | string | no | The path of the file containing the secret token used to authenticate with GitLab. |
+
+Only one of `secret` or `secret_file` can be configured.
+
### Prometheus
You can optionally configure Gitaly to record histogram latencies on GRPC method
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 5289cba10c1..81244594a59 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -50,11 +50,13 @@ The following is the recommended minimum Memory hardware guidance for a handful
- 8 GB RAM supports up to 1000 users
- More users? Consult the [reference architectures page](../administration/reference_architectures/index.md)
-In addition to the above, we generally recommend having at least 2 GB of swap on your server,
-even if you currently have enough available RAM. Having swap helps to reduce the chance of errors occurring
-if your available memory changes. We also recommend configuring the kernel's swappiness setting
-to a low value like `10` to make the most of your RAM while still having the swap
-available when needed.
+For smaller installations, you should:
+
+- Have at least 2 GB of swap on your server, even if you have enough available RAM. Having swap helps to reduce the chance of
+ errors occurring if your available memory changes.
+- Configure the kernel's swappiness setting to a low value like `10` to make the most of your RAM while still having the swap available when needed.
+
+For larger installations that follow our reference architectures, you [shouldn't configure swap](../administration/reference_architectures/index.md#no-swap).
NOTE:
Although excessive swapping is undesired and degrades performance, it is an
diff --git a/doc/update/versions/gitlab_16_changes.md b/doc/update/versions/gitlab_16_changes.md
index 4415602364a..1d03f431629 100644
--- a/doc/update/versions/gitlab_16_changes.md
+++ b/doc/update/versions/gitlab_16_changes.md
@@ -30,6 +30,12 @@ For more information about upgrading GitLab Helm Chart, see [the release notes f
If you upgrade to 16.4 from a version lower than 16.3, you must execute `ANALYZE packages_packages;` in the database before you use it.
+- A new method of configuring paths for the GitLab secret and custom hooks is preferred in GitLab 16.4 and later:
+ 1. Update your configuration `[gitlab] secret_file` to [configure the path](../../administration/gitaly/reference.md#gitlab) to the GitLab secret token.
+ 1. If you have custom hooks, update your configuration `[hooks] custom_hooks_dir` to [configure the path](../../administration/gitaly/reference.md#custom-hooks) to
+ server-side custom hooks.
+ 1. Remove the `[gitlab-shell] dir` configuration.
+
## 16.3.0
- For Go applications, [`crypto/tls`: verifying certificate chains containing large RSA keys is slow (CVE-2023-29409)](https://github.com/golang/go/issues/61460)
diff --git a/lib/api/entities/feature.rb b/lib/api/entities/feature.rb
index 48dd5a22a7e..f341472e8c2 100644
--- a/lib/api/entities/feature.rb
+++ b/lib/api/entities/feature.rb
@@ -7,8 +7,10 @@ module API
expose :state, documentation: { type: 'string', example: 'off' }
expose :gates, using: Entities::FeatureGate do |model|
model.gates.map do |gate|
- value = model.gate_values[gate.key]
-
+ # in Flipper 0.26.1, they removed two GateValues#[] method calls for performance reasons
+ # https://github.com/flippercloud/flipper/pull/706/commits/ed914b6adc329455a634be843c38db479299efc7
+ # https://github.com/flippercloud/flipper/commit/eee20f3ae278d168c8bf70a7a5fcc03bedf432b5
+ value = model.gate_values.send(gate.key) # rubocop:disable GitlabSecurity/PublicSend
# By default all gate values are populated. Only show relevant ones.
if (value.is_a?(Integer) && value == 0) || (value.is_a?(Set) && value.empty?)
next
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index edfb1880dc3..4dcca4bdbf9 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -184,6 +184,30 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
+ def find_pipeline(id)
+ return unless id
+
+ if id.to_s =~ INTEGER_ID_REGEX
+ ::Ci::Pipeline.find_by(id: id)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def find_pipeline!(id)
+ pipeline = find_pipeline(id)
+ check_pipeline_access(pipeline)
+ end
+
+ def check_pipeline_access(pipeline)
+ return forbidden! unless authorized_project_scope?(pipeline&.project)
+
+ return pipeline if can?(current_user, :read_pipeline, pipeline)
+ return unauthorized! if authenticate_non_public?
+
+ not_found!('Pipeline')
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
def find_group(id)
if id.to_s =~ INTEGER_ID_REGEX
Group.find_by(id: id)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 03f8fd19bde..e0118dd78d9 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -41222,9 +41222,6 @@ msgstr ""
msgid "ScanResultPolicy|Attributes are automatically applied by the scanners"
msgstr ""
-msgid "ScanResultPolicy|Block users from modifying protected branches"
-msgstr ""
-
msgid "ScanResultPolicy|Choose criteria type"
msgstr ""
@@ -41246,6 +41243,9 @@ msgstr ""
msgid "ScanResultPolicy|Fix available is only applicable to container and dependency scanning"
msgstr ""
+msgid "ScanResultPolicy|If selected, the following choices will overwrite %{linkStart}project settings%{linkEnd} but only affect the branches selected in the policy."
+msgstr ""
+
msgid "ScanResultPolicy|Is"
msgstr ""
@@ -41288,6 +41288,12 @@ msgstr ""
msgid "ScanResultPolicy|Pre-existing"
msgstr ""
+msgid "ScanResultPolicy|Prevent branch protection modification"
+msgstr ""
+
+msgid "ScanResultPolicy|Protected branch settings"
+msgstr ""
+
msgid "ScanResultPolicy|Select a scan type before adding criteria"
msgstr ""
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 5e28490b2c8..2017288b19d 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -247,6 +247,165 @@ RSpec.describe API::Helpers, feature_category: :shared do
end
end
+ describe '#find_pipeline' do
+ let(:pipeline) { create(:ci_pipeline) }
+
+ shared_examples 'pipeline finder' do
+ context 'when pipeline exists' do
+ it 'returns requested pipeline' do
+ expect(helper.find_pipeline(existing_id)).to eq(pipeline)
+ end
+ end
+
+ context 'when pipeline does not exists' do
+ it 'returns nil' do
+ expect(helper.find_pipeline(non_existing_id)).to be_nil
+ end
+ end
+
+ context 'when pipeline id is not provided' do
+ it 'returns nil' do
+ expect(helper.find_pipeline(nil)).to be_nil
+ end
+ end
+ end
+
+ context 'when ID is used as an argument' do
+ let(:existing_id) { pipeline.id }
+ let(:non_existing_id) { non_existing_record_id }
+
+ it_behaves_like 'pipeline finder'
+ end
+
+ context 'when string ID is used as an argument' do
+ let(:existing_id) { pipeline.id.to_s }
+ let(:non_existing_id) { non_existing_record_id }
+
+ it_behaves_like 'pipeline finder'
+ end
+
+ context 'when ID is a negative number' do
+ let(:existing_id) { pipeline.id }
+ let(:non_existing_id) { -1 }
+
+ it_behaves_like 'pipeline finder'
+ end
+ end
+
+ describe '#find_pipeline!' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:user) { create(:user) }
+
+ shared_examples 'private project without access' do
+ before do
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value('private'))
+ allow(helper).to receive(:authenticate_non_public?).and_return(false)
+ end
+
+ it 'returns not found' do
+ expect(helper).to receive(:not_found!)
+
+ helper.find_pipeline!(pipeline.id)
+ end
+ end
+
+ context 'when user is authenticated' do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ allow(helper).to receive(:initial_current_user).and_return(user)
+ end
+
+ context 'public project' do
+ it 'returns requested pipeline' do
+ expect(helper.find_pipeline!(pipeline.id)).to eq(pipeline)
+ end
+ end
+
+ context 'private project' do
+ it_behaves_like 'private project without access'
+
+ context 'without read pipeline permission' do
+ before do
+ allow(helper).to receive(:can?).with(user, :read_pipeline, pipeline).and_return(false)
+ end
+
+ it_behaves_like 'private project without access'
+ end
+ end
+
+ context 'with read pipeline permission' do
+ before do
+ allow(helper).to receive(:can?).with(user, :read_pipeline, pipeline).and_return(true)
+ end
+
+ it 'returns requested pipeline' do
+ expect(helper.find_pipeline!(pipeline.id)).to eq(pipeline)
+ end
+ end
+ end
+
+ context 'when user is not authenticated' do
+ before do
+ allow(helper).to receive(:current_user).and_return(nil)
+ allow(helper).to receive(:initial_current_user).and_return(nil)
+ end
+
+ context 'public project' do
+ it 'returns requested pipeline' do
+ expect(helper.find_pipeline!(pipeline.id)).to eq(pipeline)
+ end
+ end
+
+ context 'private project' do
+ it_behaves_like 'private project without access'
+ end
+ end
+
+ context 'support for IDs and paths as argument' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let(:user) { project.first_owner }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ allow(helper).to receive(:authorized_project_scope?).and_return(true)
+ allow(helper).to receive(:job_token_authentication?).and_return(false)
+ allow(helper).to receive(:authenticate_non_public?).and_return(false)
+ end
+
+ shared_examples 'pipeline finder' do
+ context 'when pipeline exists' do
+ it 'returns requested pipeline' do
+ expect(helper.find_pipeline!(existing_id)).to eq(pipeline)
+ end
+
+ it 'returns nil' do
+ expect(helper).to receive(:render_api_error!).with('404 Pipeline Not Found', 404)
+ expect(helper.find_pipeline!(non_existing_id)).to be_nil
+ end
+ end
+ end
+
+ context 'when ID is used as an argument' do
+ context 'when pipeline id is an integer' do
+ let(:existing_id) { pipeline.id }
+ let(:non_existing_id) { non_existing_record_id }
+
+ it_behaves_like 'pipeline finder'
+ end
+
+ context 'when pipeline id is a string' do
+ let(:existing_id) { pipeline.id.to_s }
+ let(:non_existing_id) { "non_existing_record_id" }
+
+ it_behaves_like 'pipeline finder'
+ end
+ end
+ end
+ end
+
describe '#find_group!' do
let_it_be(:group) { create(:group, :public) }
let_it_be(:user) { create(:user) }
diff --git a/spec/policies/ci/pipeline_policy_spec.rb b/spec/policies/ci/pipeline_policy_spec.rb
index 8a5b80e3051..e74bf8f7efa 100644
--- a/spec/policies/ci/pipeline_policy_spec.rb
+++ b/spec/policies/ci/pipeline_policy_spec.rb
@@ -142,5 +142,30 @@ RSpec.describe Ci::PipelinePolicy, :models do
end
end
end
+
+ describe 'read_dependency' do
+ let(:project) { create(:project, :repository) }
+
+ before do
+ project.add_developer(user)
+ allow(policy).to receive(:can?).with(:read_dependency, project).and_return(can_read_project_dependencies)
+ end
+
+ context 'when user is allowed to read project dependencies' do
+ let(:can_read_project_dependencies) { true }
+
+ it 'is enabled' do
+ expect(policy).to be_allowed :read_dependency
+ end
+ end
+
+ context 'when user is not allowed to read project dependencies' do
+ let(:can_read_project_dependencies) { false }
+
+ it 'is disabled' do
+ expect(policy).not_to be_allowed :read_dependency
+ end
+ end
+ end
end
end