diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index 54e523dbfb2..6375841e697 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -1040,6 +1040,7 @@ RSpec/ContextWording:
- 'spec/features/admin/admin_mode_spec.rb'
- 'spec/features/admin/admin_settings_spec.rb'
- 'spec/features/admin/dashboard_spec.rb'
+ - 'spec/features/admin/users/user_impersonation_spec.rb'
- 'spec/features/admin/users/user_spec.rb'
- 'spec/features/admin/users/users_spec.rb'
- 'spec/features/atom/dashboard_issues_spec.rb'
diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml
index eee81261597..885fd554ad6 100644
--- a/.rubocop_todo/rspec/named_subject.yml
+++ b/.rubocop_todo/rspec/named_subject.yml
@@ -1414,6 +1414,7 @@ RSpec/NamedSubject:
- 'spec/controllers/users/callouts_controller_spec.rb'
- 'spec/experiments/application_experiment_spec.rb'
- 'spec/experiments/in_product_guidance_environments_webide_experiment_spec.rb'
+ - 'spec/features/admin/users/user_impersonation_spec.rb'
- 'spec/features/admin/users/user_spec.rb'
- 'spec/features/groups/clusters/user_spec.rb'
- 'spec/features/merge_request/user_sees_merge_widget_spec.rb'
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/index.js b/app/assets/javascripts/pages/projects/shared/permissions/index.js
index 4b4589dc46c..78dd456aad9 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/index.js
+++ b/app/assets/javascripts/pages/projects/shared/permissions/index.js
@@ -14,6 +14,9 @@ export default function initProjectPermissionsSettings() {
const mountPoint = document.querySelector('.js-project-permissions-form');
const componentPropsEl = document.querySelector('.js-project-permissions-form-data');
+
+ if (!mountPoint) return null;
+
const componentProps = JSON.parse(componentPropsEl.innerHTML);
const {
diff --git a/app/assets/javascripts/pages/shared/mount_badge_settings.js b/app/assets/javascripts/pages/shared/mount_badge_settings.js
index aeb9f2fb8d3..9c92d4f8f1e 100644
--- a/app/assets/javascripts/pages/shared/mount_badge_settings.js
+++ b/app/assets/javascripts/pages/shared/mount_badge_settings.js
@@ -5,6 +5,8 @@ import store from '~/badges/store';
export default (kind) => {
const badgeSettingsElement = document.getElementById('badge-settings');
+ if (!badgeSettingsElement) return null;
+
store.dispatch('loadBadges', {
kind,
apiEndpointUrl: badgeSettingsElement.dataset.apiEndpointUrl,
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 1152bdcf058..b997b2e0b6b 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -29,7 +29,7 @@ class ProjectsController < Projects::ApplicationController
before_action :authorize_read_code!, only: [:refs]
# Authorize
- before_action :authorize_admin_project_or_custom_permissions!, only: :edit
+ before_action :authorize_view_edit_page!, 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]
@@ -612,11 +612,6 @@ 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')
diff --git a/app/models/namespace_setting.rb b/app/models/namespace_setting.rb
index 0263942116d..ef2f4dc05d9 100644
--- a/app/models/namespace_setting.rb
+++ b/app/models/namespace_setting.rb
@@ -7,6 +7,7 @@ class NamespaceSetting < ApplicationRecord
cascading_attr :delayed_project_removal
cascading_attr :toggle_security_policy_custom_ci
+ cascading_attr :toggle_security_policies_policy_scope
belongs_to :namespace, inverse_of: :namespace_settings
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 255538c538a..a26758974d6 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -914,6 +914,7 @@ class ProjectPolicy < BasePolicy
rule { can?(:admin_project) }.policy do
enable :read_usage_quotas
+ enable :view_edit_page
end
rule { can?(:project_bot_access) }.policy do
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index 4334c4996f2..375e5afea62 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -49,6 +49,7 @@
= render_if_exists 'groups/personal_access_token_expiration_policy', f: f, group: @group
= render 'groups/settings/membership', f: f, group: @group
= render_if_exists 'groups/settings/security_policies_custom_ci', f: f, group: @group
+ = render_if_exists 'groups/settings/security_policies_policy_scope', f: f, group: @group
%h5= _('Customer relations')
.form-group.gl-mb-3
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 9269369c83e..90837a1a291 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -118,8 +118,11 @@
= render 'remove_fork', project: @project
= render 'remove', project: @project
-- elsif can?(current_user, :archive_project, @project)
- = render_if_exists 'projects/settings/archive'
+- else
+ - if can?(current_user, :archive_project, @project)
+ = render_if_exists 'projects/settings/archive'
+ - if can?(current_user, :remove_project, @project)
+ = render 'remove', project: @project
.save-project-loader.hide
.center
diff --git a/db/migrate/20231213170159_add_remove_project_to_member_roles.rb b/db/migrate/20231213170159_add_remove_project_to_member_roles.rb
new file mode 100644
index 00000000000..d13777c1df1
--- /dev/null
+++ b/db/migrate/20231213170159_add_remove_project_to_member_roles.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddRemoveProjectToMemberRoles < Gitlab::Database::Migration[2.2]
+ milestone '16.8'
+ enable_lock_retries!
+
+ def change
+ add_column :member_roles, :remove_project, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20231215101640_add_cascading_toggle_security_policies_policy_scope_setting.rb b/db/migrate/20231215101640_add_cascading_toggle_security_policies_policy_scope_setting.rb
new file mode 100644
index 00000000000..9ef0c70173b
--- /dev/null
+++ b/db/migrate/20231215101640_add_cascading_toggle_security_policies_policy_scope_setting.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddCascadingToggleSecurityPoliciesPolicyScopeSetting < Gitlab::Database::Migration[2.2]
+ milestone '16.7'
+
+ include Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings
+
+ enable_lock_retries!
+
+ def up
+ add_cascading_namespace_setting :toggle_security_policies_policy_scope, :boolean, default: false, null: false
+ end
+
+ def down
+ remove_cascading_namespace_setting :toggle_security_policies_policy_scope
+ end
+end
diff --git a/db/schema_migrations/20231213170159 b/db/schema_migrations/20231213170159
new file mode 100644
index 00000000000..ff5e6e29a3c
--- /dev/null
+++ b/db/schema_migrations/20231213170159
@@ -0,0 +1 @@
+f73fde4e3e54fa88d8dba9ec3a98b7dfb8332aaf7a76de73baf899292ed751b1
\ No newline at end of file
diff --git a/db/schema_migrations/20231215101640 b/db/schema_migrations/20231215101640
new file mode 100644
index 00000000000..13c883c9e3d
--- /dev/null
+++ b/db/schema_migrations/20231215101640
@@ -0,0 +1 @@
+7bdc5d7aa9f9228aac355e51b1461b7d07083e8e5481ccf3e59c5ec48c9230ab
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index db86925ed8e..af8a2cde1a2 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -12284,6 +12284,8 @@ CREATE TABLE application_settings (
encrypted_arkose_labs_data_exchange_key_iv bytea,
toggle_security_policy_custom_ci boolean DEFAULT false NOT NULL,
lock_toggle_security_policy_custom_ci boolean DEFAULT false NOT NULL,
+ toggle_security_policies_policy_scope boolean DEFAULT false NOT NULL,
+ lock_toggle_security_policies_policy_scope boolean DEFAULT false NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
@@ -18640,6 +18642,7 @@ CREATE TABLE member_roles (
admin_group_member boolean DEFAULT false NOT NULL,
manage_project_access_tokens boolean DEFAULT false NOT NULL,
archive_project boolean DEFAULT false NOT NULL,
+ remove_project boolean DEFAULT false NOT NULL,
CONSTRAINT check_4364846f58 CHECK ((char_length(description) <= 255)),
CONSTRAINT check_9907916995 CHECK ((char_length(name) <= 255))
);
@@ -19592,6 +19595,8 @@ CREATE TABLE namespace_settings (
enforce_ssh_certificates boolean DEFAULT false NOT NULL,
toggle_security_policy_custom_ci boolean,
lock_toggle_security_policy_custom_ci boolean DEFAULT false NOT NULL,
+ toggle_security_policies_policy_scope boolean,
+ lock_toggle_security_policies_policy_scope boolean DEFAULT false NOT NULL,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT namespace_settings_unique_project_download_limit_alertlist_size CHECK ((cardinality(unique_project_download_limit_alertlist) <= 100)),
CONSTRAINT namespace_settings_unique_project_download_limit_allowlist_size CHECK ((cardinality(unique_project_download_limit_allowlist) <= 100))
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 7f5b6cf52c9..a9df0da4596 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -5362,6 +5362,7 @@ Input type: `MemberRoleCreateInput`
| `readCode` | [`Boolean`](#boolean) | Permission to read code. |
| `readDependency` | [`Boolean`](#boolean) | Permission to read dependency. |
| `readVulnerability` | [`Boolean`](#boolean) | Permission to read vulnerability. |
+| `removeProject` | [`Boolean`](#boolean) | Permission to delete projects. |
#### Fields
@@ -21408,6 +21409,7 @@ Represents a member role.
| `readCode` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to read code. |
| `readDependency` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to read dependency. |
| `readVulnerability` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to read vulnerability. |
+| `removeProject` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.8. This feature is an Experiment. It can be changed or removed at any time. Permission to delete projects. |
### `MergeAccessLevel`
@@ -30753,6 +30755,7 @@ Member role permission.
| `READ_CODE` | Allows read-only access to the source code. |
| `READ_DEPENDENCY` | Allows read-only access to the dependencies. |
| `READ_VULNERABILITY` | Allows read-only access to the vulnerability reports. |
+| `REMOVE_PROJECT` | Allows deletion of projects. |
### `MemberSort`
diff --git a/doc/api/member_roles.md b/doc/api/member_roles.md
index 24ac7099004..a482195b94e 100644
--- a/doc/api/member_roles.md
+++ b/doc/api/member_roles.md
@@ -17,6 +17,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [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.7.
+> - [Delete project introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139696) in GitLab 16.8.
FLAG:
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` and `manage_project_access_tokens`.
@@ -51,6 +52,7 @@ If successful, returns [`200`](rest/index.md#status-codes) and the following res
| `[].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. |
+| `[].remove_project` | boolean | Permission to delete projects. |
Example request:
@@ -74,7 +76,8 @@ Example response:
"read_dependency": false,
"read_vulnerability": false,
"manage_project_access_tokens": false,
- "archive_project": false
+ "archive_project": false,
+ "remove_project": false
},
{
"id": 3,
@@ -88,7 +91,8 @@ Example response:
"read_dependency": true,
"read_vulnerability": true,
"manage_project_access_tokens": false,
- "archive_project": false
+ "archive_project": false,
+ "remove_project": false
}
]
```
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index 62df2395fbb..8a38b0ed0e4 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -492,6 +492,7 @@ command line.
To configure markdownlint in your editor, install one of the following as appropriate:
+- Visual Studio Code [`DavidAnson.vscode-markdownlint` extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint).
- Sublime Text [`SublimeLinter-contrib-markdownlint` package](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint).
This package uses `markdownlint-cli` by default, but can be configured to use `markdownlint-cli2` with this
SublimeLinter configuration:
@@ -502,11 +503,20 @@ To configure markdownlint in your editor, install one of the following as approp
}
```
-- Visual Studio Code [`DavidAnson.vscode-markdownlint` extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint).
- Vim [ALE plugin](https://github.com/dense-analysis/ale).
+- Emacs [Flycheck extension](https://github.com/flycheck/flycheck). `Flycheck` supports
+ `markdownlint-cli` out of the box, but you must add a `.dir-locals.el` file to
+ point it to the `.markdownlint.yml` at the base of the project directory:
+
+ ```lisp
+ ;; Place this code in a file called `.dir-locals.el` at the root of the gitlab project.
+ ((markdown-mode . ((flycheck-markdown-markdownlint-cli-config . ".markdownlint.yml"))))
+ ```
To configure Vale in your editor, install one of the following as appropriate:
+- Visual Studio Code [`ChrisChinchilla.vale-vscode` extension](https://marketplace.visualstudio.com/items?itemName=ChrisChinchilla.vale-vscode).
+ You can configure the plugin to [display only a subset of alerts](#show-subset-of-vale-alerts).
- Sublime Text [`SublimeLinter-vale` package](https://packagecontrol.io/packages/SublimeLinter-vale). To have Vale
suggestions appears as blue instead of red (which is how errors appear), add `vale` configuration to your
[SublimeLinter](http://sublimelinter.readthedocs.org) configuration:
@@ -522,26 +532,12 @@ To configure Vale in your editor, install one of the following as appropriate:
```
- [LSP for Sublime Text](https://lsp.sublimetext.io) package [`LSP-vale-ls`](https://packagecontrol.io/packages/LSP-vale-ls).
-- Visual Studio Code [`ChrisChinchilla.vale-vscode` extension](https://marketplace.visualstudio.com/items?itemName=ChrisChinchilla.vale-vscode).
- You can configure the plugin to [display only a subset of alerts](#show-subset-of-vale-alerts).
- Vim [ALE plugin](https://github.com/dense-analysis/ale).
- JetBrains IDEs - No plugin exists, but
[this issue comment](https://github.com/errata-ai/vale-server/issues/39#issuecomment-751714451)
contains tips for configuring an external tool.
-- Emacs [Flycheck extension](https://github.com/flycheck/flycheck).
- This requires some configuration:
-
- - `Flycheck` supports `markdownlint-cli` out of the box, but you must point it
- to the `.markdownlint.yml` at the base of the project directory. A `.dir-locals.el`
- file can accomplish this:
-
- ```lisp
- ;; Place this code in a file called `.dir-locals.el` at the root of the gitlab project.
- ((markdown-mode . ((flycheck-markdown-markdownlint-cli-config . ".markdownlint.yml"))))
-
- ```
-
- - A minimal configuration for Flycheck to work with Vale could look like this:
+- Emacs [Flycheck extension](https://github.com/flycheck/flycheck). A minimal configuration
+ for Flycheck to work with Vale could look like:
```lisp
(flycheck-define-checker vale
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index 0b89f5b3412..910ba7bece7 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -272,10 +272,10 @@ Changing the linked namespace is not supported for all subscription types.
You cannot transfer:
-- A subscription with compute minutes.
- An expired or trial subscription.
-- A subscription to a namespace which already has a Premium or Ultimate plan.
-- A subscription from a namespace with multiple subscriptions.
+- A subscription with compute minutes which is already linked to a namespace.
+- A subscription with a Premium or Ultimate plan to a namespace which already has a Premium or Ultimate plan.
+- A subscription with code suggestions to a namespace which already has a subscriptions with code suggestions.
## Upgrade your GitLab SaaS subscription tier
diff --git a/doc/user/custom_roles.md b/doc/user/custom_roles.md
index 1f3628efa39..ac04e7cca0f 100644
--- a/doc/user/custom_roles.md
+++ b/doc/user/custom_roles.md
@@ -17,6 +17,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - 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.7.
> - Ability to use the UI to add a user to your group with a custom role, change a user's custom role, or remove a custom role from a group member [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/393239) in GitLab 16.7.
+> - Ability to delete projects [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/425959) in GitLab 16.8.
Custom roles allow group Owners or instance administrators to create roles
specific to the needs of their organization.
@@ -114,7 +115,8 @@ 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), revoke merge request approval, and view the associated merge request code.
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/migrate_projects.md#archive-a-project). |
+| `archive_project` | GitLab 16.7 and later | Not applicable | [Archive and unarchive projects](project/settings/migrate_projects.md#archive-a-project). |
+| `remove_project` | GitLab 16.8 and later | Not applicable | [Delete projects](project/working_with_projects.md#delete-a-project). |
## Billing and seat usage
diff --git a/lib/gitlab/database/partitioning_migration_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers.rb
index 3196dd20356..daafda8e7be 100644
--- a/lib/gitlab/database/partitioning_migration_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers.rb
@@ -6,6 +6,7 @@ module Gitlab
include ForeignKeyHelpers
include TableManagementHelpers
include IndexHelpers
+ include UniquenessHelpers
end
end
end
diff --git a/lib/gitlab/database/partitioning_migration_helpers/uniqueness_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/uniqueness_helpers.rb
new file mode 100644
index 00000000000..1c33371057e
--- /dev/null
+++ b/lib/gitlab/database/partitioning_migration_helpers/uniqueness_helpers.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module PartitioningMigrationHelpers
+ module UniquenessHelpers
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::Database::SchemaHelpers
+
+ def ensure_unique_id(table_name)
+ function_name = "assign_#{table_name}_id_value"
+ trigger_name = "assign_#{table_name}_id_trigger"
+
+ return if trigger_exists?(table_name, trigger_name)
+
+ change_column_default(table_name, :id, nil)
+
+ create_trigger_function(function_name) do
+ <<~SQL
+ IF NEW."id" IS NOT NULL THEN
+ RAISE WARNING 'Manually assigning ids is not allowed, the value will be ignored';
+ END IF;
+ NEW."id" := nextval('#{existing_sequence(table_name)}'::regclass);
+ RETURN NEW;
+ SQL
+ end
+
+ create_trigger(table_name, trigger_name, function_name, fires: 'BEFORE INSERT')
+ end
+
+ private
+
+ def existing_sequence(table_name)
+ Gitlab::Database::PostgresSequence.by_table_name(table_name).first
+ end
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 201c3866f22..dd0c692cadb 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -23543,6 +23543,9 @@ msgstr ""
msgid "GroupSettings|Security policy custom CI Experiment"
msgstr ""
+msgid "GroupSettings|Security policy scope Experiment"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as a source of custom templates for new projects in this group. %{link_start}Learn more%{link_end}."
msgstr ""
@@ -41613,6 +41616,9 @@ msgstr ""
msgid "Runners|Existing runners are not affected. To permit runner registration for all projects, enable this setting in the Admin Area in Settings > CI/CD."
msgstr ""
+msgid "Runners|Export as CSV"
+msgstr ""
+
msgid "Runners|Failed adding runner to project"
msgstr ""
@@ -41887,6 +41893,9 @@ msgstr ""
msgid "Runners|Runner Registration token"
msgstr ""
+msgid "Runners|Runner Usage"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -42245,9 +42254,24 @@ msgstr ""
msgid "Runners|shared"
msgstr ""
+msgid "Runner|Export runner usage"
+msgstr ""
+
+msgid "Runner|Export runner usage for previous month"
+msgstr ""
+
msgid "Runner|Runner actions"
msgstr ""
+msgid "Runner|Something went wrong while generating the CSV export. Please try again."
+msgstr ""
+
+msgid "Runner|The CSV export contains a list of projects, the number of minutes used by instance runners, and the number of jobs that ran in the previous month. When the export is completed, it is sent as an attachment to your email."
+msgstr ""
+
+msgid "Runner|Your CSV export has started. It will be sent to your email inbox when its ready."
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -45352,9 +45376,15 @@ msgstr ""
msgid "Settings|Enable this feature allows you to add customized CI YAML file to run as part of the policies action. This features is your acceptance of the %{link_start}GitLab Testing Agreement%{link_end}."
msgstr ""
+msgid "Settings|Enabling this feature allows you to scope scan result policies and scan execution policies, which determines which projects specifically will be enforced by a given policy. This features is your acceptance of the %{link_start}GitLab Testing Agreement%{link_end}."
+msgstr ""
+
msgid "Settings|Run customized CI YAML file as security policy actions"
msgstr ""
+msgid "Settings|Security Policy Scopes"
+msgstr ""
+
msgid "Settings|Unable to load the merge request options settings. Try reloading the page."
msgstr ""
diff --git a/package.json b/package.json
index 839933a6690..edaa36c3ba8 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,7 @@
"@gitlab/cluster-client": "^2.1.0",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
- "@gitlab/svgs": "3.72.0",
+ "@gitlab/svgs": "3.74.0",
"@gitlab/ui": "^72.0.0",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "^0.0.1-dev-20231211152737",
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
index 208190622d9..d874817d541 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
@@ -9,7 +9,7 @@ module QA
Flow::Login.sign_in
end
- it 'can be reverted', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347709' do
+ it 'can be reverted', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347709' do
revertible_merge_request.visit!
Page::MergeRequest::Show.perform do |merge_request|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_to_canary_gitaly_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_to_canary_gitaly_spec.rb
index b20b1f8cd92..572bd3df838 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_to_canary_gitaly_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_to_canary_gitaly_spec.rb
@@ -6,7 +6,7 @@ module QA
it 'pushes to a project using a canary specific Gitaly repository storage', :smoke, :requires_admin, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/351116' do
Flow::Login.sign_in_as_admin
- project = create(:project, name: 'canary-specific-repository-storage', repository_storage: 'nfs-file-cny01') # TODO: move to ENV var
+ project = create(:project, name: 'canary-specific-repository-storage', repository_storage: 'gitaly-cny-01-stor-gstg.c.gitlab-staging-1.internal') # TODO: move to ENV var
Resource::Repository::Push.fabricate! do |push|
push.repository_http_uri = project.repository_http_location.uri
diff --git a/scripts/review_apps/automated_cleanup.rb b/scripts/review_apps/automated_cleanup.rb
index 154a73462bb..1e4fbf85f9b 100755
--- a/scripts/review_apps/automated_cleanup.rb
+++ b/scripts/review_apps/automated_cleanup.rb
@@ -308,7 +308,7 @@ if $PROGRAM_NAME == __FILE__
puts
timed('Review Apps cleanup') do
- automated_cleanup.perform_gitlab_environment_cleanup!(days_for_delete: 3)
+ automated_cleanup.perform_gitlab_environment_cleanup!(days_for_delete: 7)
end
puts
diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb
index 5e98d2ffcf3..9c425f83508 100644
--- a/spec/features/admin/admin_abuse_reports_spec.rb
+++ b/spec/features/admin/admin_abuse_reports_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :insider_threat do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_abuse_reports_path
end
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index 2a9bff55dce..ec63e43d183 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
it 'create new appearance' do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_application_settings_appearances_path
fill_in 'appearance_title', with: 'MyCompany'
@@ -39,7 +39,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
it 'preview sign-in page appearance' do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_application_settings_appearances_path
click_link "Sign-in page"
@@ -53,7 +53,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
it 'preview new project page appearance', :js do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_application_settings_appearances_path
click_link "New project page"
@@ -64,7 +64,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
context 'Custom system header and footer' do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'when system header and footer messages are empty' do
@@ -102,7 +102,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
it 'custom new project page', :js do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit new_project_path
click_link 'Create blank project'
@@ -112,7 +112,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
context 'Profile page with custom profile image guidelines' do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_application_settings_appearances_path
fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines, please :smile:!'
click_button 'Update appearance settings'
@@ -128,7 +128,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
it 'appearance logo' do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_application_settings_appearances_path
attach_file(:appearance_logo, logo_fixture)
@@ -141,7 +141,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
it 'appearance pwa icon' do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_application_settings_appearances_path
attach_file(:appearance_pwa_icon, logo_fixture)
@@ -154,7 +154,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
it 'header logos' do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_application_settings_appearances_path
attach_file(:appearance_header_logo, logo_fixture)
@@ -167,7 +167,7 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
it 'Favicon' do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_application_settings_appearances_path
attach_file(:appearance_favicon, logo_fixture)
diff --git a/spec/features/admin/admin_browse_spam_logs_spec.rb b/spec/features/admin/admin_browse_spam_logs_spec.rb
index f781e2adf07..1f89232759c 100644
--- a/spec/features/admin/admin_browse_spam_logs_spec.rb
+++ b/spec/features/admin/admin_browse_spam_logs_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Admin browse spam logs', feature_category: :shared do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'browse spam logs' do
diff --git a/spec/features/admin/admin_deploy_keys_spec.rb b/spec/features/admin/admin_deploy_keys_spec.rb
index f9510ef296a..d6d021aeafc 100644
--- a/spec/features/admin/admin_deploy_keys_spec.rb
+++ b/spec/features/admin/admin_deploy_keys_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'admin deploy keys', :js, feature_category: :system_access do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'show all public deploy keys' do
diff --git a/spec/features/admin/admin_dev_ops_reports_spec.rb b/spec/features/admin/admin_dev_ops_reports_spec.rb
index 99d43e6b0da..e820ae866a1 100644
--- a/spec/features/admin/admin_dev_ops_reports_spec.rb
+++ b/spec/features/admin/admin_dev_ops_reports_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'DevOps Report page', :js, feature_category: :devops_reports do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'without licensed feature devops adoption' do
diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
index 76620b93557..039968025a9 100644
--- a/spec/features/admin/admin_disables_git_access_protocol_spec.rb
+++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Admin disables Git access protocol', :js, feature_category: :sou
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'with HTTP disabled' do
diff --git a/spec/features/admin/admin_disables_two_factor_spec.rb b/spec/features/admin/admin_disables_two_factor_spec.rb
index eed20d449cd..cb3c8973872 100644
--- a/spec/features/admin/admin_disables_two_factor_spec.rb
+++ b/spec/features/admin/admin_disables_two_factor_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Admin disables 2FA for a user', feature_category: :system_access
it 'successfully', :js do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
user = create(:user, :two_factor)
edit_user(user)
@@ -27,7 +27,7 @@ RSpec.describe 'Admin disables 2FA for a user', feature_category: :system_access
it 'for a user without 2FA enabled' do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
user = create(:user)
edit_user(user)
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index f071da1835a..283caddab6a 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Admin Groups', feature_category: :groups_and_projects do
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
stub_application_setting(default_group_visibility: internal)
end
diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb
index 66014e676d5..fa91159c5f5 100644
--- a/spec/features/admin/admin_health_check_spec.rb
+++ b/spec/features/admin/admin_health_check_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "Admin Health Check", :js, feature_category: :error_budgets do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe '#show' do
diff --git a/spec/features/admin/admin_hook_logs_spec.rb b/spec/features/admin/admin_hook_logs_spec.rb
index 0a537e65b99..146c83dbeee 100644
--- a/spec/features/admin/admin_hook_logs_spec.rb
+++ b/spec/features/admin/admin_hook_logs_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Admin::HookLogs', feature_category: :webhooks do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'show list of hook logs' do
diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb
index 2aec5baf351..9bdb7ce000f 100644
--- a/spec/features/admin/admin_hooks_spec.rb
+++ b/spec/features/admin/admin_hooks_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Admin::Hooks', feature_category: :webhooks do
before do
sign_in(user)
- gitlab_enable_admin_mode_sign_in(user)
+ enable_admin_mode!(user)
end
describe 'GET /admin/hooks' do
diff --git a/spec/features/admin/admin_jobs_spec.rb b/spec/features/admin/admin_jobs_spec.rb
index b3e21d02354..fc775c180ff 100644
--- a/spec/features/admin/admin_jobs_spec.rb
+++ b/spec/features/admin/admin_jobs_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Admin Jobs', :js, feature_category: :continuous_integration do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe 'GET /admin/jobs' do
diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb
index 47dc8577037..2fe68363062 100644
--- a/spec/features/admin/admin_labels_spec.rb
+++ b/spec/features/admin/admin_labels_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'admin issues labels', feature_category: :team_planning do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe 'list' do
diff --git a/spec/features/admin/admin_manage_applications_spec.rb b/spec/features/admin/admin_manage_applications_spec.rb
index b4c77e802a8..3e351af6121 100644
--- a/spec/features/admin/admin_manage_applications_spec.rb
+++ b/spec/features/admin/admin_manage_applications_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'admin manage applications', feature_category: :system_access do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
include_examples 'manage applications'
diff --git a/spec/features/admin/admin_mode/login_spec.rb b/spec/features/admin/admin_mode/login_spec.rb
index 5e4935ee4b1..5298407deb3 100644
--- a/spec/features/admin/admin_mode/login_spec.rb
+++ b/spec/features/admin/admin_mode/login_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Admin Mode Login', feature_category: :system_access do
repeated_otp = user.current_otp
enter_code(repeated_otp)
- gitlab_enable_admin_mode_sign_in(user, use_mock_admin_mode: false)
+ enable_admin_mode!(user, use_ui: true)
expect(page).to have_content(_('Enter verification code'))
@@ -41,7 +41,7 @@ RSpec.describe 'Admin Mode Login', feature_category: :system_access do
expect(page).to have_content('Enter verification code')
enter_code(user.current_otp)
- gitlab_enable_admin_mode_sign_in(user, use_mock_admin_mode: false)
+ enable_admin_mode!(user, use_ui: true)
expect(page).to have_content(_('Enter verification code'))
end
diff --git a/spec/features/admin/admin_mode/logout_spec.rb b/spec/features/admin/admin_mode/logout_spec.rb
index 584151726a6..beac36e28c5 100644
--- a/spec/features/admin/admin_mode/logout_spec.rb
+++ b/spec/features/admin/admin_mode/logout_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Admin Mode Logout', :js, feature_category: :system_access do
# TODO: This used to use gitlab_sign_in, instead of sign_in, but that is buggy. See
# this issue to look into why: https://gitlab.com/gitlab-org/gitlab/-/issues/331851
sign_in(user)
- gitlab_enable_admin_mode_sign_in(user, use_mock_admin_mode: false)
+ enable_admin_mode!(user, use_ui: true)
visit admin_root_path
end
diff --git a/spec/features/admin/admin_mode/workers_spec.rb b/spec/features/admin/admin_mode/workers_spec.rb
index 124c43eef9d..f0cea425bb7 100644
--- a/spec/features/admin/admin_mode/workers_spec.rb
+++ b/spec/features/admin/admin_mode/workers_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'Admin mode for workers', :request_store, feature_category: :syst
context 'when admin mode enabled', :delete do
before do
- gitlab_enable_admin_mode_sign_in(user)
+ enable_admin_mode!(user)
end
it 'can delete user', :js do
@@ -67,6 +67,6 @@ RSpec.describe 'Admin mode for workers', :request_store, feature_category: :syst
Sidekiq::Worker.drain_all
sign_in(user)
- gitlab_enable_admin_mode_sign_in(user)
+ enable_admin_mode!(user)
end
end
diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb
index 2a655cdb1f4..29eb24fa9b8 100644
--- a/spec/features/admin/admin_mode_spec.rb
+++ b/spec/features/admin/admin_mode_spec.rb
@@ -69,7 +69,7 @@ RSpec.describe 'Admin mode', :js, feature_category: :shared do
context 'when in admin_mode' do
before do
- gitlab_enable_admin_mode_sign_in(admin, use_mock_admin_mode: false)
+ enable_admin_mode!(admin, use_ui: true)
end
it 'contains link to leave admin mode' do
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index b793299e253..978b2176431 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe "Admin::Projects", feature_category: :groups_and_projects do
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
end
describe 'when membership is set to expire', :js do
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 653458710e3..2b4ceb05f00 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe "Admin Runners", feature_category: :fleet_visibility do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe "Admin Runners page", :js do
diff --git a/spec/features/admin/admin_search_settings_spec.rb b/spec/features/admin/admin_search_settings_spec.rb
index 3254bf75738..c20a50cf218 100644
--- a/spec/features/admin/admin_search_settings_spec.rb
+++ b/spec/features/admin/admin_search_settings_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Admin searches application settings', :js, feature_category: :gl
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'in appearances page' do
diff --git a/spec/features/admin/admin_sees_background_migrations_spec.rb b/spec/features/admin/admin_sees_background_migrations_spec.rb
index ae307b8038c..43b920c657c 100644
--- a/spec/features/admin/admin_sees_background_migrations_spec.rb
+++ b/spec/features/admin/admin_sees_background_migrations_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "Admin > Admin sees background migrations", feature_category: :da
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'can navigate to background migrations', :js do
diff --git a/spec/features/admin/admin_sees_project_statistics_spec.rb b/spec/features/admin/admin_sees_project_statistics_spec.rb
index d977735daf8..07f90d247cd 100644
--- a/spec/features/admin/admin_sees_project_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_project_statistics_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "Admin > Admin sees project statistics", feature_category: :group
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
visit admin_project_path(project)
end
diff --git a/spec/features/admin/admin_sees_projects_statistics_spec.rb b/spec/features/admin/admin_sees_projects_statistics_spec.rb
index 3363a67ea90..cc6ccbab0a0 100644
--- a/spec/features/admin/admin_sees_projects_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_projects_statistics_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "Admin > Admin sees projects statistics", feature_category: :grou
create(:project, :repository) { |project| project.statistics.destroy! }
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
visit admin_projects_path
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 77707a67d58..d1fdbfc5329 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Admin updates settings', feature_category: :shared do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin, use_mock_admin_mode: false)
+ enable_admin_mode!(admin, use_ui: true)
end
context 'General page' do
diff --git a/spec/features/admin/admin_system_info_spec.rb b/spec/features/admin/admin_system_info_spec.rb
index 71a0b829932..f285fefe6db 100644
--- a/spec/features/admin/admin_system_info_spec.rb
+++ b/spec/features/admin/admin_system_info_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Admin System Info', feature_category: :shared do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe 'GET /admin/system_info' do
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index 543dc2cc2a6..7cfe0cdbc81 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js, feature_category: :s
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe "token creation" do
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 9ab5b1fd3bb..f09c1a59b0d 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "Admin::Users", feature_category: :user_management do
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
end
describe 'Tabs' do
diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb
index 05232de35e5..a628344bfeb 100644
--- a/spec/features/admin/admin_uses_repository_checks_spec.rb
+++ b/spec/features/admin/admin_uses_repository_checks_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Admin uses repository checks', :request_store, feature_category:
context 'when admin mode is enabled' do
before do
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'to trigger a single check', :js do
diff --git a/spec/features/admin/broadcast_messages_spec.rb b/spec/features/admin/broadcast_messages_spec.rb
index e4a2e31ee1c..16651ffa07e 100644
--- a/spec/features/admin/broadcast_messages_spec.rb
+++ b/spec/features/admin/broadcast_messages_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Admin Broadcast Messages', :js, feature_category: :onboarding do
it 'previews, creates and edits a broadcast message' do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
# create
visit admin_broadcast_messages_path
diff --git a/spec/features/admin/dashboard_spec.rb b/spec/features/admin/dashboard_spec.rb
index 06f9c531e74..9e8f5138815 100644
--- a/spec/features/admin/dashboard_spec.rb
+++ b/spec/features/admin/dashboard_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'admin visits dashboard' do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'counting forks', :js, feature_category: :source_code_management do
diff --git a/spec/features/admin/users/user_identities_spec.rb b/spec/features/admin/users/user_identities_spec.rb
new file mode 100644
index 00000000000..903ddbed399
--- /dev/null
+++ b/spec/features/admin/users/user_identities_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Admin::Users::UserIdentities', feature_category: :user_management do
+ let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
+ let_it_be(:current_user) { create(:admin) }
+
+ before do
+ sign_in(current_user)
+ gitlab_enable_admin_mode_sign_in(current_user, use_mock_admin_mode: false)
+ end
+
+ describe 'GET /admin/users/:id' do
+ describe 'show user identities' do
+ it 'shows user identities', :aggregate_failures do
+ visit admin_user_identities_path(user)
+
+ expect(page).to have_content(user.name)
+ expect(page).to have_content('twitter')
+ end
+ end
+
+ describe 'update user identities' do
+ before do
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:providers).and_return([:twitter, :twitter_updated])
+ end
+
+ it 'modifies twitter identity', :aggregate_failures do
+ visit admin_user_identities_path(user)
+
+ find('.table').find(:link, 'Edit').click
+ fill_in 'identity_extern_uid', with: '654321'
+ select 'twitter_updated', from: 'identity_provider'
+ click_button 'Save changes'
+
+ expect(page).to have_content(user.name)
+ expect(page).to have_content('twitter_updated')
+ expect(page).to have_content('654321')
+ end
+ end
+
+ describe 'remove user with identities' do
+ it 'removes user with twitter identity', :aggregate_failures do
+ visit admin_user_identities_path(user)
+
+ click_link 'Delete'
+
+ expect(page).to have_content(user.name)
+ expect(page).not_to have_content('twitter')
+ end
+ end
+ end
+end
diff --git a/spec/features/admin/users/user_impersonation_spec.rb b/spec/features/admin/users/user_impersonation_spec.rb
new file mode 100644
index 00000000000..81c1d0de115
--- /dev/null
+++ b/spec/features/admin/users/user_impersonation_spec.rb
@@ -0,0 +1,209 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Admin::Users::UserImpersonation', feature_category: :user_management do
+ let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
+ let_it_be(:current_user) { create(:admin) }
+
+ before do
+ sign_in(current_user)
+ gitlab_enable_admin_mode_sign_in(current_user, use_mock_admin_mode: false)
+ end
+
+ describe 'GET /admin/users/:id' do
+ describe 'Impersonation' do
+ let_it_be(:another_user) { create(:user) }
+
+ context 'before impersonating' do
+ subject { visit admin_user_path(user_to_visit) }
+
+ let_it_be(:user_to_visit) { another_user }
+
+ shared_examples "user that cannot be impersonated" do
+ it 'disables impersonate button' do
+ subject
+
+ impersonate_btn = find_by_testid('impersonate-user-link')
+
+ expect(impersonate_btn).not_to be_nil
+ expect(impersonate_btn['disabled']).not_to be_nil
+ end
+
+ it "shows tooltip with correct error message" do
+ subject
+
+ expect(find("span[title='#{impersonation_error_msg}']")).not_to be_nil
+ end
+ end
+
+ context 'for other users' do
+ it 'shows impersonate button for other users' do
+ subject
+
+ expect(page).to have_content('Impersonate')
+ impersonate_btn = find_by_testid('impersonate-user-link')
+ expect(impersonate_btn['disabled']).to be_nil
+ end
+ end
+
+ context 'for admin itself' do
+ let(:user_to_visit) { current_user }
+
+ it 'does not show impersonate button for admin itself' do
+ subject
+
+ expect(page).not_to have_content('Impersonate')
+ end
+ end
+
+ context 'for blocked user' do
+ let_it_be(:blocked_user) { create(:user, :blocked) }
+ let(:user_to_visit) { blocked_user }
+ let(:impersonation_error_msg) { _('You cannot impersonate a blocked user') }
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'for user with expired password' do
+ let(:user_to_visit) do
+ another_user.update!(password_expires_at: Time.zone.now - 5.minutes)
+ another_user
+ end
+
+ let(:impersonation_error_msg) { _("You cannot impersonate a user with an expired password") }
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'for internal user' do
+ let_it_be(:internal_user) { create(:user, :bot) }
+ let(:user_to_visit) { internal_user }
+ let(:impersonation_error_msg) { _("You cannot impersonate an internal user") }
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'for locked user' do
+ let_it_be(:locked_user) { create(:user, :locked) }
+ let(:user_to_visit) { locked_user }
+ let(:impersonation_error_msg) { _("You cannot impersonate a user who cannot log in") }
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'when already impersonating another user' do
+ let_it_be(:admin_user) { create(:user, :admin) }
+ let(:impersonation_error_msg) { _("You are already impersonating another user") }
+
+ subject do
+ visit admin_user_path(admin_user)
+ click_link 'Impersonate'
+ visit admin_user_path(another_user)
+ end
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'when impersonation is disabled' do
+ before do
+ stub_config_setting(impersonation_enabled: false)
+ end
+
+ it 'does not show impersonate button' do
+ subject
+
+ expect(page).not_to have_content('Impersonate')
+ end
+ end
+ end
+
+ context 'when impersonating' do
+ subject { click_link 'Impersonate' }
+
+ before do
+ visit admin_user_path(another_user)
+ end
+
+ it 'logs in as the user when impersonate is clicked', :js do
+ subject
+
+ expect(page).to have_button("#{another_user.name} user’s menu")
+ end
+
+ it 'sees impersonation log out icon', :js do
+ subject
+
+ icon = first('[data-testid="incognito-icon"]')
+ expect(icon).not_to be nil
+ end
+
+ context 'when viewing the confirm email warning', :js do
+ before do
+ stub_application_setting_enum('email_confirmation_setting', 'soft')
+ end
+
+ let_it_be(:another_user) { create(:user, :unconfirmed) }
+ let(:warning_alert) { page.find(:css, '[data-testid="alert-warning"]') }
+ let(:expected_styling) { { 'pointer-events' => 'none', 'cursor' => 'default' } }
+
+ context 'with an email that does not contain HTML' do
+ before do
+ subject
+ end
+
+ it 'displays the warning alert including the email' do
+ expect(warning_alert.text).to include("Please check your email (#{another_user.email}) to verify")
+ end
+ end
+
+ context 'with an email that contains HTML' do
+ let(:malicious_email) { "malicious@test.com