Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
8e28b42532
commit
ccdcf4e139
|
@ -402,6 +402,13 @@ class Group < Namespace
|
||||||
.where(source_id: self_and_hierarchy.reorder(nil).select(:id))
|
.where(source_id: self_and_hierarchy.reorder(nil).select(:id))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def direct_and_indirect_members_with_inactive
|
||||||
|
GroupMember
|
||||||
|
.non_request
|
||||||
|
.non_invite
|
||||||
|
.where(source_id: self_and_hierarchy.reorder(nil).select(:id))
|
||||||
|
end
|
||||||
|
|
||||||
def users_with_parents
|
def users_with_parents
|
||||||
User
|
User
|
||||||
.where(id: members_with_parents.select(:user_id))
|
.where(id: members_with_parents.select(:user_id))
|
||||||
|
@ -428,6 +435,20 @@ class Group < Namespace
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns all users (also inactive) that are members of the group because:
|
||||||
|
# 1. They belong to the group
|
||||||
|
# 2. They belong to a project that belongs to the group
|
||||||
|
# 3. They belong to a sub-group or project in such sub-group
|
||||||
|
# 4. They belong to an ancestor group
|
||||||
|
def direct_and_indirect_users_with_inactive
|
||||||
|
User.from_union([
|
||||||
|
User
|
||||||
|
.where(id: direct_and_indirect_members_with_inactive.select(:user_id))
|
||||||
|
.reorder(nil),
|
||||||
|
project_users_with_descendants
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
def users_count
|
def users_count
|
||||||
members.count
|
members.count
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Add rake task to disable personal project and group creation
|
||||||
|
merge_request: 47655
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: 'Geo: Remove unused indexes'
|
||||||
|
merge_request: 48504
|
||||||
|
author:
|
||||||
|
type: changed
|
|
@ -0,0 +1,27 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class RemoveUnusedIndexes < ActiveRecord::Migration[6.0]
|
||||||
|
include Gitlab::Database::MigrationHelpers
|
||||||
|
|
||||||
|
DOWNTIME = false
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
remove_concurrent_index_by_name :packages_package_files, "packages_packages_verification_failure_partial"
|
||||||
|
remove_concurrent_index_by_name :packages_package_files, "packages_packages_verification_checksum_partial"
|
||||||
|
remove_concurrent_index_by_name :snippet_repositories, 'snippet_repositories_verification_failure_partial'
|
||||||
|
remove_concurrent_index_by_name :snippet_repositories, 'snippet_repositories_verification_checksum_partial'
|
||||||
|
remove_concurrent_index_by_name :terraform_state_versions, 'terraform_state_versions_verification_failure_partial'
|
||||||
|
remove_concurrent_index_by_name :terraform_state_versions, 'terraform_state_versions_verification_checksum_partial'
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
add_concurrent_index :packages_package_files, :verification_failure, where: "(verification_failure IS NOT NULL)", name: "packages_packages_verification_failure_partial"
|
||||||
|
add_concurrent_index :packages_package_files, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "packages_packages_verification_checksum_partial"
|
||||||
|
add_concurrent_index :snippet_repositories, :verification_failure, where: "(verification_failure IS NOT NULL)", name: 'snippet_repositories_verification_failure_partial'
|
||||||
|
add_concurrent_index :snippet_repositories, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: 'snippet_repositories_verification_checksum_partial'
|
||||||
|
add_concurrent_index :terraform_state_versions, :verification_failure, where: "(verification_failure IS NOT NULL)", name: 'terraform_state_versions_verification_failure_partial'
|
||||||
|
add_concurrent_index :terraform_state_versions, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: 'terraform_state_versions_verification_checksum_partial'
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
dd36b2815c62ef9710d88fa92c410398a228c50a7e51d44ce02e85c9f63d648e
|
|
@ -22513,20 +22513,12 @@ CREATE UNIQUE INDEX one_canonical_wiki_page_slug_per_metadata ON wiki_page_slugs
|
||||||
|
|
||||||
CREATE INDEX package_name_index ON packages_packages USING btree (name);
|
CREATE INDEX package_name_index ON packages_packages USING btree (name);
|
||||||
|
|
||||||
CREATE INDEX packages_packages_verification_checksum_partial ON packages_package_files USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
|
|
||||||
|
|
||||||
CREATE INDEX packages_packages_verification_failure_partial ON packages_package_files USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
|
|
||||||
|
|
||||||
CREATE INDEX partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs ON ci_builds USING btree (scheduled_at) WHERE ((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text));
|
CREATE INDEX partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs ON ci_builds USING btree (scheduled_at) WHERE ((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text));
|
||||||
|
|
||||||
CREATE INDEX partial_index_deployments_for_legacy_successful_deployments ON deployments USING btree (id) WHERE ((finished_at IS NULL) AND (status = 2));
|
CREATE INDEX partial_index_deployments_for_legacy_successful_deployments ON deployments USING btree (id) WHERE ((finished_at IS NULL) AND (status = 2));
|
||||||
|
|
||||||
CREATE INDEX partial_index_deployments_for_project_id_and_tag ON deployments USING btree (project_id) WHERE (tag IS TRUE);
|
CREATE INDEX partial_index_deployments_for_project_id_and_tag ON deployments USING btree (project_id) WHERE (tag IS TRUE);
|
||||||
|
|
||||||
CREATE INDEX snippet_repositories_verification_checksum_partial ON snippet_repositories USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
|
|
||||||
|
|
||||||
CREATE INDEX snippet_repositories_verification_failure_partial ON snippet_repositories USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_and_note_id_index ON snippet_user_mentions USING btree (snippet_id, note_id);
|
CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_and_note_id_index ON snippet_user_mentions USING btree (snippet_id, note_id);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_index ON snippet_user_mentions USING btree (snippet_id) WHERE (note_id IS NULL);
|
CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_index ON snippet_user_mentions USING btree (snippet_id) WHERE (note_id IS NULL);
|
||||||
|
@ -22537,10 +22529,6 @@ CREATE INDEX temporary_index_vulnerabilities_on_id ON vulnerabilities USING btre
|
||||||
|
|
||||||
CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
|
CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
|
||||||
|
|
||||||
CREATE INDEX terraform_state_versions_verification_checksum_partial ON terraform_state_versions USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
|
|
||||||
|
|
||||||
CREATE INDEX terraform_state_versions_verification_failure_partial ON terraform_state_versions USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
|
|
||||||
|
|
||||||
CREATE INDEX tmp_build_stage_position_index ON ci_builds USING btree (stage_id, stage_idx) WHERE (stage_idx IS NOT NULL);
|
CREATE INDEX tmp_build_stage_position_index ON ci_builds USING btree (stage_id, stage_idx) WHERE (stage_idx IS NOT NULL);
|
||||||
|
|
||||||
CREATE INDEX tmp_idx_blocked_by_type_links ON issue_links USING btree (target_id) WHERE (link_type = 2);
|
CREATE INDEX tmp_idx_blocked_by_type_links ON issue_links USING btree (target_id) WHERE (link_type = 2);
|
||||||
|
|
|
@ -122,9 +122,7 @@ package (highly recommended), follow the steps below:
|
||||||
Before beginning, you should already have a working GitLab instance. [Learn how
|
Before beginning, you should already have a working GitLab instance. [Learn how
|
||||||
to install GitLab](https://about.gitlab.com/install/).
|
to install GitLab](https://about.gitlab.com/install/).
|
||||||
|
|
||||||
Provision a PostgreSQL server (PostgreSQL 11 or newer). Configuration through
|
Provision a PostgreSQL server (PostgreSQL 11 or newer).
|
||||||
the Omnibus GitLab distribution is not yet supported. Follow this
|
|
||||||
[issue](https://gitlab.com/gitlab-org/gitaly/-/issues/2476) for updates.
|
|
||||||
|
|
||||||
Prepare all your new nodes by [installing
|
Prepare all your new nodes by [installing
|
||||||
GitLab](https://about.gitlab.com/install/).
|
GitLab](https://about.gitlab.com/install/).
|
||||||
|
|
|
@ -60,6 +60,20 @@ bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production
|
||||||
|
|
||||||
Administrators are added as owners so they can add additional users to the group.
|
Administrators are added as owners so they can add additional users to the group.
|
||||||
|
|
||||||
|
## Update all users in a given group to `project_limit:0` and `can_create_group: false`
|
||||||
|
|
||||||
|
To update all users in given group to `project_limit: 0` and `can_create_group: false`, run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# omnibus-gitlab
|
||||||
|
sudo gitlab-rake gitlab:user_management:disable_project_and_group_creation\[:group_id\]
|
||||||
|
|
||||||
|
# installation from source
|
||||||
|
bundle exec rake gitlab:user_management:disable_project_and_group_creation\[:group_id\] RAILS_ENV=production
|
||||||
|
```
|
||||||
|
|
||||||
|
It updates all users in the given group, its subgroups and projects in this group namespace, with the noted limits.
|
||||||
|
|
||||||
## Control the number of billable users
|
## Control the number of billable users
|
||||||
|
|
||||||
Enable this setting to keep new users blocked until they have been cleared by the administrator.
|
Enable this setting to keep new users blocked until they have been cleared by the administrator.
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
|
@ -9,7 +9,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
## On Microsoft Teams
|
## On Microsoft Teams
|
||||||
|
|
||||||
To enable Microsoft Teams integration you must create an incoming webhook integration on Microsoft
|
To enable Microsoft Teams integration you must create an incoming webhook integration on Microsoft
|
||||||
Teams by following the steps described in [Sending messages to Connectors and Webhooks](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using).
|
Teams by following the steps below:
|
||||||
|
|
||||||
|
1. Search for "incoming webhook" on the search bar in Microsoft Teams and select the
|
||||||
|
**Incoming Webhook** item.
|
||||||
|
|
||||||
|
![Select Incoming Webhook](img/microsoft_teams_select_incoming_webhook.png)
|
||||||
|
|
||||||
|
1. Click the **Add to a team** button.
|
||||||
|
1. Select the team and channel you want to add the integration to.
|
||||||
|
1. Add a name for the webhook. The name is displayed next to every message that
|
||||||
|
comes in through the webhook.
|
||||||
|
1. Copy the webhook URL for the next steps.
|
||||||
|
|
||||||
|
Learn more about
|
||||||
|
[setting up an incoming webhook on Microsoft Teams](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook).
|
||||||
|
|
||||||
## On GitLab
|
## On GitLab
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace :gitlab do
|
||||||
|
namespace :user_management do
|
||||||
|
desc "GitLab | User management | Update all users of a group with personal project limit to 0 and can_create_group to false"
|
||||||
|
task :disable_project_and_group_creation, [:group_id] => :environment do |t, args|
|
||||||
|
group = Group.find(args.group_id)
|
||||||
|
|
||||||
|
result = User.where(id: group.direct_and_indirect_users_with_inactive.select(:id)).update_all(projects_limit: 0, can_create_group: false)
|
||||||
|
ids_count = group.direct_and_indirect_users_with_inactive.count
|
||||||
|
puts "Done".green if result == ids_count
|
||||||
|
puts "Something went wrong".red if result != ids_count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -798,20 +798,36 @@ RSpec.describe Group do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#direct_and_indirect_members' do
|
context 'members-related methods' do
|
||||||
let!(:group) { create(:group, :nested) }
|
let!(:group) { create(:group, :nested) }
|
||||||
let!(:sub_group) { create(:group, parent: group) }
|
let!(:sub_group) { create(:group, parent: group) }
|
||||||
let!(:maintainer) { group.parent.add_user(create(:user), GroupMember::MAINTAINER) }
|
let!(:maintainer) { group.parent.add_user(create(:user), GroupMember::MAINTAINER) }
|
||||||
let!(:developer) { group.add_user(create(:user), GroupMember::DEVELOPER) }
|
let!(:developer) { group.add_user(create(:user), GroupMember::DEVELOPER) }
|
||||||
let!(:other_developer) { group.add_user(create(:user), GroupMember::DEVELOPER) }
|
let!(:other_developer) { group.add_user(create(:user), GroupMember::DEVELOPER) }
|
||||||
|
|
||||||
it 'returns parents members' do
|
describe '#direct_and_indirect_members' do
|
||||||
expect(group.direct_and_indirect_members).to include(developer)
|
it 'returns parents members' do
|
||||||
expect(group.direct_and_indirect_members).to include(maintainer)
|
expect(group.direct_and_indirect_members).to include(developer)
|
||||||
|
expect(group.direct_and_indirect_members).to include(maintainer)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns descendant members' do
|
||||||
|
expect(group.direct_and_indirect_members).to include(other_developer)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns descendant members' do
|
describe '#direct_and_indirect_members_with_inactive' do
|
||||||
expect(group.direct_and_indirect_members).to include(other_developer)
|
let!(:maintainer_blocked) { group.parent.add_user(create(:user, :blocked), GroupMember::MAINTAINER) }
|
||||||
|
|
||||||
|
it 'returns parents members' do
|
||||||
|
expect(group.direct_and_indirect_members_with_inactive).to include(developer)
|
||||||
|
expect(group.direct_and_indirect_members_with_inactive).to include(maintainer)
|
||||||
|
expect(group.direct_and_indirect_members_with_inactive).to include(maintainer_blocked)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns descendant members' do
|
||||||
|
expect(group.direct_and_indirect_members_with_inactive).to include(other_developer)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -834,7 +850,7 @@ RSpec.describe Group do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#direct_and_indirect_users' do
|
context 'user-related methods' do
|
||||||
let(:user_a) { create(:user) }
|
let(:user_a) { create(:user) }
|
||||||
let(:user_b) { create(:user) }
|
let(:user_b) { create(:user) }
|
||||||
let(:user_c) { create(:user) }
|
let(:user_c) { create(:user) }
|
||||||
|
@ -853,14 +869,40 @@ RSpec.describe Group do
|
||||||
project.add_developer(user_d)
|
project.add_developer(user_d)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns member users on every nest level without duplication' do
|
describe '#direct_and_indirect_users' do
|
||||||
expect(group.direct_and_indirect_users).to contain_exactly(user_a, user_b, user_c, user_d)
|
it 'returns member users on every nest level without duplication' do
|
||||||
expect(nested_group.direct_and_indirect_users).to contain_exactly(user_a, user_b, user_c)
|
expect(group.direct_and_indirect_users).to contain_exactly(user_a, user_b, user_c, user_d)
|
||||||
expect(deep_nested_group.direct_and_indirect_users).to contain_exactly(user_a, user_b, user_c)
|
expect(nested_group.direct_and_indirect_users).to contain_exactly(user_a, user_b, user_c)
|
||||||
|
expect(deep_nested_group.direct_and_indirect_users).to contain_exactly(user_a, user_b, user_c)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not return members of projects belonging to ancestor groups' do
|
||||||
|
expect(nested_group.direct_and_indirect_users).not_to include(user_d)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not return members of projects belonging to ancestor groups' do
|
describe '#direct_and_indirect_users_with_inactive' do
|
||||||
expect(nested_group.direct_and_indirect_users).not_to include(user_d)
|
let(:user_blocked_1) { create(:user, :blocked) }
|
||||||
|
let(:user_blocked_2) { create(:user, :blocked) }
|
||||||
|
let(:user_blocked_3) { create(:user, :blocked) }
|
||||||
|
let(:project_in_group) { create(:project, namespace: nested_group) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
group.add_developer(user_blocked_1)
|
||||||
|
nested_group.add_developer(user_blocked_1)
|
||||||
|
deep_nested_group.add_developer(user_blocked_2)
|
||||||
|
project_in_group.add_developer(user_blocked_3)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns member users on every nest level without duplication' do
|
||||||
|
expect(group.direct_and_indirect_users_with_inactive).to contain_exactly(user_a, user_b, user_c, user_d, user_blocked_1, user_blocked_2, user_blocked_3)
|
||||||
|
expect(nested_group.direct_and_indirect_users_with_inactive).to contain_exactly(user_a, user_b, user_c, user_blocked_1, user_blocked_2, user_blocked_3)
|
||||||
|
expect(deep_nested_group.direct_and_indirect_users_with_inactive).to contain_exactly(user_a, user_b, user_c, user_blocked_1, user_blocked_2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns members of projects belonging to group' do
|
||||||
|
expect(nested_group.direct_and_indirect_users_with_inactive).to include(user_blocked_3)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rake_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'gitlab:user_management tasks' do
|
||||||
|
before do
|
||||||
|
Rake.application.rake_require 'tasks/gitlab/user_management'
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'disable_project_and_group_creation' do
|
||||||
|
let(:group) { create(:group) }
|
||||||
|
|
||||||
|
subject(:run_rake) { run_rake_task('gitlab:user_management:disable_project_and_group_creation', group.id) }
|
||||||
|
|
||||||
|
it 'returns output info' do
|
||||||
|
expect { run_rake }.to output(/.*Done.*/).to_stdout
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with users' do
|
||||||
|
let(:user_1) { create(:user, projects_limit: 10, can_create_group: true) }
|
||||||
|
let(:user_2) { create(:user, projects_limit: 10, can_create_group: true) }
|
||||||
|
let(:user_other) { create(:user, projects_limit: 10, can_create_group: true) }
|
||||||
|
|
||||||
|
shared_examples 'updates proper users' do
|
||||||
|
it 'updates members' do
|
||||||
|
run_rake
|
||||||
|
|
||||||
|
expect(user_1.reload.projects_limit).to eq(0)
|
||||||
|
expect(user_1.can_create_group).to eq(false)
|
||||||
|
expect(user_2.reload.projects_limit).to eq(0)
|
||||||
|
expect(user_2.can_create_group).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not update other users' do
|
||||||
|
run_rake
|
||||||
|
|
||||||
|
expect(user_other.reload.projects_limit).to eq(10)
|
||||||
|
expect(user_other.reload.can_create_group).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in the group' do
|
||||||
|
let(:other_group) { create(:group) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
group.add_developer(user_1)
|
||||||
|
group.add_developer(user_2)
|
||||||
|
other_group.add_developer(user_other)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'updates proper users'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in the descendant groups' do
|
||||||
|
let(:subgroup) { create(:group, parent: group) }
|
||||||
|
let(:sub_subgroup) { create(:group, parent: subgroup) }
|
||||||
|
let(:other_group) { create(:group) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subgroup.add_developer(user_1)
|
||||||
|
sub_subgroup.add_developer(user_2)
|
||||||
|
other_group.add_developer(user_other)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'updates proper users'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in the children projects' do
|
||||||
|
let(:project_1) { create(:project, namespace: group) }
|
||||||
|
let(:project_2) { create(:project, namespace: group) }
|
||||||
|
let(:other_project) { create(:project) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
project_1.add_developer(user_1)
|
||||||
|
project_2.add_developer(user_2)
|
||||||
|
other_project.add_developer(user_other)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'updates proper users'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue