Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-11-11 00:12:08 +00:00
parent cdcfa7dc14
commit debef4f897
38 changed files with 579 additions and 117 deletions

View File

@ -29,3 +29,6 @@ include:
- local: .gitlab/ci/templates/gem.gitlab-ci.yml
inputs:
gem_name: "gitlab-http"
- local: .gitlab/ci/templates/gem.gitlab-ci.yml
inputs:
gem_name: "gitlab-backup-cli"

View File

@ -40,6 +40,7 @@ gem 'gitlab-safe_request_store', path: 'gems/gitlab-safe_request_store' # ruboco
# GitLab Monorepo Gems
group :monorepo do
gem 'gitlab-utils', path: 'gems/gitlab-utils' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'gitlab-backup-cli', path: 'gems/gitlab-backup-cli', feature_category: :backup_restore
end
# Responders respond_to and respond_with
@ -265,7 +266,7 @@ gem 're2', '2.3.0' # rubocop:todo Gemfile/MissingFeatureCategory
# Misc
gem 'semver_dialects', '~> 1.2.1' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'semver_dialects', '~> 1.5', feature_category: :static_application_security_testing
gem 'version_sorter', '~> 2.3' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'csv_builder', path: 'gems/csv_builder' # rubocop:todo Gemfile/MissingFeatureCategory

View File

@ -104,6 +104,7 @@
{"name":"date","version":"3.3.3","platform":"java","checksum":"584e0a582d1eb2207b4eaac089d8a43f2ca10bea02682f286099642f15c56cce"},
{"name":"date","version":"3.3.3","platform":"ruby","checksum":"819792019d5712b748fb15f6dfaaedef14b0328723ef23583ea35f186774530f"},
{"name":"dead_end","version":"3.1.1","platform":"ruby","checksum":"1011df7f7c0149be004e11cbbc37747760227c55305cd902fd3c06e1394b2f5b"},
{"name":"deb_version","version":"1.0.2","platform":"ruby","checksum":"c21f911d7f2fd1d61219caae254fc078e6598e477fdff8a05a18bec6c72ee713"},
{"name":"debug_inspector","version":"1.1.0","platform":"ruby","checksum":"eaa5a2d0195e1d65fb4164e8e7e466cca2e7eb53bc5e608cf12b8bf02c3a8606"},
{"name":"deckar01-task_list","version":"2.3.3","platform":"ruby","checksum":"918abaf3f81e6c0d224c2b7bef593d7f84ee5847a0692726d24e3fb272c2c758"},
{"name":"declarative","version":"0.0.20","platform":"ruby","checksum":"8021dd6cb17ab2b61233c56903d3f5a259c5cf43c80ff332d447d395b17d9ff9"},
@ -580,7 +581,7 @@
{"name":"sd_notify","version":"0.1.1","platform":"ruby","checksum":"cbc7ac6caa7cedd26b30a72b5eeb6f36050dc0752df263452ea24fb5a4ad3131"},
{"name":"seed-fu","version":"2.3.7","platform":"ruby","checksum":"f19673443e9af799b730e3d4eca6a89b39e5a36825015dffd00d02ea3365cf74"},
{"name":"selenium-webdriver","version":"4.15.0","platform":"ruby","checksum":"36134e883c4df98f1b7e8519a3753c77427b74621147f8245aa6cac306d52297"},
{"name":"semver_dialects","version":"1.2.1","platform":"ruby","checksum":"60a1f67659f79c51a667e8858ec9b089c1e4ce4f6d2a0f0b4ac101916946eb23"},
{"name":"semver_dialects","version":"1.5.0","platform":"ruby","checksum":"0080f1abafc9c1af82d34e890d7c317b9eacb56b9e03040107ef5d1a51ca49ae"},
{"name":"sentry-rails","version":"5.8.0","platform":"ruby","checksum":"c11b2d909de2c2bfda793c45f64180fd784d54c46886338b683ee3f8efa7731b"},
{"name":"sentry-raven","version":"3.1.2","platform":"ruby","checksum":"103d3b122958810d34898ce2e705bcf549ddb9d855a70ce9a3970ee2484f364a"},
{"name":"sentry-ruby","version":"5.8.0","platform":"ruby","checksum":"caeb121433be379fb94e991a45265a287b13a9a9083e7264f539752369d37110"},
@ -646,7 +647,7 @@
{"name":"test-prof","version":"1.2.3","platform":"ruby","checksum":"c52a40194cb30f399ed3eb6beb4c45b5daad8b8eb418e8ef69089e4dc7e01fd6"},
{"name":"test_file_finder","version":"0.2.1","platform":"ruby","checksum":"a5e9b369d80c76aefbb609acf5e11d89a048f35e565de3cc261c20112f0fcdb3"},
{"name":"text","version":"1.3.1","platform":"ruby","checksum":"2fbbbc82c1ce79c4195b13018a87cbb00d762bda39241bb3cdc32792759dd3f4"},
{"name":"thor","version":"1.2.2","platform":"ruby","checksum":"2f93c652828cba9fcf4f65f5dc8c306f1a7317e05aad5835a13740122c17f24c"},
{"name":"thor","version":"1.3.0","platform":"ruby","checksum":"1adc7f9e5b3655a68c71393fee8bd0ad088d14ee8e83a0b73726f23cbb3ca7c3"},
{"name":"thread_safe","version":"0.3.6","platform":"java","checksum":"bb28394cd0924c068981adee71f36a81c85c92e7d74d3f62372bd51489a0e0c2"},
{"name":"thread_safe","version":"0.3.6","platform":"ruby","checksum":"9ed7072821b51c57e8d6b7011a8e282e25aeea3a4065eab326e43f66f063b05a"},
{"name":"thrift","version":"0.16.0","platform":"ruby","checksum":"d023286ea89e30444c9f1c28dd76107f87d8aaf85fe1742da1d8cd3b5417dcce"},

View File

@ -23,6 +23,12 @@ PATH
error_tracking_open_api (1.0.0)
typhoeus (~> 1.0, >= 1.0.1)
PATH
remote: gems/gitlab-backup-cli
specs:
gitlab-backup-cli (0.0.1)
thor (~> 1.3)
PATH
remote: gems/gitlab-http
specs:
@ -422,6 +428,7 @@ GEM
database_cleaner-core (2.0.1)
date (3.3.3)
dead_end (3.1.1)
deb_version (1.0.2)
debug_inspector (1.1.0)
deckar01-task_list (2.3.3)
html-pipeline
@ -1493,9 +1500,10 @@ GEM
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
semver_dialects (1.2.1)
semver_dialects (1.5.0)
deb_version (~> 1.0.1)
pastel (~> 0.8.0)
thor (~> 1.2.0)
thor (~> 1.3)
tty-command (~> 0.10.1)
sentry-rails (5.8.0)
railties (>= 5.0)
@ -1617,7 +1625,7 @@ GEM
test_file_finder (0.2.1)
faraday (>= 1.0, < 3.0, != 2.0.0)
text (1.3.1)
thor (1.2.2)
thor (1.3.0)
thread_safe (0.3.6)
thrift (0.16.0)
tilt (2.0.11)
@ -1849,6 +1857,7 @@ DEPENDENCIES
gettext_i18n_rails (~> 1.11.0)
gettext_i18n_rails_js (~> 2.0.0)
gitaly (~> 16.5.0.pre.rc1)
gitlab-backup-cli!
gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 4.6.0)
gitlab-experiment (~> 0.8.0)
@ -2028,7 +2037,7 @@ DEPENDENCIES
sd_notify (~> 0.1.0)
seed-fu (~> 2.3.7)
selenium-webdriver (~> 4.15)
semver_dialects (~> 1.2.1)
semver_dialects (~> 1.5)
sentry-rails (~> 5.8.0)
sentry-raven (~> 3.1)
sentry-ruby (~> 5.8.0)

View File

@ -29,7 +29,8 @@ class ProjectsController < Projects::ApplicationController
before_action :authorize_read_code!, only: [:refs]
# Authorize
before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export]
before_action :authorize_admin_project_or_custom_permissions!, only: :edit
before_action :authorize_admin_project!, only: [:update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export]
before_action :authorize_archive_project!, only: [:archive, :unarchive]
before_action :event_filter, only: [:show, :activity]
@ -598,6 +599,11 @@ class ProjectsController < Projects::ApplicationController
def render_edit
render 'edit'
end
# Overridden in EE
def authorize_admin_project_or_custom_permissions!
authorize_admin_project!
end
end
ProjectsController.prepend_mod_with('ProjectsController')

View File

@ -48,6 +48,12 @@ class ProjectMember < Member
end
end
def permissible_access_level_roles_for_project_access_token(current_user, project)
permissible_access_level_roles(current_user, project).filter do |_, value|
value <= project.project_authorizations.find_by(user: current_user).access_level
end
end
def access_level_roles
Gitlab::Access.options
end

View File

@ -17,6 +17,8 @@ module ResourceAccessTokens
access_level = params[:access_level] || Gitlab::Access::MAINTAINER
return error("Could not provision owner access to project access token") if do_not_allow_owner_access_level_for_project_bot?(access_level)
return error("Access level of the token can't be greater the access level of the user who created the token") unless validate_access_level(access_level)
return error(s_('AccessTokens|Access token limit reached')) if reached_access_token_limit?
user = create_user
@ -125,6 +127,14 @@ module ResourceAccessTokens
ServiceResponse.success(payload: { access_token: access_token })
end
def validate_access_level(access_level)
return true unless resource.is_a?(Project)
return true if current_user.bot?
return true if current_user.can?(:manage_owners, resource)
current_user.authorized_project?(resource, access_level.to_i)
end
def do_not_allow_owner_access_level_for_project_bot?(access_level)
resource.is_a?(Project) &&
access_level.to_i == Gitlab::Access::OWNER &&

View File

@ -5,116 +5,119 @@
- reduce_visibility_form_id = 'reduce-visibility-form'
- @force_desktop_expanded_sidebar = true
= render Pajamas::AlertComponent.new(title: _('GitLab Pages has moved'),
- if can?(current_user, :admin_project, @project)
= render Pajamas::AlertComponent.new(title: _('GitLab Pages has moved'),
alert_options: { class: 'gl-my-5', data: { feature_id: Users::CalloutsHelper::PAGES_MOVED_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' } }) do |c|
- c.with_body do
= _('To go to GitLab Pages, on the left sidebar, select %{pages_link}.').html_safe % {pages_link: link_to('Deploy > Pages', project_pages_path(@project)).html_safe}
- c.with_body do
= _('To go to GitLab Pages, on the left sidebar, select %{pages_link}.').html_safe % {pages_link: link_to('Deploy > Pages', project_pages_path(@project)).html_safe}
%section.settings.general-settings.no-animate.expanded#js-general-settings
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Naming, topics, avatar')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= _('Collapse')
%p.gl-text-secondary= _('Update your project name, topics, description, and avatar.')
.settings-content= render 'projects/settings/general'
%section.settings.general-settings.no-animate.expanded#js-general-settings
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Naming, topics, avatar')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= _('Collapse')
%p.gl-text-secondary= _('Update your project name, topics, description, and avatar.')
.settings-content= render 'projects/settings/general'
%section.settings.sharing-permissions.no-animate#js-shared-permissions{ class: ('expanded' if expanded), data: { testid: 'visibility-features-permissions-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Visibility, project features, permissions')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary= _('Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default emoji reactions.')
%section.settings.sharing-permissions.no-animate#js-shared-permissions{ class: ('expanded' if expanded), data: { testid: 'visibility-features-permissions-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Visibility, project features, permissions')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary= _('Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default emoji reactions.')
.settings-content
= form_for @project, html: { multipart: true, class: "sharing-permissions-form", id: reduce_visibility_form_id }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-shared-permissions' }
%template.js-project-permissions-form-data{ type: "application/json" }= project_permissions_panel_data(@project).to_json.html_safe
.js-project-permissions-form{ data: visibility_confirm_modal_data(@project, reduce_visibility_form_id) }
- if show_merge_request_settings_callout?(@project)
%section.settings.expanded
= render Pajamas::AlertComponent.new(variant: :info,
.settings-content
= form_for @project, html: { multipart: true, class: "sharing-permissions-form", id: reduce_visibility_form_id }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-shared-permissions' }
%template.js-project-permissions-form-data{ type: "application/json" }= project_permissions_panel_data(@project).to_json.html_safe
.js-project-permissions-form{ data: visibility_confirm_modal_data(@project, reduce_visibility_form_id) }
- if show_merge_request_settings_callout?(@project)
%section.settings.expanded
= render Pajamas::AlertComponent.new(variant: :info,
title: _('Merge requests and approvals settings have moved.'),
alert_options: { class: 'js-merge-request-settings-callout gl-my-5', data: { feature_id: Users::CalloutsHelper::MERGE_REQUEST_SETTINGS_MOVED_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' } }) do |c|
- c.with_body do
= _('On the left sidebar, select %{merge_requests_link} to view them.').html_safe % { merge_requests_link: link_to('Settings > Merge requests', project_settings_merge_requests_path(@project)).html_safe }
- c.with_body do
= _('On the left sidebar, select %{merge_requests_link} to view them.').html_safe % { merge_requests_link: link_to('Settings > Merge requests', project_settings_merge_requests_path(@project)).html_safe }
%section.settings.no-animate{ class: ('expanded' if expanded), data: { testid: 'badges-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('ProjectSettings|Badges')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= s_('ProjectSettings|Customize this project\'s badges.')
= link_to s_('ProjectSettings|What are badges?'), help_page_path('user/project/badges')
.settings-content
= render 'shared/badges/badge_settings'
%section.settings.no-animate{ class: ('expanded' if expanded), data: { testid: 'badges-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('ProjectSettings|Badges')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= s_('ProjectSettings|Customize this project\'s badges.')
= link_to s_('ProjectSettings|What are badges?'), help_page_path('user/project/badges')
.settings-content
= render 'shared/badges/badge_settings'
= render_if_exists 'compliance_management/compliance_framework/project_settings', expanded: expanded
= render_if_exists 'compliance_management/compliance_framework/project_settings', expanded: expanded
= render_if_exists 'projects/settings/default_issue_template'
= render_if_exists 'projects/settings/default_issue_template'
= render 'projects/service_desk_settings'
= render 'projects/service_desk_settings'
%section.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded), data: { testid: 'advanced-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Advanced')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary= s_('ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete.')
%section.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded), data: { testid: 'advanced-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Advanced')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary= s_('ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete.')
.settings-content
= render_if_exists 'projects/settings/restore', project: @project
.settings-content
= render_if_exists 'projects/settings/restore', project: @project
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card gl-mt-0' }, header_options: { class: 'gl-new-card-header gl-flex-direction-column' }, body_options: { class: 'gl-new-card-body gl-px-5 gl-py-4' }) do |c|
- c.with_header do
.gl-new-card-title-wrapper
%h4.gl-new-card-title= _('Housekeeping')
%p.gl-new-card-description
= _('Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects.')
= link_to _('Learn more.'), help_page_path('administration/housekeeping'), target: '_blank', rel: 'noopener noreferrer'
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card gl-mt-0' }, header_options: { class: 'gl-new-card-header gl-flex-direction-column' }, body_options: { class: 'gl-new-card-body gl-px-5 gl-py-4' }) do |c|
- c.with_header do
.gl-new-card-title-wrapper
%h4.gl-new-card-title= _('Housekeeping')
%p.gl-new-card-description
= _('Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects.')
= link_to _('Learn more.'), help_page_path('administration/housekeeping'), target: '_blank', rel: 'noopener noreferrer'
- c.with_body do
.gl-display-flex.gl-flex-wrap.gl-gap-3
= render Pajamas::ButtonComponent.new(method: :post, href: housekeeping_project_path(@project)) do
= _('Run housekeeping')
#js-project-prune-unreachable-objects-button{ data: { prune_objects_path: housekeeping_project_path(@project, prune: true), prune_objects_doc_path: help_page_path('administration/housekeeping', anchor: 'prune-unreachable-objects') } }
- c.with_body do
.gl-display-flex.gl-flex-wrap.gl-gap-3
= render Pajamas::ButtonComponent.new(method: :post, href: housekeeping_project_path(@project)) do
= _('Run housekeeping')
#js-project-prune-unreachable-objects-button{ data: { prune_objects_path: housekeeping_project_path(@project, prune: true), prune_objects_doc_path: help_page_path('administration/housekeeping', anchor: 'prune-unreachable-objects') } }
= render 'export', project: @project
= render 'export', project: @project
= render_if_exists 'projects/settings/archive'
= render_if_exists 'projects/settings/archive'
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card rename-repository' }, header_options: { class: 'gl-new-card-header gl-flex-direction-column' }, body_options: { class: 'gl-new-card-body gl-px-5 gl-py-4' }) do |c|
- c.with_header do
.gl-new-card-title-wrapper
%h4.gl-new-card-title.warning-title= _('Change path')
%p.gl-new-card-description
- link = link_to('', help_page_path('user/project/settings/index', anchor: 'rename-a-repository'), target: '_blank', rel: 'noopener noreferrer')
= safe_format(_("A projects repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"), tag_pair(link, :link_start, :link_end))
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card rename-repository' }, header_options: { class: 'gl-new-card-header gl-flex-direction-column' }, body_options: { class: 'gl-new-card-body gl-px-5 gl-py-4' }) do |c|
- c.with_header do
.gl-new-card-title-wrapper
%h4.gl-new-card-title.warning-title= _('Change path')
%p.gl-new-card-description
- link = link_to('', help_page_path('user/project/settings/index', anchor: 'rename-a-repository'), target: '_blank', rel: 'noopener noreferrer')
= safe_format(_("A projects repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"), tag_pair(link, :link_start, :link_end))
- c.with_body do
= render 'projects/errors'
= gitlab_ui_form_for @project do |f|
.form-group
%p
%span.gl-font-weight-bold= _("Be careful. Renaming a project's repository can have unintended side effects.")
= _('You will need to update your local repositories to point to the new location.')
- if @project.deployment_platform.present?
%p= _('Your deployment services will be broken, you will need to manually fix the services after renaming.')
= f.label :path, _('Path'), class: 'label-bold'
- c.with_body do
= render 'projects/errors'
= gitlab_ui_form_for @project do |f|
.form-group
.input-group
.input-group-prepend
.input-group-text
#{Gitlab::Utils.append_path(root_url, @project.namespace.full_path)}/
= f.text_field :path, class: 'form-control gl-form-input-xl', data: { testid: 'project-path-field' }
= f.submit _('Change path'), class: "btn-danger", data: { testid: 'change-path-button' }, pajamas_button: true
%p
%span.gl-font-weight-bold= _("Be careful. Renaming a project's repository can have unintended side effects.")
= _('You will need to update your local repositories to point to the new location.')
- if @project.deployment_platform.present?
%p= _('Your deployment services will be broken, you will need to manually fix the services after renaming.')
= f.label :path, _('Path'), class: 'label-bold'
.form-group
.input-group
.input-group-prepend
.input-group-text
#{Gitlab::Utils.append_path(root_url, @project.namespace.full_path)}/
= f.text_field :path, class: 'form-control gl-form-input-xl', data: { testid: 'project-path-field' }
= f.submit _('Change path'), class: "btn-danger", data: { testid: 'change-path-button' }, pajamas_button: true
= render 'transfer', project: @project
= render 'transfer', project: @project
= render 'remove_fork', project: @project
= render 'remove_fork', project: @project
= render 'remove', project: @project
= render 'remove', project: @project
- elsif can?(current_user, :archive_project, @project)
= render_if_exists 'projects/settings/archive'
.save-project-loader.hide
.center

View File

@ -7,7 +7,7 @@
resource: @project,
token: @resource_access_token,
scopes: @scopes,
access_levels: ProjectMember.permissible_access_level_roles(current_user, @project),
access_levels: ProjectMember.permissible_access_level_roles_for_project_access_token(current_user, @project),
default_access_level: Gitlab::Access::GUEST,
prefix: :resource_access_token,
description_prefix: :project_access_token,

14
bin/gitlab-backup-cli Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
$:.unshift File.expand_path("../../lib", __FILE__)
# We require APP_PATH when the rails environment is required only,
# this allows for faster CLI execution when rails is not needed
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'gitlab/backup/cli'
Gitlab::Backup::Cli::Runner.start(ARGV)

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddArchiveProjectToMemberRoles < Gitlab::Database::Migration[2.1]
enable_lock_retries!
def change
add_column :member_roles, :archive_project, :boolean, default: false, null: false
end
end

View File

@ -0,0 +1 @@
db84d40c9afd9121aa24617167fa82b86cabc98bf274e61057eef02e1fafd7c3

View File

@ -18525,6 +18525,7 @@ CREATE TABLE member_roles (
admin_merge_request boolean DEFAULT false NOT NULL,
admin_group_member boolean DEFAULT false NOT NULL,
manage_project_access_tokens boolean DEFAULT false NOT NULL,
archive_project boolean DEFAULT false NOT NULL,
CONSTRAINT check_4364846f58 CHECK ((char_length(description) <= 255)),
CONSTRAINT check_9907916995 CHECK ((char_length(name) <= 255))
);

View File

@ -5134,6 +5134,7 @@ Input type: `MemberRoleCreateInput`
| <a id="mutationmemberrolecreateadmingroupmember"></a>`adminGroupMember` | [`Boolean`](#boolean) | Permission to admin group members. |
| <a id="mutationmemberrolecreateadminmergerequest"></a>`adminMergeRequest` | [`Boolean`](#boolean) | Permission to admin merge requests. |
| <a id="mutationmemberrolecreateadminvulnerability"></a>`adminVulnerability` | [`Boolean`](#boolean) | Permission to admin vulnerability. |
| <a id="mutationmemberrolecreatearchiveproject"></a>`archiveProject` | [`Boolean`](#boolean) | Permission to archive projects. |
| <a id="mutationmemberrolecreatebaseaccesslevel"></a>`baseAccessLevel` | [`MemberAccessLevel!`](#memberaccesslevel) | Base access level for the custom role. |
| <a id="mutationmemberrolecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationmemberrolecreatedescription"></a>`description` | [`String`](#string) | Description of the member role. |
@ -20322,6 +20323,7 @@ Represents a member role.
| <a id="memberroleadmingroupmember"></a>`adminGroupMember` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to admin group members. |
| <a id="memberroleadminmergerequest"></a>`adminMergeRequest` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to admin merge requests. |
| <a id="memberroleadminvulnerability"></a>`adminVulnerability` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to admin vulnerability. |
| <a id="memberrolearchiveproject"></a>`archiveProject` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.6. This feature is an Experiment. It can be changed or removed at any time. Permission to archive projects. |
| <a id="memberrolebaseaccesslevel"></a>`baseAccessLevel` **{warning-solid}** | [`AccessLevel!`](#accesslevel) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Base access level for the custom role. |
| <a id="memberroledescription"></a>`description` | [`String`](#string) | Description of the member role. |
| <a id="memberroleenabledpermissions"></a>`enabledPermissions` **{warning-solid}** | [`[MemberRolePermission!]`](#memberrolepermission) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Array of all permissions enabled for the custom role. |
@ -29406,6 +29408,7 @@ Member role permission.
| <a id="memberrolepermissionadmin_group_member"></a>`ADMIN_GROUP_MEMBER` | Allows admin access to group members. |
| <a id="memberrolepermissionadmin_merge_request"></a>`ADMIN_MERGE_REQUEST` | Allows admin access to the merge requests. |
| <a id="memberrolepermissionadmin_vulnerability"></a>`ADMIN_VULNERABILITY` | Allows admin access to the vulnerability reports. |
| <a id="memberrolepermissionarchive_project"></a>`ARCHIVE_PROJECT` | Allows to archive projects. |
| <a id="memberrolepermissionmanage_project_access_tokens"></a>`MANAGE_PROJECT_ACCESS_TOKENS` | Allows manage access to the project access tokens. |
| <a id="memberrolepermissionread_code"></a>`READ_CODE` | Allows read-only access to the source code. |
| <a id="memberrolepermissionread_dependency"></a>`READ_DEPENDENCY` | Allows read-only access to the dependencies. |

View File

@ -13,12 +13,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Read dependency added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126247) in GitLab 16.3.
> - [Name and description fields added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126423) in GitLab 16.3.
> - [Admin merge request introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128302) in GitLab 16.4 [with a flag](../administration/feature_flags.md) named `admin_merge_request`. Disabled by default.
> - [Feature flag `admin_merge_request` removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132578) in GitLab 16.5.
> - [Admin group members introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131914) in GitLab 16.5 [with a flag](../administration/feature_flags.md) named `admin_group_member`. Disabled by default. The feature flag has been removed in GitLab 16.6.
> - [Manage project access tokens introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132342) in GitLab 16.5 in [with a flag](../administration/feature_flags.md) named `manage_project_access_tokens`. Disabled by default.
> - [Archive project introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134998) in GitLab 16.6 in [with a flag](../administration/feature_flags.md) named `archive_project`. Disabled by default.
FLAG:
On self-managed GitLab, by default these two features are not available. To make them available, an administrator can [enable the feature flags](../administration/feature_flags.md) named `admin_merge_request` and `admin_member_custom_role`.
On GitLab.com, this feature is not available.
On self-managed GitLab, by default these features are not available. To make them available, an administrator can [enable the feature flags](../administration/feature_flags.md) named `admin_group_member`, `manage_project_access_tokens` and `archive_project`.
On GitLab.com, these features are not available.
## List all member roles of a group
@ -48,6 +50,7 @@ If successful, returns [`200`](rest/index.md#status-codes) and the following res
| `[].read_vulnerability` | boolean | Permission to read project vulnerabilities. |
| `[].admin_group_member` | boolean | Permission to admin members of a group. |
| `[].manage_project_access_tokens` | boolean | Permission to manage project access tokens. |
| `[].archive_project` | boolean | Permission to archive projects. |
Example request:
@ -70,7 +73,8 @@ Example response:
"read_code": true,
"read_dependency": false,
"read_vulnerability": false,
"manage_project_access_tokens": false
"manage_project_access_tokens": false,
"archive_project": false
},
{
"id": 3,
@ -83,7 +87,8 @@ Example response:
"read_code": false,
"read_dependency": true,
"read_vulnerability": true,
"manage_project_access_tokens": false
"manage_project_access_tokens": false,
"archive_project": false
}
]
```

View File

@ -15,6 +15,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - Ability to create and remove a custom role with the UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/393235) in GitLab 16.4.
> - Ability to manage group members [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17364) in GitLab 16.5.
> - Ability to manage project access tokens [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/421778) in GitLab 16.5 [with a flag](../administration/feature_flags.md) named `manage_project_access_tokens`.
> - Ability to archive projects [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/425957) in GitLab 16.6 in [with a flag](../administration/feature_flags.md) named `archive_project`. Disabled by default.
Custom roles allow group Owners or instance administrators to create roles
specific to the needs of their organization.
@ -97,6 +98,7 @@ These requirements are documented in the `Required permission` column in the fol
| `admin_merge_request` | GitLab 16.4 and later | Not applicable | View and approve [merge requests](project/merge_requests/index.md), and view the associated merge request code. <br> Does not allow users to view or change merge request approval rules. |
| `manage_project_access_tokens` | GitLab 16.5 and later | Not applicable | Create, delete, and list [project access tokens](project/settings/project_access_tokens.md). |
| `admin_group_member` | GitLab 16.5 and later | Not applicable | Add or remove [group members](group/manage.md). |
| `archive_project` | GitLab 16.6 and later | Not applicable | Archive and unarchive [projects](project/settings/index.md#archive-a-project). |
## Billing and seat usage

11
gems/gitlab-backup-cli/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
/.bundle/
/.yardoc
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
# rspec failure tracking
.rspec_status

View File

@ -0,0 +1,4 @@
include:
- local: gems/gem.gitlab-ci.yml
inputs:
gem_name: "gitlab-backup-cli"

View File

@ -0,0 +1,3 @@
--format documentation
--color
--require spec_helper

View File

@ -0,0 +1,19 @@
---
inherit_gem:
gitlab-styles:
- rubocop-bundler.yml
- rubocop-fips.yml
- rubocop-gemspec.yml
- rubocop-layout.yml
- rubocop-lint.yml
- rubocop-metrics.yml
- rubocop-naming.yml
- rubocop-performance.yml
- rubocop-rspec.yml
- rubocop-security.yml
- rubocop-style.yml
AllCops:
TargetRubyVersion: 3.0
SuggestExtensions: false
NewCops: disable

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
source "https://rubygems.org"
# Specify your gem's dependencies in gitlab-backup-cli.gemspec
gemspec

View File

@ -0,0 +1,114 @@
PATH
remote: .
specs:
gitlab-backup-cli (0.0.1)
thor (~> 1.3)
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.1)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
ast (2.4.2)
base64 (0.2.0)
bigdecimal (3.1.4)
concurrent-ruby (1.2.2)
connection_pool (2.4.1)
diff-lcs (1.5.0)
drb (2.2.0)
ruby2_keywords
gitlab-styles (11.0.0)
rubocop (~> 1.57.1)
rubocop-graphql (~> 0.18)
rubocop-performance (~> 1.15)
rubocop-rails (~> 2.17)
rubocop-rspec (~> 2.22)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
json (2.6.3)
language_server-protocol (3.17.0.3)
minitest (5.20.0)
mutex_m (0.2.0)
parallel (1.23.0)
parser (3.2.2.4)
ast (~> 2.4.1)
racc
racc (1.7.3)
rack (3.0.8)
rainbow (3.1.1)
rake (13.1.0)
regexp_parser (2.8.2)
rexml (3.2.6)
rspec (3.12.0)
rspec-core (~> 3.12.0)
rspec-expectations (~> 3.12.0)
rspec-mocks (~> 3.12.0)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-mocks (3.12.6)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-support (3.12.1)
rubocop (1.57.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.4)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-capybara (2.19.0)
rubocop (~> 1.41)
rubocop-factory_bot (2.24.0)
rubocop (~> 1.33)
rubocop-graphql (0.19.0)
rubocop (>= 0.87, < 2)
rubocop-performance (1.19.1)
rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.20.0)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-rspec (2.25.0)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
thor (1.3.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
PLATFORMS
arm64-darwin-21
arm64-darwin-22
ruby
x86_64-linux
DEPENDENCIES
gitlab-backup-cli!
gitlab-styles (~> 11.0)
rake (~> 13.0)
rspec (~> 3.0)
rubocop-rails (<= 2.20)
BUNDLED WITH
2.4.21

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2023-present GitLab B.V.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,7 @@
# Gitlab::Backup::Cli
This gem will contain the Backup CLI logic.
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
require "bundler/gem_tasks"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
require "rubocop/rake_task"
RuboCop::RakeTask.new
task default: %i[spec rubocop]

View File

@ -0,0 +1,11 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require "bundler/setup"
require "gitlab/backup/cli"
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
require "irb"
IRB.start(__FILE__)

View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx
bundle install
# Do any other automated setup that you need to do here

View File

@ -0,0 +1,43 @@
# frozen_string_literal: true
require_relative "lib/gitlab/backup/cli/version"
Gem::Specification.new do |spec|
spec.name = "gitlab-backup-cli"
spec.version = Gitlab::Backup::Cli::VERSION
spec.authors = ["Gabriel Mazetto"]
spec.email = ["brodock@gmail.com"]
spec.summary = "GitLab Backup CLI"
spec.description = "GitLab Backup CLI"
spec.homepage = "https://gitlab.com/gitlab-org/gitlab/-/tree/master/gems/gitlab-backup-cli"
spec.license = "MIT"
spec.required_ruby_version = ">= 3.0"
spec.metadata["rubygems_mfa_required"] = "true"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
spec.files = Dir['lib/**/*.rb']
spec.test_files = Dir['spec/**/*']
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(__dir__) do
`git ls-files -z`.split("\x0").reject do |f|
(File.expand_path(f) == __FILE__) ||
f.start_with?(*%w[bin/ test/ spec/ features/ .git .gitlab-ci .rspec .rubocop.yml Gemfile])
end
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_dependency "thor", "~> 1.3"
spec.add_development_dependency "gitlab-styles", "~> 11.0"
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency "rubocop-rails", "<= 2.20" # https://github.com/rubocop/rubocop-rails/issues/1173
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
module Gitlab
module Backup
# GitLab Backup CLI
module Cli
autoload :VERSION, 'gitlab/backup/cli/version'
autoload :Runner, 'gitlab/backup/cli/runner'
class Error < StandardError; end
# Your code goes here...
end
end
end

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
require 'thor'
module Gitlab
module Backup
module Cli
# GitLab Backup CLI
#
# This supersedes the previous backup rake files and will be
# the default interface to handle backups
class Runner < Thor
def self.exit_on_failure?
true
end
map %w[--version -v] => :version
desc 'version', 'Display the version information'
def version
puts "GitLab Backup CLI (#{VERSION})"
end
private
def rails_environment!
require APP_PATH
Rails.application.load_tasks
end
end
end
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
module Gitlab
module Backup
module Cli
VERSION = "0.0.1"
end
end
end

View File

@ -0,0 +1,7 @@
module Gitlab
module Backup
module Cli
VERSION: String
end
end
end

View File

@ -0,0 +1,15 @@
module Gitlab
module Backup
module Cli
class Runner
def self.exit_on_failure?: -> bool
def version: -> void
private
def rails_environment!: -> void
end
end
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
RSpec.describe Gitlab::Backup::Cli do
it "has a version number" do
expect(Gitlab::Backup::Cli::VERSION).not_to be nil
end
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
require "gitlab/backup/cli"
RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
config.example_status_persistence_file_path = ".rspec_status"
# Disable RSpec exposing methods globally on `Module` and `main`
config.disable_monkey_patching!
config.expect_with :rspec do |c|
c.syntax = :expect
end
end

View File

@ -57,10 +57,6 @@ module Sidebars
monitor_menu_item,
usage_quotas_menu_item
]
elsif context.current_user && can?(context.current_user, :manage_resource_access_tokens, context.project)
[
access_tokens_menu_item
]
else
[]
end

View File

@ -59,18 +59,6 @@ RSpec.describe Sidebars::Projects::Menus::SettingsMenu, feature_category: :navig
let(:item_id) { :access_tokens }
it_behaves_like 'access rights checks'
describe 'when the user is not an admin but has manage_resource_access_tokens' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :admin_project, project).and_return(false)
allow(Ability).to receive(:allowed?).with(user, :manage_resource_access_tokens, project).and_return(true)
end
it 'includes access token menu item' do
expect(subject.title).to eql('Access Tokens')
end
end
end
describe 'Repository' do

View File

@ -51,6 +51,50 @@ RSpec.describe ProjectMember, feature_category: :groups_and_projects do
end
end
describe '.permissible_access_level_roles_for_project_access_token' do
let_it_be(:owner) { create(:user) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
before do
project.add_owner(owner)
project.add_maintainer(maintainer)
project.add_developer(developer)
end
subject(:access_levels) { described_class.permissible_access_level_roles_for_project_access_token(user, project) }
context 'when member can manage owners' do
let(:user) { owner }
it 'returns Gitlab::Access.options_with_owner' do
expect(access_levels).to eq(Gitlab::Access.options_with_owner)
end
end
context 'when member cannot manage owners' do
let(:user) { maintainer }
it 'returns Gitlab::Access.options' do
expect(access_levels).to eq(Gitlab::Access.options)
end
end
context 'when the user is a developer' do
let(:user) { developer }
it 'returns Gitlab::Access.options' do
expect(access_levels).to eq({
"Guest" => 10,
"Reporter" => 20,
"Developer" => 30
})
end
end
end
describe '#real_source_type' do
subject { create(:project_member).real_source_type }