Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
9b07a0e872
commit
f72c02a9a5
16 changed files with 312 additions and 12 deletions
|
@ -249,7 +249,7 @@ function UsersSelect(currentUser, els, options = {}) {
|
||||||
)} <% } %>`,
|
)} <% } %>`,
|
||||||
);
|
);
|
||||||
assigneeTemplate = template(
|
assigneeTemplate = template(
|
||||||
`<% if (username) { %> <a class="author-link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself">
|
`<% if (username) { %> <a class="author-link gl-font-weight-bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself">
|
||||||
${sprintf(s__('UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}'), {
|
${sprintf(s__('UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}'), {
|
||||||
openingTag: '<a href="#" class="js-assign-yourself">',
|
openingTag: '<a href="#" class="js-assign-yourself">',
|
||||||
closingTag: '</a>',
|
closingTag: '</a>',
|
||||||
|
@ -585,7 +585,7 @@ function UsersSelect(currentUser, els, options = {}) {
|
||||||
)}</a></li>`;
|
)}</a></li>`;
|
||||||
} else {
|
} else {
|
||||||
// 0 margin, because it's now handled by a wrapper
|
// 0 margin, because it's now handled by a wrapper
|
||||||
img = `<img src='${avatar}' class='avatar avatar-inline m-0' width='32' />`;
|
img = `<img src='${avatar}' class='avatar avatar-inline gl-m-0!' width='32' />`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return userSelect.renderRow(
|
return userSelect.renderRow(
|
||||||
|
@ -806,9 +806,9 @@ UsersSelect.prototype.renderRow = function (
|
||||||
: user.name;
|
: user.name;
|
||||||
return `
|
return `
|
||||||
<li data-user-id=${user.id}>
|
<li data-user-id=${user.id}>
|
||||||
<a href="#" class="dropdown-menu-user-link d-flex align-items-center ${linkClasses}" ${tooltipAttributes}>
|
<a href="#" class="dropdown-menu-user-link gl-display-flex! gl-align-items-center ${linkClasses}" ${tooltipAttributes}>
|
||||||
${this.renderRowAvatar(issuableType, user, img)}
|
${this.renderRowAvatar(issuableType, user, img)}
|
||||||
<span class="d-flex flex-column overflow-hidden">
|
<span class="gl-display-flex gl-flex-direction-column gl-overflow-hidden">
|
||||||
<strong class="dropdown-menu-user-full-name gl-font-weight-bold">
|
<strong class="dropdown-menu-user-full-name gl-font-weight-bold">
|
||||||
${escape(name)}
|
${escape(name)}
|
||||||
</strong>
|
</strong>
|
||||||
|
@ -836,7 +836,7 @@ UsersSelect.prototype.renderRowAvatar = function (issuableType, user, img) {
|
||||||
? spriteIcon('warning-solid', 's12 merge-icon')
|
? spriteIcon('warning-solid', 's12 merge-icon')
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
return `<span class="position-relative mr-2">
|
return `<span class="gl-relative gl-mr-3">
|
||||||
${img}
|
${img}
|
||||||
${mergeIcon}
|
${mergeIcon}
|
||||||
</span>`;
|
</span>`;
|
||||||
|
@ -851,7 +851,7 @@ UsersSelect.prototype.renderApprovalRules = function (elsClassName, approvalRule
|
||||||
|
|
||||||
const [rule] = approvalRules;
|
const [rule] = approvalRules;
|
||||||
const countText = sprintf(__('(+%{count} rules)'), { count });
|
const countText = sprintf(__('(+%{count} rules)'), { count });
|
||||||
const renderApprovalRulesCount = count > 1 ? `<span class="ml-1">${countText}</span>` : '';
|
const renderApprovalRulesCount = count > 1 ? `<span class="gl-ml-2">${countText}</span>` : '';
|
||||||
const ruleName = rule.rule_type === 'code_owner' ? __('Code Owner') : escape(rule.name);
|
const ruleName = rule.rule_type === 'code_owner' ? __('Code Owner') : escape(rule.name);
|
||||||
|
|
||||||
return `<div class="gl-display-flex gl-font-sm">
|
return `<div class="gl-display-flex gl-font-sm">
|
||||||
|
|
|
@ -69,6 +69,11 @@ class ProjectFeature < ApplicationRecord
|
||||||
default_value_for :metrics_dashboard_access_level, value: PRIVATE, allows_nil: false
|
default_value_for :metrics_dashboard_access_level, value: PRIVATE, allows_nil: false
|
||||||
default_value_for :operations_access_level, value: ENABLED, allows_nil: false
|
default_value_for :operations_access_level, value: ENABLED, allows_nil: false
|
||||||
default_value_for :security_and_compliance_access_level, value: PRIVATE, allows_nil: false
|
default_value_for :security_and_compliance_access_level, value: PRIVATE, allows_nil: false
|
||||||
|
default_value_for :monitor_access_level, value: ENABLED, allows_nil: false
|
||||||
|
default_value_for :infrastructure_access_level, value: ENABLED, allows_nil: false
|
||||||
|
default_value_for :feature_flags_access_level, value: ENABLED, allows_nil: false
|
||||||
|
default_value_for :environments_access_level, value: ENABLED, allows_nil: false
|
||||||
|
default_value_for :releases_access_level, value: ENABLED, allows_nil: false
|
||||||
|
|
||||||
default_value_for(:pages_access_level, allows_nil: false) do |feature|
|
default_value_for(:pages_access_level, allows_nil: false) do |feature|
|
||||||
if ::Gitlab::Pages.access_control_is_forced?
|
if ::Gitlab::Pages.access_control_is_forced?
|
||||||
|
|
|
@ -10,6 +10,7 @@ module Projects
|
||||||
def execute
|
def execute
|
||||||
build_topics
|
build_topics
|
||||||
remove_unallowed_params
|
remove_unallowed_params
|
||||||
|
mirror_operations_access_level_changes
|
||||||
validate!
|
validate!
|
||||||
|
|
||||||
ensure_wiki_exists if enabling_wiki?
|
ensure_wiki_exists if enabling_wiki?
|
||||||
|
@ -82,6 +83,21 @@ module Projects
|
||||||
params.delete(:emails_disabled) unless can?(current_user, :set_emails_disabled, project)
|
params.delete(:emails_disabled) unless can?(current_user, :set_emails_disabled, project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Temporary code to sync permissions changes as operations access setting
|
||||||
|
# is being split into monitor_access_level, deployments_access_level, infrastructure_access_level.
|
||||||
|
# To be removed as part of https://gitlab.com/gitlab-org/gitlab/-/issues/364240
|
||||||
|
def mirror_operations_access_level_changes
|
||||||
|
return if Feature.enabled?(:split_operations_visibility_permissions, project)
|
||||||
|
|
||||||
|
operations_access_level = params.dig(:project_feature_attributes, :operations_access_level)
|
||||||
|
|
||||||
|
return if operations_access_level.nil?
|
||||||
|
|
||||||
|
[:monitor_access_level, :infrastructure_access_level, :feature_flags_access_level, :environments_access_level].each do |key|
|
||||||
|
params[:project_feature_attributes][key] = operations_access_level
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def after_update
|
def after_update
|
||||||
todos_features_changes = %w(
|
todos_features_changes = %w(
|
||||||
issues_access_level
|
issues_access_level
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: split_operations_visibility_permissions
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89089
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/364240
|
||||||
|
milestone: '15.1'
|
||||||
|
type: development
|
||||||
|
group: group::respond
|
||||||
|
default_enabled: false
|
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddOperationsAccessLevelsToProjectFeature < Gitlab::Database::Migration[2.0]
|
||||||
|
OPERATIONS_DEFAULT_VALUE = 20
|
||||||
|
|
||||||
|
enable_lock_retries!
|
||||||
|
|
||||||
|
# rubocop:disable Layout/LineLength
|
||||||
|
def up
|
||||||
|
add_column :project_features, :monitor_access_level, :integer, null: false, default: OPERATIONS_DEFAULT_VALUE
|
||||||
|
add_column :project_features, :infrastructure_access_level, :integer, null: false, default: OPERATIONS_DEFAULT_VALUE
|
||||||
|
add_column :project_features, :feature_flags_access_level, :integer, null: false, default: OPERATIONS_DEFAULT_VALUE
|
||||||
|
add_column :project_features, :environments_access_level, :integer, null: false, default: OPERATIONS_DEFAULT_VALUE
|
||||||
|
add_column :project_features, :releases_access_level, :integer, null: false, default: OPERATIONS_DEFAULT_VALUE
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :project_features, :monitor_access_level
|
||||||
|
remove_column :project_features, :infrastructure_access_level
|
||||||
|
remove_column :project_features, :feature_flags_access_level
|
||||||
|
remove_column :project_features, :environments_access_level
|
||||||
|
remove_column :project_features, :releases_access_level
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,29 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class PopulateOperationVisibilityPermissions < Gitlab::Database::Migration[2.0]
|
||||||
|
BATCH_SIZE = 50_000
|
||||||
|
MAX_BATCH_SIZE = 50_000
|
||||||
|
SUB_BATCH_SIZE = 1_000
|
||||||
|
INTERVAL = 2.minutes
|
||||||
|
MIGRATION = 'PopulateOperationVisibilityPermissionsFromOperations'
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||||
|
|
||||||
|
def up
|
||||||
|
queue_batched_background_migration(
|
||||||
|
MIGRATION,
|
||||||
|
:project_features,
|
||||||
|
:id,
|
||||||
|
job_interval: INTERVAL,
|
||||||
|
batch_size: BATCH_SIZE,
|
||||||
|
max_batch_size: MAX_BATCH_SIZE,
|
||||||
|
sub_batch_size: SUB_BATCH_SIZE
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
delete_batched_background_migration(MIGRATION, :project_features, :id, [])
|
||||||
|
end
|
||||||
|
end
|
1
db/schema_migrations/20220531024905
Normal file
1
db/schema_migrations/20220531024905
Normal file
|
@ -0,0 +1 @@
|
||||||
|
3470fa801f5d6c343c95d78a710aa1907a581575465718c8d971f4b8f305a39b
|
1
db/schema_migrations/20220531035113
Normal file
1
db/schema_migrations/20220531035113
Normal file
|
@ -0,0 +1 @@
|
||||||
|
4e4e158655d40797c4f9152ad3e4f8b9b4894ce1ce92bf89c6219f9c69847c45
|
|
@ -19350,7 +19350,12 @@ CREATE TABLE project_features (
|
||||||
analytics_access_level integer DEFAULT 20 NOT NULL,
|
analytics_access_level integer DEFAULT 20 NOT NULL,
|
||||||
security_and_compliance_access_level integer DEFAULT 10 NOT NULL,
|
security_and_compliance_access_level integer DEFAULT 10 NOT NULL,
|
||||||
container_registry_access_level integer DEFAULT 0 NOT NULL,
|
container_registry_access_level integer DEFAULT 0 NOT NULL,
|
||||||
package_registry_access_level integer DEFAULT 0 NOT NULL
|
package_registry_access_level integer DEFAULT 0 NOT NULL,
|
||||||
|
monitor_access_level integer DEFAULT 20 NOT NULL,
|
||||||
|
infrastructure_access_level integer DEFAULT 20 NOT NULL,
|
||||||
|
feature_flags_access_level integer DEFAULT 20 NOT NULL,
|
||||||
|
environments_access_level integer DEFAULT 20 NOT NULL,
|
||||||
|
releases_access_level integer DEFAULT 20 NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE SEQUENCE project_features_id_seq
|
CREATE SEQUENCE project_features_id_seq
|
||||||
|
|
|
@ -156,7 +156,8 @@ Each streaming destination can have up to 20 custom HTTP headers included with e
|
||||||
|
|
||||||
### Add with the API
|
### Add with the API
|
||||||
|
|
||||||
Group owners can add a HTTP header using the GraphQL `auditEventsStreamingHeadersCreate` mutation.
|
Group owners can add a HTTP header using the GraphQL `auditEventsStreamingHeadersCreate` mutation. You can retrieve the destination ID
|
||||||
|
by [listing the external audit destinations](#list-streaming-destinations) on the group.
|
||||||
|
|
||||||
```graphql
|
```graphql
|
||||||
mutation {
|
mutation {
|
||||||
|
@ -166,19 +167,48 @@ mutation {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The header is created if the returned `errors` object is empty.
|
||||||
|
|
||||||
### Delete with the API
|
### Delete with the API
|
||||||
|
|
||||||
Group owners can remove a HTTP header using the GraphQL `auditEventsStreamingHeadersDestroy` mutation.
|
Group owners can remove a HTTP header using the GraphQL `auditEventsStreamingHeadersDestroy` mutation. You can retrieve the header ID
|
||||||
|
by [listing all the custom headers](#list-all-custom-headers-with-the-api) on the group.
|
||||||
|
|
||||||
```graphql
|
```graphql
|
||||||
mutation {
|
mutation {
|
||||||
auditEventsStreamingHeadersDestroy(input: { headerId: "gid://gitlab/AuditEvents::ExternalAuditEventDestination/24601" }) {
|
auditEventsStreamingHeadersDestroy(input: { headerId: "gid://gitlab/AuditEvents::Streaming::Header/1" }) {
|
||||||
errors
|
errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The header is created if the returned `errors` object is empty.
|
The header is deleted if the returned `errors` object is empty.
|
||||||
|
|
||||||
|
### List all custom headers with the API
|
||||||
|
|
||||||
|
You can list all custom headers for a top-level group as well as their value and ID using the GraphQL `externalAuditEventDestinations` query. The ID
|
||||||
|
value returned by this query is what you need to pass to the `deletion` mutation.
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
query {
|
||||||
|
group(fullPath: "your-group") {
|
||||||
|
id
|
||||||
|
externalAuditEventDestinations {
|
||||||
|
nodes {
|
||||||
|
destinationUrl
|
||||||
|
id
|
||||||
|
headers {
|
||||||
|
nodes {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Verify event authenticity
|
## Verify event authenticity
|
||||||
|
|
||||||
|
|
|
@ -700,7 +700,7 @@ GET /user/status
|
||||||
```
|
```
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/user/status"
|
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/user/status"
|
||||||
```
|
```
|
||||||
|
|
||||||
Example response:
|
Example response:
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
module BackgroundMigration
|
||||||
|
# Migrates the value operations_access_level to the new colums
|
||||||
|
# monitor_access_level, deployments_access_level, infrastructure_access_level.
|
||||||
|
# The operations_access_level setting is being split into three seperate toggles.
|
||||||
|
class PopulateOperationVisibilityPermissionsFromOperations < BatchedMigrationJob
|
||||||
|
def perform
|
||||||
|
each_sub_batch(operation_name: :populate_operations_visibility) do |batch|
|
||||||
|
batch.update_all('monitor_access_level=operations_access_level,' \
|
||||||
|
'infrastructure_access_level=operations_access_level,' \
|
||||||
|
' feature_flags_access_level=operations_access_level,'\
|
||||||
|
' environments_access_level=operations_access_level')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def mark_job_as_succeeded(*arguments)
|
||||||
|
Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
|
||||||
|
'PopulateOperationVisibilityPermissionsFromOperations',
|
||||||
|
arguments
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,80 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Gitlab::BackgroundMigration::PopulateOperationVisibilityPermissionsFromOperations do
|
||||||
|
let(:namespaces) { table(:namespaces) }
|
||||||
|
let(:project_features) { table(:project_features) }
|
||||||
|
let(:projects) { table(:projects) }
|
||||||
|
|
||||||
|
let(:namespace) { namespaces.create!(name: 'user', path: 'user') }
|
||||||
|
|
||||||
|
let(:proj_namespace1) { namespaces.create!(name: 'proj1', path: 'proj1', type: 'Project', parent_id: namespace.id) }
|
||||||
|
let(:proj_namespace2) { namespaces.create!(name: 'proj2', path: 'proj2', type: 'Project', parent_id: namespace.id) }
|
||||||
|
let(:proj_namespace3) { namespaces.create!(name: 'proj3', path: 'proj3', type: 'Project', parent_id: namespace.id) }
|
||||||
|
|
||||||
|
let(:project1) { create_project('test1', proj_namespace1) }
|
||||||
|
let(:project2) { create_project('test2', proj_namespace2) }
|
||||||
|
let(:project3) { create_project('test3', proj_namespace3) }
|
||||||
|
|
||||||
|
let!(:record1) { create_project_feature(project1) }
|
||||||
|
let!(:record2) { create_project_feature(project2, 20) }
|
||||||
|
let!(:record3) { create_project_feature(project3) }
|
||||||
|
|
||||||
|
let(:sub_batch_size) { 2 }
|
||||||
|
let(:start_id) { record1.id }
|
||||||
|
let(:end_id) { record3.id }
|
||||||
|
let(:batch_table) { :project_features }
|
||||||
|
let(:batch_column) { :id }
|
||||||
|
let(:pause_ms) { 1 }
|
||||||
|
let(:connection) { ApplicationRecord.connection }
|
||||||
|
|
||||||
|
let(:job) do
|
||||||
|
described_class.new(
|
||||||
|
start_id: start_id,
|
||||||
|
end_id: end_id,
|
||||||
|
batch_table: batch_table,
|
||||||
|
batch_column: batch_column,
|
||||||
|
sub_batch_size: sub_batch_size,
|
||||||
|
pause_ms: pause_ms,
|
||||||
|
connection: connection
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject(:perform) { job.perform }
|
||||||
|
|
||||||
|
it 'updates all project settings records from their operations_access_level', :aggregate_failures do
|
||||||
|
perform
|
||||||
|
|
||||||
|
expect_project_features_match_operations_access_level(record1)
|
||||||
|
expect_project_features_match_operations_access_level(record2)
|
||||||
|
expect_project_features_match_operations_access_level(record3)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def expect_project_features_match_operations_access_level(record)
|
||||||
|
record.reload
|
||||||
|
expect(record.monitor_access_level).to eq(record.operations_access_level)
|
||||||
|
expect(record.infrastructure_access_level).to eq(record.operations_access_level)
|
||||||
|
expect(record.feature_flags_access_level).to eq(record.operations_access_level)
|
||||||
|
expect(record.environments_access_level).to eq(record.operations_access_level)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_project(proj_name, proj_namespace)
|
||||||
|
projects.create!(
|
||||||
|
namespace_id: namespace.id,
|
||||||
|
project_namespace_id: proj_namespace.id,
|
||||||
|
name: proj_name,
|
||||||
|
path: proj_name
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_project_feature(project, operations_access_level = 10)
|
||||||
|
project_features.create!(
|
||||||
|
project_id: project.id,
|
||||||
|
pages_access_level: 10,
|
||||||
|
operations_access_level: operations_access_level
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,32 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
require_migration!
|
||||||
|
|
||||||
|
RSpec.describe PopulateOperationVisibilityPermissions, :migration do
|
||||||
|
let(:migration) { described_class::MIGRATION }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_const("#{described_class.name}::SUB_BATCH_SIZE", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'schedules background migrations', :aggregate_failures do
|
||||||
|
migrate!
|
||||||
|
|
||||||
|
expect(migration).to have_scheduled_batched_migration(
|
||||||
|
table_name: :project_features,
|
||||||
|
column_name: :id,
|
||||||
|
interval: described_class::INTERVAL
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#down' do
|
||||||
|
it 'deletes all batched migration records' do
|
||||||
|
migrate!
|
||||||
|
schema_migrate_down!
|
||||||
|
|
||||||
|
expect(migration).not_to have_scheduled_batched_migration
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -124,6 +124,11 @@ project_feature:
|
||||||
- created_at
|
- created_at
|
||||||
- metrics_dashboard_access_level
|
- metrics_dashboard_access_level
|
||||||
- package_registry_access_level
|
- package_registry_access_level
|
||||||
|
- monitor_access_level
|
||||||
|
- infrastructure_access_level
|
||||||
|
- feature_flags_access_level
|
||||||
|
- environments_access_level
|
||||||
|
- releases_access_level
|
||||||
- project_id
|
- project_id
|
||||||
- updated_at
|
- updated_at
|
||||||
computed_attributes:
|
computed_attributes:
|
||||||
|
|
|
@ -289,6 +289,42 @@ RSpec.describe Projects::UpdateService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when changing operations feature visibility' do
|
||||||
|
let(:feature_params) { { operations_access_level: ProjectFeature::DISABLED } }
|
||||||
|
|
||||||
|
it 'does not sync the changes to the related fields' do
|
||||||
|
result = update_project(project, user, project_feature_attributes: feature_params)
|
||||||
|
|
||||||
|
expect(result).to eq({ status: :success })
|
||||||
|
feature = project.project_feature
|
||||||
|
|
||||||
|
expect(feature.operations_access_level).to eq(ProjectFeature::DISABLED)
|
||||||
|
expect(feature.monitor_access_level).not_to eq(ProjectFeature::DISABLED)
|
||||||
|
expect(feature.infrastructure_access_level).not_to eq(ProjectFeature::DISABLED)
|
||||||
|
expect(feature.feature_flags_access_level).not_to eq(ProjectFeature::DISABLED)
|
||||||
|
expect(feature.environments_access_level).not_to eq(ProjectFeature::DISABLED)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when split_operations_visibility_permissions feature is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(split_operations_visibility_permissions: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'syncs the changes to the related fields' do
|
||||||
|
result = update_project(project, user, project_feature_attributes: feature_params)
|
||||||
|
|
||||||
|
expect(result).to eq({ status: :success })
|
||||||
|
feature = project.project_feature
|
||||||
|
|
||||||
|
expect(feature.operations_access_level).to eq(ProjectFeature::DISABLED)
|
||||||
|
expect(feature.monitor_access_level).to eq(ProjectFeature::DISABLED)
|
||||||
|
expect(feature.infrastructure_access_level).to eq(ProjectFeature::DISABLED)
|
||||||
|
expect(feature.feature_flags_access_level).to eq(ProjectFeature::DISABLED)
|
||||||
|
expect(feature.environments_access_level).to eq(ProjectFeature::DISABLED)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when updating a project that contains container images' do
|
context 'when updating a project that contains container images' do
|
||||||
before do
|
before do
|
||||||
stub_container_registry_config(enabled: true)
|
stub_container_registry_config(enabled: true)
|
||||||
|
|
Loading…
Reference in a new issue