Commit 386abf71 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 0ec5d3f1 1ebcfec5
...@@ -247,16 +247,6 @@ $gl-line-height-42: px-to-rem(42px); ...@@ -247,16 +247,6 @@ $gl-line-height-42: px-to-rem(42px);
max-width: 50%; max-width: 50%;
} }
// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1465
.gl-popover {
.popover-header {
.gl-button.close {
margin-top: -$gl-spacing-scale-3;
margin-right: -$gl-spacing-scale-4;
}
}
}
// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1490 // Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1490
.gl-w-grid-size-28 { .gl-w-grid-size-28 {
width: $grid-size * 28; width: $grid-size * 28;
......
...@@ -9,10 +9,17 @@ module Resolvers ...@@ -9,10 +9,17 @@ module Resolvers
delegate :project, to: :agent delegate :project, to: :agent
argument :status, Types::Clusters::AgentTokenStatusEnum,
required: false,
description: 'Status of the token.'
def resolve(**args) def resolve(**args)
return ::Clusters::AgentToken.none unless can_read_agent_tokens? return ::Clusters::AgentToken.none unless can_read_agent_tokens?
agent.last_used_agent_tokens tokens = agent.last_used_agent_tokens
tokens = tokens.with_status(args[:status]) if args[:status].present?
tokens
end end
private private
......
# frozen_string_literal: true
module Types
module Clusters
class AgentTokenStatusEnum < BaseEnum
graphql_name 'AgentTokenStatus'
description 'Agent token statuses'
::Clusters::AgentToken.statuses.keys.each do |status|
value status.upcase, value: status, description: "#{status.titleize} agent token."
end
end
end
end
...@@ -45,7 +45,7 @@ module Types ...@@ -45,7 +45,7 @@ module Types
description: 'Name given to the token.' description: 'Name given to the token.'
field :status, field :status,
GraphQL::Types::String, Types::Clusters::AgentTokenStatusEnum,
null: true, null: true,
description: 'Current status of the token.' description: 'Current status of the token.'
......
...@@ -22,6 +22,7 @@ module Clusters ...@@ -22,6 +22,7 @@ module Clusters
validates :name, presence: true, length: { maximum: 255 } validates :name, presence: true, length: { maximum: 255 }
scope :order_last_used_at_desc, -> { order(::Gitlab::Database.nulls_last_order('last_used_at', 'DESC')) } scope :order_last_used_at_desc, -> { order(::Gitlab::Database.nulls_last_order('last_used_at', 'DESC')) }
scope :with_status, -> (status) { where(status: status) }
enum status: { enum status: {
active: 0, active: 0,
......
...@@ -12,9 +12,6 @@ class NamespaceSetting < ApplicationRecord ...@@ -12,9 +12,6 @@ class NamespaceSetting < ApplicationRecord
validate :allow_mfa_for_group validate :allow_mfa_for_group
validate :allow_resource_access_token_creation_for_group validate :allow_resource_access_token_creation_for_group
before_save :set_prevent_sharing_groups_outside_hierarchy, if: -> { user_cap_enabled? }
after_save :disable_project_sharing!, if: -> { user_cap_enabled? }
before_validation :normalize_default_branch_name before_validation :normalize_default_branch_name
enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true
...@@ -59,18 +56,6 @@ class NamespaceSetting < ApplicationRecord ...@@ -59,18 +56,6 @@ class NamespaceSetting < ApplicationRecord
errors.add(:resource_access_token_creation_allowed, _('is not allowed since the group is not top-level group.')) errors.add(:resource_access_token_creation_allowed, _('is not allowed since the group is not top-level group.'))
end end
end end
def set_prevent_sharing_groups_outside_hierarchy
self.prevent_sharing_groups_outside_hierarchy = true
end
def disable_project_sharing!
namespace.update_attribute(:share_with_group_lock, true)
end
def user_cap_enabled?
new_user_signups_cap.present? && namespace.root?
end
end end
NamespaceSetting.prepend_mod_with('NamespaceSetting') NamespaceSetting.prepend_mod_with('NamespaceSetting')
...@@ -9027,10 +9027,27 @@ GitLab CI/CD configuration template. ...@@ -9027,10 +9027,27 @@ GitLab CI/CD configuration template.
| <a id="clusteragentid"></a>`id` | [`ID!`](#id) | ID of the cluster agent. | | <a id="clusteragentid"></a>`id` | [`ID!`](#id) | ID of the cluster agent. |
| <a id="clusteragentname"></a>`name` | [`String`](#string) | Name of the cluster agent. | | <a id="clusteragentname"></a>`name` | [`String`](#string) | Name of the cluster agent. |
| <a id="clusteragentproject"></a>`project` | [`Project`](#project) | Project this cluster agent is associated with. | | <a id="clusteragentproject"></a>`project` | [`Project`](#project) | Project this cluster agent is associated with. |
| <a id="clusteragenttokens"></a>`tokens` | [`ClusterAgentTokenConnection`](#clusteragenttokenconnection) | Tokens associated with the cluster agent. (see [Connections](#connections)) |
| <a id="clusteragentupdatedat"></a>`updatedAt` | [`Time`](#time) | Timestamp the cluster agent was updated. | | <a id="clusteragentupdatedat"></a>`updatedAt` | [`Time`](#time) | Timestamp the cluster agent was updated. |
| <a id="clusteragentwebpath"></a>`webPath` | [`String`](#string) | Web path of the cluster agent. | | <a id="clusteragentwebpath"></a>`webPath` | [`String`](#string) | Web path of the cluster agent. |
#### Fields with arguments
##### `ClusterAgent.tokens`
Tokens associated with the cluster agent.
Returns [`ClusterAgentTokenConnection`](#clusteragenttokenconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="clusteragenttokensstatus"></a>`status` | [`AgentTokenStatus`](#agenttokenstatus) | Status of the token. |
### `ClusterAgentActivityEvent` ### `ClusterAgentActivityEvent`
#### Fields #### Fields
...@@ -9056,7 +9073,7 @@ GitLab CI/CD configuration template. ...@@ -9056,7 +9073,7 @@ GitLab CI/CD configuration template.
| <a id="clusteragenttokenid"></a>`id` | [`ClustersAgentTokenID!`](#clustersagenttokenid) | Global ID of the token. | | <a id="clusteragenttokenid"></a>`id` | [`ClustersAgentTokenID!`](#clustersagenttokenid) | Global ID of the token. |
| <a id="clusteragenttokenlastusedat"></a>`lastUsedAt` | [`Time`](#time) | Timestamp the token was last used. | | <a id="clusteragenttokenlastusedat"></a>`lastUsedAt` | [`Time`](#time) | Timestamp the token was last used. |
| <a id="clusteragenttokenname"></a>`name` | [`String`](#string) | Name given to the token. | | <a id="clusteragenttokenname"></a>`name` | [`String`](#string) | Name given to the token. |
| <a id="clusteragenttokenstatus"></a>`status` | [`String`](#string) | Current status of the token. | | <a id="clusteragenttokenstatus"></a>`status` | [`AgentTokenStatus`](#agenttokenstatus) | Current status of the token. |
### `CodeCoverageActivity` ### `CodeCoverageActivity`
...@@ -16150,6 +16167,15 @@ Access level to a resource. ...@@ -16150,6 +16167,15 @@ Access level to a resource.
| <a id="accesslevelenumowner"></a>`OWNER` | Owner access. | | <a id="accesslevelenumowner"></a>`OWNER` | Owner access. |
| <a id="accesslevelenumreporter"></a>`REPORTER` | Reporter access. | | <a id="accesslevelenumreporter"></a>`REPORTER` | Reporter access. |
### `AgentTokenStatus`
Agent token statuses.
| Value | Description |
| ----- | ----------- |
| <a id="agenttokenstatusactive"></a>`ACTIVE` | Active agent token. |
| <a id="agenttokenstatusrevoked"></a>`REVOKED` | Revoked agent token. |
### `AlertManagementAlertSort` ### `AlertManagementAlertSort`
Values for sorting alerts. Values for sorting alerts.
...@@ -523,6 +523,14 @@ module EE ...@@ -523,6 +523,14 @@ module EE
user_cap <= members_count user_cap <= members_count
end end
def shared_externally?
strong_memoize(:shared_externally) do
invited_group_in_groups
.where.not(group_group_links: { shared_with_group_id: ::Group.groups_including_descendants_by([self]) })
.limit(1).any?
end
end
private private
override :post_create_hook override :post_create_hook
......
...@@ -4,14 +4,47 @@ module EE ...@@ -4,14 +4,47 @@ module EE
module NamespaceSetting module NamespaceSetting
extend ActiveSupport::Concern extend ActiveSupport::Concern
delegate :root_ancestor, to: :namespace prepended do
validate :user_cap_allowed, if: -> { enabling_user_cap? }
def prevent_forking_outside_group? before_save :set_prevent_sharing_groups_outside_hierarchy, if: -> { user_cap_enabled? }
saml_setting = root_ancestor.saml_provider&.prohibited_outer_forks? after_save :disable_project_sharing!, if: -> { user_cap_enabled? }
return saml_setting unless namespace.feature_available?(:group_forking_protection) delegate :root_ancestor, to: :namespace
saml_setting || root_ancestor.namespace_settings&.prevent_forking_outside_group def prevent_forking_outside_group?
saml_setting = root_ancestor.saml_provider&.prohibited_outer_forks?
return saml_setting unless namespace.feature_available?(:group_forking_protection)
saml_setting || root_ancestor.namespace_settings&.prevent_forking_outside_group
end
private
def enabling_user_cap?
return false unless persisted? && new_user_signups_cap_changed?
new_user_signups_cap_was.nil?
end
def user_cap_allowed
return if namespace.user_cap_available? && namespace.root? && !namespace.shared_externally?
errors.add(:new_user_signups_cap, _("cannot be enabled"))
end
def set_prevent_sharing_groups_outside_hierarchy
self.prevent_sharing_groups_outside_hierarchy = true
end
def disable_project_sharing!
namespace.update_attribute(:share_with_group_lock, true)
end
def user_cap_enabled?
new_user_signups_cap.present? && namespace.root?
end
end end
end end
end end
...@@ -629,6 +629,15 @@ RSpec.describe GroupsController do ...@@ -629,6 +629,15 @@ RSpec.describe GroupsController do
end end
context 'authenticated as group owner' do context 'authenticated as group owner' do
before do
allow_next_found_instance_of(Group) do |group|
allow(group).to receive(:user_cap_available?).and_return(true)
end
group.add_owner(user)
sign_in(user)
end
where(:new_user_signups_cap, :result, :status) do where(:new_user_signups_cap, :result, :status) do
nil | nil | :found nil | nil | :found
10 | 10 | :found 10 | 10 | :found
...@@ -639,11 +648,6 @@ RSpec.describe GroupsController do ...@@ -639,11 +648,6 @@ RSpec.describe GroupsController do
{ id: group.to_param, group: { new_user_signups_cap: new_user_signups_cap } } { id: group.to_param, group: { new_user_signups_cap: new_user_signups_cap } }
end end
before do
group.add_owner(user)
sign_in(user)
end
it_behaves_like 'updates the attribute' it_behaves_like 'updates the attribute'
end end
end end
......
...@@ -7,6 +7,7 @@ exports[`Corpus upload modal corpus modal uploading state does show the upload p ...@@ -7,6 +7,7 @@ exports[`Corpus upload modal corpus modal uploading state does show the upload p
> >
<span <span
class="gl-spinner-container" class="gl-spinner-container"
role="status"
> >
<span <span
aria-label="Loading" aria-label="Loading"
......
...@@ -5,6 +5,7 @@ exports[`Security Dashboard default states sets up group-level 1`] = ` ...@@ -5,6 +5,7 @@ exports[`Security Dashboard default states sets up group-level 1`] = `
<div> <div>
<div <div
class="gl-spinner-container gl-mt-6" class="gl-spinner-container gl-mt-6"
role="status"
> >
<span <span
aria-label="Loading" aria-label="Loading"
...@@ -20,6 +21,7 @@ exports[`Security Dashboard default states sets up instance-level 1`] = ` ...@@ -20,6 +21,7 @@ exports[`Security Dashboard default states sets up instance-level 1`] = `
<div> <div>
<div <div
class="gl-spinner-container gl-mt-6" class="gl-spinner-container gl-mt-6"
role="status"
> >
<span <span
aria-label="Loading" aria-label="Loading"
......
...@@ -1521,6 +1521,7 @@ RSpec.describe Group do ...@@ -1521,6 +1521,7 @@ RSpec.describe Group do
shared_examples 'returning the right value for user_cap_reached?' do shared_examples 'returning the right value for user_cap_reached?' do
before do before do
allow(root_group).to receive(:user_cap_available?).and_return(true)
root_group.namespace_settings.update!(new_user_signups_cap: new_user_signups_cap) root_group.namespace_settings.update!(new_user_signups_cap: new_user_signups_cap)
end end
...@@ -1571,6 +1572,43 @@ RSpec.describe Group do ...@@ -1571,6 +1572,43 @@ RSpec.describe Group do
end end
end end
describe '#shared_externally?' do
let_it_be(:group, refind: true) { create(:group) }
let_it_be(:subgroup_1) { create(:group, parent: group) }
let_it_be(:subgroup_2) { create(:group, parent: group) }
let_it_be(:external_group) { create(:group) }
subject(:shared_externally?) { group.shared_externally? }
it 'returns false when the group is not shared outside of the namespace hierarchy' do
expect(shared_externally?).to be false
end
it 'returns true when the group is shared outside of the namespace hierarchy' do
create(:group_group_link, shared_group: group, shared_with_group: external_group)
expect(shared_externally?).to be true
end
it 'returns false when the group is shared internally within the namespace hierarchy' do
create(:group_group_link, shared_group: subgroup_1, shared_with_group: subgroup_2)
expect(shared_externally?).to be false
end
it 'returns true when a subgroup is shared outside of the namespace hierarchy' do
create(:group_group_link, shared_group: subgroup_1, shared_with_group: external_group)
expect(shared_externally?).to be true
end
it 'returns false when the only shared groups are outside of the namespace hierarchy' do
create(:group_group_link)
expect(shared_externally?).to be false
end
end
it_behaves_like 'can move repository storage' do it_behaves_like 'can move repository storage' do
let_it_be(:container) { create(:group, :wiki_repo) } let_it_be(:container) { create(:group, :wiki_repo) }
......
...@@ -96,4 +96,128 @@ RSpec.describe NamespaceSetting do ...@@ -96,4 +96,128 @@ RSpec.describe NamespaceSetting do
end end
end end
end end
context 'validating new_user_signup_cap' do
using RSpec::Parameterized::TableSyntax
where(:feature_available, :old_value, :new_value, :expectation) do
true | nil | 10 | true
true | 0 | 10 | true
true | 0 | 0 | true
false | nil | 10 | false
false | 10 | 10 | true
end
with_them do
let(:setting) { build(:namespace_settings, new_user_signups_cap: old_value) }
let(:group) { create(:group, namespace_settings: setting) }
before do
allow(group).to receive(:user_cap_available?).and_return feature_available
setting.new_user_signups_cap = new_value
end
it 'returns the expected response' do
expect(setting.valid?).to be expectation
expect(setting.errors.messages[:new_user_signups_cap]).to include("cannot be enabled") unless expectation
end
end
context 'when enabling the setting' do
let(:feature_available) { true }
before do
allow(group).to receive(:user_cap_available?).and_return feature_available
setting.new_user_signups_cap = 10
end
shared_examples 'user cap is not available' do
it 'is invalid' do
expect(setting.valid?).to be false
expect(setting.errors.messages[:new_user_signups_cap]).to include("cannot be enabled")
end
end
context 'when the group is a subgroup' do
before do
group.parent = build(:group)
end
it_behaves_like 'user cap is not available'
end
context 'when the group is shared externally' do
before do
create(:group_group_link, shared_group: group)
end
it_behaves_like 'user cap is not available'
end
context 'when the namespace is a user' do
let(:user) { create(:user) }
let(:setting) { user.namespace.namespace_settings }
it_behaves_like 'user cap is not available'
end
end
end
context 'hooks related to group user cap update' do
let(:group) { create(:group) }
let(:settings) { group.namespace_settings }
before do
allow(group).to receive(:root?).and_return(true)
allow(group).to receive(:user_cap_available?).and_return(true)
group.namespace_settings.update!(new_user_signups_cap: user_cap)
end
context 'when updating a group with a user cap' do
let(:user_cap) { nil }
it 'also sets share_with_group_lock and prevent_sharing_groups_outside_hierarchy to true' do
expect(group.new_user_signups_cap).to be_nil
expect(group.share_with_group_lock).to be_falsey
expect(settings.prevent_sharing_groups_outside_hierarchy).to be_falsey
settings.update!(new_user_signups_cap: 10)
group.reload
expect(group.new_user_signups_cap).to eq(10)
expect(group.share_with_group_lock).to be_truthy
expect(settings.reload.prevent_sharing_groups_outside_hierarchy).to be_truthy
end
it 'has share_with_group_lock and prevent_sharing_groups_outside_hierarchy returning true for descendent groups' do
descendent = create(:group, parent: group)
desc_settings = descendent.namespace_settings
expect(descendent.share_with_group_lock).to be_falsey
expect(desc_settings.prevent_sharing_groups_outside_hierarchy).to be_falsey
settings.update!(new_user_signups_cap: 10)
expect(descendent.reload.share_with_group_lock).to be_truthy
expect(desc_settings.reload.prevent_sharing_groups_outside_hierarchy).to be_truthy
end
end
context 'when removing a user cap from namespace settings' do
let(:user_cap) { 10 }
it 'leaves share_with_group_lock and prevent_sharing_groups_outside_hierarchy set to true to the related group' do
expect(group.share_with_group_lock).to be_truthy
expect(settings.prevent_sharing_groups_outside_hierarchy).to be_truthy
settings.update!(new_user_signups_cap: nil)
expect(group.reload.share_with_group_lock).to be_truthy
expect(settings.reload.prevent_sharing_groups_outside_hierarchy).to be_truthy
end
end
end
end end
...@@ -41541,6 +41541,9 @@ msgstr "" ...@@ -41541,6 +41541,9 @@ msgstr ""
msgid "cannot be changed if shared runners are enabled" msgid "cannot be changed if shared runners are enabled"
msgstr "" msgstr ""
msgid "cannot be enabled"
msgstr ""
msgid "cannot be enabled because parent group does not allow it" msgid "cannot be enabled because parent group does not allow it"
msgstr "" msgstr ""
......
...@@ -7,5 +7,9 @@ FactoryBot.define do ...@@ -7,5 +7,9 @@ FactoryBot.define do
token_encrypted { Gitlab::CryptoHelper.aes256_gcm_encrypt(SecureRandom.hex(50)) } token_encrypted { Gitlab::CryptoHelper.aes256_gcm_encrypt(SecureRandom.hex(50)) }
sequence(:name) { |n| "agent-token-#{n}" } sequence(:name) { |n| "agent-token-#{n}" }
trait :revoked do
status { :revoked }
end
end end
end end
...@@ -7,6 +7,7 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do ...@@ -7,6 +7,7 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do
it { expect(described_class.type).to eq(Types::Clusters::AgentTokenType) } it { expect(described_class.type).to eq(Types::Clusters::AgentTokenType) }
it { expect(described_class.null).to be_truthy } it { expect(described_class.null).to be_truthy }
it { expect(described_class.arguments.keys).to contain_exactly('status') }
describe '#resolve' do describe '#resolve' do
let(:agent) { create(:cluster_agent) } let(:agent) { create(:cluster_agent) }
...@@ -23,6 +24,14 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do ...@@ -23,6 +24,14 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do
expect(subject).to eq([matching_token2, matching_token1]) expect(subject).to eq([matching_token2, matching_token1])
end end
context 'token status is specified' do
let!(:revoked_token) { create(:cluster_agent_token, :revoked, agent: agent) }
subject { resolve(described_class, obj: agent, ctx: ctx, args: { status: 'revoked' }) }
it { is_expected.to contain_exactly(revoked_token) }
end
context 'user does not have permission' do context 'user does not have permission' do
let(:user) { create(:user, developer_projects: [agent.project]) } let(:user) { create(:user, developer_projects: [agent.project]) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Types::Clusters::AgentTokenStatusEnum do
it { expect(described_class.graphql_name).to eq('AgentTokenStatus') }
it { expect(described_class.values.keys).to match_array(Clusters::AgentToken.statuses.keys.map(&:upcase)) }
end
...@@ -13,15 +13,25 @@ RSpec.describe Clusters::AgentToken do ...@@ -13,15 +13,25 @@ RSpec.describe Clusters::AgentToken do
describe 'scopes' do describe 'scopes' do
describe '.order_last_used_at_desc' do describe '.order_last_used_at_desc' do
let_it_be(:token_1) { create(:cluster_agent_token, last_used_at: 7.days.ago) } let_it_be(:agent) { create(:cluster_agent) }
let_it_be(:token_2) { create(:cluster_agent_token, last_used_at: nil) } let_it_be(:token_1) { create(:cluster_agent_token, agent: agent, last_used_at: 7.days.ago) }
let_it_be(:token_3) { create(:cluster_agent_token, last_used_at: 2.days.ago) } let_it_be(:token_2) { create(:cluster_agent_token, agent: agent, last_used_at: nil) }
let_it_be(:token_3) { create(:cluster_agent_token, agent: agent, last_used_at: 2.days.ago) }
it 'sorts by last_used_at descending, with null values at last' do it 'sorts by last_used_at descending, with null values at last' do
expect(described_class.order_last_used_at_desc) expect(described_class.order_last_used_at_desc)
.to eq([token_3, token_1, token_2]) .to eq([token_3, token_1, token_2])
end end
end end
describe '.with_status' do
let!(:active_token) { create(:cluster_agent_token) }
let!(:revoked_token) { create(:cluster_agent_token, :revoked) }
subject { described_class.with_status(:active) }
it { is_expected.to contain_exactly(active_token) }
end
end end
describe '#token' do describe '#token' do
......
...@@ -126,57 +126,4 @@ RSpec.describe NamespaceSetting, type: :model do ...@@ -126,57 +126,4 @@ RSpec.describe NamespaceSetting, type: :model do
end end
end end
end end
describe 'hooks related to group user cap update' do
let(:settings) { create(:namespace_settings, new_user_signups_cap: user_cap) }
let(:group) { create(:group, namespace_settings: settings) }
before do
allow(group).to receive(:root?).and_return(true)
end
context 'when updating a group with a user cap' do
let(:user_cap) { nil }
it 'also sets share_with_group_lock and prevent_sharing_groups_outside_hierarchy to true' do
expect(group.new_user_signups_cap).to be_nil
expect(group.share_with_group_lock).to be_falsey
expect(settings.prevent_sharing_groups_outside_hierarchy).to be_falsey
settings.update!(new_user_signups_cap: 10)
group.reload
expect(group.new_user_signups_cap).to eq(10)
expect(group.share_with_group_lock).to be_truthy
expect(settings.reload.prevent_sharing_groups_outside_hierarchy).to be_truthy
end
it 'has share_with_group_lock and prevent_sharing_groups_outside_hierarchy returning true for descendent groups' do
descendent = create(:group, parent: group)
desc_settings = descendent.namespace_settings
expect(descendent.share_with_group_lock).to be_falsey
expect(desc_settings.prevent_sharing_groups_outside_hierarchy).to be_falsey
settings.update!(new_user_signups_cap: 10)
expect(descendent.reload.share_with_group_lock).to be_truthy
expect(desc_settings.reload.prevent_sharing_groups_outside_hierarchy).to be_truthy
end
end
context 'when removing a user cap from namespace settings' do
let(:user_cap) { 10 }
it 'leaves share_with_group_lock and prevent_sharing_groups_outside_hierarchy set to true to the related group' do
expect(group.share_with_group_lock).to be_truthy
expect(settings.prevent_sharing_groups_outside_hierarchy).to be_truthy
settings.update!(new_user_signups_cap: nil)
expect(group.reload.share_with_group_lock).to be_truthy
expect(settings.reload.prevent_sharing_groups_outside_hierarchy).to be_truthy
end
end
end
end end
...@@ -914,20 +914,20 @@ ...@@ -914,20 +914,20 @@
stylelint-declaration-strict-value "1.7.7" stylelint-declaration-strict-value "1.7.7"
stylelint-scss "3.18.0" stylelint-scss "3.18.0"
"@gitlab/svgs@2.0.0": "@gitlab/svgs@2.2.0":
version "2.0.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.0.0.tgz#06af5e91c36498ccf7e3e30e432eefcb3b1276c2" resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.2.0.tgz#95cf58d6ae634d535145159f08f5cff6241d4013"
integrity sha512-kBq7RZ0N+h41b4JbPOmwzx1X++fD+tz8HhaBmHTkOmRFY/7Ygvt2A8GodUUtpFK/NxRxy8O+knZvLNdfMLAIoQ== integrity sha512-mCwR3KfNPsxRoojtTjMIZwdd4FFlBh5DlR9AeodP+7+k8rILdWGYxTZbJMPNXoPbZx16R94nG8c5bR7toD4QBw==
"@gitlab/tributejs@1.0.0": "@gitlab/tributejs@1.0.0":
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8" resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw== integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
"@gitlab/ui@32.51.3": "@gitlab/ui@32.54.0":
version "32.51.3" version "32.54.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.51.3.tgz#1ba4802a16ecf5465774f4083e5ec1ed6adc4579" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.54.0.tgz#86002a6796bdd68fd54cd01e11292d2b29f361f7"
integrity sha512-PWC0FtpsW9SM3O935XPU2el/JtLtvHQCL9qblKCeR98eJNYmIpjrw45ow+01jsqpjufcUI49n4id/sYHq8b6og== integrity sha512-a1QUbQ3KQtmmenOaSGMp8clwi0o8H/u2c8Q1s9EbWHuXN3UwVnhxP+0ncNUpdTlHyEPn4UbYpAZOowtnikXn8Q==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
bootstrap-vue "2.20.1" bootstrap-vue "2.20.1"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment