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:
authorGitLab Release Tools Bot <delivery-team+release-tools@gitlab.com>2023-11-30 21:23:36 +0300
committerGitLab Release Tools Bot <delivery-team+release-tools@gitlab.com>2023-11-30 21:23:36 +0300
commitaf9f690528dd4fb0f8b0c72a04fec965b2390e69 (patch)
treef56964b06f3792e52682e87d09cc8910c2046fbf
parent97353eb5582895e2dfbd3d518886cdea6ccfb3af (diff)
parent0cf5cc0917cb29ecea5f9dedbd7ad5ea23005d8d (diff)
Merge remote-tracking branch 'dev/16-4-stable' into 16-4-stable
-rw-r--r--CHANGELOG.md19
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--VERSION2
-rw-r--r--app/controllers/projects/tags_controller.rb2
-rw-r--r--app/finders/packages/composer/packages_finder.rb8
-rw-r--r--app/finders/packages/group_packages_finder.rb19
-rw-r--r--app/graphql/types/permission_types/base_permission_type.rb2
-rw-r--r--app/models/ability.rb14
-rw-r--r--app/models/concerns/protected_branch_access.rb2
-rw-r--r--app/models/integrations/jira.rb4
-rw-r--r--app/models/pages_domain.rb5
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/user.rb4
-rw-r--r--app/policies/ci/pipeline_schedule_policy.rb3
-rw-r--r--app/policies/issue_policy.rb5
-rw-r--r--app/services/ci/pipeline_schedules/base_save_service.rb6
-rw-r--r--app/services/ci/pipeline_schedules/update_service.rb6
-rw-r--r--lib/gitlab/checks/branch_check.rb4
-rw-r--r--lib/gitlab/regex.rb4
-rw-r--r--package.json2
-rw-r--r--spec/controllers/projects/pipeline_schedules_controller_spec.rb4
-rw-r--r--spec/controllers/projects/tags_controller_spec.rb12
-rw-r--r--spec/features/projects/pages/user_adds_domain_spec.rb1
-rw-r--r--spec/finders/packages/composer/packages_finder_spec.rb15
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb24
-rw-r--r--spec/lib/gitlab/checks/branch_check_spec.rb34
-rw-r--r--spec/models/ability_spec.rb39
-rw-r--r--spec/models/integrations/jira_spec.rb2
-rw-r--r--spec/models/pages_domain_spec.rb23
-rw-r--r--spec/models/project_spec.rb11
-rw-r--r--spec/policies/ci/pipeline_schedule_policy_spec.rb338
-rw-r--r--spec/policies/issue_policy_spec.rb30
-rw-r--r--spec/services/ci/pipeline_schedules/update_service_spec.rb56
-rw-r--r--yarn.lock8
35 files changed, 524 insertions, 189 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77e7f8813e0..970c800f715 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,25 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 16.4.3 (2023-11-30)
+
+### Fixed (1 change)
+
+- [Fix assign security check permission checks](gitlab-org/security/gitlab@68b0fe3e41199a47e5851f3f00412ba18cc61a27) **GitLab Enterprise Edition**
+
+### Security (10 changes)
+
+- [Enforce ref protection on pipeline schedule updates](gitlab-org/security/gitlab@222b8d02d95e6c33ef26bfbb69718fa73daf31bc) ([merge request](gitlab-org/security/gitlab!3657))
+- [Update mermaid version for DOS security fixes](gitlab-org/security/gitlab@91f6263eb4697e9aebe059aee46ccfe1974d481c) ([merge request](gitlab-org/security/gitlab!3672))
+- [Prevent guest users from being able to add emojis in confidential issues](gitlab-org/security/gitlab@cc233c603bc595ef60f1b7ea2fcd69ab6113a374) ([merge request](gitlab-org/security/gitlab!3689))
+- [Do not run ssl cert validation if key has errors](gitlab-org/security/gitlab@ce234f97638d9182c22636301eccae87e7af854a) ([merge request](gitlab-org/security/gitlab!3662))
+- [Ensure access is checked when loading releases associated with tags](gitlab-org/security/gitlab@fead41322a5cf79513b5e3375fb2372ca936ef10) ([merge request](gitlab-org/security/gitlab!3696))
+- [XSS and ReDoS in Markdown via Banzai pipeline of Jira](gitlab-org/security/gitlab@7d9d64aa7123287c495b6be291a9b00dc60f179e) ([merge request](gitlab-org/security/gitlab!3692))
+- [Prevent branch names starting with SHA-1 and SHA-256 values](gitlab-org/security/gitlab@f51d428a6961bf77661cffffd50face4d02c6f43) ([merge request](gitlab-org/security/gitlab!3688))
+- [Filter out projects with disabled package registry in Composer finder](gitlab-org/security/gitlab@844ddc2028fd7389beee440034a1e83a42693ba2) ([merge request](gitlab-org/security/gitlab!3683))
+- [Check max role for user for group access to protected ref](gitlab-org/security/gitlab@1f6036ab1e227d013c0d42210a9c08ac7ff231c6) ([merge request](gitlab-org/security/gitlab!3643))
+- [Treat security policy bots as external](gitlab-org/security/gitlab@b0cf61131f21381978509ab2698b9da57522e726) ([merge request](gitlab-org/security/gitlab!3677))
+
## 16.4.2 (2023-10-30)
### Fixed (4 changes)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 189aba114d8..11701a599de 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-16.4.2 \ No newline at end of file
+16.4.3 \ No newline at end of file
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 189aba114d8..11701a599de 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-16.4.2 \ No newline at end of file
+16.4.3 \ No newline at end of file
diff --git a/VERSION b/VERSION
index 189aba114d8..11701a599de 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-16.4.2 \ No newline at end of file
+16.4.3 \ No newline at end of file
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index 3c1735c728c..d3e38774aaa 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -29,7 +29,7 @@ class Projects::TagsController < Projects::ApplicationController
tag_names = @tags.map(&:name)
@tags_pipelines = @project.ci_pipelines.latest_successful_for_refs(tag_names)
- @releases = project.releases.where(tag: tag_names)
+ @releases = ReleasesFinder.new(project, current_user, tag: tag_names).execute
@tag_pipeline_statuses = Ci::CommitStatusesFinder.new(@project, @repository, current_user, @tags).execute
rescue Gitlab::Git::CommandError => e
diff --git a/app/finders/packages/composer/packages_finder.rb b/app/finders/packages/composer/packages_finder.rb
index b5a1b19216f..1581c48dd74 100644
--- a/app/finders/packages/composer/packages_finder.rb
+++ b/app/finders/packages/composer/packages_finder.rb
@@ -2,14 +2,12 @@
module Packages
module Composer
class PackagesFinder < Packages::GroupPackagesFinder
- def initialize(current_user, group, params = {})
- @current_user = current_user
- @group = group
- @params = params
+ def initialize(current_user, group, params = { package_type: :composer, with_package_registry_enabled: true })
+ super(current_user, group, params)
end
def execute
- packages_for_group_projects(installable_only: true).composer.preload_composer
+ packages_for_group_projects(installable_only: true).preload_composer
end
end
end
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index 3a068252d5c..3b211882fa0 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -40,14 +40,17 @@ module Packages
# access to packages is ruled by:
# - project is public or the current user has access to it with at least the reporter level
# - the repository feature is available to the current_user
- if current_user.is_a?(DeployToken)
- current_user.accessible_projects
- else
- ::Project
- .in_namespace(groups)
- .public_or_visible_to_user(current_user, Gitlab::Access::REPORTER)
- .with_feature_available_for_user(:repository, current_user)
- end
+ projects = if current_user.is_a?(DeployToken)
+ current_user.accessible_projects
+ else
+ ::Project
+ .in_namespace(groups)
+ .public_or_visible_to_user(current_user, Gitlab::Access::REPORTER)
+ .with_feature_available_for_user(:repository, current_user)
+ end
+
+ projects = projects.with_package_registry_enabled if params[:with_package_registry_enabled]
+ projects
end
def groups
diff --git a/app/graphql/types/permission_types/base_permission_type.rb b/app/graphql/types/permission_types/base_permission_type.rb
index d45c61f489b..ae9de845593 100644
--- a/app/graphql/types/permission_types/base_permission_type.rb
+++ b/app/graphql/types/permission_types/base_permission_type.rb
@@ -30,7 +30,7 @@ module Types
def self.define_field_resolver_method(ability)
unless respond_to?(ability)
define_method ability.to_sym do |*args|
- Ability.allowed?(context[:current_user], ability, object, args.to_h)
+ Ability.allowed?(context[:current_user], ability, object, **args.to_h)
end
end
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index d8510524c1f..d9a875bf93e 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -70,13 +70,13 @@ class Ability
end
end
- def allowed?(user, ability, subject = :global, opts = {})
+ def allowed?(user, ability, subject = :global, **opts)
if subject.is_a?(Hash)
opts = subject
subject = :global
end
- policy = policy_for(user, subject)
+ policy = policy_for(user, subject, **opts.slice(:cache))
before_check(policy, ability.to_sym, user, subject, opts)
@@ -100,8 +100,14 @@ class Ability
# See Support::AbilityCheck and Support::PermissionsCheck.
end
- def policy_for(user, subject = :global)
- DeclarativePolicy.policy_for(user, subject, cache: ::Gitlab::SafeRequestStore.storage)
+ # We cache in the request store by default. This can lead to unexpected
+ # results if abilities are re-checked after objects are modified and the
+ # check depends on the modified attributes. In such cases, you should pass
+ # `cache: false` for the second check to ensure all rules get re-evaluated.
+ def policy_for(user, subject = :global, cache: true)
+ policy_cache = cache ? ::Gitlab::SafeRequestStore.storage : {}
+
+ DeclarativePolicy.policy_for(user, subject, cache: policy_cache)
end
# This method is something of a band-aid over the problem. The problem is
diff --git a/app/models/concerns/protected_branch_access.rb b/app/models/concerns/protected_branch_access.rb
index 8156090fd9c..6a7fdce62fb 100644
--- a/app/models/concerns/protected_branch_access.rb
+++ b/app/models/concerns/protected_branch_access.rb
@@ -10,3 +10,5 @@ module ProtectedBranchAccess
delegate :project, to: :protected_branch
end
end
+
+ProtectedBranchAccess.prepend_mod_with('ProtectedBranchAccess')
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index d8d1f860e9a..4255d0bbcab 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -384,9 +384,9 @@ module Integrations
private
def jira_issue_match_regex
- return /\b#{jira_issue_prefix}(?<issue>#{Gitlab::Regex.jira_issue_key_regex})/ if jira_issue_regex.blank?
+ jira_regex = jira_issue_regex.presence || Gitlab::Regex.jira_issue_key_regex.source
- Gitlab::UntrustedRegexp.new("\\b#{jira_issue_prefix}(?P<issue>#{jira_issue_regex})")
+ Gitlab::UntrustedRegexp.new("\\b#{jira_issue_prefix}(?P<issue>#{jira_regex})")
end
def parse_project_from_issue_key(issue_key)
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index b86bc761cc1..08326cf39e6 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -33,10 +33,11 @@ class PagesDomain < ApplicationRecord
validates :verification_code, presence: true, allow_blank: false
validate :validate_pages_domain
+ validate :max_certificate_key_length, if: ->(domain) { domain.key.present? }
validate :validate_matching_key, if: ->(domain) { domain.certificate.present? || domain.key.present? }
- validate :validate_intermediates, if: ->(domain) { domain.certificate.present? && domain.certificate_changed? }
+ # validate_intermediates must run after key validations to skip expensive SSL validation when there is a key error
+ validate :validate_intermediates, if: ->(domain) { domain.certificate.present? && domain.certificate_changed? && errors[:key].blank? }
validate :validate_custom_domain_count_per_project, on: :create
- validate :max_certificate_key_length, if: ->(domain) { domain.key.present? }
attribute :auto_ssl_enabled, default: -> { ::Gitlab::LetsEncrypt.enabled? }
attribute :wildcard, default: false
diff --git a/app/models/project.rb b/app/models/project.rb
index 5989584ce43..96a23c4b03d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -749,6 +749,7 @@ class Project < ApplicationRecord
scope :service_desk_enabled, -> { where(service_desk_enabled: true) }
scope :with_builds_enabled, -> { with_feature_enabled(:builds) }
scope :with_issues_enabled, -> { with_feature_enabled(:issues) }
+ scope :with_package_registry_enabled, -> { with_feature_enabled(:package_registry) }
scope :with_issues_available_for_user, ->(current_user) { with_feature_available_for_user(:issues, current_user) }
scope :with_merge_requests_available_for_user, ->(current_user) { with_feature_available_for_user(:merge_requests, current_user) }
scope :with_issues_or_mrs_available_for_user, -> (user) do
diff --git a/app/models/user.rb b/app/models/user.rb
index c4e867ab571..b1349cd3f65 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1297,8 +1297,8 @@ class User < MainClusterwide::ApplicationRecord
several_namespaces? || admin
end
- def can?(action, subject = :global)
- Ability.allowed?(self, action, subject)
+ def can?(action, subject = :global, **opts)
+ Ability.allowed?(self, action, subject, **opts)
end
def confirm_deletion_with_password?
diff --git a/app/policies/ci/pipeline_schedule_policy.rb b/app/policies/ci/pipeline_schedule_policy.rb
index cbc60c4a30a..9e558cd91c1 100644
--- a/app/policies/ci/pipeline_schedule_policy.rb
+++ b/app/policies/ci/pipeline_schedule_policy.rb
@@ -25,7 +25,7 @@ module Ci
rule { can?(:create_pipeline) }.enable :play_pipeline_schedule
- rule { can?(:admin_pipeline) | (can?(:update_build) & owner_of_schedule) }.policy do
+ rule { can?(:admin_pipeline) | (owner_of_schedule & can?(:update_build)) }.policy do
enable :admin_pipeline_schedule
enable :read_pipeline_schedule_variables
end
@@ -45,6 +45,7 @@ module Ci
rule { protected_ref }.policy do
prevent :play_pipeline_schedule
prevent :create_pipeline_schedule
+ prevent :update_pipeline_schedule
end
private
diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb
index 538959c92bd..f642c6eab2d 100644
--- a/app/policies/issue_policy.rb
+++ b/app/policies/issue_policy.rb
@@ -51,7 +51,10 @@ class IssuePolicy < IssuablePolicy
prevent :read_issue
end
- rule { ~can?(:read_issue) }.prevent :create_note
+ rule { ~can?(:read_issue) }.policy do
+ prevent :create_note
+ prevent :award_emoji
+ end
rule { locked }.policy do
prevent :reopen_issue
diff --git a/app/services/ci/pipeline_schedules/base_save_service.rb b/app/services/ci/pipeline_schedules/base_save_service.rb
index 45d70e5a65d..e6f633498e9 100644
--- a/app/services/ci/pipeline_schedules/base_save_service.rb
+++ b/app/services/ci/pipeline_schedules/base_save_service.rb
@@ -23,7 +23,11 @@ module Ci
attr_reader :project, :user, :params, :schedule
def allowed_to_save?
- user.can?(self.class::AUTHORIZE, schedule)
+ # Disable cache because the same ability may already have been checked
+ # for the same records with different attributes. For example, we do not
+ # want an unauthorized user to change an unprotected ref to a protected
+ # ref.
+ user.can?(self.class::AUTHORIZE, schedule, cache: false)
end
def forbidden_to_save
diff --git a/app/services/ci/pipeline_schedules/update_service.rb b/app/services/ci/pipeline_schedules/update_service.rb
index 2fd1173ecce..76b2121c4e1 100644
--- a/app/services/ci/pipeline_schedules/update_service.rb
+++ b/app/services/ci/pipeline_schedules/update_service.rb
@@ -12,6 +12,12 @@ module Ci
@params = params
end
+ def execute
+ return forbidden_to_save unless allowed_to_save?
+
+ super
+ end
+
private
def authorize_message
diff --git a/lib/gitlab/checks/branch_check.rb b/lib/gitlab/checks/branch_check.rb
index b675eca826a..3bedc483e75 100644
--- a/lib/gitlab/checks/branch_check.rb
+++ b/lib/gitlab/checks/branch_check.rb
@@ -13,7 +13,7 @@ module Gitlab
create_protected_branch: 'You are not allowed to create protected branches on this project.',
invalid_commit_create_protected_branch: 'You can only use an existing protected branch ref as the basis of a new protected branch.',
non_web_create_protected_branch: 'You can only create protected branches using the web interface and API.',
- prohibited_hex_branch_name: 'You cannot create a branch with a 40-character hexadecimal branch name.',
+ prohibited_hex_branch_name: 'You cannot create a branch with a SHA-1 or SHA-256 branch name.',
invalid_branch_name: 'You cannot create a branch with an invalid name.'
}.freeze
@@ -43,7 +43,7 @@ module Gitlab
def prohibited_branch_checks
return if deletion?
- if %r{\A#{Gitlab::Git::Commit::RAW_FULL_SHA_PATTERN}(-/|/|\z)}o.match?(branch_name)
+ if %r{\A#{Gitlab::Git::Commit::RAW_FULL_SHA_PATTERN}}o.match?(branch_name)
raise GitAccess::ForbiddenError, ERROR_MESSAGES[:prohibited_hex_branch_name]
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 8ef455efe07..fd72376513f 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -255,10 +255,8 @@ module Gitlab
# Based on Jira's project key format
# https://confluence.atlassian.com/adminjiraserver073/changing-the-project-key-format-861253229.html
- # Avoids linking CVE IDs (https://cve.mitre.org/cve/identifiers/syntaxchange.html#new) as Jira issues.
- # CVE IDs use the format of CVE-YYYY-NNNNNNN
def jira_issue_key_regex(expression_escape: '\b')
- /#{expression_escape}(?!CVE-\d+-\d+)[A-Z][A-Z_0-9]+-\d+/
+ /#{expression_escape}([A-Z][A-Z_0-9]+-\d+)/
end
def jira_issue_key_project_key_extraction_regex
diff --git a/package.json b/package.json
index 0893f6a6dde..0133e2d8871 100644
--- a/package.json
+++ b/package.json
@@ -167,7 +167,7 @@
"marked-bidi": "^1.0.3",
"mathjax": "3",
"mdurl": "^1.0.1",
- "mermaid": "10.5.0",
+ "mermaid": "10.6.1",
"micromatch": "^4.0.5",
"minimatch": "^3.0.4",
"monaco-editor": "^0.30.1",
diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
index cd828c956a0..7cd4f43d4da 100644
--- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb
+++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
@@ -65,6 +65,10 @@ RSpec.describe Projects::PipelineSchedulesController, feature_category: :continu
create(:protected_branch, *branch_access_levels, name: ref_name, project: project)
end
+ after do
+ ProtectedBranches::CacheService.new(project).refresh
+ end
+
it { expect { go }.to try(maintainer_accessible, :maintainer).of(project) }
it { expect { go }.to try(developer_accessible, :developer).of(project) }
end
diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb
index 3d1f8c12022..cab0778bd13 100644
--- a/spec/controllers/projects/tags_controller_spec.rb
+++ b/spec/controllers/projects/tags_controller_spec.rb
@@ -52,6 +52,18 @@ RSpec.describe Projects::TagsController do
expect(assigns(:releases)).not_to include(invalid_release)
end
+ context 'when releases are private' do
+ before do
+ project.project_feature.update!(releases_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'does not contain release data' do
+ subject
+
+ expect(assigns(:releases)).to be_empty
+ end
+ end
+
context '@tag_pipeline_status' do
context 'when no pipelines exist' do
it 'is empty' do
diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb
index 14b01cb63d2..04a9f450b52 100644
--- a/spec/features/projects/pages/user_adds_domain_spec.rb
+++ b/spec/features/projects/pages/user_adds_domain_spec.rb
@@ -155,7 +155,6 @@ RSpec.describe 'User adds pages domain', :js, feature_category: :pages do
click_button 'Save Changes'
expect(page).to have_content('Certificate must be a valid PEM certificate')
- expect(page).to have_content('Certificate misses intermediates')
expect(page).to have_content("Key doesn't match the certificate")
end
end
diff --git a/spec/finders/packages/composer/packages_finder_spec.rb b/spec/finders/packages/composer/packages_finder_spec.rb
index d4328827de3..1701243063b 100644
--- a/spec/finders/packages/composer/packages_finder_spec.rb
+++ b/spec/finders/packages/composer/packages_finder_spec.rb
@@ -1,18 +1,19 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe ::Packages::Composer::PackagesFinder do
+RSpec.describe ::Packages::Composer::PackagesFinder, feature_category: :package_registry do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
- let(:params) { {} }
+ let(:params) { { package_type: :composer } }
describe '#execute' do
let_it_be(:composer_package) { create(:composer_package, project: project) }
let_it_be(:composer_package2) { create(:composer_package, project: project) }
let_it_be(:error_package) { create(:composer_package, :error, project: project) }
let_it_be(:composer_package3) { create(:composer_package) }
+ let_it_be(:nuget_package) { create(:nuget_package, project: project) }
subject { described_class.new(user, group, params).execute }
@@ -21,5 +22,15 @@ RSpec.describe ::Packages::Composer::PackagesFinder do
end
it { is_expected.to match_array([composer_package, composer_package2]) }
+
+ context 'when disabling the package registry for the project' do
+ let(:params) { super().merge(with_package_registry_enabled: true) }
+
+ before do
+ project.update!(package_registry_access_level: 'disabled', packages_enabled: false)
+ end
+
+ it { is_expected.to be_empty }
+ end
end
end
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index e4a944eb837..f78be857357 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe Packages::GroupPackagesFinder do
+RSpec.describe Packages::GroupPackagesFinder, feature_category: :package_registry do
using RSpec::Parameterized::TableSyntax
let_it_be(:user) { create(:user) }
@@ -25,6 +25,16 @@ RSpec.describe Packages::GroupPackagesFinder do
it { is_expected.to match_array([send("package_#{package_type}")]) }
end
+ shared_examples 'disabling package registry for project' do
+ let(:params) { super().merge(with_package_registry_enabled: true) }
+
+ before do
+ project.update!(package_registry_access_level: 'disabled', packages_enabled: false)
+ end
+
+ it { is_expected.to match_array(packages_returned) }
+ end
+
def self.package_types
@package_types ||= Packages::Package.package_types.keys
end
@@ -117,6 +127,10 @@ RSpec.describe Packages::GroupPackagesFinder do
let(:user) { deploy_token_for_group }
it { is_expected.to match_array([package1, package2, package4]) }
+
+ it_behaves_like 'disabling package registry for project' do
+ let(:packages_returned) { [package4] }
+ end
end
context 'project deploy token' do
@@ -126,6 +140,11 @@ RSpec.describe Packages::GroupPackagesFinder do
let(:user) { deploy_token_for_project }
it { is_expected.to match_array([package4]) }
+
+ it_behaves_like 'disabling package registry for project' do
+ let(:project) { subproject }
+ let(:packages_returned) { [] }
+ end
end
end
@@ -200,6 +219,9 @@ RSpec.describe Packages::GroupPackagesFinder do
it_behaves_like 'concerning versionless param'
it_behaves_like 'concerning package statuses'
+ it_behaves_like 'disabling package registry for project' do
+ let(:packages_returned) { [] }
+ end
end
context 'group has package of all types' do
diff --git a/spec/lib/gitlab/checks/branch_check_spec.rb b/spec/lib/gitlab/checks/branch_check_spec.rb
index c3d6b9510e5..8772e8dd904 100644
--- a/spec/lib/gitlab/checks/branch_check_spec.rb
+++ b/spec/lib/gitlab/checks/branch_check_spec.rb
@@ -19,39 +19,39 @@ RSpec.describe Gitlab::Checks::BranchCheck, feature_category: :source_code_manag
end
end
- context "prohibited branches check" do
- it "prohibits 40-character hexadecimal branch names" do
+ describe "prohibited branches check" do
+ it "forbids SHA-1 values" do
allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e")
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a 40-character hexadecimal branch name.")
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a SHA-1 or SHA-256 branch name.")
end
- it "prohibits 40-character hexadecimal branch names as the start of a path" do
- allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e/test")
+ it "forbids SHA-256 values" do
+ allow(subject).to receive(:branch_name).and_return("09b9fd3ea68e9b95a51b693a29568c898e27d1476bbd83c825664f18467fc175")
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a 40-character hexadecimal branch name.")
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a SHA-1 or SHA-256 branch name.")
end
- it "prohibits 40-character hexadecimal branch names followed by a dash as the start of a path" do
- allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e-/test")
+ it "forbids '{SHA-1}{+anything}' values" do
+ allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e-")
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a 40-character hexadecimal branch name.")
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a SHA-1 or SHA-256 branch name.")
end
- it "prohibits 64-character hexadecimal branch names" do
- allow(subject).to receive(:branch_name).and_return("09b9fd3ea68e9b95a51b693a29568c898e27d1476bbd83c825664f18467fc175")
+ it "forbids '{SHA-256}{+anything} values" do
+ allow(subject).to receive(:branch_name).and_return("09b9fd3ea68e9b95a51b693a29568c898e27d1476bbd83c825664f18467fc175-")
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a 40-character hexadecimal branch name.")
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a SHA-1 or SHA-256 branch name.")
end
- it "prohibits 64-character hexadecimal branch names as the start of a path" do
- allow(subject).to receive(:branch_name).and_return("09b9fd3ea68e9b95a51b693a29568c898e27d1476bbd83c825664f18467fc175/test")
+ it "allows SHA-1 values to be appended to the branch name" do
+ allow(subject).to receive(:branch_name).and_return("fix-267208abfe40e546f5e847444276f7d43a39503e")
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a 40-character hexadecimal branch name.")
+ expect { subject.validate! }.not_to raise_error
end
- it "doesn't prohibit a nested hexadecimal in a branch name" do
- allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e-fix")
+ it "allows SHA-256 values to be appended to the branch name" do
+ allow(subject).to receive(:branch_name).and_return("fix-09b9fd3ea68e9b95a51b693a29568c898e27d1476bbd83c825664f18467fc175")
expect { subject.validate! }.not_to raise_error
end
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index a808cb1c823..1f0e074d90b 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -3,9 +3,42 @@
require 'spec_helper'
RSpec.describe Ability do
- context 'using a nil subject' do
- it 'has no permissions' do
- expect(described_class.policy_for(nil, nil)).to be_banned
+ describe '#policy_for' do
+ subject(:policy) { described_class.policy_for(user, subject, **options) }
+
+ let(:user) { User.new }
+ let(:subject) { :global }
+ let(:options) { {} }
+
+ context 'using a nil subject' do
+ let(:user) { nil }
+ let(:subject) { nil }
+
+ it 'has no permissions' do
+ expect(policy).to be_banned
+ end
+ end
+
+ context 'with request store', :request_store do
+ before do
+ ::Gitlab::SafeRequestStore.write(:example, :value) # make request store different from {}
+ end
+
+ it 'caches in the request store' do
+ expect(DeclarativePolicy).to receive(:policy_for).with(user, subject, cache: ::Gitlab::SafeRequestStore.storage)
+
+ policy
+ end
+
+ context 'when cache: false' do
+ let(:options) { { cache: false } }
+
+ it 'uses a fresh cache each time' do
+ expect(DeclarativePolicy).to receive(:policy_for).with(user, subject, cache: {})
+
+ policy
+ end
+ end
end
end
diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb
index 9bb77f6d6d4..f5eaed4d7e4 100644
--- a/spec/models/integrations/jira_spec.rb
+++ b/spec/models/integrations/jira_spec.rb
@@ -251,7 +251,7 @@ RSpec.describe Integrations::Jira, feature_category: :integrations do
'EXT_EXT-1234' | 'EXT_EXT-1234'
'EXT3_EXT-1234' | 'EXT3_EXT-1234'
'3EXT_EXT-1234' | ''
- 'CVE-2022-123' | ''
+ 'CVE-2022-123' | 'CVE-2022'
'CVE-123' | 'CVE-123'
'abc-JIRA-1234' | 'JIRA-1234'
end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index cd740bca502..5f7b5e9c7fb 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -165,7 +165,7 @@ RSpec.describe PagesDomain do
it "adds error to certificate" do
domain.valid?
- expect(domain.errors.attribute_names).to contain_exactly(:key, :certificate)
+ expect(domain.errors.attribute_names).to contain_exactly(:key)
end
end
@@ -206,10 +206,25 @@ RSpec.describe PagesDomain do
it 'validates the certificate key length' do
valid_domain = build(:pages_domain, :key_length_8192)
expect(valid_domain).to be_valid
+ end
+
+ context 'when the key has more than 8192 bytes' do
+ let(:domain) do
+ build(:pages_domain, :extra_long_key)
+ end
- invalid_domain = build(:pages_domain, :extra_long_key)
- expect(invalid_domain).to be_invalid
- expect(invalid_domain.errors[:key]).to include('Certificate Key is too long. (Max 8192 bytes)')
+ it 'adds a human readable error' do
+ expect(domain).to be_invalid
+ expect(domain.errors[:key]).to include('Certificate Key is too long. (Max 8192 bytes)')
+ end
+
+ it 'does not run SSL key verification' do
+ allow(domain).to receive(:validate_intermediates)
+
+ domain.valid?
+
+ expect(domain).not_to have_received(:validate_intermediates)
+ end
end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 46bf80b1e8f..341f5f2b078 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -6908,6 +6908,17 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
+ describe '.with_package_registry_enabled' do
+ subject { described_class.with_package_registry_enabled }
+
+ it 'returns projects with the package registry enabled' do
+ project_1 = create(:project)
+ create(:project, package_registry_access_level: ProjectFeature::DISABLED, packages_enabled: false)
+
+ expect(subject).to contain_exactly(project_1)
+ end
+ end
+
describe '.deployments' do
subject { project.deployments }
diff --git a/spec/policies/ci/pipeline_schedule_policy_spec.rb b/spec/policies/ci/pipeline_schedule_policy_spec.rb
index 8fc5c6ca296..1d353b9a35e 100644
--- a/spec/policies/ci/pipeline_schedule_policy_spec.rb
+++ b/spec/policies/ci/pipeline_schedule_policy_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Ci::PipelineSchedulePolicy, :models, :clean_gitlab_redis_cache, f
using RSpec::Parameterized::TableSyntax
let_it_be(:user) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
let_it_be_with_reload(:project) { create(:project, :repository, create_tag: tag_ref_name) }
let_it_be_with_reload(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project) }
let_it_be(:tag_ref_name) { "v1.0.0" }
@@ -17,89 +18,180 @@ RSpec.describe Ci::PipelineSchedulePolicy, :models, :clean_gitlab_redis_cache, f
describe 'rules' do
describe 'rules for protected ref' do
context 'for branch' do
+ subject(:policy) { described_class.new(user, pipeline_schedule) }
+
%w[refs/heads/master master].each do |branch_ref|
context "with #{branch_ref}" do
let_it_be(:branch_ref_name) { "master" }
- let_it_be(:branch_pipeline_schedule) do
+ let_it_be(:pipeline_schedule) do
create(:ci_pipeline_schedule, :nightly, project: project, ref: branch_ref)
end
- where(:push_access_level, :merge_access_level, :project_role, :accessible) do
- :no_one_can_push | :no_one_can_merge | :owner | :be_disallowed
- :no_one_can_push | :no_one_can_merge | :maintainer | :be_disallowed
- :no_one_can_push | :no_one_can_merge | :developer | :be_disallowed
- :no_one_can_push | :no_one_can_merge | :reporter | :be_disallowed
- :no_one_can_push | :no_one_can_merge | :guest | :be_disallowed
-
- :maintainers_can_push | :no_one_can_merge | :owner | :be_allowed
- :maintainers_can_push | :no_one_can_merge | :maintainer | :be_allowed
- :maintainers_can_push | :no_one_can_merge | :developer | :be_disallowed
- :maintainers_can_push | :no_one_can_merge | :reporter | :be_disallowed
- :maintainers_can_push | :no_one_can_merge | :guest | :be_disallowed
-
- :developers_can_push | :no_one_can_merge | :owner | :be_allowed
- :developers_can_push | :no_one_can_merge | :maintainer | :be_allowed
- :developers_can_push | :no_one_can_merge | :developer | :be_allowed
- :developers_can_push | :no_one_can_merge | :reporter | :be_disallowed
- :developers_can_push | :no_one_can_merge | :guest | :be_disallowed
-
- :no_one_can_push | :maintainers_can_merge | :owner | :be_allowed
- :no_one_can_push | :maintainers_can_merge | :maintainer | :be_allowed
- :no_one_can_push | :maintainers_can_merge | :developer | :be_disallowed
- :no_one_can_push | :maintainers_can_merge | :reporter | :be_disallowed
- :no_one_can_push | :maintainers_can_merge | :guest | :be_disallowed
-
- :maintainers_can_push | :maintainers_can_merge | :owner | :be_allowed
- :maintainers_can_push | :maintainers_can_merge | :maintainer | :be_allowed
- :maintainers_can_push | :maintainers_can_merge | :developer | :be_disallowed
- :maintainers_can_push | :maintainers_can_merge | :reporter | :be_disallowed
- :maintainers_can_push | :maintainers_can_merge | :guest | :be_disallowed
-
- :developers_can_push | :maintainers_can_merge | :owner | :be_allowed
- :developers_can_push | :maintainers_can_merge | :maintainer | :be_allowed
- :developers_can_push | :maintainers_can_merge | :developer | :be_allowed
- :developers_can_push | :maintainers_can_merge | :reporter | :be_disallowed
- :developers_can_push | :maintainers_can_merge | :guest | :be_disallowed
-
- :no_one_can_push | :developers_can_merge | :owner | :be_allowed
- :no_one_can_push | :developers_can_merge | :maintainer | :be_allowed
- :no_one_can_push | :developers_can_merge | :developer | :be_allowed
- :no_one_can_push | :developers_can_merge | :reporter | :be_disallowed
- :no_one_can_push | :developers_can_merge | :guest | :be_disallowed
-
- :maintainers_can_push | :developers_can_merge | :owner | :be_allowed
- :maintainers_can_push | :developers_can_merge | :maintainer | :be_allowed
- :maintainers_can_push | :developers_can_merge | :developer | :be_allowed
- :maintainers_can_push | :developers_can_merge | :reporter | :be_disallowed
- :maintainers_can_push | :developers_can_merge | :guest | :be_disallowed
-
- :developers_can_push | :developers_can_merge | :owner | :be_allowed
- :developers_can_push | :developers_can_merge | :maintainer | :be_allowed
- :developers_can_push | :developers_can_merge | :developer | :be_allowed
- :developers_can_push | :developers_can_merge | :reporter | :be_disallowed
- :developers_can_push | :developers_can_merge | :guest | :be_disallowed
+ shared_examples_for 'allowed by those who can update the branch' do
+ where(:push_access_level, :merge_access_level, :project_role, :accessible) do
+ :no_one_can_push | :no_one_can_merge | :owner | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :maintainer | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :developer | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :reporter | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :guest | :be_disallowed
+
+ :maintainers_can_push | :no_one_can_merge | :owner | :be_allowed
+ :maintainers_can_push | :no_one_can_merge | :maintainer | :be_allowed
+ :maintainers_can_push | :no_one_can_merge | :developer | :be_disallowed
+ :maintainers_can_push | :no_one_can_merge | :reporter | :be_disallowed
+ :maintainers_can_push | :no_one_can_merge | :guest | :be_disallowed
+
+ :developers_can_push | :no_one_can_merge | :owner | :be_allowed
+ :developers_can_push | :no_one_can_merge | :maintainer | :be_allowed
+ :developers_can_push | :no_one_can_merge | :developer | :be_allowed
+ :developers_can_push | :no_one_can_merge | :reporter | :be_disallowed
+ :developers_can_push | :no_one_can_merge | :guest | :be_disallowed
+
+ :no_one_can_push | :maintainers_can_merge | :owner | :be_allowed
+ :no_one_can_push | :maintainers_can_merge | :maintainer | :be_allowed
+ :no_one_can_push | :maintainers_can_merge | :developer | :be_disallowed
+ :no_one_can_push | :maintainers_can_merge | :reporter | :be_disallowed
+ :no_one_can_push | :maintainers_can_merge | :guest | :be_disallowed
+
+ :maintainers_can_push | :maintainers_can_merge | :owner | :be_allowed
+ :maintainers_can_push | :maintainers_can_merge | :maintainer | :be_allowed
+ :maintainers_can_push | :maintainers_can_merge | :developer | :be_disallowed
+ :maintainers_can_push | :maintainers_can_merge | :reporter | :be_disallowed
+ :maintainers_can_push | :maintainers_can_merge | :guest | :be_disallowed
+
+ :developers_can_push | :maintainers_can_merge | :owner | :be_allowed
+ :developers_can_push | :maintainers_can_merge | :maintainer | :be_allowed
+ :developers_can_push | :maintainers_can_merge | :developer | :be_allowed
+ :developers_can_push | :maintainers_can_merge | :reporter | :be_disallowed
+ :developers_can_push | :maintainers_can_merge | :guest | :be_disallowed
+
+ :no_one_can_push | :developers_can_merge | :owner | :be_allowed
+ :no_one_can_push | :developers_can_merge | :maintainer | :be_allowed
+ :no_one_can_push | :developers_can_merge | :developer | :be_allowed
+ :no_one_can_push | :developers_can_merge | :reporter | :be_disallowed
+ :no_one_can_push | :developers_can_merge | :guest | :be_disallowed
+
+ :maintainers_can_push | :developers_can_merge | :owner | :be_allowed
+ :maintainers_can_push | :developers_can_merge | :maintainer | :be_allowed
+ :maintainers_can_push | :developers_can_merge | :developer | :be_allowed
+ :maintainers_can_push | :developers_can_merge | :reporter | :be_disallowed
+ :maintainers_can_push | :developers_can_merge | :guest | :be_disallowed
+
+ :developers_can_push | :developers_can_merge | :owner | :be_allowed
+ :developers_can_push | :developers_can_merge | :maintainer | :be_allowed
+ :developers_can_push | :developers_can_merge | :developer | :be_allowed
+ :developers_can_push | :developers_can_merge | :reporter | :be_disallowed
+ :developers_can_push | :developers_can_merge | :guest | :be_disallowed
+ end
+
+ with_them do
+ before do
+ create(:protected_branch, push_access_level, merge_access_level, name: branch_ref_name,
+ project: project)
+ project.add_role(user, project_role)
+ end
+
+ it { expect(policy).to try(accessible, :create_pipeline_schedule) }
+ end
end
- with_them do
- before do
- create(:protected_branch, push_access_level, merge_access_level, name: branch_ref_name,
- project: project)
- project.add_role(user, project_role)
+ shared_examples_for 'only allowed by schedule owners who can update the branch' do
+ where(:push_access_level, :merge_access_level, :schedule_owner, :project_role, :accessible) do
+ :no_one_can_push | :no_one_can_merge | :other_user | :owner | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :user | :owner | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :user | :maintainer | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :user | :developer | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :user | :reporter | :be_disallowed
+ :no_one_can_push | :no_one_can_merge | :user | :guest | :be_disallowed
+
+ :maintainers_can_push | :no_one_can_merge | :other_user | :owner | :be_disallowed
+ :maintainers_can_push | :no_one_can_merge | :user | :owner | :be_allowed
+ :maintainers_can_push | :no_one_can_merge | :user | :maintainer | :be_allowed
+ :maintainers_can_push | :no_one_can_merge | :user | :developer | :be_disallowed
+ :maintainers_can_push | :no_one_can_merge | :user | :reporter | :be_disallowed
+ :maintainers_can_push | :no_one_can_merge | :user | :guest | :be_disallowed
+
+ :developers_can_push | :no_one_can_merge | :other_user | :owner | :be_disallowed
+ :developers_can_push | :no_one_can_merge | :user | :owner | :be_allowed
+ :developers_can_push | :no_one_can_merge | :user | :maintainer | :be_allowed
+ :developers_can_push | :no_one_can_merge | :user | :developer | :be_allowed
+ :developers_can_push | :no_one_can_merge | :user | :reporter | :be_disallowed
+ :developers_can_push | :no_one_can_merge | :user | :guest | :be_disallowed
+
+ :no_one_can_push | :maintainers_can_merge | :other_user | :owner | :be_disallowed
+ :no_one_can_push | :maintainers_can_merge | :user | :owner | :be_allowed
+ :no_one_can_push | :maintainers_can_merge | :user | :maintainer | :be_allowed
+ :no_one_can_push | :maintainers_can_merge | :user | :developer | :be_disallowed
+ :no_one_can_push | :maintainers_can_merge | :user | :reporter | :be_disallowed
+ :no_one_can_push | :maintainers_can_merge | :user | :guest | :be_disallowed
+
+ :maintainers_can_push | :maintainers_can_merge | :other_user | :owner | :be_disallowed
+ :maintainers_can_push | :maintainers_can_merge | :user | :owner | :be_allowed
+ :maintainers_can_push | :maintainers_can_merge | :user | :maintainer | :be_allowed
+ :maintainers_can_push | :maintainers_can_merge | :user | :developer | :be_disallowed
+ :maintainers_can_push | :maintainers_can_merge | :user | :reporter | :be_disallowed
+ :maintainers_can_push | :maintainers_can_merge | :user | :guest | :be_disallowed
+
+ :developers_can_push | :maintainers_can_merge | :other_user | :owner | :be_disallowed
+ :developers_can_push | :maintainers_can_merge | :user | :owner | :be_allowed
+ :developers_can_push | :maintainers_can_merge | :user | :maintainer | :be_allowed
+ :developers_can_push | :maintainers_can_merge | :user | :developer | :be_allowed
+ :developers_can_push | :maintainers_can_merge | :user | :reporter | :be_disallowed
+ :developers_can_push | :maintainers_can_merge | :user | :guest | :be_disallowed
+
+ :no_one_can_push | :developers_can_merge | :other_user | :owner | :be_disallowed
+ :no_one_can_push | :developers_can_merge | :user | :owner | :be_allowed
+ :no_one_can_push | :developers_can_merge | :user | :maintainer | :be_allowed
+ :no_one_can_push | :developers_can_merge | :user | :developer | :be_allowed
+ :no_one_can_push | :developers_can_merge | :user | :reporter | :be_disallowed
+ :no_one_can_push | :developers_can_merge | :user | :guest | :be_disallowed
+
+ :maintainers_can_push | :developers_can_merge | :other_user | :owner | :be_disallowed
+ :maintainers_can_push | :developers_can_merge | :user | :owner | :be_allowed
+ :maintainers_can_push | :developers_can_merge | :user | :maintainer | :be_allowed
+ :maintainers_can_push | :developers_can_merge | :user | :developer | :be_allowed
+ :maintainers_can_push | :developers_can_merge | :user | :reporter | :be_disallowed
+ :maintainers_can_push | :developers_can_merge | :user | :guest | :be_disallowed
+
+ :developers_can_push | :developers_can_merge | :other_user | :owner | :be_disallowed
+ :developers_can_push | :developers_can_merge | :user | :owner | :be_allowed
+ :developers_can_push | :developers_can_merge | :user | :maintainer | :be_allowed
+ :developers_can_push | :developers_can_merge | :user | :developer | :be_allowed
+ :developers_can_push | :developers_can_merge | :user | :reporter | :be_disallowed
+ :developers_can_push | :developers_can_merge | :user | :guest | :be_disallowed
end
- context 'for create_pipeline_schedule' do
- subject(:policy) { described_class.new(user, new_branch_pipeline_schedule) }
+ with_them do
+ before do
+ create(:protected_branch, push_access_level, merge_access_level, name: branch_ref_name,
+ project: project)
+ project.add_role(user, project_role)
+ project.add_role(other_user, project_role)
- let(:new_branch_pipeline_schedule) { project.pipeline_schedules.new(ref: branch_ref) }
+ pipeline_schedule.owner = schedule_owner == :user ? user : other_user
+ end
- it { expect(policy).to try(accessible, :create_pipeline_schedule) }
+ it { expect(policy).to try(accessible, ability_name) }
end
+ end
- context 'for play_pipeline_schedule' do
- subject(:policy) { described_class.new(user, branch_pipeline_schedule) }
+ describe 'create_pipeline_schedule' do
+ let(:ability_name) { :create_pipeline_schedule }
+ let(:pipeline_schedule) { project.pipeline_schedules.new(ref: branch_ref) }
- it { expect(policy).to try(accessible, :play_pipeline_schedule) }
- end
+ it_behaves_like 'allowed by those who can update the branch'
+ end
+
+ describe 'play_pipeline_schedule' do
+ let(:ability_name) { :play_pipeline_schedule }
+
+ it_behaves_like 'allowed by those who can update the branch'
+ end
+
+ describe 'update_pipeline_schedule' do
+ let(:ability_name) { :update_pipeline_schedule }
+
+ it_behaves_like 'only allowed by schedule owners who can update the branch'
end
end
end
@@ -108,49 +200,97 @@ RSpec.describe Ci::PipelineSchedulePolicy, :models, :clean_gitlab_redis_cache, f
context 'for tag' do
%w[refs/tags/v1.0.0 v1.0.0].each do |tag_ref|
context "with #{tag_ref}" do
- let_it_be(:tag_pipeline_schedule) do
+ let_it_be(:pipeline_schedule) do
create(:ci_pipeline_schedule, :nightly, project: project, ref: tag_ref)
end
- where(:access_level, :project_role, :accessible) do
- :no_one_can_create | :owner | :be_disallowed
- :no_one_can_create | :maintainer | :be_disallowed
- :no_one_can_create | :developer | :be_disallowed
- :no_one_can_create | :reporter | :be_disallowed
- :no_one_can_create | :guest | :be_disallowed
-
- :maintainers_can_create | :owner | :be_allowed
- :maintainers_can_create | :maintainer | :be_allowed
- :maintainers_can_create | :developer | :be_disallowed
- :maintainers_can_create | :reporter | :be_disallowed
- :maintainers_can_create | :guest | :be_disallowed
-
- :developers_can_create | :owner | :be_allowed
- :developers_can_create | :maintainer | :be_allowed
- :developers_can_create | :developer | :be_allowed
- :developers_can_create | :reporter | :be_disallowed
- :developers_can_create | :guest | :be_disallowed
+ subject(:policy) { described_class.new(user, pipeline_schedule) }
+
+ shared_examples_for 'allowed by those who can update the tag' do
+ where(:access_level, :project_role, :accessible) do
+ :no_one_can_create | :owner | :be_disallowed
+ :no_one_can_create | :maintainer | :be_disallowed
+ :no_one_can_create | :developer | :be_disallowed
+ :no_one_can_create | :reporter | :be_disallowed
+ :no_one_can_create | :guest | :be_disallowed
+
+ :maintainers_can_create | :owner | :be_allowed
+ :maintainers_can_create | :maintainer | :be_allowed
+ :maintainers_can_create | :developer | :be_disallowed
+ :maintainers_can_create | :reporter | :be_disallowed
+ :maintainers_can_create | :guest | :be_disallowed
+
+ :developers_can_create | :owner | :be_allowed
+ :developers_can_create | :maintainer | :be_allowed
+ :developers_can_create | :developer | :be_allowed
+ :developers_can_create | :reporter | :be_disallowed
+ :developers_can_create | :guest | :be_disallowed
+ end
+
+ with_them do
+ before do
+ create(:protected_tag, access_level, name: tag_ref_name, project: project)
+ project.add_role(user, project_role)
+ end
+
+ it { expect(policy).to try(accessible, ability_name) }
+ end
end
- with_them do
- before do
- create(:protected_tag, access_level, name: tag_ref_name, project: project)
- project.add_role(user, project_role)
+ shared_examples_for 'only allowed by schedule owners who can update the tag' do
+ where(:access_level, :schedule_owner, :project_role, :accessible) do
+ :no_one_can_create | :other_user | :owner | :be_disallowed
+ :no_one_can_create | :user | :owner | :be_disallowed
+ :no_one_can_create | :user | :maintainer | :be_disallowed
+ :no_one_can_create | :user | :developer | :be_disallowed
+ :no_one_can_create | :user | :reporter | :be_disallowed
+ :no_one_can_create | :user | :guest | :be_disallowed
+
+ :maintainers_can_create | :other_user | :owner | :be_disallowed
+ :maintainers_can_create | :user | :owner | :be_allowed
+ :maintainers_can_create | :user | :maintainer | :be_allowed
+ :maintainers_can_create | :user | :developer | :be_disallowed
+ :maintainers_can_create | :user | :reporter | :be_disallowed
+ :maintainers_can_create | :user | :guest | :be_disallowed
+
+ :developers_can_create | :other_user | :owner | :be_disallowed
+ :developers_can_create | :user | :owner | :be_allowed
+ :developers_can_create | :user | :maintainer | :be_allowed
+ :developers_can_create | :user | :developer | :be_allowed
+ :developers_can_create | :user | :reporter | :be_disallowed
+ :developers_can_create | :user | :guest | :be_disallowed
end
- context 'for create_pipeline_schedule' do
- subject(:policy) { described_class.new(user, new_tag_pipeline_schedule) }
+ with_them do
+ before do
+ create(:protected_tag, access_level, name: tag_ref_name, project: project)
+ project.add_role(user, project_role)
+ project.add_role(other_user, project_role)
- let(:new_tag_pipeline_schedule) { project.pipeline_schedules.new(ref: tag_ref) }
+ pipeline_schedule.owner = schedule_owner == :user ? user : other_user
+ end
- it { expect(policy).to try(accessible, :create_pipeline_schedule) }
+ it { expect(policy).to try(accessible, ability_name) }
end
+ end
- context 'for play_pipeline_schedule' do
- subject(:policy) { described_class.new(user, tag_pipeline_schedule) }
+ describe 'create_pipeline_schedule' do
+ let(:ability_name) { :create_pipeline_schedule }
+ let(:pipeline_schedule) { project.pipeline_schedules.new(ref: tag_ref) }
- it { expect(policy).to try(accessible, :play_pipeline_schedule) }
- end
+ it_behaves_like 'allowed by those who can update the tag'
+ end
+
+ describe 'play_pipeline_schedule' do
+ let(:ability_name) { :play_pipeline_schedule }
+
+ it_behaves_like 'allowed by those who can update the tag'
+ end
+
+ describe 'update_pipeline_schedule' do
+ let(:ability_name) { :update_pipeline_schedule }
+
+ it_behaves_like 'only allowed by schedule owners who can update the tag'
end
end
end
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index 743d96ee3dd..61d5b11d69d 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -142,50 +142,50 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do
let(:confidential_issue_no_assignee) { create(:issue, :confidential, project: project) }
it 'does not allow non-members to read confidential issues' do
- expect(permissions(non_member, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation)
- expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
+ expect(permissions(non_member, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation, :award_emoji)
+ expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
end
it 'does not allow guests to read confidential issues' do
- expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation)
- expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
+ expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation, :award_emoji)
+ expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
end
it 'allows reporters to read, update, and admin confidential issues' do
- expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
- expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
+ expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
+ expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
end
it 'allows reporters from group links to read, update, and admin confidential issues' do
- expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
- expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
+ expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
+ expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
end
it 'allows issue authors to read and update their confidential issues' do
- expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue_relation)
+ expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue_relation, :award_emoji)
expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality)
- expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation)
- expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality)
+ expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation, :award_emoji)
+ expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality, :award_emoji)
end
it 'does not allow issue author to read or update confidential issue moved to an private project' do
confidential_issue.project = create(:project, :private)
- expect(permissions(author, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
+ expect(permissions(author, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
end
it 'allows issue assignees to read and update their confidential issues' do
- expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
+ expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :award_emoji)
expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality)
- expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
+ expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
end
it 'does not allow issue assignees to read or update confidential issue moved to an private project' do
confidential_issue.project = create(:project, :private)
- expect(permissions(assignee, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
+ expect(permissions(assignee, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation, :award_emoji)
end
end
end
diff --git a/spec/services/ci/pipeline_schedules/update_service_spec.rb b/spec/services/ci/pipeline_schedules/update_service_spec.rb
index 834bbcfcfeb..b84afacdcff 100644
--- a/spec/services/ci/pipeline_schedules/update_service_spec.rb
+++ b/spec/services/ci/pipeline_schedules/update_service_spec.rb
@@ -7,16 +7,16 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
let_it_be_with_reload(:project) { create(:project, :public, :repository) }
let_it_be_with_reload(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
let_it_be(:reporter) { create(:user) }
+ let_it_be(:project_owner) { create(:user) }
let_it_be(:pipeline_schedule_variable) do
create(:ci_pipeline_schedule_variable,
key: 'foo', value: 'foovalue', pipeline_schedule: pipeline_schedule)
end
- subject(:service) { described_class.new(pipeline_schedule, user, params) }
-
before_all do
project.add_maintainer(user)
+ project.add_owner(project_owner)
project.add_reporter(reporter)
pipeline_schedule.reload
@@ -54,8 +54,10 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
subject(:service) { described_class.new(pipeline_schedule, user, params) }
it 'updates database values with passed params' do
- expect { service.execute }
- .to change { pipeline_schedule.description }.from('pipeline schedule').to('updated_desc')
+ expect do
+ service.execute
+ pipeline_schedule.reload
+ end.to change { pipeline_schedule.description }.from('pipeline schedule').to('updated_desc')
.and change { pipeline_schedule.ref }.from('master').to('patch-x')
.and change { pipeline_schedule.active }.from(true).to(false)
.and change { pipeline_schedule.cron }.from('0 1 * * *').to('*/1 * * * *')
@@ -63,6 +65,48 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
.and change { pipeline_schedule.variables.last.value }.from('foovalue').to('barvalue')
end
+ context 'when the new branch is protected', :request_store do
+ let(:maintainer_access) { :no_one_can_merge }
+
+ before do
+ create(:protected_branch, :no_one_can_push, maintainer_access, name: 'patch-x', project: project)
+ end
+
+ after do
+ ProtectedBranches::CacheService.new(project).refresh
+ end
+
+ context 'when called by someone other than the schedule owner who can update the ref' do
+ let(:maintainer_access) { :maintainers_can_merge }
+
+ subject(:service) { described_class.new(pipeline_schedule, project_owner, params) }
+
+ it 'does not update the schedule' do
+ expect do
+ service.execute
+ pipeline_schedule.reload
+ end.not_to change { pipeline_schedule.description }
+ end
+ end
+
+ context 'when called by the schedule owner' do
+ it 'does not update the schedule' do
+ expect do
+ service.execute
+ pipeline_schedule.reload
+ end.not_to change { pipeline_schedule.description }
+ end
+
+ context 'when the owner can update the ref' do
+ let(:maintainer_access) { :maintainers_can_merge }
+
+ it 'updates the schedule' do
+ expect { service.execute }.to change { pipeline_schedule.description }
+ end
+ end
+ end
+ end
+
context 'when creating a variable' do
let(:params) do
{
@@ -126,6 +170,8 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
end
end
- it_behaves_like 'pipeline schedules checking variables permission'
+ it_behaves_like 'pipeline schedules checking variables permission' do
+ subject(:service) { described_class.new(pipeline_schedule, user, params) }
+ end
end
end
diff --git a/yarn.lock b/yarn.lock
index 0e6fc9ea1ee..1eecf751d11 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9450,10 +9450,10 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-mermaid@10.5.0:
- version "10.5.0"
- resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-10.5.0.tgz#e90512a65b5c6e29bd86cd04ce45aa31da2be76d"
- integrity sha512-9l0o1uUod78D3/FVYPGSsgV+Z0tSnzLBDiC9rVzvelPxuO80HbN1oDr9ofpPETQy9XpypPQa26fr09VzEPfvWA==
+mermaid@10.6.1:
+ version "10.6.1"
+ resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-10.6.1.tgz#701f4160484137a417770ce757ce1887a98c00fc"
+ integrity sha512-Hky0/RpOw/1il9X8AvzOEChfJtVvmXm+y7JML5C//ePYMy0/9jCEmW1E1g86x9oDfW9+iVEdTV/i+M6KWRNs4A==
dependencies:
"@braintree/sanitize-url" "^6.0.1"
"@types/d3-scale" "^4.0.3"