Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
78f02b73cf
commit
054c9f71bc
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
f73fde4e3e54fa88d8dba9ec3a98b7dfb8332aaf7a76de73baf899292ed751b1
|
||||
|
|
@ -0,0 +1 @@
|
|||
7bdc5d7aa9f9228aac355e51b1461b7d07083e8e5481ccf3e59c5ec48c9230ab
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
]
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ module Gitlab
|
|||
include ForeignKeyHelpers
|
||||
include TableManagementHelpers
|
||||
include IndexHelpers
|
||||
include UniquenessHelpers
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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 ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>" }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
||||
allow(Gitlab::Auth::CurrentUserMode).to receive(:new).and_call_original
|
||||
wait_for_requests
|
||||
else
|
||||
fake_user_mode = instance_double(Gitlab::Auth::CurrentUserMode)
|
||||
|
||||
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).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?)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue