Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a1f2c38e4b
commit
dfd347c174
|
|
@ -311,8 +311,7 @@ jest:
|
|||
junit: junit_jest.xml
|
||||
parallel: 11
|
||||
script:
|
||||
- if [[ -z "${CI_MERGE_REQUEST_IID}" ]] && ! [[ "$CI_COMMIT_BRANCH" =~ ^as-if-foss/ ]]; then export JEST_COVERAGE="--coverage"; fi
|
||||
- run_timed_command "scripts/frontend/jest_ci.js $JEST_COVERAGE"
|
||||
- run_timed_command scripts/frontend/jest_ci.js
|
||||
|
||||
jest-with-fixtures:
|
||||
extends:
|
||||
|
|
@ -326,8 +325,7 @@ jest-with-fixtures:
|
|||
- !reference [.with-fixtures-needs, needs]
|
||||
parallel: 2
|
||||
script:
|
||||
- if [[ -z "${CI_MERGE_REQUEST_IID}" ]] && ! [[ "$CI_COMMIT_BRANCH" =~ ^as-if-foss/ ]]; then export JEST_COVERAGE="--coverage"; fi
|
||||
- run_timed_command "scripts/frontend/jest_ci.js --fixtures $JEST_COVERAGE"
|
||||
- run_timed_command "scripts/frontend/jest_ci.js --fixtures"
|
||||
|
||||
jest vue3:
|
||||
extends:
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
# Cop supports --autocorrect.
|
||||
Layout/SpaceInsideParens:
|
||||
Exclude:
|
||||
- 'spec/policies/clusters/agent_policy_spec.rb'
|
||||
- 'spec/presenters/ci/build_presenter_spec.rb'
|
||||
- 'spec/presenters/packages/conan/package_presenter_spec.rb'
|
||||
- 'spec/requests/jwt_controller_spec.rb'
|
||||
- 'spec/requests/projects/merge_requests/diffs_spec.rb'
|
||||
- 'spec/requests/projects/merge_requests_spec.rb'
|
||||
- 'spec/requests/projects/releases_controller_spec.rb'
|
||||
- 'spec/requests/search_controller_spec.rb'
|
||||
- 'spec/serializers/analytics_build_entity_spec.rb'
|
||||
- 'spec/services/bulk_imports/create_service_spec.rb'
|
||||
- 'spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb'
|
||||
- 'spec/tasks/gitlab/db_rake_spec.rb'
|
||||
- 'spec/validators/devise_email_validator_spec.rb'
|
||||
- 'spec/views/dashboard/projects/_blank_state_welcome.html.haml_spec.rb'
|
||||
- 'spec/workers/concerns/gitlab/github_import/object_importer_spec.rb'
|
||||
- 'spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb'
|
||||
- 'spec/workers/pipeline_schedule_worker_spec.rb'
|
||||
- 'spec/workers/purge_dependency_proxy_cache_worker_spec.rb'
|
||||
- 'spec/workers/releases/manage_evidence_worker_spec.rb'
|
||||
|
|
@ -70,9 +70,9 @@ export default {
|
|||
[types.SET_REVIEW_BAR_RENDERED]() {
|
||||
this.reviewBarRendered = true;
|
||||
},
|
||||
[types.SET_DRAFT_EDITING](state, { draftId, isEditing }) {
|
||||
const draftIndex = state.drafts.findIndex((draft) => draft.id === draftId);
|
||||
const draft = state.drafts[draftIndex];
|
||||
state.drafts.splice(draftIndex, 1, { ...draft, isEditing });
|
||||
[types.SET_DRAFT_EDITING]({ draftId, isEditing }) {
|
||||
const draftIndex = this.drafts.findIndex((draft) => draft.id === draftId);
|
||||
const draft = this.drafts[draftIndex];
|
||||
this.drafts.splice(draftIndex, 1, { ...draft, isEditing });
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -171,9 +171,9 @@ export default {
|
|||
<div class="row gl-mt-8">
|
||||
<main class="col-md-6 gl-pr-8">
|
||||
<header class="gl-mb-5">
|
||||
<h3 class="gl-mt-0 gl-text-subtle" data-testid="step-count">
|
||||
<h2 class="gl-mt-0" data-testid="step-count">
|
||||
{{ sprintf($options.i18n.stepNofN, { currentStep, stepCount }) }}
|
||||
</h3>
|
||||
</h2>
|
||||
<gl-progress-bar :value="progress" />
|
||||
</header>
|
||||
<section class="gl-mb-4">
|
||||
|
|
|
|||
|
|
@ -63,12 +63,16 @@ module Packages
|
|||
def projects_visible_to_reporters(user, within_group:, within_public_package_registry: false)
|
||||
return user.accessible_projects if user.is_a?(DeployToken)
|
||||
|
||||
unless within_public_package_registry
|
||||
return within_group.all_projects.public_or_visible_to_user(user, ::Gitlab::Access::REPORTER)
|
||||
end
|
||||
access = if Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, within_group.root_ancestor)
|
||||
::Gitlab::Access::GUEST
|
||||
else
|
||||
::Gitlab::Access::REPORTER
|
||||
end
|
||||
|
||||
return within_group.all_projects.public_or_visible_to_user(user, access) unless within_public_package_registry
|
||||
|
||||
::Project
|
||||
.public_or_visible_to_user(user, Gitlab::Access::REPORTER)
|
||||
.public_or_visible_to_user(user, access)
|
||||
.or(::Project.with_public_package_registry)
|
||||
.in_namespace(within_group.self_and_descendants)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ module Packages
|
|||
end
|
||||
|
||||
def projects_available_in_current_context
|
||||
return ::Project.public_or_visible_to_user(current_user, ::Gitlab::Access::REPORTER) unless username.present?
|
||||
return ::Project.public_or_visible_to_user(current_user, project_min_access_level) unless username.present?
|
||||
|
||||
return project_from_path if can_access_project_package?
|
||||
|
||||
nil
|
||||
|
|
@ -55,6 +56,12 @@ module Packages
|
|||
def can_access_project_package?
|
||||
Ability.allowed?(current_user, :read_package, project_from_path.try(:packages_policy_subject))
|
||||
end
|
||||
|
||||
def project_min_access_level
|
||||
return ::Gitlab::Access::GUEST if Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, current_user)
|
||||
|
||||
::Gitlab::Access::REPORTER
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -60,7 +60,13 @@ module Packages
|
|||
end
|
||||
|
||||
def visible_projects
|
||||
public_or_visible = ::Project.public_or_visible_to_user(current_user, Gitlab::Access::REPORTER)
|
||||
access = if Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, group.root_ancestor)
|
||||
::Gitlab::Access::GUEST
|
||||
else
|
||||
::Gitlab::Access::REPORTER
|
||||
end
|
||||
|
||||
public_or_visible = ::Project.public_or_visible_to_user(current_user, access)
|
||||
|
||||
return public_or_visible.or(with_public_package_registry) if params[:within_public_package_registry]
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@
|
|||
class BulkImports::Configuration < ApplicationRecord
|
||||
self.table_name = 'bulk_import_configurations'
|
||||
|
||||
include IgnorableColumns
|
||||
|
||||
ignore_column :migrate_memberships, remove_with: '17.8', remove_after: '2025-01-20'
|
||||
|
||||
belongs_to :bulk_import, inverse_of: :configuration, optional: false
|
||||
|
||||
validates :url, :access_token, length: { maximum: 255 }, presence: true
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class DeployToken < ApplicationRecord
|
|||
|
||||
AVAILABLE_SCOPES = %i[read_repository read_registry write_registry
|
||||
read_package_registry write_package_registry
|
||||
read_virtual_registry].freeze
|
||||
read_virtual_registry write_virtual_registry].freeze
|
||||
GITLAB_DEPLOY_TOKEN_NAME = 'gitlab-deploy-token'
|
||||
DEPLOY_TOKEN_PREFIX = 'gldt-'
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
class Vulnerability < Gitlab::Database::SecApplicationRecord
|
||||
include EachBatch
|
||||
include AfterCommitQueue
|
||||
include IgnorableColumns
|
||||
|
||||
ignore_column :confidence, :confidence_overridden, remove_after: '2025-01-19', remove_with: '17.9'
|
||||
|
||||
alias_attribute :vulnerability_id, :id
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
@subject.allow_runner_registration_token?
|
||||
end
|
||||
|
||||
condition(:allow_guest_plus_roles_to_pull_packages_enabled, scope: :subject) do
|
||||
Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, @subject.root_ancestor)
|
||||
end
|
||||
|
||||
rule { can?(:read_group) & design_management_enabled }.policy do
|
||||
enable :read_design_activity
|
||||
end
|
||||
|
|
@ -436,6 +440,11 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
|
||||
rule { can?(:remove_group) }.enable :view_edit_page
|
||||
|
||||
# TODO: Remove this rule and move :read_package permission from reporter to guest
|
||||
# with the rollout of the FF allow_guest_plus_roles_to_pull_packages
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/512210
|
||||
rule { guest & allow_guest_plus_roles_to_pull_packages_enabled }.enable :read_package
|
||||
|
||||
def access_level(for_any_session: false)
|
||||
return GroupMember::NO_ACCESS if @user.nil?
|
||||
return GroupMember::NO_ACCESS unless user_is_user?
|
||||
|
|
|
|||
|
|
@ -14,10 +14,16 @@ module Packages
|
|||
@subject.all_projects.with_public_package_registry.any?
|
||||
end
|
||||
|
||||
condition(:allow_guest_plus_roles_to_pull_packages_enabled, scope: :subject) do
|
||||
Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, @subject.root_ancestor)
|
||||
end
|
||||
|
||||
rule { group.public_group }.policy do
|
||||
enable :read_package
|
||||
end
|
||||
|
||||
# TODO: Remove with the rollout of the FF allow_guest_plus_roles_to_pull_packages
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/512210
|
||||
rule { group.reporter }.policy do
|
||||
enable :read_package
|
||||
end
|
||||
|
|
@ -38,6 +44,10 @@ module Packages
|
|||
# package-related actions that we don't want to.
|
||||
enable :read_package_within_public_registries
|
||||
end
|
||||
|
||||
rule { group.guest & allow_guest_plus_roles_to_pull_packages_enabled }.policy do
|
||||
enable :read_package
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,10 +12,16 @@ module Packages
|
|||
Gitlab::CurrentSettings.package_registry_allow_anyone_to_pull_option
|
||||
end
|
||||
|
||||
condition(:allow_guest_plus_roles_to_pull_packages_enabled, scope: :subject) do
|
||||
Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, @subject.project.root_ancestor)
|
||||
end
|
||||
|
||||
rule { project.packages_disabled }.policy do
|
||||
prevent(:read_package)
|
||||
end
|
||||
|
||||
# TODO: Remove with the rollout of the FF allow_guest_plus_roles_to_pull_packages
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/512210
|
||||
rule { can?(:reporter_access) }.policy do
|
||||
enable :read_package
|
||||
end
|
||||
|
|
@ -24,6 +30,10 @@ module Packages
|
|||
enable :read_package
|
||||
end
|
||||
|
||||
rule { can?(:guest_access) & allow_guest_plus_roles_to_pull_packages_enabled }.policy do
|
||||
enable :read_package
|
||||
end
|
||||
|
||||
rule { project.read_package_registry_deploy_token }.policy do
|
||||
enable :read_package
|
||||
end
|
||||
|
|
|
|||
|
|
@ -320,6 +320,10 @@ class ProjectPolicy < BasePolicy
|
|||
can?(:reporter_access) || can?(:planner_access)
|
||||
end
|
||||
|
||||
condition(:allow_guest_plus_roles_to_pull_packages_enabled, scope: :subject) do
|
||||
Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, @subject.root_ancestor)
|
||||
end
|
||||
|
||||
# `:read_project` may be prevented in EE, but `:read_project_for_iids` should
|
||||
# not.
|
||||
rule { guest | admin | organization_owner }.enable :read_project_for_iids
|
||||
|
|
@ -1096,6 +1100,12 @@ class ProjectPolicy < BasePolicy
|
|||
enable :read_ci_pipeline_schedules_plan_limit
|
||||
end
|
||||
|
||||
# TODO: Remove this rule and move :read_package permission from
|
||||
# can?(:reporter_access) to can?(:guest_access)
|
||||
# with the rollout of the FF allow_guest_plus_roles_to_pull_packages
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/512210
|
||||
rule { can?(:guest_access) & allow_guest_plus_roles_to_pull_packages_enabled }.enable :read_package
|
||||
|
||||
private
|
||||
|
||||
def team_member?
|
||||
|
|
|
|||
|
|
@ -144,10 +144,9 @@ class AuditEventService
|
|||
def log_authentication_event_to_database
|
||||
return unless Gitlab::Database.read_write? && authentication_event?
|
||||
|
||||
event = AuthenticationEvent.new(authentication_event_payload)
|
||||
save_or_track event
|
||||
|
||||
event
|
||||
AuthenticationEvent.new(authentication_event_payload).tap do |event|
|
||||
save_or_track event
|
||||
end
|
||||
end
|
||||
|
||||
def save_or_track(event)
|
||||
|
|
@ -155,6 +154,8 @@ class AuditEventService
|
|||
stream_event_to_external_destinations(event) if should_save_stream?(@save_type)
|
||||
rescue StandardError => e
|
||||
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, audit_event_type: event.class.to_s)
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
name: license_scanning_with_sbom_licenses
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370013
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/162102
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/415946
|
||||
milestone: '17.4'
|
||||
group: group::threat insights
|
||||
type: beta
|
||||
default_enabled: true
|
||||
name: allow_guest_plus_roles_to_pull_packages
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336622
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177267
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/512210
|
||||
milestone: '17.9'
|
||||
group: group::package registry
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -5,4 +5,5 @@ feature_category: security_policy_management
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173790
|
||||
milestone: '17.7'
|
||||
queued_migration_version: 20241127151803
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
finalized_by: 20250114213926
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ description: >
|
|||
If there is no other assigned project to fall back to, the runner manager is deleted.
|
||||
feature_category: runner
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177423
|
||||
milestone: '17.9'
|
||||
milestone: '17.8'
|
||||
queued_migration_version: 20250108170045
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ description: >
|
|||
If there is no other assigned project to fall back to, the runner manager is deleted.
|
||||
feature_category: runner
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177423
|
||||
milestone: '17.9'
|
||||
milestone: '17.8'
|
||||
queued_migration_version: 20250109133913
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ description: >
|
|||
If there is no other assigned project to fall back to, the runner is deleted.
|
||||
feature_category: runner
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177271
|
||||
milestone: '17.9'
|
||||
milestone: '17.8'
|
||||
queued_migration_version: 20250108120138
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddWriteVirtualRegistryScopeToDeployTokens < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
|
||||
def change
|
||||
add_column :deploy_tokens, :write_virtual_registry, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddUserProvidedToWorkspaceVariables < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
|
||||
def change
|
||||
add_column :workspace_variables, :user_provided, :boolean, null: false, default: false, if_not_exists: true
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class BackfillUserProvidedWorkspaceVariables < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
class WorkspaceVariable < MigrationRecord
|
||||
self.table_name = :workspace_variables
|
||||
|
||||
include EachBatch
|
||||
end
|
||||
|
||||
BATCH_SIZE = 100
|
||||
|
||||
# Since file type is not supported for user variables
|
||||
VARIABLE_ENV_TYPE = 0
|
||||
|
||||
# Internal workspace variables that get created on workspace creation
|
||||
# Reference: /ee/lib/remote_development/workspace_operations/create/workspace_variables.rb
|
||||
WORKSPACE_INTERNAL_VARIABLES = %w[
|
||||
GIT_CONFIG_COUNT
|
||||
GIT_CONFIG_KEY_0
|
||||
GIT_CONFIG_VALUE_0
|
||||
GIT_CONFIG_KEY_1
|
||||
GIT_CONFIG_VALUE_1
|
||||
GIT_CONFIG_KEY_2
|
||||
GIT_CONFIG_VALUE_2
|
||||
GL_GIT_CREDENTIAL_STORE_FILE_PATH
|
||||
GL_TOKEN_FILE_PATH
|
||||
GL_WORKSPACE_DOMAIN_TEMPLATE
|
||||
GL_EDITOR_EXTENSIONS_GALLERY_SERVICE_URL
|
||||
GL_EDITOR_EXTENSIONS_GALLERY_ITEM_URL
|
||||
GL_EDITOR_EXTENSIONS_GALLERY_RESOURCE_URL_TEMPLATE
|
||||
GITLAB_WORKFLOW_INSTANCE_URL
|
||||
GITLAB_WORKFLOW_TOKEN_FILE
|
||||
].freeze
|
||||
|
||||
def up
|
||||
WorkspaceVariable.reset_column_information
|
||||
|
||||
WorkspaceVariable.each_batch(of: BATCH_SIZE) do |batch|
|
||||
batch.where(variable_type: VARIABLE_ENV_TYPE).where.not(key: WORKSPACE_INTERNAL_VARIABLES)
|
||||
.update_all(user_provided: true)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
WorkspaceVariable.reset_column_information
|
||||
|
||||
# Column is NOT NULL DEFAULT 0, so setting back to default
|
||||
WorkspaceVariable.update_all(user_provided: false)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QueueRecalculateShardingKeyIdForOrphanedProjectRunners < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
milestone '17.8'
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_ci
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QueueRecalculateShardingKeyIdForOrphanedProjectRunnerManagers < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
milestone '17.8'
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_ci
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QueueRecalculateShardingKeyIdForOrphanedProjectRunnerTaggings < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
milestone '17.8'
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_ci
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FinalizeMigrateSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
|
||||
disable_ddl_transaction!
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
MIGRATION = "MigrateRemainingSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses"
|
||||
|
||||
def up
|
||||
ensure_batched_background_migration_is_finished(
|
||||
job_class_name: MIGRATION,
|
||||
table_name: :software_license_policies,
|
||||
column_name: :id,
|
||||
job_arguments: [],
|
||||
finalize: true
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
22a0025bf1ff0bf243698761c17bcfdb181599a4f31ac696c20511dfd1afbf9b
|
||||
|
|
@ -0,0 +1 @@
|
|||
79ded29b939ad063a58275fec52191c01161d48b89758b05f3dc3f15c41f018d
|
||||
|
|
@ -0,0 +1 @@
|
|||
e57acf78acb8d7c507b2e4d611be22d6741f4a0e09970776bb86f2aca266b542
|
||||
|
|
@ -0,0 +1 @@
|
|||
b358e94b4be73e82fe3140c3cd0e0d2568a1e6eccd682ca0edb932207f28cf26
|
||||
|
|
@ -12204,7 +12204,8 @@ CREATE TABLE deploy_tokens (
|
|||
creator_id bigint,
|
||||
read_virtual_registry boolean DEFAULT false NOT NULL,
|
||||
project_id bigint,
|
||||
group_id bigint
|
||||
group_id bigint,
|
||||
write_virtual_registry boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE deploy_tokens_id_seq
|
||||
|
|
@ -23305,6 +23306,7 @@ CREATE TABLE workspace_variables (
|
|||
encrypted_value bytea NOT NULL,
|
||||
encrypted_value_iv bytea NOT NULL,
|
||||
project_id bigint,
|
||||
user_provided boolean DEFAULT false NOT NULL,
|
||||
CONSTRAINT check_5545042100 CHECK ((char_length(key) <= 255)),
|
||||
CONSTRAINT check_ed95da8691 CHECK ((project_id IS NOT NULL))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ Upgrades occur in your selected [maintenance window](#maintenance-windows) accor
|
|||
|
||||
For example, GitLab 16.9 released on 2024-02-15. Instances in the EMEA and Americas (Option 1) regions were then upgraded to 16.8 on 2024-02-20, 5 days after the 16.9 release.
|
||||
|
||||
NOTE:
|
||||
If a production change lock (PCL) is active during a scheduled upgrade, GitLab defers the upgrade to the first maintenance window after the PCL ends. For more information, including upcoming and current PCL periods, see [Production Change Lock](https://handbook.gitlab.com/handbook/engineering/infrastructure/team/gitlab-dedicated/#production-change-lock-pcl).
|
||||
|
||||
## Emergency maintenance
|
||||
|
||||
In an event of a platform outage, degradation, or a security event requiring urgent action,
|
||||
|
|
|
|||
|
|
@ -248,3 +248,51 @@ To find a state file path:
|
|||
```
|
||||
|
||||
The relative path is displayed.
|
||||
|
||||
## Restoring Terraform state files from backups
|
||||
|
||||
To restore Terraform state files from backups, you must have access to the encrypted state files and the GitLab database.
|
||||
|
||||
### Database tables
|
||||
|
||||
The following database table helps trace the S3 path back to specific projects:
|
||||
|
||||
- `terraform_states`: Contains the base state information, including the universally unique ID (UUID) for each state.
|
||||
|
||||
### File structure and path composition
|
||||
|
||||
The state files are stored in a specific directory structure, where:
|
||||
|
||||
- The first three segments of the path are derived from the SHA-2 hash value of the project ID.
|
||||
- Each state has a UUID stored on the `terraform_states` database table that forms part of the path.
|
||||
|
||||
For example, for a project where the:
|
||||
|
||||
- Project ID is `12345`
|
||||
- State UUID is `example-uuid`
|
||||
|
||||
If the SHA-2 hash value of `12345` is `5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5`, the folder structure would be:
|
||||
|
||||
```plaintext
|
||||
terraform/ <- configured Terraform storage directory
|
||||
├─ 59/ <- first and second character of project ID hash
|
||||
| ├─ 94/ <- third and fourth character of project ID hash
|
||||
| | ├─ 5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5/ <- full project ID hash
|
||||
| | | ├─ example-uuid/ <- state UUID
|
||||
| | | | ├─ 1.tf <- individual state versions
|
||||
| | | | ├─ 2.tf
|
||||
| | | | ├─ 3.tf
|
||||
```
|
||||
|
||||
### Decryption process
|
||||
|
||||
The state files are encrypted using Lockbox and require the following information for decryption:
|
||||
|
||||
- The `db_key_base` [application secret](../development/application_secrets.md#secret-entries)
|
||||
- The project ID
|
||||
|
||||
The encryption key is derived from both the `db_key_base` and the project ID. If you can't access `db_key_base`, decryption is not possible.
|
||||
|
||||
To learn how to manually decrypt files, see the documentation from [Lockbox](https://github.com/ankane/lockbox).
|
||||
|
||||
To view the encryption key generation process, see the [state uploader code](https://gitlab.com/gitlab-org/gitlab/-/blob/e0137111fbbd28316f38da30075aba641e702b98/app/uploaders/terraform/state_uploader.rb#L43).
|
||||
|
|
|
|||
|
|
@ -18344,6 +18344,29 @@ The edge type for [`Workspace`](#workspace).
|
|||
| <a id="workspaceedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="workspaceedgenode"></a>`node` | [`Workspace`](#workspace) | The item at the end of the edge. |
|
||||
|
||||
#### `WorkspaceVariableConnection`
|
||||
|
||||
The connection type for [`WorkspaceVariable`](#workspacevariable).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="workspacevariableconnectionedges"></a>`edges` | [`[WorkspaceVariableEdge]`](#workspacevariableedge) | A list of edges. |
|
||||
| <a id="workspacevariableconnectionnodes"></a>`nodes` | [`[WorkspaceVariable]`](#workspacevariable) | A list of nodes. |
|
||||
| <a id="workspacevariableconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||
|
||||
#### `WorkspaceVariableEdge`
|
||||
|
||||
The edge type for [`WorkspaceVariable`](#workspacevariable).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="workspacevariableedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="workspacevariableedgenode"></a>`node` | [`WorkspaceVariable`](#workspacevariable) | The item at the end of the edge. |
|
||||
|
||||
## Object types
|
||||
|
||||
Object types represent the resources that the GitLab GraphQL API can return.
|
||||
|
|
@ -21308,7 +21331,7 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="clusteragentworkspacesactualstates"></a>`actualStates` | [`[String!]`](#string) | Filter workspaces by actual states. |
|
||||
| <a id="clusteragentworkspacesids"></a>`ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Filter workspaces by workspace GlobalIDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. |
|
||||
| <a id="clusteragentworkspacesprojectids"></a>`projectIds` | [`[ProjectID!]`](#projectid) | Filter workspaces by project GlobalID. |
|
||||
| <a id="clusteragentworkspacesprojectids"></a>`projectIds` | [`[ProjectID!]`](#projectid) | Filter workspaces by project GlobalIDs. |
|
||||
|
||||
### `ClusterAgentActivityEvent`
|
||||
|
||||
|
|
@ -38476,8 +38499,24 @@ Represents a remote development workspace.
|
|||
| <a id="workspaceupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of the last update to any mutable workspace property. |
|
||||
| <a id="workspaceurl"></a>`url` | [`String!`](#string) | URL of the workspace. |
|
||||
| <a id="workspaceuser"></a>`user` | [`UserCore!`](#usercore) | Owner of the workspace. |
|
||||
| <a id="workspaceworkspacevariables"></a>`workspaceVariables` **{warning-solid}** | [`WorkspaceVariableConnection`](#workspacevariableconnection) | **Introduced** in GitLab 17.9. **Status**: Experiment. User defined variables associated with the workspace. |
|
||||
| <a id="workspaceworkspacesagentconfigversion"></a>`workspacesAgentConfigVersion` **{warning-solid}** | [`Int!`](#int) | **Introduced** in GitLab 17.6. **Status**: Experiment. Version of the associated WorkspacesAgentConfig for the workspace. |
|
||||
|
||||
### `WorkspaceVariable`
|
||||
|
||||
Represents a remote development workspace variable.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="workspacevariablecreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of when the workspace variable was created. |
|
||||
| <a id="workspacevariableid"></a>`id` | [`RemoteDevelopmentWorkspaceVariableID!`](#remotedevelopmentworkspacevariableid) | Global ID of the workspace variable. |
|
||||
| <a id="workspacevariablekey"></a>`key` | [`String`](#string) | Name of the workspace variable. |
|
||||
| <a id="workspacevariableupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the workspace variable was updated. |
|
||||
| <a id="workspacevariablevalue"></a>`value` | [`String`](#string) | Value of the workspace variable. |
|
||||
| <a id="workspacevariablevariabletype"></a>`variableType` | [`WorkspaceVariableType`](#workspacevariabletype) | Type of the workspace variable. |
|
||||
|
||||
### `WorkspacesAgentConfig`
|
||||
|
||||
Represents a workspaces agent config.
|
||||
|
|
@ -42179,6 +42218,14 @@ Enum for the type of the variable to be injected in a workspace.
|
|||
| ----- | ----------- |
|
||||
| <a id="workspacevariableinputtypeenvironment"></a>`ENVIRONMENT` | Name type. |
|
||||
|
||||
### `WorkspaceVariableType`
|
||||
|
||||
Enum for the type of the variable injected in a workspace.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| <a id="workspacevariabletypeenvironment"></a>`ENVIRONMENT` | Environment type. |
|
||||
|
||||
## Scalar types
|
||||
|
||||
Scalar values are atomic values, and do not have fields of their own.
|
||||
|
|
@ -43151,6 +43198,12 @@ A `RemoteDevelopmentWorkspaceID` is a global ID. It is encoded as a string.
|
|||
|
||||
An example `RemoteDevelopmentWorkspaceID` is: `"gid://gitlab/RemoteDevelopment::Workspace/1"`.
|
||||
|
||||
### `RemoteDevelopmentWorkspaceVariableID`
|
||||
|
||||
A `RemoteDevelopmentWorkspaceVariableID` is a global ID. It is encoded as a string.
|
||||
|
||||
An example `RemoteDevelopmentWorkspaceVariableID` is: `"gid://gitlab/RemoteDevelopment::WorkspaceVariable/1"`.
|
||||
|
||||
### `RemoteDevelopmentWorkspacesAgentConfigID`
|
||||
|
||||
A `RemoteDevelopmentWorkspacesAgentConfigID` is a global ID. It is encoded as a string.
|
||||
|
|
@ -45636,6 +45689,7 @@ Attributes for defining a variable to be injected in a workspace.
|
|||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="workspacevariableinputkey"></a>`key` | [`String!`](#string) | Key of the variable. |
|
||||
| <a id="workspacevariableinputtype"></a>`type` | [`WorkspaceVariableInputType!`](#workspacevariableinputtype) | Type of the variable to be injected in a workspace. |
|
||||
| <a id="workspacevariableinputkey"></a>`key` | [`String!`](#string) | Name of the workspace variable. |
|
||||
| <a id="workspacevariableinputtype"></a>`type` **{warning-solid}** | [`WorkspaceVariableInputType`](#workspacevariableinputtype) | **Deprecated:** Use `variableType` instead. Deprecated in GitLab 17.9. |
|
||||
| <a id="workspacevariableinputvalue"></a>`value` | [`String!`](#string) | Value of the variable. |
|
||||
| <a id="workspacevariableinputvariabletype"></a>`variableType` | [`WorkspaceVariableType`](#workspacevariabletype) | Type of the variable to be injected in a workspace. |
|
||||
|
|
|
|||
|
|
@ -214,6 +214,17 @@ For more information, see [issue 480328](https://gitlab.com/gitlab-org/gitlab/-/
|
|||
gitlab-rake db:migrate:up:ci VERSION=20241028085044
|
||||
```
|
||||
|
||||
## 17.8.0
|
||||
|
||||
- In GitLab 17.8.0, GitLab agent server for Kubernetes (KAS) does not start with the default settings on the GitLab Linux package (Omnibus) and Docker installations.
|
||||
To resolve this issue, edit `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitlab_kas['env'] = { 'OWN_PRIVATE_API_URL' => 'grpc://127.0.0.1:8155' }
|
||||
```
|
||||
|
||||
Multiple node installations should use the settings described in the [documentation](../../administration/clusters/kas.md).
|
||||
|
||||
## 17.7.0
|
||||
|
||||
- Git 2.47.0 and later is required by Gitaly. For installations from source, you should use the [Git version provided by Gitaly](../../install/installation.md#git).
|
||||
|
|
|
|||
|
|
@ -12,10 +12,7 @@ DETAILS:
|
|||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5708) support for enforcing policies on projects in GitLab 17.7 [with a flag](../../../administration/feature_flags.md) named `vulnerability_management_policy_type`. Enabled by default.
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/15697) support for enforcing policies on groups in GitLab 17.8 for the group-level [with a flag](../../../administration/feature_flags.md) named `vulnerability_management_policy_type_group`. Enabled by default.
|
||||
|
||||
FLAG:
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178031) in GitLab 17.9. Feature flags `vulnerability_management_policy_type` and `vulnerability_management_policy_type_group` removed.
|
||||
|
||||
Use a vulnerability management policy to automatically resolve vulnerabilities that are no longer
|
||||
detected. This can help reduce the workload of triaging vulnerabilities.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ DETAILS:
|
|||
> - The legacy License Compliance analyzer (`License-Scanning.gitlab-ci.yml`) was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/439162) in GitLab 17.0.
|
||||
> - In GitLab 17.5 we introduced the ability to use a CycloneDX report artifact as a source of data for license information behind the feature flag `license_scanning_with_sbom_licenses`, disabled by default.
|
||||
> - In GitLab 17.6 the ability to use a CycloneDX report artifact as a source of data for license information has been enabled by default. The feature flag `license_scanning_with_sbom_licenses` is still present to disable the feature if necessary.
|
||||
> - In GitLab 17.8 the feature flag `license_scanning_with_sbom_licenses` was removed.
|
||||
|
||||
To detect the licenses in use, License Compliance relies on running the
|
||||
[Dependency Scanning CI Jobs](../../application_security/dependency_scanning/index.md),
|
||||
|
|
@ -216,8 +217,9 @@ CycloneDX reports for licenses. For more information, see the offline [quick sta
|
|||
## Use CycloneDX report as a source of license information
|
||||
|
||||
The ability to use a CI report artifact as a source of license information data was introduced in GitLab 17.5 behind the feature flag `license_scanning_with_sbom_licenses` and enabled by default in 17.6.
|
||||
In GitLab 17.8 the feature flag `license_scanning_with_sbom_licenses` was removed.
|
||||
|
||||
When the feature flag `license_scanning_with_sbom_licenses` is enabled, the License Scanning uses the [licenses](https://cyclonedx.org/use-cases/#license-compliance) field of the CycloneDX JSON SBOM when available. If the license information is unavailable, the license information imported from the external license database will be used(current behavior).
|
||||
The License Scanning uses the [licenses](https://cyclonedx.org/use-cases/#license-compliance) field of the CycloneDX JSON SBOM when available. If the license information is unavailable, the license information imported from the external license database will be used(current behavior).
|
||||
License information can be provided using a valid SPDX identifier or a license name. However, providing a license using an SPDX License Expression is not supported.
|
||||
More information about the license field format can be found on the [CycloneDX](https://cyclonedx.org/use-cases/#license-compliance) specification.
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ module API
|
|||
result_hash[:read_package_registry] = scopes.include?('read_package_registry')
|
||||
result_hash[:write_package_registry] = scopes.include?('write_package_registry')
|
||||
result_hash[:read_repository] = scopes.include?('read_repository')
|
||||
result_hash[:read_virtual_registry] = scopes.include?('read_virtual_registry')
|
||||
result_hash[:write_virtual_registry] = scopes.include?('write_virtual_registry')
|
||||
result_hash
|
||||
end
|
||||
|
||||
|
|
@ -90,7 +92,7 @@ module API
|
|||
type: Array[String],
|
||||
coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
|
||||
values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s),
|
||||
desc: 'Indicates the deploy token scopes. Must be at least one of `read_repository`, `read_registry`, `write_registry`, `read_package_registry`, or `write_package_registry`.'
|
||||
desc: 'Indicates the deploy token scopes. Must be at least one of `read_repository`, `read_registry`, `write_registry`, `read_package_registry`, `write_package_registry`, `read_virtual_registry`, or `write_virtual_registry`.'
|
||||
optional :expires_at, type: DateTime, desc: 'Expiration date for the deploy token. Does not expire if no value is provided. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`).'
|
||||
optional :username, type: String, desc: 'Username for deploy token. Default is `gitlab+deploy-token-{n}`'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -196,6 +196,8 @@ module Gitlab
|
|||
end
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
::Gitlab::ErrorTracking.track_exception(e, audit_operation: @name)
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def log_to_file(events)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ module Gitlab
|
|||
events.each { |event| log_event(event) }
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
::Gitlab::ErrorTracking.track_exception(e, audit_operation: audit_operation)
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ module Gitlab
|
|||
WRITE_REGISTRY_SCOPE = :write_registry
|
||||
REGISTRY_SCOPES = [READ_REGISTRY_SCOPE, WRITE_REGISTRY_SCOPE].freeze
|
||||
|
||||
# Scopes used for Virtual Registry access
|
||||
READ_VIRTUAL_REGISTRY_SCOPE = :read_virtual_registry
|
||||
WRITE_VIRTUAL_REGISTRY_SCOPE = :write_virtual_registry
|
||||
VIRTUAL_REGISTRY_SCOPES = [
|
||||
READ_VIRTUAL_REGISTRY_SCOPE, WRITE_VIRTUAL_REGISTRY_SCOPE
|
||||
].freeze
|
||||
|
||||
# Scopes used for GitLab Observability access which is outside of the GitLab app itself.
|
||||
# Hence the lack of ability mapping in `abilities_for_scopes`.
|
||||
READ_OBSERVABILITY_SCOPE = :read_observability
|
||||
|
|
@ -289,6 +296,8 @@ module Gitlab
|
|||
read_api: read_only_authentication_abilities,
|
||||
read_registry: %i[read_container_image],
|
||||
write_registry: %i[create_container_image],
|
||||
read_virtual_registry: %i[read_dependency_proxy],
|
||||
write_virtual_registry: %i[write_dependency_proxy],
|
||||
read_repository: %i[download_code],
|
||||
write_repository: %i[download_code push_code],
|
||||
create_runner: %i[create_instance_runner create_runner],
|
||||
|
|
@ -435,6 +444,12 @@ module Gitlab
|
|||
REGISTRY_SCOPES
|
||||
end
|
||||
|
||||
def virtual_registry_scopes
|
||||
return [] unless Gitlab.config.dependency_proxy.enabled
|
||||
|
||||
VIRTUAL_REGISTRY_SCOPES
|
||||
end
|
||||
|
||||
def resource_bot_scopes
|
||||
non_admin_available_scopes - [READ_USER_SCOPE]
|
||||
end
|
||||
|
|
@ -479,7 +494,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def non_admin_available_scopes
|
||||
API_SCOPES + REPOSITORY_SCOPES + registry_scopes + OBSERVABILITY_SCOPES + AI_FEATURES_SCOPES
|
||||
API_SCOPES + REPOSITORY_SCOPES + registry_scopes + virtual_registry_scopes + OBSERVABILITY_SCOPES + AI_FEATURES_SCOPES
|
||||
end
|
||||
|
||||
def find_build_by_token(token)
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ module Gitlab
|
|||
|
||||
TRIVY_SOURCE_PACKAGE_FIELD = 'SrcName'
|
||||
|
||||
def initialize(data, project: nil)
|
||||
def initialize(data)
|
||||
@data = data
|
||||
@project = project
|
||||
end
|
||||
|
||||
def parse
|
||||
|
|
@ -57,8 +56,6 @@ module Gitlab
|
|||
strong_memoize_attr :container_scanning_component?
|
||||
|
||||
def licenses
|
||||
return [] unless Feature.enabled?(:license_scanning_with_sbom_licenses, @project)
|
||||
|
||||
data.fetch('licenses', []).filter_map do |license_data|
|
||||
license = License.new(license_data).parse
|
||||
next unless license
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@ module Gitlab
|
|||
module Parsers
|
||||
module Sbom
|
||||
class Cyclonedx
|
||||
def initialize(project: nil)
|
||||
@project = project
|
||||
end
|
||||
|
||||
def parse!(blob, sbom_report)
|
||||
@report = sbom_report
|
||||
@data = Gitlab::Json.parse(blob)
|
||||
|
|
@ -64,7 +60,7 @@ module Gitlab
|
|||
|
||||
def parse_components
|
||||
data['components']&.each_with_index do |component_data, index|
|
||||
component = Component.new(component_data, project: @project).parse
|
||||
component = Component.new(component_data).parse
|
||||
report.add_component(component) if component.ingestible?
|
||||
rescue ::Sbom::PackageUrl::InvalidPackageUrl
|
||||
report.add_error("/components/#{index}/purl is invalid")
|
||||
|
|
|
|||
|
|
@ -40789,9 +40789,18 @@ msgstr ""
|
|||
msgid "PagesUsageQuota|Learn about limits for Pages deployments"
|
||||
msgstr ""
|
||||
|
||||
msgid "PagesUsageQuota|Other projects in namespace"
|
||||
msgstr ""
|
||||
|
||||
msgid "PagesUsageQuota|Remaining deployments"
|
||||
msgstr ""
|
||||
|
||||
msgid "PagesUsageQuota|This project"
|
||||
msgstr ""
|
||||
|
||||
msgid "PagesUsageQuota|This project is using the namespace domain \"%{domain}\". The usage quota includes parallel deployments for all projects in the namespace that use this domain."
|
||||
msgstr ""
|
||||
|
||||
msgid "Pages|+ %{n} more deployments"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -51728,9 +51737,6 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Security policy projects store your organization's security policies. They are identified when policies are created, or when a project is linked as a security policy project. %{linkStart}Learn more%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Security policy scheduled scans maximum top-level group concurrency"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|SecurityOrchestration|Scan execution policies with more than %{maxCount} actions detected. Those policies will not work after GitLab 18.0 (May 15, 2025). Before then you must edit these policies to reduce the number of actions."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
diff --git a/node_modules/@vue/compat/dist/vue.cjs.js b/node_modules/@vue/compat/dist/vue.cjs.js
|
||||
index 5b4b617..1baafa5 100644
|
||||
--- a/node_modules/@vue/compat/dist/vue.cjs.js
|
||||
+++ b/node_modules/@vue/compat/dist/vue.cjs.js
|
||||
@@ -10208,8 +10208,20 @@ function emit(instance, event, ...rawArgs) {
|
||||
}
|
||||
}
|
||||
let args = rawArgs;
|
||||
- const isModelListener = event.startsWith("update:");
|
||||
- const modifiers = isModelListener && getModelModifiers(props, event.slice(7));
|
||||
+
|
||||
+ // This applies https://github.com/vuejs/core/pull/12654. Once that has been
|
||||
+ // merged and we've upgraded to the version of @vue/compat that includes it,
|
||||
+ // this patch can be removed.
|
||||
+ let isModelListener;
|
||||
+ let modifiers;
|
||||
+ if (
|
||||
+ (isModelListener = compatModelEventPrefix + event in props)
|
||||
+ ) {
|
||||
+ modifiers = props.modelModifiers
|
||||
+ } else if ((isModelListener = event.startsWith('update:'))) {
|
||||
+ modifiers = getModelModifiers(props, event.slice(7));
|
||||
+ }
|
||||
+
|
||||
if (modifiers) {
|
||||
if (modifiers.trim) {
|
||||
args = rawArgs.map((a) => isString(a) ? a.trim() : a);
|
||||
|
|
@ -29,7 +29,10 @@ function parseArgumentsAndEnvironment() {
|
|||
program
|
||||
.usage('[options]')
|
||||
.description(`Runs Jest under CI.`)
|
||||
.option('--vue3', 'Run tests under Vue 3 (via @vue/compat). The default is to run under Vue 2.')
|
||||
.option(
|
||||
'--vue3',
|
||||
'Run tests under Vue 3 (via @vue/compat). The default is to run under Vue 2. The VUE_VERSION environment variable must agree with this option.',
|
||||
)
|
||||
.option(
|
||||
'--predictive',
|
||||
'Only run specs affected by the changes in the merge request. The default is to run all specs.',
|
||||
|
|
@ -38,7 +41,10 @@ function parseArgumentsAndEnvironment() {
|
|||
'--fixtures',
|
||||
'Only run specs which rely on generated fixtures. The default is to only run specs which do not rely on generated fixtures.',
|
||||
)
|
||||
.option('--coverage', 'Tell Jest to generate coverage. The default is not to.')
|
||||
.option(
|
||||
'--coverage',
|
||||
"Tell Jest to generate coverage. If not specified, it's enabled only on non-FOSS branch or tag pipelines under Vue 2, non-predictive runs.",
|
||||
)
|
||||
.parse(process.argv);
|
||||
|
||||
if (!IS_CI) {
|
||||
|
|
@ -47,6 +53,20 @@ function parseArgumentsAndEnvironment() {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
if (program.vue3 && process.env.VUE_VERSION !== '3') {
|
||||
console.warn(
|
||||
`Expected environment variable VUE_VERSION=3 given option '--vue3', got VUE_VERSION="${process.env.VUE_VERSION}".`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!program.vue3 && ![undefined, '2'].includes(process.env.VUE_VERSION)) {
|
||||
console.warn(
|
||||
`Expected unset environment variable VUE_VERSION, or VUE_VERSION=2, got VUE_VERSION="${process.env.VUE_VERSION}".`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const changedFiles = [];
|
||||
if (program.predictive) {
|
||||
const { RSPEC_MATCHING_JS_FILES_PATH, RSPEC_CHANGED_FILES_PATH } = process.env;
|
||||
|
|
@ -72,11 +92,18 @@ function parseArgumentsAndEnvironment() {
|
|||
}
|
||||
}
|
||||
|
||||
const coverage =
|
||||
program.coverage ||
|
||||
(!process.env.CI_MERGE_REQUEST_IID &&
|
||||
!/^as-if-foss\//.test(process.env.CI_COMMIT_BRANCH) &&
|
||||
!program.vue3 &&
|
||||
!program.predictive);
|
||||
|
||||
return {
|
||||
vue3: program.vue3,
|
||||
predictive: program.predictive,
|
||||
fixtures: program.fixtures,
|
||||
coverage: program.coverage,
|
||||
coverage,
|
||||
nodeIndex: process.env.CI_NODE_INDEX ?? '1',
|
||||
nodeTotal: process.env.CI_NODE_TOTAL ?? '1',
|
||||
changedFiles,
|
||||
|
|
@ -124,7 +151,6 @@ function runJest({ vue3, predictive, fixtures, coverage, nodeIndex, nodeTotal, c
|
|||
env: {
|
||||
...process.env,
|
||||
...(fixtures ? { JEST_FIXTURE_JOBS_ONLY: '1' } : {}),
|
||||
...(vue3 ? { VUE_VERSION: '3' } : {}),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
ee/spec/frontend/access_tokens/components/expires_at_field_spec.js
|
||||
ee/spec/frontend/admin/application_settings/general/components/license_dropzone_spec.js
|
||||
ee/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js
|
||||
ee/spec/frontend/admin/subscriptions/show/components/subscription_activation_form_spec.js
|
||||
ee/spec/frontend/admin/subscriptions/show/components/subscription_breakdown_spec.js
|
||||
ee/spec/frontend/ai/settings/components/duo_experiment_beta_features_form_spec.js
|
||||
ee/spec/frontend/analytics/analytics_dashboards/components/analytics_dashboard_panel_spec.js
|
||||
|
|
@ -135,7 +134,6 @@ spec/frontend/ci/pipeline_editor/components/pipeline_editor_tabs_spec.js
|
|||
spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
|
||||
spec/frontend/ci/runner/components/registration/runner_instructions/runner_instructions_modal_spec.js
|
||||
spec/frontend/ci/runner/components/runner_filtered_search_bar_spec.js
|
||||
spec/frontend/ci/runner/components/runner_form_fields_spec.js
|
||||
spec/frontend/ci_settings_pipeline_triggers/components/edit_trigger_modal_spec.js
|
||||
spec/frontend/clusters/agents/components/activity_history_item_spec.js
|
||||
spec/frontend/clusters/agents/components/revoke_token_button_spec.js
|
||||
|
|
@ -220,9 +218,7 @@ spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
|
|||
spec/frontend/packages_and_registries/settings/group/components/forwarding_settings_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_repository_rule_form_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_repository_rules_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/packages_protection_rule_form_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/packages_protection_rules_spec.js
|
||||
spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
|
||||
spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js
|
||||
|
|
|
|||
|
|
@ -472,18 +472,6 @@ tests = [
|
|||
## END Remote development GraphQL mutations
|
||||
|
||||
## BEGIN Remote development GraphQL resolvers (in alphabetical order by resolver source file path)
|
||||
{
|
||||
explanation: 'Map Remote Development GraphQL query root admin_workspaces_resolver.rb to request specs',
|
||||
changed_file: 'ee/app/graphql/resolvers/remote_development/admin_workspaces_resolver.rb',
|
||||
expected: %w[
|
||||
ee/spec/requests/api/graphql/remote_development/workspace/with_id_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_actual_states_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_agent_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_no_args_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_project_ids_arg_spec.rb
|
||||
]
|
||||
},
|
||||
{
|
||||
explanation:
|
||||
'Map Remote Development GraphQL cluster_agent/remote_development_agent_config_resolver.rb to request specs',
|
||||
|
|
@ -502,6 +490,7 @@ tests = [
|
|||
ee/spec/requests/api/graphql/remote_development/cluster_agent/workspaces/with_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/cluster_agent/workspaces/with_no_args_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/cluster_agent/workspaces/with_project_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -526,6 +515,19 @@ tests = [
|
|||
]
|
||||
# rubocop:enable Layout/LineLength
|
||||
},
|
||||
{
|
||||
explanation: 'Map Remote Development GraphQL query root workspaces_admin_resolver.rb to request specs',
|
||||
changed_file: 'ee/app/graphql/resolvers/remote_development/workspaces_admin_resolver.rb',
|
||||
expected: %w[
|
||||
ee/spec/requests/api/graphql/remote_development/workspace/with_id_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_actual_states_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_agent_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_no_args_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspaces/with_project_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
|
||||
]
|
||||
},
|
||||
{
|
||||
explanation: 'Map Remote Development GraphQL workspaces_resolver.rb to request specs',
|
||||
changed_file: 'ee/app/graphql/resolvers/remote_development/workspaces_resolver.rb',
|
||||
|
|
@ -536,9 +538,12 @@ tests = [
|
|||
ee/spec/requests/api/graphql/remote_development/current_user/workspaces/with_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/current_user/workspaces/with_no_args_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/current_user/workspaces/with_project_ids_arg_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
|
||||
]
|
||||
},
|
||||
## END Remote development GraphQL resolvers
|
||||
|
||||
## BEGIN Remote development GraphQL types
|
||||
{
|
||||
explanation: 'Map Remote Development GraphQL query root workspace type resolver to request specs',
|
||||
changed_file: 'ee/app/graphql/types/remote_development/workspace_type.rb',
|
||||
|
|
@ -547,7 +552,37 @@ tests = [
|
|||
ee/spec/requests/api/graphql/remote_development/workspace/with_id_arg_spec.rb
|
||||
]
|
||||
},
|
||||
## END Remote development GraphQL resolvers
|
||||
{
|
||||
explanation: 'Map Remote Development GraphQL workspace_variable_type.rb to request specs',
|
||||
changed_file: 'ee/app/graphql/types/remote_development/workspace_variable_type.rb',
|
||||
expected: %w[
|
||||
ee/spec/graphql/types/remote_development/workspace_variable_type_spec.rb
|
||||
ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
|
||||
]
|
||||
},
|
||||
{
|
||||
explanation: 'Map Remote Development GraphQL workspace_variable_input_type_enum.rb to request specs',
|
||||
changed_file: 'ee/app/graphql/types/remote_development/workspace_variable_input.rb',
|
||||
expected: %w[
|
||||
ee/spec/graphql/types/remote_development/workspace_variable_input_spec.rb
|
||||
ee/spec/requests/api/graphql/mutations/remote_development/workspace_operations/create_spec.rb
|
||||
]
|
||||
},
|
||||
{
|
||||
explanation: 'Map Remote Development GraphQL workspace_variable_type_enum.rb to request specs',
|
||||
changed_file: 'ee/app/graphql/types/remote_development/workspace_variable_type_enum.rb',
|
||||
expected: %w[
|
||||
ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
|
||||
]
|
||||
},
|
||||
{
|
||||
explanation: 'Map Remote Development GraphQL workspace_variable_input_type_enum.rb to request specs',
|
||||
changed_file: 'ee/app/graphql/types/remote_development/workspace_variable_input_type_enum.rb',
|
||||
expected: %w[
|
||||
ee/spec/requests/api/graphql/mutations/remote_development/workspace_operations/create_spec.rb
|
||||
]
|
||||
},
|
||||
## END Remote development GraphQL types
|
||||
|
||||
{
|
||||
explanation: 'https://gitlab.com/gitlab-org/gitlab/-/issues/466068#note_1987834618',
|
||||
|
|
|
|||
|
|
@ -420,7 +420,8 @@ RSpec.describe 'Database schema',
|
|||
'ProjectAutoDevops' => %w[deploy_strategy],
|
||||
'ResourceLabelEvent' => %w[action],
|
||||
'User' => %w[layout dashboard project_view],
|
||||
'Users::Callout' => %w[feature_name]
|
||||
'Users::Callout' => %w[feature_name],
|
||||
'Vulnerability' => %w[confidence] # this enum is in the process of being deprecated
|
||||
}.freeze
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ FactoryBot.define do
|
|||
read_package_registry { true }
|
||||
write_package_registry { true }
|
||||
read_virtual_registry { true }
|
||||
write_virtual_registry { true }
|
||||
end
|
||||
|
||||
trait :dependency_proxy_scopes do
|
||||
|
|
|
|||
|
|
@ -164,15 +164,15 @@ RSpec.describe ::Packages::FinderHelper, feature_category: :package_registry do
|
|||
'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both packages'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both packages'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both packages'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning package1'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning both packages'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning package1'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning package1'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning both packages'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning package1'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no packages'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning both packages'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no packages'
|
||||
end
|
||||
|
||||
|
|
@ -211,6 +211,33 @@ RSpec.describe ::Packages::FinderHelper, feature_category: :package_registry do
|
|||
it_behaves_like 'returning package1'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before_all do
|
||||
group.add_guest(user)
|
||||
subgroup.add_guest(user)
|
||||
project1.add_guest(user)
|
||||
project2.add_guest(user)
|
||||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
|
||||
subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
|
||||
project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
|
||||
group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
|
||||
end
|
||||
|
||||
where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning package1'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning package1'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning no packages'
|
||||
end
|
||||
|
||||
with_them do
|
||||
it_behaves_like params[:shared_example_name]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a group deploy token' do
|
||||
|
|
@ -303,15 +330,15 @@ RSpec.describe ::Packages::FinderHelper, feature_category: :package_registry do
|
|||
'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both projects'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both projects'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both projects'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning project1'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning both projects'
|
||||
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning project1'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning project1'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning both projects'
|
||||
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning project1'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no project'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning both projects'
|
||||
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no project'
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ RSpec.describe ::Packages::Conan::PackageFinder, feature_category: :package_regi
|
|||
:private | :maintainer | true
|
||||
:private | :developer | true
|
||||
:private | :reporter | true
|
||||
:private | :guest | false
|
||||
:private | :guest | true
|
||||
:private | :anonymous | false
|
||||
|
||||
:internal | :maintainer | true
|
||||
|
|
@ -98,6 +98,19 @@ RSpec.describe ::Packages::Conan::PackageFinder, feature_category: :package_regi
|
|||
it { is_expected.to match_array([private_package]) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before_all do
|
||||
project.update_column(:visibility_level, Gitlab::VisibilityLevel.string_options['private'])
|
||||
project.add_guest(user)
|
||||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it { is_expected.to eq([]) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with package user name' do
|
||||
|
|
|
|||
|
|
@ -74,12 +74,12 @@ RSpec.describe Packages::GroupPackagesFinder, feature_category: :package_registr
|
|||
:developer | :public | :private | :all
|
||||
:maintainer | :public | :private | :all
|
||||
:anonymous | :private | :enabled | :none
|
||||
:guest | :private | :enabled | :none
|
||||
:guest | :private | :enabled | :all
|
||||
:reporter | :private | :enabled | :all
|
||||
:developer | :private | :enabled | :all
|
||||
:maintainer | :private | :enabled | :all
|
||||
:anonymous | :private | :private | :none
|
||||
:guest | :private | :private | :none
|
||||
:guest | :private | :private | :all
|
||||
:reporter | :private | :private | :all
|
||||
:developer | :private | :private | :all
|
||||
:maintainer | :private | :private | :all
|
||||
|
|
@ -117,6 +117,31 @@ RSpec.describe Packages::GroupPackagesFinder, feature_category: :package_registr
|
|||
end
|
||||
end
|
||||
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
let(:add_user_to_group) { false }
|
||||
|
||||
before do
|
||||
subgroup.update!(visibility: 'private')
|
||||
group.update!(visibility: 'private')
|
||||
|
||||
project.add_guest(user)
|
||||
subproject.add_guest(user)
|
||||
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
%w[enabled private].each do |repository_visibility|
|
||||
context "when repository visiblity #{repository_visibility}" do
|
||||
before do
|
||||
project.update!(visibility: 'private', repository_access_level: repository_visibility)
|
||||
subproject.update!(visibility: 'private', repository_access_level: repository_visibility)
|
||||
end
|
||||
|
||||
it { is_expected.to match_array([]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'deploy tokens' do
|
||||
let(:add_user_to_group) { false }
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,15 @@
|
|||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"enum": [
|
||||
"read_repository",
|
||||
"read_registry",
|
||||
"write_registry",
|
||||
"read_package_registry",
|
||||
"write_package_registry",
|
||||
"read_virtual_registry",
|
||||
"write_virtual_registry"
|
||||
]
|
||||
}
|
||||
},
|
||||
"token": {
|
||||
|
|
@ -38,4 +46,4 @@
|
|||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,26 @@
|
|||
import { createTestingPinia } from '@pinia/testing';
|
||||
import * as types from '~/batch_comments/stores/modules/batch_comments/mutation_types';
|
||||
import mutations from '~/batch_comments/stores/modules/batch_comments/mutations';
|
||||
import createState from '~/batch_comments/stores/modules/batch_comments/state';
|
||||
import { useBatchComments } from '~/batch_comments/store';
|
||||
import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
|
||||
import { globalAccessorPlugin } from '~/pinia/plugins';
|
||||
import { useNotes } from '~/notes/store/legacy_notes';
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
describe.skip('Batch comments mutations', () => {
|
||||
let state;
|
||||
describe('Batch comments mutations', () => {
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
state = createState();
|
||||
createTestingPinia({ stubActions: false, plugins: [globalAccessorPlugin] });
|
||||
useLegacyDiffs();
|
||||
useNotes();
|
||||
store = useBatchComments();
|
||||
});
|
||||
|
||||
describe(types.ADD_NEW_DRAFT, () => {
|
||||
const draft = { id: 1, note: 'test' };
|
||||
it('adds processed object into drafts array', () => {
|
||||
mutations[types.ADD_NEW_DRAFT](state, draft);
|
||||
store[types.ADD_NEW_DRAFT](draft);
|
||||
|
||||
expect(state.drafts).toEqual([
|
||||
expect(store.drafts).toEqual([
|
||||
{
|
||||
...draft,
|
||||
isDraft: true,
|
||||
|
|
@ -24,26 +29,26 @@ describe.skip('Batch comments mutations', () => {
|
|||
});
|
||||
|
||||
it('sets `shouldAnimateReviewButton` to true if it is a first draft', () => {
|
||||
mutations[types.ADD_NEW_DRAFT](state, draft);
|
||||
store[types.ADD_NEW_DRAFT](draft);
|
||||
|
||||
expect(state.shouldAnimateReviewButton).toBe(true);
|
||||
expect(store.shouldAnimateReviewButton).toBe(true);
|
||||
});
|
||||
|
||||
it('does not set `shouldAnimateReviewButton` to true if it is not a first draft', () => {
|
||||
state.drafts.push({ id: 1 }, { id: 2 });
|
||||
mutations[types.ADD_NEW_DRAFT](state, { id: 2, note: 'test2' });
|
||||
store.drafts.push({ id: 1 }, { id: 2 });
|
||||
store[types.ADD_NEW_DRAFT]({ id: 2, note: 'test2' });
|
||||
|
||||
expect(state.shouldAnimateReviewButton).toBe(false);
|
||||
expect(store.shouldAnimateReviewButton).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe(types.DELETE_DRAFT, () => {
|
||||
it('removes draft from array by ID', () => {
|
||||
state.drafts.push({ id: 1 }, { id: 2 });
|
||||
store.drafts.push({ id: 1 }, { id: 2 });
|
||||
|
||||
mutations[types.DELETE_DRAFT](state, 1);
|
||||
store[types.DELETE_DRAFT](1);
|
||||
|
||||
expect(state.drafts).toEqual([{ id: 2 }]);
|
||||
expect(store.drafts).toEqual([{ id: 2 }]);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -51,9 +56,9 @@ describe.skip('Batch comments mutations', () => {
|
|||
it('adds to processed drafts in state', () => {
|
||||
const drafts = [{ id: 1 }, { id: 2 }];
|
||||
|
||||
mutations[types.SET_BATCH_COMMENTS_DRAFTS](state, drafts);
|
||||
store[types.SET_BATCH_COMMENTS_DRAFTS](drafts);
|
||||
|
||||
expect(state.drafts).toEqual([
|
||||
expect(store.drafts).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
isDraft: true,
|
||||
|
|
@ -68,39 +73,39 @@ describe.skip('Batch comments mutations', () => {
|
|||
|
||||
describe(types.REQUEST_PUBLISH_REVIEW, () => {
|
||||
it('sets isPublishing to true', () => {
|
||||
mutations[types.REQUEST_PUBLISH_REVIEW](state);
|
||||
store[types.REQUEST_PUBLISH_REVIEW]();
|
||||
|
||||
expect(state.isPublishing).toBe(true);
|
||||
expect(store.isPublishing).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(types.RECEIVE_PUBLISH_REVIEW_SUCCESS, () => {
|
||||
it('sets isPublishing to false', () => {
|
||||
state.isPublishing = true;
|
||||
store.isPublishing = true;
|
||||
|
||||
mutations[types.RECEIVE_PUBLISH_REVIEW_SUCCESS](state);
|
||||
store[types.RECEIVE_PUBLISH_REVIEW_SUCCESS]();
|
||||
|
||||
expect(state.isPublishing).toBe(false);
|
||||
expect(store.isPublishing).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe(types.RECEIVE_PUBLISH_REVIEW_ERROR, () => {
|
||||
it('updates isPublishing to false', () => {
|
||||
state.isPublishing = true;
|
||||
store.isPublishing = true;
|
||||
|
||||
mutations[types.RECEIVE_PUBLISH_REVIEW_ERROR](state);
|
||||
store[types.RECEIVE_PUBLISH_REVIEW_ERROR]();
|
||||
|
||||
expect(state.isPublishing).toBe(false);
|
||||
expect(store.isPublishing).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe(types.RECEIVE_DRAFT_UPDATE_SUCCESS, () => {
|
||||
it('updates draft in store', () => {
|
||||
state.drafts.push({ id: 1 });
|
||||
store.drafts.push({ id: 1 });
|
||||
|
||||
mutations[types.RECEIVE_DRAFT_UPDATE_SUCCESS](state, { id: 1, note: 'test' });
|
||||
store[types.RECEIVE_DRAFT_UPDATE_SUCCESS]({ id: 1, note: 'test' });
|
||||
|
||||
expect(state.drafts).toEqual([
|
||||
expect(store.drafts).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
note: 'test',
|
||||
|
|
@ -112,21 +117,21 @@ describe.skip('Batch comments mutations', () => {
|
|||
|
||||
describe(types.CLEAR_DRAFTS, () => {
|
||||
it('clears drafts array', () => {
|
||||
state.drafts.push({ id: 1 });
|
||||
store.drafts.push({ id: 1 });
|
||||
|
||||
mutations[types.CLEAR_DRAFTS](state);
|
||||
store[types.CLEAR_DRAFTS]();
|
||||
|
||||
expect(state.drafts).toEqual([]);
|
||||
expect(store.drafts).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe(types.SET_DRAFT_EDITING, () => {
|
||||
it('sets draft editing mode', () => {
|
||||
state.drafts.push({ id: 1, isEditing: false });
|
||||
store.drafts.push({ id: 1, isEditing: false });
|
||||
|
||||
mutations[types.SET_DRAFT_EDITING](state, { draftId: 1, isEditing: true });
|
||||
store[types.SET_DRAFT_EDITING]({ draftId: 1, isEditing: true });
|
||||
|
||||
expect(state.drafts[0].isEditing).toBe(true);
|
||||
expect(store.drafts[0].isEditing).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -262,10 +262,8 @@ RSpec.describe API::Helpers::PackagesHelpers, feature_category: :package_registr
|
|||
project.add_guest(user)
|
||||
end
|
||||
|
||||
it 'returns Forbidden' do
|
||||
expect(helper).to receive(:render_api_error!).with('403 Forbidden', 403)
|
||||
|
||||
is_expected.to be_nil
|
||||
it 'returns project' do
|
||||
is_expected.to eq(project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -312,12 +312,11 @@ RSpec.describe Gitlab::Audit::Auditor, feature_category: :audit_events do
|
|||
|
||||
context 'when audit events are invalid' do
|
||||
before do
|
||||
expect_next_instance_of(AuditEvent) do |instance|
|
||||
allow(instance).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
|
||||
end
|
||||
allow(Gitlab::ErrorTracking).to receive(:track_exception)
|
||||
end
|
||||
|
||||
let(:author) { build(:user) } # use non-persisted author (hence non-valid id)
|
||||
|
||||
it 'tracks error' do
|
||||
audit!
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
it 'DEFAULT_SCOPES contains all default scopes' do
|
||||
expect(subject::DEFAULT_SCOPES).to match_array [:api]
|
||||
end
|
||||
|
||||
it 'VIRTUAL_REGISTRY_SCOPES contains all scopes for Virtual Registry access' do
|
||||
expect(subject::VIRTUAL_REGISTRY_SCOPES).to match_array %i[read_virtual_registry write_virtual_registry]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'available_scopes' do
|
||||
|
|
@ -227,6 +231,28 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'virtual_registry_scopes' do
|
||||
context 'when dependency proxy and virtual registry are both disabled' do
|
||||
before do
|
||||
stub_config(dependency_proxy: { enabled: false })
|
||||
end
|
||||
|
||||
it 'is empty' do
|
||||
expect(subject.virtual_registry_scopes).to eq []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when dependency proxy is enabled' do
|
||||
before do
|
||||
stub_config(dependency_proxy: { enabled: true })
|
||||
end
|
||||
|
||||
it 'contains all virtual registry related scopes' do
|
||||
expect(subject.virtual_registry_scopes).to eq %i[read_virtual_registry write_virtual_registry]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'find_for_git_client' do
|
||||
|
|
|
|||
|
|
@ -38,30 +38,18 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Component, feature_category: :dependen
|
|||
data.merge!(license_info)
|
||||
end
|
||||
|
||||
context "when the feature flag `license_scanning_with_sbom_licenses` is enabled" do
|
||||
it "sets the license information" do
|
||||
is_expected.to be_kind_of(::Gitlab::Ci::Reports::Sbom::Component)
|
||||
expect(component.licenses.count).to eq(1)
|
||||
expect(component.licenses.first.name).to eq(license_name)
|
||||
end
|
||||
|
||||
context "when the license is defined by an expression" do
|
||||
let(:license_info) do
|
||||
{ "licenses" => [{ "expression" => "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0" }] }
|
||||
end
|
||||
|
||||
it "ignores the license" do
|
||||
expect(component.licenses).to be_empty
|
||||
end
|
||||
end
|
||||
it "sets the license information" do
|
||||
is_expected.to be_kind_of(::Gitlab::Ci::Reports::Sbom::Component)
|
||||
expect(component.licenses.count).to eq(1)
|
||||
expect(component.licenses.first.name).to eq(license_name)
|
||||
end
|
||||
|
||||
context "when the feature flag `license_scanning_with_sbom_licenses` is disabled" do
|
||||
before do
|
||||
stub_feature_flags(license_scanning_with_sbom_licenses: false)
|
||||
context "when the license is defined by an expression" do
|
||||
let(:license_info) do
|
||||
{ "licenses" => [{ "expression" => "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0" }] }
|
||||
end
|
||||
|
||||
it "does not includes the license information" do
|
||||
it "ignores the license" do
|
||||
expect(component.licenses).to be_empty
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe BackfillUserProvidedWorkspaceVariables, feature_category: :workspaces do
|
||||
let(:user) { table(:users).create!(name: 'test-user', email: 'test@example.com', projects_limit: 5) }
|
||||
let(:organization) { table(:organizations).create!(name: 'test-org', path: 'default') }
|
||||
let(:namespace) { table(:namespaces).create!(name: 'name', path: 'path', organization_id: organization.id) }
|
||||
let(:workspace_variables) { table(:workspace_variables) }
|
||||
|
||||
let(:project) do
|
||||
table(:projects).create!(namespace_id: namespace.id, project_namespace_id: namespace.id,
|
||||
organization_id: organization.id)
|
||||
end
|
||||
|
||||
let!(:personal_access_token) do
|
||||
table(:personal_access_tokens).create!(
|
||||
user_id: user.id,
|
||||
name: 'token_name',
|
||||
organization_id: organization.id,
|
||||
expires_at: Time.now
|
||||
)
|
||||
end
|
||||
|
||||
let(:cluster_agent) { table(:cluster_agents).create!(name: 'remotedev', project_id: project.id) }
|
||||
|
||||
let!(:agent) do
|
||||
table(:workspaces_agent_configs).create!(
|
||||
cluster_agent_id: cluster_agent.id,
|
||||
enabled: true,
|
||||
dns_zone: 'test.workspace.me',
|
||||
project_id: project.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:agent_config_version) do
|
||||
table(:workspaces_agent_config_versions).create!(
|
||||
project_id: project.id,
|
||||
item_id: agent.id,
|
||||
item_type: 'RemoteDevelopment::WorkspacesAgentConfig',
|
||||
event: 'create'
|
||||
)
|
||||
end
|
||||
|
||||
let!(:workspace) do
|
||||
table(:workspaces).create!(
|
||||
user_id: user.id,
|
||||
project_id: project.id,
|
||||
cluster_agent_id: cluster_agent.id,
|
||||
desired_state_updated_at: Time.now,
|
||||
responded_to_agent_at: Time.now,
|
||||
name: 'workspace-1',
|
||||
namespace: 'workspace_1_namespace',
|
||||
desired_state: 'Running',
|
||||
actual_state: 'Running',
|
||||
project_ref: 'devfile-ref',
|
||||
devfile_path: 'devfile-path',
|
||||
devfile: 'devfile',
|
||||
processed_devfile: 'processed_dev_file',
|
||||
url: 'workspace-url',
|
||||
deployment_resource_version: 'v1',
|
||||
personal_access_token_id: personal_access_token.id,
|
||||
max_hours_before_termination: 5760,
|
||||
workspaces_agent_config_version: agent_config_version.id,
|
||||
desired_config_generator_version: 3
|
||||
)
|
||||
end
|
||||
|
||||
let!(:workspace_static_file_variable) do
|
||||
workspace_variables.create!(
|
||||
workspace_id: workspace.id,
|
||||
project_id: project.id,
|
||||
key: 'gl_token',
|
||||
variable_type: 1,
|
||||
encrypted_value: 'encrypted_value',
|
||||
encrypted_value_iv: 'encrypted_value_iv'
|
||||
)
|
||||
end
|
||||
|
||||
let!(:workspace_static_env_variable) do
|
||||
workspace_variables.create!(
|
||||
workspace_id: workspace.id,
|
||||
project_id: project.id,
|
||||
key: 'GIT_CONFIG_COUNT',
|
||||
variable_type: 0,
|
||||
encrypted_value: 'encrypted_value',
|
||||
encrypted_value_iv: 'encrypted_value_iv'
|
||||
)
|
||||
end
|
||||
|
||||
let!(:workspace_user_provided_variable) do
|
||||
workspace_variables.create!(
|
||||
workspace_id: workspace.id,
|
||||
project_id: project.id,
|
||||
key: 'variable_key',
|
||||
variable_type: 0,
|
||||
encrypted_value: 'encrypted_value',
|
||||
encrypted_value_iv: 'encrypted_value_iv'
|
||||
)
|
||||
end
|
||||
|
||||
it 'sets user_provided to true for all non-internal environment variables in the table' do
|
||||
reversible_migration do |migration|
|
||||
migration.before -> {
|
||||
expect(workspace_variables.pluck(:user_provided)).to all(be false)
|
||||
}
|
||||
|
||||
migration.after -> {
|
||||
user_provided_variable = workspace_variables.where(variable_type: described_class::VARIABLE_ENV_TYPE)
|
||||
.where.not(key: described_class::WORKSPACE_INTERNAL_VARIABLES).first
|
||||
|
||||
expect(workspace_static_file_variable.user_provided).to be(false)
|
||||
expect(workspace_static_env_variable.user_provided).to be(false)
|
||||
expect(user_provided_variable.user_provided).to be(true)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe FinalizeMigrateSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses, feature_category: :security_policy_management do
|
||||
it 'finalizes FinalizeMigrateRemainingSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses migration' do
|
||||
expect_next_instance_of(described_class) do |instance|
|
||||
expect(instance).to receive(:ensure_batched_background_migration_is_finished).with(
|
||||
job_class_name: 'MigrateRemainingSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses',
|
||||
table_name: :software_license_policies,
|
||||
column_name: :id,
|
||||
job_arguments: [],
|
||||
finalize: true
|
||||
)
|
||||
end
|
||||
|
||||
migrate!
|
||||
end
|
||||
end
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Clusters::AgentPolicy do
|
||||
let(:cluster_agent) { create(:cluster_agent, name: 'agent' ) }
|
||||
let(:cluster_agent) { create(:cluster_agent, name: 'agent') }
|
||||
let(:user) { create(:admin) }
|
||||
let(:policy) { described_class.new(user, cluster_agent) }
|
||||
let(:project) { cluster_agent.project }
|
||||
|
|
|
|||
|
|
@ -1190,13 +1190,29 @@ RSpec.describe GroupPolicy, feature_category: :system_access do
|
|||
context 'with planner' do
|
||||
let(:current_user) { planner }
|
||||
|
||||
it { is_expected.to be_disallowed(:read_package) }
|
||||
it { is_expected.to be_allowed(:read_package) }
|
||||
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_disallowed(:read_package) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with guest' do
|
||||
let(:current_user) { guest }
|
||||
|
||||
it { is_expected.to be_disallowed(:read_package) }
|
||||
it { is_expected.to be_allowed(:read_package) }
|
||||
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_disallowed(:read_package) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non member' do
|
||||
|
|
|
|||
|
|
@ -41,7 +41,15 @@ RSpec.describe Packages::Policies::GroupPolicy, feature_category: :package_regis
|
|||
context 'with guest' do
|
||||
let(:current_user) { guest }
|
||||
|
||||
it { is_expected.to be_disallowed(:read_package) }
|
||||
it { is_expected.to be_allowed(:read_package) }
|
||||
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_disallowed(:read_package) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non member' do
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ RSpec.describe Packages::Policies::ProjectPolicy, feature_category: :package_reg
|
|||
|
||||
ref(:private_project) | ProjectFeature::PRIVATE | ref(:anonymous) | false
|
||||
ref(:private_project) | ProjectFeature::PRIVATE | ref(:non_member) | false
|
||||
ref(:private_project) | ProjectFeature::PRIVATE | ref(:guest) | false
|
||||
ref(:private_project) | ProjectFeature::PRIVATE | ref(:guest) | true
|
||||
ref(:private_project) | ProjectFeature::PRIVATE | ref(:reporter) | true
|
||||
ref(:private_project) | ProjectFeature::PRIVATE | ref(:developer) | true
|
||||
ref(:private_project) | ProjectFeature::PRIVATE | ref(:maintainer) | true
|
||||
|
|
@ -122,6 +122,17 @@ RSpec.describe Packages::Policies::ProjectPolicy, feature_category: :package_reg
|
|||
end
|
||||
end
|
||||
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
let(:project) { private_project }
|
||||
let(:current_user) { guest }
|
||||
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_disallowed(:read_package) }
|
||||
end
|
||||
|
||||
context 'with admin' do
|
||||
let(:current_user) { admin }
|
||||
|
||||
|
|
|
|||
|
|
@ -1698,6 +1698,8 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
|
|||
end
|
||||
|
||||
describe 'read_package' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
context 'with admin' do
|
||||
let(:current_user) { admin }
|
||||
|
||||
|
|
@ -1706,11 +1708,39 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
|
|||
it_behaves_like 'package access with repository disabled'
|
||||
end
|
||||
|
||||
%w[anonymous non_member guest planner reporter developer maintainer owner].each do |role|
|
||||
context "with #{role}" do
|
||||
let(:current_user) { send(role) }
|
||||
where(:project, :role, :allowed) do
|
||||
ref(:public_project) | :anonymous | true
|
||||
ref(:public_project) | :non_member | true
|
||||
ref(:public_project) | :guest | true
|
||||
|
||||
it { is_expected.to be_allowed(:read_package) }
|
||||
ref(:private_project) | :anonymous | false
|
||||
ref(:private_project) | :non_member | false
|
||||
ref(:private_project) | :guest | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:current_user) { send(role) }
|
||||
|
||||
it do
|
||||
expect(subject.can?(:read_package)).to be(allowed)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with private project' do
|
||||
let(:project) { private_project }
|
||||
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
%w[guest planner].each do |role|
|
||||
context "with #{role}" do
|
||||
let(:current_user) { send(role) }
|
||||
|
||||
it { is_expected.to be_disallowed(:read_package) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ RSpec.describe Ci::BuildPresenter do
|
|||
|
||||
context 'when variable is stored in ci_trigger_requests.variables' do
|
||||
before do
|
||||
trigger_request.update_attribute(:variables, { 'TRIGGER_KEY_1' => 'TRIGGER_VALUE_1' } )
|
||||
trigger_request.update_attribute(:variables, { 'TRIGGER_KEY_1' => 'TRIGGER_VALUE_1' })
|
||||
end
|
||||
|
||||
it 'returns variables' do
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ RSpec.describe ::Packages::Conan::PackagePresenter, feature_category: :package_r
|
|||
it { is_expected.to eq(expected_result) }
|
||||
|
||||
context 'when there are multiple channels for the same package' do
|
||||
let(:conan_metadatum) { create(:conan_metadatum, package_channel: 'newest' ) }
|
||||
let(:conan_metadatum) { create(:conan_metadatum, package_channel: 'newest') }
|
||||
let!(:newest_package) { create(:conan_package, name: package.name, version: package.version, project: project, conan_metadatum: conan_metadatum) }
|
||||
|
||||
it { is_expected.to eq(expected_result) }
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | true
|
||||
'PRIVATE' | :developer | :user | false | false # Anonymous User - fallback
|
||||
'PRIVATE' | :developer | :job | true | true
|
||||
'PRIVATE' | :guest | :user | true | false
|
||||
'PRIVATE' | :guest | :user | true | true
|
||||
'PRIVATE' | :guest | :user | false | false # Anonymous User - fallback
|
||||
'PRIVATE' | :guest | :job | true | false
|
||||
'PRIVATE' | :guest | :job | true | true
|
||||
'PRIVATE' | nil | :user | true | false
|
||||
'PRIVATE' | nil | :user | false | false # Anonymous User - fallback
|
||||
'PRIVATE' | nil | :job | true | false
|
||||
|
|
@ -82,9 +82,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
:PRIVATE | :developer | :user | true | :success | true
|
||||
:PRIVATE | :developer | :user | false | :unauthorized | false
|
||||
:PRIVATE | :developer | :job | true | :success | false # Anonymous User - fallback
|
||||
:PRIVATE | :guest | :user | true | :success | false
|
||||
:PRIVATE | :guest | :user | true | :success | true
|
||||
:PRIVATE | :guest | :user | false | :unauthorized | false
|
||||
:PRIVATE | :guest | :job | true | :success | false # Anonymous User - fallback
|
||||
:PRIVATE | :guest | :job | true | :success | false
|
||||
:PRIVATE | nil | :user | true | :success | false
|
||||
:PRIVATE | nil | :user | false | :unauthorized | false
|
||||
:PRIVATE | nil | nil | nil | :success | false # Anonymous User
|
||||
|
|
@ -110,9 +110,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
:developer | :user | true | 'Composer package index' | :success | true
|
||||
:developer | :user | false | 'process Composer api request' | :unauthorized | false
|
||||
:developer | :job | true | 'Composer package index' | :success | true
|
||||
:guest | :user | true | 'Composer package index' | :success | false
|
||||
:guest | :user | true | 'Composer package index' | :success | true
|
||||
:guest | :user | false | 'process Composer api request' | :unauthorized | false
|
||||
:guest | :job | true | 'Composer package index' | :success | false
|
||||
:guest | :job | true | 'Composer package index' | :success | true
|
||||
nil | :user | true | 'Composer package index' | :not_found | false
|
||||
nil | :user | false | 'process Composer api request' | :unauthorized | false
|
||||
nil | :job | true | 'Composer package index' | :not_found | false
|
||||
|
|
@ -131,7 +131,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
:developer | :user | true | 'Composer package index' | :success | true
|
||||
:developer | :user | false | 'process Composer api request' | :unauthorized | false
|
||||
:developer | :job | true | 'process Composer api request' | :unauthorized | false
|
||||
:guest | :user | true | 'Composer package index' | :success | false
|
||||
:guest | :user | true | 'Composer package index' | :success | true
|
||||
:guest | :user | false | 'process Composer api request' | :unauthorized | false
|
||||
:guest | :job | true | 'process Composer api request' | :unauthorized | false
|
||||
nil | :user | true | 'Composer package index' | :not_found | false
|
||||
|
|
@ -175,9 +175,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | 'Composer provider index' | :success
|
||||
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :developer | :job | true | 'Composer provider index' | :success
|
||||
'PRIVATE' | :guest | :user | true | 'Composer empty provider index' | :success
|
||||
'PRIVATE' | :guest | :user | true | 'Composer provider index' | :success
|
||||
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :job | true | 'Composer empty provider index' | :success
|
||||
'PRIVATE' | :guest | :job | true | 'Composer provider index' | :success
|
||||
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | nil | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | nil | :job | true | 'process Composer api request' | :not_found
|
||||
|
|
@ -206,7 +206,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | 'Composer provider index' | :success
|
||||
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :developer | :job | true | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :user | true | 'Composer empty provider index' | :success
|
||||
'PRIVATE' | :guest | :user | true | 'Composer provider index' | :success
|
||||
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :job | true | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
|
||||
|
|
@ -259,9 +259,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :developer | :job | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :guest | :user | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | :guest | :user | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :job | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | :guest | :job | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | nil | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | nil | :job | true | 'process Composer api request' | :not_found
|
||||
|
|
@ -290,7 +290,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :developer | :job | true | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :user | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | :guest | :user | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :job | true | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
|
||||
|
|
@ -350,9 +350,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :developer | :job | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :guest | :user | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | :guest | :user | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :job | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | :guest | :job | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | nil | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | nil | :job | true | 'process Composer api request' | :not_found
|
||||
|
|
@ -381,7 +381,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :developer | :job | true | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :user | true | 'process Composer api request' | :not_found
|
||||
'PRIVATE' | :guest | :user | true | 'Composer package api request' | :success
|
||||
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | :guest | :job | true | 'process Composer api request' | :unauthorized
|
||||
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
|
||||
|
|
@ -602,9 +602,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | :success
|
||||
'PRIVATE' | :developer | :user | false | :unauthorized
|
||||
'PRIVATE' | :developer | :job | true | :success
|
||||
'PRIVATE' | :guest | :user | true | :forbidden
|
||||
'PRIVATE' | :guest | :user | true | :success
|
||||
'PRIVATE' | :guest | :user | false | :unauthorized
|
||||
'PRIVATE' | :guest | :job | true | :forbidden
|
||||
'PRIVATE' | :guest | :job | true | :success
|
||||
'PRIVATE' | nil | :user | true | :not_found
|
||||
'PRIVATE' | nil | :user | false | :unauthorized
|
||||
'PRIVATE' | nil | :job | true | :not_found
|
||||
|
|
@ -660,7 +660,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
|
|||
'PRIVATE' | :developer | :user | true | :success
|
||||
'PRIVATE' | :developer | :user | false | :unauthorized
|
||||
'PRIVATE' | :developer | :job | true | :unauthorized
|
||||
'PRIVATE' | :guest | :user | true | :forbidden
|
||||
'PRIVATE' | :guest | :user | true | :success
|
||||
'PRIVATE' | :guest | :user | false | :unauthorized
|
||||
'PRIVATE' | :guest | :job | true | :unauthorized
|
||||
'PRIVATE' | nil | :user | true | :not_found
|
||||
|
|
|
|||
|
|
@ -386,16 +386,38 @@ RSpec.describe API::DeployTokens, :aggregate_failures, feature_category: :contin
|
|||
send(entity).send("add_#{authorized_role}", user)
|
||||
end
|
||||
|
||||
it 'creates the deploy token' do
|
||||
expect { subject }.to change { DeployToken.count }.by(1)
|
||||
::DeployToken::AVAILABLE_SCOPES.map(&:to_s).each do |scope|
|
||||
context "with valid scope #{scope}" do
|
||||
before do
|
||||
params[:scopes] = [scope.to_sym]
|
||||
end
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(response).to match_response_schema('public_api/v4/deploy_token')
|
||||
expect(json_response['name']).to eq('Foo')
|
||||
expect(json_response['scopes']).to eq(['read_repository'])
|
||||
expect(json_response['username']).to eq('Bar')
|
||||
expect(json_response['expires_at'].to_time.to_i).to eq(expires_time.to_i)
|
||||
expect(json_response['token']).to match(/gldt-[A-Za-z0-9_-]{20}/)
|
||||
it 'creates the deploy token' do
|
||||
expect { subject }.to change { DeployToken.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(response).to match_response_schema('public_api/v4/deploy_token')
|
||||
expect(json_response['name']).to eq('Foo')
|
||||
expect(json_response['scopes']).to eq([scope])
|
||||
expect(json_response['username']).to eq('Bar')
|
||||
expect(json_response['expires_at'].to_time.to_i).to eq(expires_time.to_i)
|
||||
expect(json_response['token']).to match(/gldt-[A-Za-z0-9_-]{20}/)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with all scopes' do
|
||||
before do
|
||||
params[:scopes] = ::DeployToken::AVAILABLE_SCOPES
|
||||
end
|
||||
|
||||
it 'creates the deploy token with all scopes' do
|
||||
expect { subject }.to change { DeployToken.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(response).to match_response_schema('public_api/v4/deploy_token')
|
||||
expect(json_response['scopes']).to eq(::DeployToken::AVAILABLE_SCOPES.map(&:to_s))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with no optional params given' do
|
||||
|
|
|
|||
|
|
@ -771,9 +771,9 @@ RSpec.describe API::GenericPackages, feature_category: :package_registry do
|
|||
'PUBLIC' | :guest | false | :invalid_user_basic_auth | :success
|
||||
'PUBLIC' | :anonymous | false | :none | :success
|
||||
'PRIVATE' | :developer | true | :personal_access_token | :success
|
||||
'PRIVATE' | :guest | true | :personal_access_token | :forbidden
|
||||
'PRIVATE' | :guest | true | :personal_access_token | :success
|
||||
'PRIVATE' | :developer | true | :user_basic_auth | :success
|
||||
'PRIVATE' | :guest | true | :user_basic_auth | :forbidden
|
||||
'PRIVATE' | :guest | true | :user_basic_auth | :success
|
||||
'PRIVATE' | :developer | true | :invalid_personal_access_token | :unauthorized
|
||||
'PRIVATE' | :guest | true | :invalid_personal_access_token | :unauthorized
|
||||
'PRIVATE' | :developer | true | :invalid_user_basic_auth | :unauthorized
|
||||
|
|
|
|||
|
|
@ -42,32 +42,38 @@ RSpec.describe 'package details', feature_category: :package_registry do
|
|||
|
||||
subject { post_graphql(query, current_user: user) }
|
||||
|
||||
context 'with unauthorized user' do
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
|
||||
project.add_guest(user)
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it 'returns no packages' do
|
||||
subject
|
||||
|
||||
expect(graphql_data_at(:package)).to be_nil
|
||||
end
|
||||
|
||||
context 'with access to package registry for everyone' do
|
||||
context 'with unauthorized user' do
|
||||
before do
|
||||
project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC)
|
||||
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
|
||||
project.add_guest(user)
|
||||
end
|
||||
|
||||
it 'returns no packages' do
|
||||
subject
|
||||
|
||||
expect(graphql_data_at(:package)).to be_nil
|
||||
end
|
||||
|
||||
it_behaves_like 'a working graphql query' do
|
||||
it 'matches the JSON schema' do
|
||||
expect(package_details).to match_schema('graphql/packages/package_details')
|
||||
context 'with access to package registry for everyone' do
|
||||
before do
|
||||
project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC)
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
it '`public_package` returns true' do
|
||||
expect(graphql_data_at(:package, :public_package)).to eq(true)
|
||||
it_behaves_like 'a working graphql query' do
|
||||
it 'matches the JSON schema' do
|
||||
expect(package_details).to match_schema('graphql/packages/package_details')
|
||||
end
|
||||
end
|
||||
|
||||
it '`public_package` returns true' do
|
||||
expect(graphql_data_at(:package, :public_package)).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ RSpec.describe API::GroupPackages, feature_category: :package_registry do
|
|||
it_behaves_like 'returns packages', :group, :maintainer
|
||||
it_behaves_like 'returns packages', :group, :developer
|
||||
it_behaves_like 'returns packages', :group, :reporter
|
||||
it_behaves_like 'rejects packages access', :group, :guest, :forbidden
|
||||
it_behaves_like 'returns packages', :group, :guest
|
||||
|
||||
context 'with subgroup' do
|
||||
let(:subgroup) { create(:group, :private, parent: group) }
|
||||
|
|
@ -93,7 +93,7 @@ RSpec.describe API::GroupPackages, feature_category: :package_registry do
|
|||
it_behaves_like 'returns packages with subgroups', :group, :maintainer
|
||||
it_behaves_like 'returns packages with subgroups', :group, :developer
|
||||
it_behaves_like 'returns packages with subgroups', :group, :reporter
|
||||
it_behaves_like 'rejects packages access', :group, :guest, :forbidden
|
||||
it_behaves_like 'returns packages with subgroups', :group, :guest
|
||||
|
||||
context 'excluding subgroup' do
|
||||
let(:url) { "/groups/#{group.id}/packages?exclude_subgroups=true" }
|
||||
|
|
@ -102,7 +102,7 @@ RSpec.describe API::GroupPackages, feature_category: :package_registry do
|
|||
it_behaves_like 'returns packages', :group, :maintainer
|
||||
it_behaves_like 'returns packages', :group, :developer
|
||||
it_behaves_like 'returns packages', :group, :reporter
|
||||
it_behaves_like 'rejects packages access', :group, :guest, :forbidden
|
||||
it_behaves_like 'returns packages', :group, :guest
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ RSpec.describe API::HelmPackages, feature_category: :package_registry do
|
|||
:public | :not_a_member | 'process helm download content request' | :success
|
||||
:public | :anonymous | 'process helm download content request' | :success
|
||||
:private | :reporter | 'process helm download content request' | :success
|
||||
:private | :guest | 'rejects helm packages access' | :forbidden
|
||||
:private | :guest | 'process helm download content request' | :success
|
||||
:private | :not_a_member | 'rejects helm packages access' | :not_found
|
||||
:private | :anonymous | 'rejects helm packages access' | :unauthorized
|
||||
end
|
||||
|
|
|
|||
|
|
@ -431,13 +431,19 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
|
|||
it_behaves_like 'bumping the package last downloaded at field'
|
||||
it_behaves_like 'successfully returning the file'
|
||||
|
||||
it 'denies download when not enough permissions' do
|
||||
unless project.root_namespace == user.namespace
|
||||
project.add_guest(user)
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
subject
|
||||
it 'denies download when not enough permissions' do
|
||||
unless project.root_namespace == user.namespace
|
||||
project.add_guest(user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -587,12 +593,18 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
|
|||
it_behaves_like 'bumping the package last downloaded at field'
|
||||
it_behaves_like 'successfully returning the file'
|
||||
|
||||
it 'denies download when not enough permissions' do
|
||||
group.add_guest(user)
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
subject
|
||||
it 'denies download when not enough permissions' do
|
||||
group.add_guest(user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(download_denied_status)
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(download_denied_status)
|
||||
end
|
||||
end
|
||||
|
||||
it 'denies download when no private token' do
|
||||
|
|
@ -643,21 +655,27 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
|
|||
project.add_developer(user)
|
||||
end
|
||||
|
||||
context 'when user does not have enough permission for the recent project' do
|
||||
it 'tries to download the recent package' do
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the FF maven_remove_permissions_check_from_finder disabled' do
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(maven_remove_permissions_check_from_finder: false)
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'bumping the package last downloaded at field'
|
||||
it_behaves_like 'successfully returning the file'
|
||||
context 'when user does not have enough permission for the recent project' do
|
||||
it 'tries to download the recent package' do
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the FF maven_remove_permissions_check_from_finder disabled' do
|
||||
before do
|
||||
stub_feature_flags(maven_remove_permissions_check_from_finder: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'bumping the package last downloaded at field'
|
||||
it_behaves_like 'successfully returning the file'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -818,12 +836,18 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
|
|||
it_behaves_like 'bumping the package last downloaded at field'
|
||||
it_behaves_like 'successfully returning the file'
|
||||
|
||||
it 'denies download when not enough permissions' do
|
||||
project.add_guest(user)
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
subject
|
||||
it 'denies download when not enough permissions' do
|
||||
project.add_guest(user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
it 'denies download when no private token' do
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do
|
|||
true | :developer | :private | true | :personal_access_token | :success
|
||||
true | :developer | :public | true | :job_token | :success
|
||||
true | :developer | :public | true | :personal_access_token | :success
|
||||
true | :guest | :private | true | :job_token | :forbidden
|
||||
true | :guest | :private | true | :personal_access_token | :forbidden
|
||||
true | :guest | :private | true | :job_token | :success
|
||||
true | :guest | :private | true | :personal_access_token | :success
|
||||
true | :guest | :public | true | :job_token | :success
|
||||
true | :guest | :public | true | :personal_access_token | :success
|
||||
true | :reporter | :private | true | :job_token | :success
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ RSpec.describe API::NpmGroupPackages, feature_category: :package_registry do
|
|||
|
||||
:oauth | :public | :public | :guest | :ok
|
||||
:oauth | :public | :internal | :guest | :ok
|
||||
:oauth | :public | :private | :guest | :forbidden
|
||||
:oauth | :public | :private | :guest | :ok
|
||||
:oauth | :internal | :internal | :guest | :ok
|
||||
:oauth | :internal | :private | :guest | :forbidden
|
||||
:oauth | :private | :private | :guest | :forbidden
|
||||
:oauth | :internal | :private | :guest | :ok
|
||||
:oauth | :private | :private | :guest | :ok
|
||||
:oauth | :public | :public | :reporter | :ok
|
||||
:oauth | :public | :internal | :reporter | :ok
|
||||
:oauth | :public | :private | :reporter | :ok
|
||||
|
|
@ -43,10 +43,10 @@ RSpec.describe API::NpmGroupPackages, feature_category: :package_registry do
|
|||
|
||||
:personal_access_token | :public | :public | :guest | :ok
|
||||
:personal_access_token | :public | :internal | :guest | :ok
|
||||
:personal_access_token | :public | :private | :guest | :forbidden
|
||||
:personal_access_token | :public | :private | :guest | :ok
|
||||
:personal_access_token | :internal | :internal | :guest | :ok
|
||||
:personal_access_token | :internal | :private | :guest | :forbidden
|
||||
:personal_access_token | :private | :private | :guest | :forbidden
|
||||
:personal_access_token | :internal | :private | :guest | :ok
|
||||
:personal_access_token | :private | :private | :guest | :ok
|
||||
:personal_access_token | :public | :public | :reporter | :ok
|
||||
:personal_access_token | :public | :internal | :reporter | :ok
|
||||
:personal_access_token | :public | :private | :reporter | :ok
|
||||
|
|
|
|||
|
|
@ -205,15 +205,21 @@ RSpec.describe API::NpmProjectPackages, feature_category: :package_registry do
|
|||
|
||||
it_behaves_like 'a package file that requires auth'
|
||||
|
||||
context 'with guest' do
|
||||
let(:headers) { build_token_auth_header(token.plaintext_token) }
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it 'denies download when not enough permissions' do
|
||||
project.add_guest(user)
|
||||
context 'with guest' do
|
||||
let(:headers) { build_token_auth_header(token.plaintext_token) }
|
||||
|
||||
subject
|
||||
it 'denies download when not enough permissions' do
|
||||
project.add_guest(user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,7 @@ RSpec.describe API::NugetGroupPackages, feature_category: :package_registry do
|
|||
example_names_with_status:
|
||||
{
|
||||
anonymous_requests_example_name: 'rejects nuget packages access',
|
||||
anonymous_requests_status: :unauthorized,
|
||||
guest_requests_example_name: 'rejects nuget packages access',
|
||||
guest_requests_status: :not_found
|
||||
anonymous_requests_status: :unauthorized
|
||||
}
|
||||
|
||||
it_behaves_like 'allows anyone to pull public nuget packages on group level' do
|
||||
|
|
@ -62,9 +60,7 @@ RSpec.describe API::NugetGroupPackages, feature_category: :package_registry do
|
|||
example_names_with_status:
|
||||
{
|
||||
anonymous_requests_example_name: 'rejects nuget packages access',
|
||||
anonymous_requests_status: :unauthorized,
|
||||
guest_requests_example_name: 'rejects nuget packages access',
|
||||
guest_requests_status: :not_found
|
||||
anonymous_requests_status: :unauthorized
|
||||
}
|
||||
|
||||
it_behaves_like 'allows anyone to pull public nuget packages on group level' do
|
||||
|
|
@ -78,9 +74,7 @@ RSpec.describe API::NugetGroupPackages, feature_category: :package_registry do
|
|||
it_behaves_like 'handling nuget search requests',
|
||||
example_names_with_status: {
|
||||
anonymous_requests_example_name: 'rejects nuget packages access',
|
||||
anonymous_requests_status: :unauthorized,
|
||||
guest_requests_example_name: 'process empty nuget search request',
|
||||
guest_requests_status: :success
|
||||
anonymous_requests_status: :unauthorized
|
||||
}
|
||||
|
||||
it_behaves_like 'allows anyone to pull public nuget packages on group level' do
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ RSpec.describe API::NugetProjectPackages, feature_category: :package_registry do
|
|||
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
|
||||
'PUBLIC' | :anonymous | false | true | 'process nuget download versions request' | :success
|
||||
'PRIVATE' | :developer | true | true | 'process nuget download versions request' | :success
|
||||
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
|
||||
'PRIVATE' | :guest | true | true | 'process nuget download versions request' | :success
|
||||
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
|
||||
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
|
||||
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
|
||||
|
|
@ -228,7 +228,7 @@ RSpec.describe API::NugetProjectPackages, feature_category: :package_registry do
|
|||
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
|
||||
'PUBLIC' | :anonymous | false | true | 'process nuget download content request' | :success
|
||||
'PRIVATE' | :developer | true | true | 'process nuget download content request' | :success
|
||||
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
|
||||
'PRIVATE' | :guest | true | true | 'process nuget download content request' | :success
|
||||
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
|
||||
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
|
||||
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ RSpec.describe API::ProjectPackages, feature_category: :package_registry do
|
|||
it_behaves_like 'returns packages', :project, :developer
|
||||
it_behaves_like 'returns packages', :project, :reporter
|
||||
it_behaves_like 'rejects packages access', :project, :no_type, :not_found
|
||||
it_behaves_like 'rejects packages access', :project, :guest, :forbidden
|
||||
it_behaves_like 'returns packages', :project, :guest
|
||||
|
||||
context 'user is a maintainer' do
|
||||
before do
|
||||
|
|
@ -450,7 +450,7 @@ RSpec.describe API::ProjectPackages, feature_category: :package_registry do
|
|||
:public | :guest | false | :personal_access_token | false | 'returning response status' | :unauthorized
|
||||
:public | :anonymous | false | nil | true | 'returns package pipelines' | :success
|
||||
:private | :developer | true | :personal_access_token | true | 'returns package pipelines' | :success
|
||||
:private | :guest | true | :personal_access_token | true | 'returning response status' | :forbidden
|
||||
:private | :guest | true | :personal_access_token | true | 'returns package pipelines' | :success
|
||||
:private | :developer | true | :personal_access_token | false | 'returning response status' | :unauthorized
|
||||
:private | :guest | true | :personal_access_token | false | 'returning response status' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | true | 'returning response status' | :not_found
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ RSpec.describe API::RpmProjectPackages, feature_category: :package_registry do
|
|||
context 'with valid project' do
|
||||
where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
|
||||
'PUBLIC' | :developer | true | true | 'process rpm packages upload/download' | success_status
|
||||
'PUBLIC' | :guest | true | true | 'process rpm packages upload/download' | :forbidden
|
||||
'PUBLIC' | :guest | true | true | 'process rpm packages upload/download' | success_status
|
||||
'PUBLIC' | :developer | true | false | 'rejects rpm packages access' | :unauthorized
|
||||
'PUBLIC' | :guest | true | false | 'rejects rpm packages access' | :unauthorized
|
||||
'PUBLIC' | :developer | false | true | 'process rpm packages upload/download' | :not_found
|
||||
|
|
@ -97,7 +97,7 @@ RSpec.describe API::RpmProjectPackages, feature_category: :package_registry do
|
|||
'PUBLIC' | :guest | false | false | 'rejects rpm packages access' | :unauthorized
|
||||
'PUBLIC' | :anonymous | false | true | 'process rpm packages upload/download' | :unauthorized
|
||||
'PRIVATE' | :developer | true | true | 'process rpm packages upload/download' | success_status
|
||||
'PRIVATE' | :guest | true | true | 'rejects rpm packages access' | :forbidden
|
||||
'PRIVATE' | :guest | true | true | 'process rpm packages upload/download' | success_status
|
||||
'PRIVATE' | :developer | true | false | 'rejects rpm packages access' | :unauthorized
|
||||
'PRIVATE' | :guest | true | false | 'rejects rpm packages access' | :unauthorized
|
||||
'PRIVATE' | :developer | false | true | 'rejects rpm packages access' | :not_found
|
||||
|
|
|
|||
|
|
@ -63,11 +63,11 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
|
|||
end
|
||||
|
||||
where(:user_role, :token_type, :valid_token, :status) do
|
||||
:guest | :personal_access_token | true | :forbidden
|
||||
:guest | :personal_access_token | true | :not_found
|
||||
:guest | :personal_access_token | false | :unauthorized
|
||||
:guest | :deploy_token | true | :not_found
|
||||
:guest | :deploy_token | false | :unauthorized
|
||||
:guest | :job_token | true | :forbidden
|
||||
:guest | :job_token | true | :not_found
|
||||
:guest | :job_token | false | :unauthorized
|
||||
:reporter | :personal_access_token | true | :not_found
|
||||
:reporter | :personal_access_token | false | :unauthorized
|
||||
|
|
@ -139,7 +139,7 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
|
|||
:public | :guest | false | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:public | :anonymous | false | :personal_access_token | true | 'Rubygems gem download' | :success
|
||||
:private | :developer | true | :personal_access_token | true | 'Rubygems gem download' | :success
|
||||
:private | :guest | true | :personal_access_token | true | 'rejects rubygems packages access' | :forbidden
|
||||
:private | :guest | true | :personal_access_token | true | 'Rubygems gem download' | :success
|
||||
:private | :developer | true | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :guest | true | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | true | 'rejects rubygems packages access' | :not_found
|
||||
|
|
@ -156,7 +156,7 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
|
|||
:public | :developer | false | :job_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:public | :guest | false | :job_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :developer | true | :job_token | true | 'Rubygems gem download' | :success
|
||||
:private | :guest | true | :job_token | true | 'rejects rubygems packages access' | :forbidden
|
||||
:private | :guest | true | :job_token | true | 'Rubygems gem download' | :success
|
||||
:private | :developer | true | :job_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :guest | true | :job_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :developer | false | :job_token | true | 'rejects rubygems packages access' | :not_found
|
||||
|
|
@ -406,7 +406,7 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
|
|||
:public | :guest | false | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:public | :anonymous | false | :personal_access_token | true | 'dependency endpoint success' | :success
|
||||
:private | :developer | true | :personal_access_token | true | 'dependency endpoint success' | :success
|
||||
:private | :guest | true | :personal_access_token | true | 'rejects rubygems packages access' | :forbidden
|
||||
:private | :guest | true | :personal_access_token | true | 'dependency endpoint success' | :success
|
||||
:private | :developer | true | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :guest | true | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | true | 'rejects rubygems packages access' | :not_found
|
||||
|
|
@ -423,7 +423,7 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
|
|||
:public | :developer | false | :job_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:public | :guest | false | :job_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :developer | true | :job_token | true | 'dependency endpoint success' | :success
|
||||
:private | :guest | true | :job_token | true | 'rejects rubygems packages access' | :forbidden
|
||||
:private | :guest | true | :job_token | true | 'dependency endpoint success' | :success
|
||||
:private | :developer | true | :job_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :guest | true | :job_token | false | 'rejects rubygems packages access' | :unauthorized
|
||||
:private | :developer | false | :job_token | true | 'rejects rubygems packages access' | :not_found
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :anonymous | false | nil | 'returns no terraform module packages' | :success
|
||||
:private | :developer | true | :personal_access_token | 'returns terraform module packages' | :success
|
||||
:private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :developer | true | :personal_access_token | 'returns terraform module packages' | :success
|
||||
:private | :guest | true | :personal_access_token | 'returns terraform module packages' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -49,15 +49,15 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:private | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :anonymous | false | nil | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :developer | true | :job_token | 'returns terraform module packages' | :success
|
||||
:public | :guest | true | :job_token | 'returns no terraform module packages' | :success
|
||||
:public | :developer | true | :job_token | 'returns terraform module packages' | :success
|
||||
:public | :guest | true | :job_token | 'returns terraform module packages' | :success
|
||||
:public | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :developer | false | :job_token | 'returns no terraform module packages' | :success
|
||||
:public | :guest | false | :job_token | 'returns no terraform module packages' | :success
|
||||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | true | :job_token | 'returns terraform module packages' | :success
|
||||
:private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :developer | true | :job_token | 'returns terraform module packages' | :success
|
||||
:private | :guest | true | :job_token | 'returns terraform module packages' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -116,7 +116,7 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :anonymous | false | nil | 'redirects to version download' | :found
|
||||
:private | :developer | true | :personal_access_token | 'redirects to version download' | :found
|
||||
:private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :guest | true | :personal_access_token | 'redirects to version download' | :found
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -132,7 +132,7 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | true | :job_token | 'redirects to version download' | :found
|
||||
:private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :guest | true | :job_token | 'redirects to version download' | :found
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -185,8 +185,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :anonymous | false | nil | 'returns terraform module version' | :success
|
||||
:private | :developer | true | :personal_access_token | 'returns terraform module version' | :success
|
||||
:private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :developer | true | :personal_access_token | 'returns terraform module version' | :success
|
||||
:private | :guest | true | :personal_access_token | 'returns terraform module version' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -201,8 +201,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :guest | false | :job_token | 'returns terraform module version' | :success
|
||||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | true | :job_token | 'returns terraform module version' | :success
|
||||
:private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :developer | true | :job_token | 'returns terraform module version' | :success
|
||||
:private | :guest | true | :job_token | 'returns terraform module version' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -257,8 +257,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :anonymous | false | nil | 'returns terraform module version' | :success
|
||||
:private | :developer | true | :personal_access_token | 'returns terraform module version' | :success
|
||||
:private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :developer | true | :personal_access_token | 'returns terraform module version' | :success
|
||||
:private | :guest | true | :personal_access_token | 'returns terraform module version' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -273,8 +273,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :guest | false | :job_token | 'returns terraform module version' | :success
|
||||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | true | :job_token | 'returns terraform module version' | :success
|
||||
:private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :developer | true | :job_token | 'returns terraform module version' | :success
|
||||
:private | :guest | true | :job_token | 'returns terraform module version' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -316,8 +316,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :anonymous | false | nil | 'grants terraform module download' | :success
|
||||
:private | :developer | true | :personal_access_token | 'grants terraform module download' | :success
|
||||
:private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :developer | true | :personal_access_token | 'grants terraform module download' | :success
|
||||
:private | :guest | true | :personal_access_token | 'grants terraform module download' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -332,8 +332,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :guest | false | :job_token | 'grants terraform module download' | :success
|
||||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | true | :job_token | 'grants terraform module download' | :success
|
||||
:private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :developer | true | :job_token | 'grants terraform module download' | :success
|
||||
:private | :guest | true | :job_token | 'grants terraform module download' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -385,7 +385,7 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :anonymous | false | nil | 'grants terraform module package file access' | :success
|
||||
:private | :developer | true | :personal_access_token | 'grants terraform module package file access' | :success
|
||||
:private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :guest | true | :personal_access_token | 'grants terraform module package file access' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
@ -401,7 +401,7 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
|
|||
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | true | :job_token | 'grants terraform module package file access' | :success
|
||||
:private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
:private | :guest | true | :job_token | 'grants terraform module package file access' | :success
|
||||
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
|
||||
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
RSpec.describe JwtController, feature_category: :system_access do
|
||||
include_context 'parsed logs'
|
||||
|
||||
let(:service) { double(execute: {} ) }
|
||||
let(:service) { double(execute: {}) }
|
||||
let(:service_class) { Auth::ContainerRegistryAuthenticationService }
|
||||
let(:service_name) { 'container_registry' }
|
||||
let(:parameters) { { service: service_name } }
|
||||
|
|
@ -23,7 +23,7 @@ RSpec.describe JwtController, feature_category: :system_access do
|
|||
end
|
||||
|
||||
shared_examples 'a token that expires today' do
|
||||
let(:pat) { create(:personal_access_token, user: user, scopes: ['api'], expires_at: Date.today ) }
|
||||
let(:pat) { create(:personal_access_token, user: user, scopes: ['api'], expires_at: Date.today) }
|
||||
let(:headers) { { authorization: credentials('personal_access_token', pat.token) } }
|
||||
|
||||
it 'fails authentication' do
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ RSpec.describe 'Merge Requests Diffs', feature_category: :code_review_workflow d
|
|||
end
|
||||
|
||||
context 'with the different expanded option' do
|
||||
subject { go(page: 0, per_page: 5, expanded: true ) }
|
||||
subject { go(page: 0, per_page: 5, expanded: true) }
|
||||
|
||||
let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
|
||||
let(:expected_options) { collection_arguments(total_pages: 20) }
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ RSpec.describe 'merge requests actions', feature_category: :source_code_manageme
|
|||
|
||||
context 'when the assignee is changed' do
|
||||
before do
|
||||
update_service( assignee_ids: [] )
|
||||
update_service(assignee_ids: [])
|
||||
end
|
||||
|
||||
it_behaves_like 'a non-cached request'
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
|
|||
|
||||
# Added as a request spec because of https://gitlab.com/gitlab-org/gitlab/-/issues/232386
|
||||
describe 'GET #downloads' do
|
||||
let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
|
||||
let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2') }
|
||||
let(:internal_redirect_url) { "https://#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}/abcd" }
|
||||
let!(:link) do
|
||||
create(:release_link, release: release, name: 'internal gitlab url', filepath: filepath,
|
||||
|
|
@ -117,7 +117,7 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
|
|||
end
|
||||
|
||||
context 'when user has permissions to read code' do
|
||||
let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
|
||||
let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2') }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
|
|
@ -131,7 +131,7 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
|
|||
end
|
||||
|
||||
context 'when user doesn\'t have permissions to read code' do
|
||||
let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
|
||||
let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2') }
|
||||
let_it_be(:new_user) { create(:user, guest_of: project) }
|
||||
|
||||
before do
|
||||
|
|
@ -153,7 +153,7 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
|
|||
create(:project, :repository, :public, repository_access_level: ProjectFeature::PRIVATE)
|
||||
end
|
||||
|
||||
let_it_be(:release) { create(:release, project: public_project, tag: 'v11.9.0-rc2' ) }
|
||||
let_it_be(:release) { create(:release, project: public_project, tag: 'v11.9.0-rc2') }
|
||||
|
||||
it 'dosn\'t show commit details in the atom feed' do
|
||||
get(project_releases_url(public_project, format: :atom))
|
||||
|
|
|
|||
|
|
@ -149,20 +149,20 @@ RSpec.describe SearchController, type: :request, feature_category: :global_searc
|
|||
end
|
||||
|
||||
it 'finds a commit in uppercase and redirects to its page' do
|
||||
send_search_request( { search: sha.upcase, scope: 'projects', project_id: project.id })
|
||||
send_search_request({ search: sha.upcase, scope: 'projects', project_id: project.id })
|
||||
|
||||
expect(response).to redirect_to(project_commit_path(project, sha))
|
||||
end
|
||||
|
||||
it 'finds a commit with a partial sha and redirects to its page' do
|
||||
send_search_request( { search: sha[0..10], scope: 'projects', project_id: project.id })
|
||||
send_search_request({ search: sha[0..10], scope: 'projects', project_id: project.id })
|
||||
|
||||
expect(response).to redirect_to(project_commit_path(project, sha))
|
||||
end
|
||||
|
||||
it 'redirects to the commit even if another scope result is returned' do
|
||||
create(:note, project: project, note: "This is the #{sha}")
|
||||
send_search_request( { search: sha, scope: 'projects', project_id: project.id })
|
||||
send_search_request({ search: sha, scope: 'projects', project_id: project.id })
|
||||
|
||||
expect(response).to redirect_to(project_commit_path(project, sha))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ RSpec.describe AnalyticsBuildEntity do
|
|||
end
|
||||
|
||||
it 'contains the duration' do
|
||||
expect(subject[:total_time]).to eq(hours: 1 )
|
||||
expect(subject[:total_time]).to eq(hours: 1)
|
||||
end
|
||||
|
||||
context 'no started at or finished at date' do
|
||||
|
|
|
|||
|
|
@ -116,16 +116,18 @@ RSpec.describe AuditEventService, :with_license, feature_category: :audit_events
|
|||
audit_service.for_authentication.security_event
|
||||
end
|
||||
|
||||
it 'tracks exceptions when the event cannot be created' do
|
||||
allow_next_instance_of(AuditEvent) do |event|
|
||||
allow(event).to receive(:valid?).and_return(false)
|
||||
context 'when the event cannot be created' do
|
||||
let(:user) { create(:user, current_sign_in_ip: "not-an-ip-address") }
|
||||
|
||||
before do
|
||||
allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return("not-an-ip-address")
|
||||
end
|
||||
|
||||
expect(Gitlab::ErrorTracking).to(
|
||||
receive(:track_and_raise_for_dev_exception)
|
||||
)
|
||||
it 'tracks exceptions' do
|
||||
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
|
||||
|
||||
audit_service.for_authentication.security_event
|
||||
audit_service.for_authentication.security_event
|
||||
end
|
||||
end
|
||||
|
||||
context 'with IP address', :request_store do
|
||||
|
|
@ -138,7 +140,6 @@ RSpec.describe AuditEventService, :with_license, feature_category: :audit_events
|
|||
|
||||
with_them do
|
||||
let(:user) { create(:user, current_sign_in_ip: from_author_sign_in) }
|
||||
let(:audit_service) { described_class.new(user, user, with: 'standard') }
|
||||
|
||||
before do
|
||||
allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(from_context)
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
.to receive(:execute)
|
||||
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
|
||||
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
|
||||
} ))
|
||||
}))
|
||||
|
||||
allow(client).to receive(:parse)
|
||||
end
|
||||
|
|
@ -142,7 +142,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
.to receive(:execute)
|
||||
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
|
||||
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
|
||||
} ))
|
||||
}))
|
||||
|
||||
allow(client).to receive(:parse)
|
||||
end
|
||||
|
|
@ -174,7 +174,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
.to receive(:execute)
|
||||
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
|
||||
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
|
||||
} ))
|
||||
}))
|
||||
|
||||
allow(client).to receive(:parse)
|
||||
end
|
||||
|
|
@ -391,7 +391,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
.to receive(:execute)
|
||||
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
|
||||
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
|
||||
} ))
|
||||
}))
|
||||
|
||||
allow(client).to receive(:parse)
|
||||
end
|
||||
|
|
@ -407,7 +407,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
.to receive(:execute)
|
||||
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
|
||||
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
|
||||
} ))
|
||||
}))
|
||||
|
||||
allow(client).to receive(:parse)
|
||||
end
|
||||
|
|
@ -542,7 +542,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
|
||||
describe '#user-role' do
|
||||
context 'when there is a parent_namespace and the user is a member' do
|
||||
let(:group2) { create(:group, path: 'destination200', source_id: parent_group.id ) }
|
||||
let(:group2) { create(:group, path: 'destination200', source_id: parent_group.id) }
|
||||
let(:params) do
|
||||
[
|
||||
{
|
||||
|
|
@ -856,8 +856,8 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
|
||||
context 'when the source_type is a group' do
|
||||
context 'when the provided destination_slug already exists in the destination_namespace' do
|
||||
let_it_be(:existing_subgroup) { create(:group, path: 'existing-subgroup', parent_id: parent_group.id ) }
|
||||
let_it_be(:existing_subgroup_2) { create(:group, path: 'existing-subgroup_2', parent_id: parent_group.id ) }
|
||||
let_it_be(:existing_subgroup) { create(:group, path: 'existing-subgroup', parent_id: parent_group.id) }
|
||||
let_it_be(:existing_subgroup_2) { create(:group, path: 'existing-subgroup_2', parent_id: parent_group.id) }
|
||||
let(:params) do
|
||||
[
|
||||
{
|
||||
|
|
@ -937,8 +937,8 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
|
||||
context 'when the source_type is a project' do
|
||||
context 'when the provided destination_slug already exists in the destination_namespace' do
|
||||
let_it_be(:existing_group) { create(:group, path: 'existing-group' ) }
|
||||
let_it_be(:existing_project) { create(:project, path: 'existing-project', parent_id: existing_group.id ) }
|
||||
let_it_be(:existing_group) { create(:group, path: 'existing-group') }
|
||||
let_it_be(:existing_project) { create(:project, path: 'existing-project', parent_id: existing_group.id) }
|
||||
let(:params) do
|
||||
[
|
||||
{
|
||||
|
|
@ -968,7 +968,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
|
|||
end
|
||||
|
||||
context 'when the destination_slug does not conflict with an existing project' do
|
||||
let_it_be(:existing_group) { create(:group, path: 'existing-group' ) }
|
||||
let_it_be(:existing_group) { create(:group, path: 'existing-group') }
|
||||
let(:params) do
|
||||
[
|
||||
{
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ RSpec.describe JiraConnectInstallations::ProxyLifecycleEventService, feature_cat
|
|||
it 'returns an error ServiceResponse', :aggregate_failures do
|
||||
expect(execute_service).to be_kind_of(ServiceResponse)
|
||||
expect(execute_service[:status]).to eq(:error)
|
||||
expect(execute_service[:message]).to eq( { type: :response_error, code: 422 } )
|
||||
expect(execute_service[:message]).to eq({ type: :response_error, code: 422 })
|
||||
end
|
||||
|
||||
it 'logs the error response' do
|
||||
|
|
|
|||
|
|
@ -113,10 +113,34 @@ RSpec::Matchers.define :have_graphql_arguments do |*expected|
|
|||
end
|
||||
|
||||
failure_message do |field|
|
||||
names = expected_names(field).inspect
|
||||
args = field.arguments.keys.inspect
|
||||
expected_values = expected_names(field).sort
|
||||
actual_values = field.arguments.keys.sort
|
||||
|
||||
"expected #{field.name} to have the following arguments: #{names}, but it has #{args}."
|
||||
extra_values = actual_values - expected_values
|
||||
missing_values = expected_values - actual_values
|
||||
|
||||
message = <<~MESSAGE
|
||||
expected #{field.name} to have the following arguments:
|
||||
#{expected_values.inspect}
|
||||
but it has
|
||||
#{actual_values.inspect}
|
||||
MESSAGE
|
||||
|
||||
if extra_values.present?
|
||||
message += <<~MESSAGE
|
||||
\n Extra values:
|
||||
#{extra_values.inspect}
|
||||
MESSAGE
|
||||
end
|
||||
|
||||
if missing_values.present?
|
||||
message += <<~MESSAGE
|
||||
\n Missing values:
|
||||
#{missing_values.inspect}
|
||||
MESSAGE
|
||||
end
|
||||
|
||||
message
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ RSpec.shared_examples 'conan search endpoint' do
|
|||
:maintainer | true
|
||||
:developer | true
|
||||
:reporter | true
|
||||
:guest | false
|
||||
:guest | true
|
||||
:anonymous | false
|
||||
end
|
||||
|
||||
|
|
@ -715,12 +715,18 @@ RSpec.shared_examples 'a private project with packages' do
|
|||
expect(response.media_type).to eq('application/octet-stream')
|
||||
end
|
||||
|
||||
it 'denies download when not enough permissions' do
|
||||
project.add_guest(user)
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
subject
|
||||
it 'denies download when not enough permissions' do
|
||||
project.add_guest(user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ RSpec.shared_examples 'Debian distributions read endpoint' do |desired_behavior,
|
|||
:public | :invalid_token | :private_token | :unauthorized | nil
|
||||
:private | :developer | :private_token | success_status | success_body
|
||||
:private | :developer | :basic | :not_found | nil
|
||||
:private | :guest | :private_token | :forbidden | nil
|
||||
:private | :guest | :private_token | success_status | success_body
|
||||
:private | :not_a_member | :private_token | :not_found | nil
|
||||
:private | :anonymous | :private_token | :not_found | nil
|
||||
:private | :invalid_token | :private_token | :unauthorized | nil
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ RSpec.shared_examples 'Debian packages read endpoint' do |desired_behavior, succ
|
|||
:public | :invalid_token | :basic | :unauthorized | nil
|
||||
:private | :developer | :basic | success_status | success_body
|
||||
:private | :developer | :private_token | :unauthorized | nil
|
||||
:private | :guest | :basic | :forbidden | nil
|
||||
:private | :guest | :basic | success_status | success_body
|
||||
:private | :not_a_member | :basic | :not_found | nil
|
||||
:private | :anonymous | :basic | :unauthorized | nil
|
||||
:private | :invalid_token | :basic | :unauthorized | nil
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ RSpec.shared_examples 'handling helm chart index requests' do
|
|||
:public | :not_a_member | 'process helm service index request' | :success
|
||||
:public | :anonymous | 'process helm service index request' | :success
|
||||
:private | :reporter | 'process helm service index request' | :success
|
||||
:private | :guest | 'rejects helm packages access' | :forbidden
|
||||
:private | :guest | 'process helm service index request' | :success
|
||||
:private | :not_a_member | 'rejects helm packages access' | :not_found
|
||||
:private | :anonymous | 'rejects helm packages access' | :unauthorized
|
||||
end
|
||||
|
|
@ -264,7 +264,7 @@ RSpec.shared_examples 'handling helm chart index requests' do
|
|||
:public | :not_a_member | 'process helm service index request' | :success
|
||||
:public | :anonymous | 'process helm service index request' | :success
|
||||
:private | :reporter | 'process helm service index request' | :success
|
||||
:private | :guest | 'rejects helm packages access' | :forbidden
|
||||
:private | :guest | 'process helm service index request' | :success
|
||||
:private | :not_a_member | 'rejects helm packages access' | :not_found
|
||||
:private | :anonymous | 'rejects helm packages access' | :unauthorized
|
||||
end
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
|
|||
set_visibility('private', scope)
|
||||
end
|
||||
|
||||
it_behaves_like 'reject metadata request', status: :forbidden
|
||||
it_behaves_like 'accept metadata request', status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
|
|||
true | :public | nil | 'redirect metadata request' | :redirected
|
||||
false | :public | nil | 'returning response status with error' | :not_found
|
||||
false | :private | nil | 'reject metadata request' | :unauthorized
|
||||
false | :private | :guest | 'reject metadata request' | :forbidden
|
||||
false | :private | :guest | 'returning response status with error' | :not_found
|
||||
false | :private | :reporter | 'returning response status with error' | :not_found
|
||||
end
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ RSpec.shared_examples 'handling audit request' do |path:, scope: :project|
|
|||
project.add_guest(user)
|
||||
end
|
||||
|
||||
it_behaves_like 'reject audit request', status: :forbidden
|
||||
it_behaves_like 'accept audit request', status: :ok
|
||||
end
|
||||
|
||||
%i[oauth personal_access_token job_token deploy_token].each do |auth|
|
||||
|
|
@ -451,7 +451,7 @@ RSpec.shared_examples 'handling get dist tags requests' do |scope: :project|
|
|||
project.update!(visibility: 'private')
|
||||
end
|
||||
|
||||
it_behaves_like 'reject package tags request', status: :forbidden
|
||||
it_behaves_like 'accept package tags request', status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -524,7 +524,7 @@ RSpec.shared_examples 'handling get dist tags requests' do |scope: :project|
|
|||
:internal | nil | 'reject package tags request' | :unauthorized
|
||||
:public | :guest | 'returning response status with error' | :not_found
|
||||
:internal | :guest | 'returning response status with error' | :not_found
|
||||
:private | :guest | 'reject package tags request' | :forbidden
|
||||
:private | :guest | 'returning response status with error' | :not_found
|
||||
:public | :reporter | 'returning response status with error' | :not_found
|
||||
end
|
||||
|
||||
|
|
@ -778,28 +778,34 @@ RSpec.shared_examples 'handling get metadata requests for packages in multiple p
|
|||
end
|
||||
end
|
||||
|
||||
context 'with limited access to the project with the last package version' do
|
||||
before_all do
|
||||
project2.add_guest(user)
|
||||
end
|
||||
|
||||
it 'includes matching package versions from authorized projects in the response' do
|
||||
subject
|
||||
|
||||
expect(json_response['versions'].keys).to contain_exactly(package.version)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with limited access to the project with the first package version' do
|
||||
context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
|
||||
before do
|
||||
project.update!(visibility: 'private')
|
||||
project.add_guest(user)
|
||||
stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
|
||||
end
|
||||
|
||||
it 'includes matching package versions from authorized projects in the response' do
|
||||
subject
|
||||
context 'with limited access to the project with the last package version' do
|
||||
before_all do
|
||||
project2.add_guest(user)
|
||||
end
|
||||
|
||||
expect(json_response['versions'].keys).to contain_exactly(package2.version)
|
||||
it 'includes matching package versions from authorized projects in the response' do
|
||||
subject
|
||||
|
||||
expect(json_response['versions'].keys).to contain_exactly(package.version)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with limited access to the project with the first package version' do
|
||||
before do
|
||||
project.update!(visibility: 'private')
|
||||
project.add_guest(user)
|
||||
end
|
||||
|
||||
it 'includes matching package versions from authorized projects in the response' do
|
||||
subject
|
||||
|
||||
expect(json_response['versions'].keys).to contain_exactly(package2.version)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue