Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-27 03:09:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-27 03:09:42 +0300
commitccdcf4e139790b97b55c364ccdbd42af58c2a07f (patch)
treef159a4ead4f3c5caff86d44ecd3817760f50c3c5
parent8e28b42532fa7c0c6f33113187d7378a1e48a1c6 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/models/group.rb21
-rw-r--r--changelogs/unreleased/275962-update-users-rake.yml5
-rw-r--r--changelogs/unreleased/mk-remove-unused-indexes.yml5
-rw-r--r--db/post_migrate/20201124185639_remove_unused_indexes.rb27
-rw-r--r--db/schema_migrations/202011241856391
-rw-r--r--db/structure.sql12
-rw-r--r--doc/administration/gitaly/praefect.md4
-rw-r--r--doc/raketasks/user_management.md14
-rw-r--r--doc/user/project/integrations/img/microsoft_teams_select_incoming_webhook.pngbin0 -> 30819 bytes
-rw-r--r--doc/user/project/integrations/microsoft_teams.md16
-rw-r--r--lib/tasks/gitlab/user_management.rake13
-rw-r--r--spec/models/group_spec.rb68
-rw-r--r--spec/tasks/gitlab/user_management_rake_spec.rb83
13 files changed, 240 insertions, 29 deletions
diff --git a/app/models/group.rb b/app/models/group.rb
index 3509299a579..0ce5f0cf2cf 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -402,6 +402,13 @@ class Group < Namespace
.where(source_id: self_and_hierarchy.reorder(nil).select(:id))
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
User
.where(id: members_with_parents.select(:user_id))
@@ -428,6 +435,20 @@ class Group < Namespace
])
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
members.count
end
diff --git a/changelogs/unreleased/275962-update-users-rake.yml b/changelogs/unreleased/275962-update-users-rake.yml
new file mode 100644
index 00000000000..f8cd1a6753e
--- /dev/null
+++ b/changelogs/unreleased/275962-update-users-rake.yml
@@ -0,0 +1,5 @@
+---
+title: Add rake task to disable personal project and group creation
+merge_request: 47655
+author:
+type: added
diff --git a/changelogs/unreleased/mk-remove-unused-indexes.yml b/changelogs/unreleased/mk-remove-unused-indexes.yml
new file mode 100644
index 00000000000..50969f834b8
--- /dev/null
+++ b/changelogs/unreleased/mk-remove-unused-indexes.yml
@@ -0,0 +1,5 @@
+---
+title: 'Geo: Remove unused indexes'
+merge_request: 48504
+author:
+type: changed
diff --git a/db/post_migrate/20201124185639_remove_unused_indexes.rb b/db/post_migrate/20201124185639_remove_unused_indexes.rb
new file mode 100644
index 00000000000..c4b0d8a84cc
--- /dev/null
+++ b/db/post_migrate/20201124185639_remove_unused_indexes.rb
@@ -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
diff --git a/db/schema_migrations/20201124185639 b/db/schema_migrations/20201124185639
new file mode 100644
index 00000000000..9ca03d7d837
--- /dev/null
+++ b/db/schema_migrations/20201124185639
@@ -0,0 +1 @@
+dd36b2815c62ef9710d88fa92c410398a228c50a7e51d44ce02e85c9f63d648e \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 54888195975..3be04c5f68d 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -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 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_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 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_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 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_idx_blocked_by_type_links ON issue_links USING btree (target_id) WHERE (link_type = 2);
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 160d9705639..dd0b93b4e84 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -122,9 +122,7 @@ package (highly recommended), follow the steps below:
Before beginning, you should already have a working GitLab instance. [Learn how
to install GitLab](https://about.gitlab.com/install/).
-Provision a PostgreSQL server (PostgreSQL 11 or newer). Configuration through
-the Omnibus GitLab distribution is not yet supported. Follow this
-[issue](https://gitlab.com/gitlab-org/gitaly/-/issues/2476) for updates.
+Provision a PostgreSQL server (PostgreSQL 11 or newer).
Prepare all your new nodes by [installing
GitLab](https://about.gitlab.com/install/).
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index 717b6be7bff..4152b348ac6 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -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.
+## 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
Enable this setting to keep new users blocked until they have been cleared by the administrator.
diff --git a/doc/user/project/integrations/img/microsoft_teams_select_incoming_webhook.png b/doc/user/project/integrations/img/microsoft_teams_select_incoming_webhook.png
new file mode 100644
index 00000000000..5fab8c77540
--- /dev/null
+++ b/doc/user/project/integrations/img/microsoft_teams_select_incoming_webhook.png
Binary files differ
diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md
index b444c30c162..5a8d699ab11 100644
--- a/doc/user/project/integrations/microsoft_teams.md
+++ b/doc/user/project/integrations/microsoft_teams.md
@@ -9,7 +9,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## On Microsoft Teams
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
diff --git a/lib/tasks/gitlab/user_management.rake b/lib/tasks/gitlab/user_management.rake
new file mode 100644
index 00000000000..5bf3b8c806e
--- /dev/null
+++ b/lib/tasks/gitlab/user_management.rake
@@ -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
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index dd1faf999b3..81a932649df 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -798,20 +798,36 @@ RSpec.describe Group do
end
end
- describe '#direct_and_indirect_members' do
+ context 'members-related methods' do
let!(:group) { create(:group, :nested) }
let!(:sub_group) { create(:group, parent: group) }
let!(:maintainer) { group.parent.add_user(create(:user), GroupMember::MAINTAINER) }
let!(:developer) { group.add_user(create(:user), GroupMember::DEVELOPER) }
let!(:other_developer) { group.add_user(create(:user), GroupMember::DEVELOPER) }
- it 'returns parents members' do
- expect(group.direct_and_indirect_members).to include(developer)
- expect(group.direct_and_indirect_members).to include(maintainer)
+ describe '#direct_and_indirect_members' do
+ it 'returns parents members' do
+ 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
- it 'returns descendant members' do
- expect(group.direct_and_indirect_members).to include(other_developer)
+ describe '#direct_and_indirect_members_with_inactive' do
+ 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
@@ -834,7 +850,7 @@ RSpec.describe Group do
end
end
- describe '#direct_and_indirect_users' do
+ context 'user-related methods' do
let(:user_a) { create(:user) }
let(:user_b) { create(:user) }
let(:user_c) { create(:user) }
@@ -853,14 +869,40 @@ RSpec.describe Group do
project.add_developer(user_d)
end
- it 'returns member users on every nest level without duplication' do
- expect(group.direct_and_indirect_users).to contain_exactly(user_a, user_b, user_c, user_d)
- 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)
+ describe '#direct_and_indirect_users' do
+ it 'returns member users on every nest level without duplication' do
+ expect(group.direct_and_indirect_users).to contain_exactly(user_a, user_b, user_c, user_d)
+ 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
- it 'does not return members of projects belonging to ancestor groups' do
- expect(nested_group.direct_and_indirect_users).not_to include(user_d)
+ describe '#direct_and_indirect_users_with_inactive' do
+ 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
diff --git a/spec/tasks/gitlab/user_management_rake_spec.rb b/spec/tasks/gitlab/user_management_rake_spec.rb
new file mode 100644
index 00000000000..958055780d0
--- /dev/null
+++ b/spec/tasks/gitlab/user_management_rake_spec.rb
@@ -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