diff options
87 files changed, 640 insertions, 374 deletions
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` | <a id="mutationmemberrolecreatereadcode"></a>`readCode` | [`Boolean`](#boolean) | Permission to read code. | | <a id="mutationmemberrolecreatereaddependency"></a>`readDependency` | [`Boolean`](#boolean) | Permission to read dependency. | | <a id="mutationmemberrolecreatereadvulnerability"></a>`readVulnerability` | [`Boolean`](#boolean) | Permission to read vulnerability. | +| <a id="mutationmemberrolecreateremoveproject"></a>`removeProject` | [`Boolean`](#boolean) | Permission to delete projects. | #### Fields @@ -21408,6 +21409,7 @@ Represents a member role. | <a id="memberrolereadcode"></a>`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. | | <a id="memberrolereaddependency"></a>`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. | | <a id="memberrolereadvulnerability"></a>`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. | +| <a id="memberroleremoveproject"></a>`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. | <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. | | <a id="memberrolepermissionread_vulnerability"></a>`READ_VULNERABILITY` | Allows read-only access to the vulnerability reports. | +| <a id="memberrolepermissionremove_project"></a>`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. <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/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<form><input/title='<script>alert(document.domain)</script>'>" } + let(:another_user) { create(:user, confirmed_at: nil, unconfirmed_email: malicious_email) } + + before do + subject + end + + it 'displays the impersonation alert, excludes email, and disables links' do + expect(warning_alert.text).to include("check your email (#{another_user.unconfirmed_email}) to verify") + end + end + end + end + + context 'ending impersonation', :js do + subject { click_on 'Stop impersonating' } + + before do + visit admin_user_path(another_user) + click_link 'Impersonate' + end + + it 'logs out of impersonated user back to original user' do + subject + + expect(page).to have_button("#{current_user.name} user’s menu") + end + + it 'is redirected back to the impersonated users page in the admin after stopping' do + subject + + expect(page).to have_current_path("/admin/users/#{another_user.username}", ignore_query: true) + end + + context 'a user with an expired password' do + before do + another_user.update!(password_expires_at: Time.zone.now - 5.minutes) + end + + it 'is redirected back to the impersonated users page in the admin after stopping' do + subject + + expect(page).to have_current_path("/admin/users/#{another_user.username}", ignore_query: true) + end + end + end + end + end +end diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb index d0110b3e013..b7e7a037ffc 100644 --- a/spec/features/admin/users/user_spec.rb +++ b/spec/features/admin/users/user_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'Admin::Users::User', feature_category: :user_management do before do sign_in(current_user) - gitlab_enable_admin_mode_sign_in(current_user, use_mock_admin_mode: false) + enable_admin_mode!(current_user, use_ui: true) end describe 'GET /admin/users/:id' do @@ -144,200 +144,6 @@ RSpec.describe 'Admin::Users::User', feature_category: :user_management do end end - 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<form><input/title='<script>alert(document.domain)</script>'>" } - let(:another_user) { create(:user, confirmed_at: nil, unconfirmed_email: malicious_email) } - - before do - subject - end - - it 'displays the impersonation alert, excludes email, and disables links' do - expect(warning_alert.text).to include("check your email (#{another_user.unconfirmed_email}) to verify") - end - end - end - end - - context 'ending impersonation', :js do - subject { click_on 'Stop impersonating' } - - before do - visit admin_user_path(another_user) - click_link 'Impersonate' - end - - it 'logs out of impersonated user back to original user' do - subject - - expect(page).to have_button("#{current_user.name} user’s menu") - end - - it 'is redirected back to the impersonated users page in the admin after stopping' do - subject - - expect(page).to have_current_path("/admin/users/#{another_user.username}", ignore_query: true) - end - - context 'a user with an expired password' do - before do - another_user.update!(password_expires_at: Time.zone.now - 5.minutes) - end - - it 'is redirected back to the impersonated users page in the admin after stopping' do - subject - - expect(page).to have_current_path("/admin/users/#{another_user.username}", ignore_query: true) - end - end - end - end - describe 'Two-factor Authentication status' do it 'shows when enabled' do user.update!(otp_required_for_login: true) @@ -479,26 +285,6 @@ RSpec.describe 'Admin::Users::User', feature_category: :user_management do end end - describe 'GET /admin/users', :js do - context 'user pending approval' do - it 'shows user info', :aggregate_failures do - user = create(:user, :blocked_pending_approval) - - visit admin_users_path - click_link 'Pending approval' - click_link user.name - - expect(page).to have_content(user.name) - expect(page).to have_content('Pending approval') - - click_user_dropdown_toggle(user.id) - - expect(page).to have_button('Approve') - expect(page).to have_button('Reject') - end - end - end - context 'when user has an unconfirmed email', :js do # Email address contains HTML to ensure email address is displayed in an HTML safe way. let_it_be(:unconfirmed_email) { "#{generate(:email)}<h2>testing<img/src=http://localhost:8000/test.png>" } diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb index 4e988674858..20cedda626b 100644 --- a/spec/features/admin/users/users_spec.rb +++ b/spec/features/admin/users/users_spec.rb @@ -12,7 +12,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 'GET /admin/users', :js do @@ -381,6 +381,24 @@ RSpec.describe 'Admin::Users', feature_category: :user_management do expect(find_by_testid("user-group-count-#{current_user.id}").text).to eq("2") end end + + context 'user pending approval' do + it 'shows user info', :aggregate_failures do + user = create(:user, :blocked_pending_approval) + + visit admin_users_path + click_link 'Pending approval' + click_link user.name + + expect(page).to have_content(user.name) + expect(page).to have_content('Pending approval') + + click_user_dropdown_toggle(user.id) + + expect(page).to have_button('Approve') + expect(page).to have_button('Reject') + end + end end describe 'GET /admin/users/new' do diff --git a/spec/features/admin_variables_spec.rb b/spec/features/admin_variables_spec.rb index caa94209e50..0fc0ae9e199 100644 --- a/spec/features/admin_variables_spec.rb +++ b/spec/features/admin_variables_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'Instance variables', :js, feature_category: :secrets_management before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit page_path wait_for_requests diff --git a/spec/features/boards/keyboard_shortcut_spec.rb b/spec/features/boards/keyboard_shortcut_spec.rb index 6f03f6db3ab..d4777fa671c 100644 --- a/spec/features/boards/keyboard_shortcut_spec.rb +++ b/spec/features/boards/keyboard_shortcut_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'Issue Boards shortcut', :js, feature_category: :team_planning do admin = create(:admin) sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit project_path(project) end @@ -30,7 +30,7 @@ RSpec.describe 'Issue Boards shortcut', :js, feature_category: :team_planning do before do admin = create(:admin) sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit project_path(project) end diff --git a/spec/features/broadcast_messages_spec.rb b/spec/features/broadcast_messages_spec.rb index f887242384c..867ed3c3acb 100644 --- a/spec/features/broadcast_messages_spec.rb +++ b/spec/features/broadcast_messages_spec.rb @@ -121,7 +121,7 @@ RSpec.describe 'Broadcast Messages', feature_category: :onboarding do stub_const('Gitlab::Cache::JsonCaches::JsonKeyed::STRATEGY_KEY_COMPONENTS', original_strategy_value) admin = create(:admin) sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit admin_broadcast_messages_path diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb index 31dec5e38da..78ac752a375 100644 --- a/spec/features/clusters/cluster_detail_page_spec.rb +++ b/spec/features/clusters/cluster_detail_page_spec.rb @@ -145,7 +145,7 @@ RSpec.describe 'Clusterable > Show page', feature_category: :deployment_manageme let(:cluster) { create(:cluster, :provided_by_gcp, :instance) } before do - gitlab_enable_admin_mode_sign_in(current_user) + enable_admin_mode!(current_user) end it_behaves_like 'show page' do diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb index 7fbd6c4e235..523ef8990bb 100644 --- a/spec/features/expand_collapse_diffs_spec.rb +++ b/spec/features/expand_collapse_diffs_spec.rb @@ -12,7 +12,7 @@ RSpec.describe 'Expand and collapse diffs', :js, feature_category: :source_code_ allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes) sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) wait_for_requests diff --git a/spec/features/gitlab_experiments_spec.rb b/spec/features/gitlab_experiments_spec.rb index facf4994c44..0d0afa801c8 100644 --- a/spec/features/gitlab_experiments_spec.rb +++ b/spec/features/gitlab_experiments_spec.rb @@ -12,7 +12,7 @@ RSpec.describe "Gitlab::Experiment", :js, feature_category: :activation do before do admin = create(:admin) sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) stub_experiments(null_hypothesis: :candidate) end diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb index 9089fba1886..24552daa11b 100644 --- a/spec/features/groups/clusters/user_spec.rb +++ b/spec/features/groups/clusters/user_spec.rb @@ -130,7 +130,7 @@ RSpec.describe 'User Cluster', :js, feature_category: :environment_management do gitlab_sign_out gitlab_sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit group_clusters_path(group) end diff --git a/spec/features/groups/members/list_members_spec.rb b/spec/features/groups/members/list_members_spec.rb index b16d61a5fe4..b6e0deb2e73 100644 --- a/spec/features/groups/members/list_members_spec.rb +++ b/spec/features/groups/members/list_members_spec.rb @@ -66,7 +66,7 @@ RSpec.describe 'Groups > Members > List members', :js, feature_category: :groups it 'shows 2FA badge to admins' do sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit group_group_members_path(group) diff --git a/spec/features/help_dropdown_spec.rb b/spec/features/help_dropdown_spec.rb index 3e4c0bc55fe..89040ec9ab6 100644 --- a/spec/features/help_dropdown_spec.rb +++ b/spec/features/help_dropdown_spec.rb @@ -27,7 +27,7 @@ RSpec.describe "Help Dropdown", :js, feature_category: :shared do context "when severity is #{severity}" do before do sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) allow_next_instance_of(VersionCheck) do |instance| allow(instance).to receive(:response).and_return({ "severity" => severity }) diff --git a/spec/features/merge_requests/admin_views_hidden_merge_requests_spec.rb b/spec/features/merge_requests/admin_views_hidden_merge_requests_spec.rb index 7e33946f713..f52520313b2 100644 --- a/spec/features/merge_requests/admin_views_hidden_merge_requests_spec.rb +++ b/spec/features/merge_requests/admin_views_hidden_merge_requests_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'Admin views hidden merge requests', feature_category: :insider_t before do sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit(project_merge_requests_path(project)) end diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index c223053606b..e7e419a4c60 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -110,7 +110,7 @@ RSpec.describe 'Gcp Cluster', :js, feature_category: :deployment_management do before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - gitlab_enable_admin_mode_sign_in(user) + enable_admin_mode!(user) visit general_admin_application_settings_path end diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb index 067963e06e0..bc4d64dad21 100644 --- a/spec/features/projects/clusters/user_spec.rb +++ b/spec/features/projects/clusters/user_spec.rb @@ -120,7 +120,7 @@ RSpec.describe 'User Cluster', :js, feature_category: :deployment_management do gitlab_sign_out gitlab_sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit project_clusters_path(project) end diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index c6a770cee9e..5f1bc4f86c1 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -153,7 +153,7 @@ RSpec.describe 'Edit Project Settings', feature_category: :groups_and_projects d before do non_member.update_attribute(:admin, true) sign_in(non_member) - gitlab_enable_admin_mode_sign_in(non_member) + enable_admin_mode!(non_member) end it 'renders 404 if feature is disabled' do diff --git a/spec/features/projects/members/manage_members_spec.rb b/spec/features/projects/members/manage_members_spec.rb index 3423c636c2b..2ab0e63d840 100644 --- a/spec/features/projects/members/manage_members_spec.rb +++ b/spec/features/projects/members/manage_members_spec.rb @@ -265,7 +265,7 @@ RSpec.describe 'Projects > Members > Manage members', :js, feature_category: :on it 'shows 2FA badge to admins' do sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit_members_page diff --git a/spec/features/projects/user_views_empty_project_spec.rb b/spec/features/projects/user_views_empty_project_spec.rb index ed34b109d29..7dc3dd1da1e 100644 --- a/spec/features/projects/user_views_empty_project_spec.rb +++ b/spec/features/projects/user_views_empty_project_spec.rb @@ -43,7 +43,7 @@ RSpec.describe 'User views an empty project', feature_category: :groups_and_proj context 'when admin mode is enabled' do before do sign_in(user) - gitlab_enable_admin_mode_sign_in(user) + enable_admin_mode!(user) end it_behaves_like 'allowing push to default branch' diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb index 41105630204..c29323cba27 100644 --- a/spec/features/protected_branches_spec.rb +++ b/spec/features/protected_branches_spec.rb @@ -82,7 +82,7 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem context 'logged in as admin' do before do sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) end describe "explicit protected branches" do diff --git a/spec/features/usage_stats_consent_spec.rb b/spec/features/usage_stats_consent_spec.rb index ebf1cd9e143..5436018250d 100644 --- a/spec/features/usage_stats_consent_spec.rb +++ b/spec/features/usage_stats_consent_spec.rb @@ -19,7 +19,7 @@ RSpec.describe 'Usage stats consent', feature_category: :service_ping do end gitlab_sign_in(user) - gitlab_enable_admin_mode_sign_in(user) + enable_admin_mode!(user) end shared_examples 'dismissible banner' do |button_text| diff --git a/spec/features/user_settings/active_sessions_spec.rb b/spec/features/user_settings/active_sessions_spec.rb index 5d1d4bc6490..bc0693d79e1 100644 --- a/spec/features/user_settings/active_sessions_spec.rb +++ b/spec/features/user_settings/active_sessions_spec.rb @@ -47,7 +47,7 @@ RSpec.describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state, fe ) gitlab_sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) visit admin_user_path(user) diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/uniqueness_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/uniqueness_helpers_spec.rb new file mode 100644 index 00000000000..230847f6902 --- /dev/null +++ b/spec/lib/gitlab/database/partitioning_migration_helpers/uniqueness_helpers_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::UniquenessHelpers, feature_category: :database do + let(:migration) do + ActiveRecord::Migration.new.extend(described_class) + end + + let(:connection) { ActiveRecord::Base.connection } + let(:table_not_partitioned) { '_test_not_partitioned_table' } + let(:table_partitioned) { '_test_partitioned_table' } + + before do + connection.execute(<<~SQL) + CREATE TABLE _test_partitioned_table + ( + id serial NOT NULL, + PARTITION bigint NULL DEFAULT 1, + PRIMARY KEY (id, partition) + ) PARTITION BY list(partition); + + CREATE TABLE _test_partitioned_table_1 + PARTITION OF _test_partitioned_table FOR VALUES IN (1); + SQL + end + + describe '#ensure_unique_id' do + subject(:ensure_unique_id) { migration.ensure_unique_id(table_name) } + + context 'when table is partitioned' do + let(:table_name) { table_partitioned } + let(:trigger_name) { "assign_#{table_name}_id_trigger" } + let(:function_name) { "assign_#{table_name}_id_value" } + + context 'when trigger already exists' do + before do + allow(migration).to receive(:trigger_exists?) + .with(table_name, trigger_name) + .and_return(true) + end + + it 'does not modify existing trigger' do + expect(migration).not_to receive(:change_column_default) + expect(migration).not_to receive(:create_trigger_function) + expect(migration).not_to receive(:create_trigger) + + expect do + ensure_unique_id + end.not_to raise_error + end + end + + context 'when trigger is not defined' do + it 'creates trigger', :aggregate_failures do + expect(migration).to receive(:change_column_default).with(table_name, :id, nil).and_call_original + expect(migration).to receive(:create_trigger_function).with(function_name).and_call_original + expect(migration).to receive(:create_trigger) + .with(table_name, trigger_name, function_name, fires: 'BEFORE INSERT') + .and_call_original + + expect do + ensure_unique_id + end.not_to raise_error + + expect(migration.trigger_exists?(table_name, trigger_name)).to eq(true) + end + end + end + end +end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index a9a4575d747..9f4bf4f6b36 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -472,12 +472,12 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - context 'reading usage quotas' do + context 'reading usage quotas and viewing the edit page' do %w[maintainer owner].each do |role| context "with #{role}" do let(:current_user) { send(role) } - it { is_expected.to be_allowed(:read_usage_quotas) } + it { is_expected.to be_allowed(:read_usage_quotas, :view_edit_page) } end end @@ -485,7 +485,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do context "with #{role}" do let(:current_user) { send(role) } - it { is_expected.to be_disallowed(:read_usage_quotas) } + it { is_expected.to be_disallowed(:read_usage_quotas, :view_edit_page) } end end @@ -493,11 +493,11 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do let(:current_user) { admin } context 'when admin mode is enabled', :enable_admin_mode do - it { expect_allowed(:read_usage_quotas) } + it { expect_allowed(:read_usage_quotas, :view_edit_page) } end context 'when admin mode is disabled' do - it { expect_disallowed(:read_usage_quotas) } + it { expect_disallowed(:read_usage_quotas, :view_edit_page) } end end end diff --git a/spec/scripts/internal_events/cli_spec.rb b/spec/scripts/internal_events/cli_spec.rb index d84a4498fe8..571517f005b 100644 --- a/spec/scripts/internal_events/cli_spec.rb +++ b/spec/scripts/internal_events/cli_spec.rb @@ -8,6 +8,11 @@ RSpec.describe Cli, feature_category: :service_ping do let(:prompt) { TTY::Prompt::Test.new } let(:files_to_cleanup) { [] } + let(:example_timeout) { 3 } + let(:example_error) { Class.new(Timeout::Error) } + let(:interaction_timeout) { 1 } + let(:interaction_error) { Class.new(Timeout::Error) } + let(:event1_filepath) { 'config/events/internal_events_cli_used.yml' } let(:event1_content) { internal_event_fixture('events/event_with_identifiers.yml') } let(:event2_filepath) { 'ee/config/events/internal_events_cli_opened.yml' } @@ -26,13 +31,29 @@ RSpec.describe Cli, feature_category: :service_ping do delete_files(files_to_cleanup) end + around do |example| + Timeout.timeout(example_timeout, example_error) { example.run } + rescue example_error => e + # Override error to include CLI output in error detail + raise e.class, timeout_error_message, e.backtrace + end + + subject(:execute) do + Timeout.timeout(interaction_timeout, interaction_error) { described_class.new(prompt).run } + rescue interaction_error + # Rescue from timeout so we can make assertions on the CLI output + end + + # Shared examples used for examples defined in new_events.yml & new_metrics.yml fixtures. + # Note: Expects CLI to be exited using the 'Exit' option or completing definition flow shared_examples 'creates the right defintion files' do |description, test_case = {}| # For expected keystroke mapping, see https://github.com/piotrmurach/tty-reader/blob/master/lib/tty/reader/keys.rb let(:keystrokes) { test_case.dig('inputs', 'keystrokes') || [] } let(:input_files) { test_case.dig('inputs', 'files') || [] } let(:output_files) { test_case.dig('outputs', 'files') || [] } - subject { run_with_verbose_timeout } + # Script execution should stop without a reduced timeout + let(:interaction_timeout) { example_timeout } it "in scenario: #{description}" do delete_old_ouputs # just in case @@ -40,7 +61,7 @@ RSpec.describe Cli, feature_category: :service_ping do queue_cli_inputs(keystrokes) expect_file_creation - subject + execute end private @@ -117,7 +138,7 @@ RSpec.describe Cli, feature_category: :service_ping do "\n" # Copy & continue ]) - run_with_timeout + execute # Filter down to "dev" options expect(plain_last_lines(9)).to eq <<~TEXT.chomp @@ -149,7 +170,7 @@ RSpec.describe Cli, feature_category: :service_ping do "\n" # Copy & continue ]) - run_with_timeout + execute # Filter down to "dev:create" options expect(plain_last_lines(5)).to eq <<~TEXT.chomp @@ -185,7 +206,7 @@ RSpec.describe Cli, feature_category: :service_ping do "2\n" # Modify attributes ]) - run_with_timeout + execute # Filter down to "dev" options expect(plain_last_lines(50)).to include 'Select one: Which group owns the metric?' @@ -262,7 +283,7 @@ RSpec.describe Cli, feature_category: :service_ping do "\n" # Select: config/events/internal_events_cli_used.yml ]) - run_with_timeout + execute end end @@ -279,7 +300,7 @@ RSpec.describe Cli, feature_category: :service_ping do "\n" # Select: config/events/internal_events_cli_opened.yml ]) - run_with_timeout + execute expect(plain_last_lines(5)).to eq <<~TEXT.chomp ✘ Monthly/Weekly count of unique users [who triggered internal_events_cli_opened] (user unavailable) @@ -318,7 +339,7 @@ RSpec.describe Cli, feature_category: :service_ping do "\n" # Select: config/events/00_event1.yml ]) - run_with_timeout + execute expect(plain_last_lines(15)).to include 'Looks like the potential metrics for this event ' \ 'either already exist or are unsupported.' @@ -389,7 +410,7 @@ RSpec.describe Cli, feature_category: :service_ping do "8\n" # Exit ]) - run_with_timeout + execute output = plain_last_lines(100) @@ -556,7 +577,7 @@ RSpec.describe Cli, feature_category: :service_ping do "8\n" # Exit ]) - run_with_timeout + execute output = plain_last_lines(1000) @@ -616,7 +637,7 @@ RSpec.describe Cli, feature_category: :service_ping do "8\n" # Exit ]) - run_with_timeout + execute output = plain_last_lines(300) @@ -735,7 +756,7 @@ RSpec.describe Cli, feature_category: :service_ping do "n\n" # No --> Are you trying to track customer usage of a GitLab feature? ]) - run_with_timeout + execute expect(plain_last_lines(50)).to include("Oh no! This probably isn't the tool you need!") end @@ -747,7 +768,7 @@ RSpec.describe Cli, feature_category: :service_ping do "n\n" # No --> Can usage for the feature be measured by tracking a specific user action? ]) - run_with_timeout + execute expect(plain_last_lines(50)).to include("Oh no! This probably isn't the tool you need!") end @@ -761,7 +782,7 @@ RSpec.describe Cli, feature_category: :service_ping do "n\n" # No --> Ready to start? ]) - run_with_timeout + execute expect(plain_last_lines(30)).to include("Okay! The next step is adding a new event! (~5 min)") end @@ -775,7 +796,7 @@ RSpec.describe Cli, feature_category: :service_ping do "n\n" # No --> Ready to start? ]) - run_with_timeout + execute expect(plain_last_lines(30)).to include("Amazing! The next step is adding a new metric! (~8 min)") end @@ -788,18 +809,8 @@ RSpec.describe Cli, feature_category: :service_ping do prompt.input.rewind end - def run_with_timeout(duration = 1) - Timeout.timeout(duration) { described_class.new(prompt).run } - rescue Timeout::Error - # Timeout is needed to break out of the CLI, but we may want - # to make assertions afterwards - end - - def run_with_verbose_timeout(duration = 1) - Timeout.timeout(duration) { described_class.new(prompt).run } - rescue Timeout::Error => e - # Re-raise error so CLI output is printed with the error - message = <<~TEXT + def timeout_error_message + <<~TEXT Awaiting input too long. Entire CLI output: #{ @@ -811,8 +822,6 @@ RSpec.describe Cli, feature_category: :service_ping do TEXT - - raise e.class, message, e.backtrace end def plain_last_lines(size) @@ -820,7 +829,8 @@ RSpec.describe Cli, feature_category: :service_ping do .lines .last(size) .join('') - .gsub(/\e[^\sm]{2,4}[mh]/, '') + .gsub(/\e[^\sm]{2,4}[mh]/, '') # Ignore text colors + .gsub(/(\e\[(2K|1G|1A))+\z/, '') # Remove trailing characters if timeout occurs end def collect_file_writes(collector) @@ -844,7 +854,7 @@ RSpec.describe Cli, feature_category: :service_ping do def stub_product_groups(body) allow(Net::HTTP).to receive(:get) - .with(URI('https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/stages.yml')) + .with(URI(InternalEventsCli::Helpers::GroupOwnership::STAGES_YML)) .and_return(body) end diff --git a/spec/support/helpers/admin_mode_helpers.rb b/spec/support/helpers/admin_mode_helpers.rb index a6e31791127..8b71552f928 100644 --- a/spec/support/helpers/admin_mode_helpers.rb +++ b/spec/support/helpers/admin_mode_helpers.rb @@ -5,17 +5,30 @@ module AdminModeHelper # Administrators are logged in by default in user mode and have to switch to admin # mode for accessing any administrative functionality. This helper lets a user - # be in admin mode without requiring a second authentication step (provided - # the user is an admin) + # access the admin area in two different ways: + # + # * Fast (use_ui: false) and suitable form the most use cases: fakes calls and grants + # access to the admin area without requiring a second authentication step (provided the + # user is an admin) + # * Slow (use_ui: true): visits the admin UI and enters the users password. A second + # authentication step may be needed. # # See also tag :enable_admin_mode in spec/spec_helper.rb for a spec-wide # alternative - def enable_admin_mode!(user) - fake_user_mode = instance_double(Gitlab::Auth::CurrentUserMode) + def enable_admin_mode!(user, use_ui: false) + if use_ui + visit new_admin_session_path + fill_in 'user_password', with: user.password + click_button 'Enter admin mode' + + wait_for_requests + else + fake_user_mode = instance_double(Gitlab::Auth::CurrentUserMode) - allow(Gitlab::Auth::CurrentUserMode).to receive(:new).and_call_original + allow(Gitlab::Auth::CurrentUserMode).to receive(:new).and_call_original - allow(Gitlab::Auth::CurrentUserMode).to receive(:new).with(user).and_return(fake_user_mode) - allow(fake_user_mode).to receive(:admin_mode?).and_return(user&.admin?) + allow(Gitlab::Auth::CurrentUserMode).to receive(:new).with(user).and_return(fake_user_mode) + allow(fake_user_mode).to receive(:admin_mode?).and_return(user&.admin?) + end end end diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb index 0cdddeaa84a..ff1c528d94a 100644 --- a/spec/support/helpers/login_helpers.rb +++ b/spec/support/helpers/login_helpers.rb @@ -49,18 +49,6 @@ module LoginHelpers @current_user = user end - def gitlab_enable_admin_mode_sign_in(user, use_mock_admin_mode: true) - if use_mock_admin_mode - enable_admin_mode!(user) - else - visit new_admin_session_path - fill_in 'user_password', with: user.password - click_button 'Enter admin mode' - - wait_for_requests - end - end - def gitlab_sign_in_via(provider, user, uid, saml_response = nil) mock_auth_hash_with_saml_xml(provider, uid, user.email, saml_response) visit new_user_session_path diff --git a/spec/support/shared_contexts/features/integrations/instance_integrations_shared_context.rb b/spec/support/shared_contexts/features/integrations/instance_integrations_shared_context.rb index c740917cec4..678199a35ea 100644 --- a/spec/support/shared_contexts/features/integrations/instance_integrations_shared_context.rb +++ b/spec/support/shared_contexts/features/integrations/instance_integrations_shared_context.rb @@ -7,7 +7,7 @@ RSpec.shared_context 'instance integration activation' do before do sign_in(user) - gitlab_enable_admin_mode_sign_in(user) + enable_admin_mode!(user) end def visit_instance_integrations diff --git a/spec/support/shared_examples/features/inviting_groups_shared_examples.rb b/spec/support/shared_examples/features/inviting_groups_shared_examples.rb index 4921676a065..d21e69b72e1 100644 --- a/spec/support/shared_examples/features/inviting_groups_shared_examples.rb +++ b/spec/support/shared_examples/features/inviting_groups_shared_examples.rb @@ -9,7 +9,7 @@ RSpec.shared_examples 'inviting groups search results' do before do sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + enable_admin_mode!(admin) end it 'shows groups where the admin has no direct membership' do diff --git a/yarn.lock b/yarn.lock index d70e6d32e5a..c1162707e39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1269,10 +1269,10 @@ stylelint-declaration-strict-value "1.9.2" stylelint-scss "5.1.0" -"@gitlab/svgs@3.72.0": - version "3.72.0" - resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.72.0.tgz#5daaa7366913b52ea89439305067e030f967c8a5" - integrity sha512-VbSdwXxu9Y6NAXNFTROjZa83e2b8QeDAO7byqjJ0z+2Y3gGGXdw+HclAzz0Ns8B0+DMV5mV7dtmTlv/1xAXXYQ== +"@gitlab/svgs@3.74.0": + version "3.74.0" + resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.74.0.tgz#b6b41be65b9e70378c0cef0435f96edd5467e759" + integrity sha512-eHoywPSLrYb+I/IYGapei2Tum5vLtgWkFxN0fxmUUAnBnxFSA+67aheI33kQVV3WjANuZGkglfPBX3QAmN8BLA== "@gitlab/ui@^72.0.0": version "72.0.0" |