From 2c4e0ce5ca4f127cee6b7da20ae1657d8d37af9d Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Fri, 7 May 2021 16:44:33 -0500 Subject: [PATCH 1/9] Shadow ban UI Add shadow ban user state and UI Add config admin route Add shadow ban admin user path Run rake translate Add shadow banned user state Add specs and UI touches Remove line about hiding comments and issues Add shadow banned users tab Run bin/rake translate Add specs for shadow ban user Model and controller specs, factory Add specs for unsuccessful shadow ban Add specs for unsuccessful shadow ban Add application log when user shadow banned Changelog: added Add changelog entry Add shadow_ban_user_feature_flag Add feature flag, flag yml, modify code and tests to check for flag Check if shadow_ban_user_feature_flag enabled Add un shadow ban option Add route for un shadow ban user Add docs page for shadow banning Add docs for shadow banning users Change un shadow ban to unban Change to unban Move shadow ban docs to block docs Combine banning and blocking docs Move shadow ban docs to block docs Combine banning and blocking docs Move activate deactivate into user moderation Combine block, ban, and deactivate into one file Rename blocking and unblocking to user moderation Now that this page has blocking, banning, and deactivating, rename to user moderation Remove activating deactivating users page All included in user moderation page Apply MR review suggestion Apply MR review suggestion Fix broken anchors Fix anchor, run translation Fix anchor links Fix anchor links to removed pages Apply MR review suggestions Check feature available helpers Rename shadow ban to ban Modify references to shadow ban, WIP, clicking shadow ban just blocks the user rename shadow ban files to ban Remove references to shadow ban Remove shadow ban from docs and changelog Link to ban user docs Add link to banned users docs Move confirm text to helper Move confirm text to helper --- app/controllers/admin/users_controller.rb | 23 +++ app/helpers/users_helper.rb | 46 +++++ app/models/user.rb | 13 +- app/services/users/ban_service.rb | 23 +++ app/views/admin/users/_ban_user.html.haml | 9 + app/views/admin/users/_head.html.haml | 3 + app/views/admin/users/_users.html.haml | 5 + app/views/admin/users/show.html.haml | 15 ++ changelogs/unreleased/ban-user-state-ui.yml | 5 + .../development/ban_user_feature_flag.yml | 8 + config/routes/admin.rb | 2 + doc/subscriptions/self_managed/index.md | 6 +- .../activating_deactivating_users.md | 69 -------- doc/user/admin_area/approving_users.md | 2 +- .../admin_area/blocking_unblocking_users.md | 51 ------ doc/user/admin_area/index.md | 4 +- doc/user/admin_area/user_moderation.md | 164 ++++++++++++++++++ doc/user/profile/account/delete_account.md | 2 +- doc/user/upgrade_email_bypass.md | 2 +- locale/gitlab.pot | 57 ++++++ .../admin/users_controller_spec.rb | 22 +++ spec/factories/users.rb | 4 + spec/features/admin/users/users_spec.rb | 1 + spec/helpers/users_helper_spec.rb | 10 ++ spec/models/user_spec.rb | 16 ++ spec/services/users/ban_service_spec.rb | 50 ++++++ 26 files changed, 482 insertions(+), 130 deletions(-) create mode 100644 app/services/users/ban_service.rb create mode 100644 app/views/admin/users/_ban_user.html.haml create mode 100644 changelogs/unreleased/ban-user-state-ui.yml create mode 100644 config/feature_flags/development/ban_user_feature_flag.yml delete mode 100644 doc/user/admin_area/activating_deactivating_users.md delete mode 100644 doc/user/admin_area/blocking_unblocking_users.md create mode 100644 doc/user/admin_area/user_moderation.md create mode 100644 spec/services/users/ban_service_spec.rb diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 9f0d911f5ef34f..2e9229db56cc31 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -7,6 +7,7 @@ class Admin::UsersController < Admin::ApplicationController before_action :user, except: [:index, :cohorts, :new, :create] before_action :check_impersonation_availability, only: :impersonate before_action :ensure_destroy_prerequisites_met, only: [:destroy] + before_action :check_ban_user_feature_flag, only: [:ban] feature_category :users @@ -130,6 +131,24 @@ def unblock end end + def ban + result = Users::BanService.new(current_user).execute(user) + + if result[:status] == :success + redirect_back_or_admin_user(notice: _("Successfully banned")) + else + redirect_back_or_admin_user(alert: _("Error occurred. User was not banned")) + end + end + + def unban + if update_user { |user| user.activate } + redirect_back_or_admin_user(notice: _("Successfully unbanned")) + else + redirect_back_or_admin_user(alert: _("Error occurred. User was not unbanned")) + end + end + def unlock if update_user { |user| user.unlock_access! } redirect_back_or_admin_user(alert: _("Successfully unlocked")) @@ -325,6 +344,10 @@ def check_impersonation_availability access_denied! unless Gitlab.config.gitlab.impersonation_enabled end + def check_ban_user_feature_flag + access_denied! unless Feature.enabled?(:ban_user_feature_flag) + end + def log_impersonation_event Gitlab::AppLogger.info(_("User %{current_user_username} has started impersonating %{username}") % { current_user_username: current_user.username, username: user.username }) end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 998c697e6176e0..845d381892215f 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -162,6 +162,49 @@ def user_block_effects header + list end + def user_ban_data(user) + { + path: ban_admin_user_path(user), + method: 'put', + modal_attributes: { + title: s_('AdminUsers|Ban user %{username}?') % { username: sanitize_name(user.name) }, + message: s_('AdminUsers|You can always unban their account. Their data remains intact.'), + okVariant: 'warning', + okTitle: s_('AdminUsers|Ban') + }.to_json + } + end + + def user_unban_data(user) + { + path: unban_admin_user_path(user), + method: 'put', + modal_attributes: { + title: s_('AdminUsers|Unban %{username}?') % { username: sanitize_name(user.name) }, + message: s_('AdminUsers|You can always ban their account again if needed.'), + okVariant: 'info', + okTitle: s_('AdminUsers|Unban') + }.to_json + } + end + + def user_ban_effects + header = tag.p s_('AdminUsers|Banning the user has the following effects:') + + list = tag.ul do + concat tag.li s_('AdminUsers|User will be blocked') + end + + link_start = ''.html_safe % { url: help_page_path("user/admin_area/user_moderation", anchor: "banning-a-user") } + info = tag.p s_('AdminUsers|Learn more about %{link_start}banned users.%{link_end}').html_safe % { link_start: link_start, link_end: ''.html_safe } + + header + list + info + end + + def ban_feature_available? + Feature.enabled?(:ban_user_feature_flag) + end + def user_deactivation_data(user, message) { path: deactivate_admin_user_path(user), @@ -235,6 +278,9 @@ def blocked_user_badge(user) pending_approval_badge = { text: s_('AdminUsers|Pending approval'), variant: 'info' } return pending_approval_badge if user.blocked_pending_approval? + banned_badge = { text: s_('AdminUsers|Banned'), variant: 'danger' } + return banned_badge if user.banned? + { text: s_('AdminUsers|Blocked'), variant: 'danger' } end diff --git a/app/models/user.rb b/app/models/user.rb index 4b38ef771a125e..40c5fa083d5e96 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -326,6 +326,7 @@ def max_access_for_group transition deactivated: :blocked transition ldap_blocked: :blocked transition blocked_pending_approval: :blocked + transition banned: :blocked end event :ldap_block do @@ -338,19 +339,24 @@ def max_access_for_group transition blocked: :active transition ldap_blocked: :active transition blocked_pending_approval: :active + transition banned: :active end event :block_pending_approval do transition active: :blocked_pending_approval end + event :ban do + transition active: :banned + end + event :deactivate do # Any additional changes to this event should be also # reflected in app/workers/users/deactivate_dormant_users_worker.rb transition active: :deactivated end - state :blocked, :ldap_blocked, :blocked_pending_approval do + state :blocked, :ldap_blocked, :blocked_pending_approval, :banned do def blocked? true end @@ -375,8 +381,9 @@ def blocked? # Scopes scope :admins, -> { where(admin: true) } scope :instance_access_request_approvers_to_be_notified, -> { admins.active.order_recent_sign_in.limit(INSTANCE_ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT) } - scope :blocked, -> { with_states(:blocked, :ldap_blocked) } + scope :blocked, -> { with_states(:blocked, :ldap_blocked, :banned) } scope :blocked_pending_approval, -> { with_states(:blocked_pending_approval) } + scope :banned, -> { with_states(:banned) } scope :external, -> { where(external: true) } scope :non_external, -> { where(external: false) } scope :confirmed, -> { where.not(confirmed_at: nil) } @@ -598,6 +605,8 @@ def filter_items(filter_name) blocked when 'blocked_pending_approval' blocked_pending_approval + when 'banned' + banned when 'two_factor_disabled' without_two_factor when 'two_factor_enabled' diff --git a/app/services/users/ban_service.rb b/app/services/users/ban_service.rb new file mode 100644 index 00000000000000..3017afd9c0040d --- /dev/null +++ b/app/services/users/ban_service.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Users + class BanService < BaseService + def initialize(current_user) + @current_user = current_user + end + + def execute(user) + if user.ban + log_event(user) + success + else + messages = user.errors.full_messages + error(messages.uniq.join('. ')) + end + end + + def log_event(user) + Gitlab::AppLogger.info(message: "User banned", user: "#{user.username}", email: "#{user.email}", banned_by: "#{current_user.username}", ip_address: "#{current_user.current_sign_in_ip}") + end + end +end diff --git a/app/views/admin/users/_ban_user.html.haml b/app/views/admin/users/_ban_user.html.haml new file mode 100644 index 00000000000000..b8d61b5dead4a3 --- /dev/null +++ b/app/views/admin/users/_ban_user.html.haml @@ -0,0 +1,9 @@ +- if ban_feature_available? + .card.border-warning + .card-header.bg-warning.text-white + = s_('AdminUsers|Ban user') + .card-body + = user_ban_effects + %br + %button.btn.gl-button.btn-warning.js-confirm-modal-button{ data: user_ban_data(user) } + = s_('AdminUsers|Ban user') diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml index ade3581e5b90c9..be04e87f8b9cbe 100644 --- a/app/views/admin/users/_head.html.haml +++ b/app/views/admin/users/_head.html.haml @@ -3,6 +3,9 @@ - if @user.blocked_pending_approval? %span.cred = s_('AdminUsers|(Pending approval)') + - elsif @user.banned? + %span.cred + = s_('AdminUsers|(Banned)') - elsif @user.blocked? %span.cred = s_('AdminUsers|(Blocked)') diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml index efa50ec47f5b67..e4438f38a47577 100644 --- a/app/views/admin/users/_users.html.haml +++ b/app/views/admin/users/_users.html.haml @@ -28,6 +28,11 @@ = link_to admin_users_path(filter: "blocked") do = s_('AdminUsers|Blocked') %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.blocked) + - if ban_feature_available? + = nav_link(html_options: { class: active_when(params[:filter] == 'banned') }) do + = link_to admin_users_path(filter: "banned") do + = s_('AdminUsers|Banned') + %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.banned) = nav_link(html_options: { class: "#{active_when(params[:filter] == 'blocked_pending_approval')} filter-blocked-pending-approval" }) do = link_to admin_users_path(filter: "blocked_pending_approval"), data: { qa_selector: 'pending_approval_tab' } do = s_('AdminUsers|Pending approval') diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 03ddf5c76a0275..18756ebc1f1305 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -176,6 +176,20 @@ - if @user.blocked_pending_approval? = render 'admin/users/approve_user', user: @user = render 'admin/users/reject_pending_user', user: @user + - elsif @user.banned? + .gl-card.border-info.gl-mb-5 + .gl-card-header.gl-bg-blue-500.gl-text-white + = _('This user is banned') + .gl-card-body + %p= _('A banned user cannot:') + %ul + %li= _('Log in') + %li= _('Access Git repositories') + - link_start = ''.html_safe % { url: help_page_path("user/admin_area/user_moderation", anchor: "banning-a-user") } + = s_('AdminUsers|Learn more about %{link_start}banned users.%{link_end}').html_safe % { link_start: link_start, link_end: ''.html_safe } + %p + %button.btn.gl-button.btn-info.js-confirm-modal-button{ data: user_unban_data(@user) } + = s_('AdminUsers|Unban user') - else .gl-card.border-info.gl-mb-5 .gl-card-header.gl-bg-blue-500.gl-text-white @@ -190,6 +204,7 @@ = s_('AdminUsers|Unblock user') - elsif !@user.internal? = render 'admin/users/block_user', user: @user + = render 'admin/users/ban_user', user: @user - if @user.access_locked? .card.border-info.gl-mb-5 diff --git a/changelogs/unreleased/ban-user-state-ui.yml b/changelogs/unreleased/ban-user-state-ui.yml new file mode 100644 index 00000000000000..6da3d575dc9a20 --- /dev/null +++ b/changelogs/unreleased/ban-user-state-ui.yml @@ -0,0 +1,5 @@ +--- +title: Ban user state and UI +merge_request: 61292 +author: +type: added diff --git a/config/feature_flags/development/ban_user_feature_flag.yml b/config/feature_flags/development/ban_user_feature_flag.yml new file mode 100644 index 00000000000000..6765e82e25205b --- /dev/null +++ b/config/feature_flags/development/ban_user_feature_flag.yml @@ -0,0 +1,8 @@ +--- +name: ban_user_feature_flag +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61292 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330667 +milestone: '13.12' +type: development +group: group::access +default_enabled: false diff --git a/config/routes/admin.rb b/config/routes/admin.rb index e7f851f7de4d76..2ba00e3bf66537 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -21,6 +21,8 @@ get :keys put :block put :unblock + put :ban + put :unban put :deactivate put :activate put :unlock diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index db0d54ff14c335..03466785c5164f 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -48,8 +48,8 @@ using [Seat Link](#seat-link). A _billable user_ counts against the number of subscription seats. Every user is considered a billable user, with the following exceptions: -- [Deactivated users](../../user/admin_area/activating_deactivating_users.md#deactivating-a-user) and - [blocked users](../../user/admin_area/blocking_unblocking_users.md) don't count as billable users in the current subscription. When they are either deactivated or blocked they release a _billable user_ seat. However, they may +- [Deactivated users](../../user/admin_area/user_moderation.md#deactivating-a-user) and + [blocked users](../../user/admin_area/user_moderation.md#blocking-a-user) don't count as billable users in the current subscription. When they are either deactivated or blocked they release a _billable user_ seat. However, they may count toward overages in the subscribed seat count. - Users who are [pending approval](../../user/admin_area/approving_users.md). - Members with Guest permissions on an Ultimate subscription. @@ -183,7 +183,7 @@ Starting 30 days before a subscription expires, GitLab notifies administrators o We recommend following these steps during renewal: -1. Prune any inactive or unwanted users by [blocking them](../../user/admin_area/blocking_unblocking_users.md#blocking-a-user). +1. Prune any inactive or unwanted users by [blocking them](../../user/admin_area/user_moderation.md#blocking-a-user). 1. Determine if you have a need for user growth in the upcoming subscription. 1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in) and select the **Renew** button beneath your existing subscription. diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md deleted file mode 100644 index 144ee2dbf98732..00000000000000 --- a/doc/user/admin_area/activating_deactivating_users.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -stage: Manage -group: Access -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: howto ---- - -# Activating and deactivating users - -GitLab administrators can deactivate and activate users. - -## Deactivating a user - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. - -In order to temporarily prevent access by a GitLab user that has no recent activity, administrators -can choose to deactivate the user. - -Deactivating a user is functionally identical to [blocking a user](blocking_unblocking_users.md), -with the following differences: - -- It does not prohibit the user from logging back in via the UI. -- Once a deactivated user logs back into the GitLab UI, their account is set to active. - -A deactivated user: - -- Cannot access Git repositories or the API. -- Will not receive any notifications from GitLab. -- Will not be able to use [slash commands](../../integration/slash_commands.md). - -Personal projects, and group and user history of the deactivated user will be left intact. - -A user can be deactivated from the Admin Area. To do this: - -1. Navigate to **Admin Area > Overview > Users**. -1. Select a user. -1. Under the **Account** tab, click **Deactivate user**. - -Please note that for the deactivation option to be visible to an admin, the user: - -- Must be currently active. -- Must not have signed in, or have any activity, in the last 90 days. - -Users can also be deactivated using the [GitLab API](../../api/users.md#deactivate-user). - -NOTE: -A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). - -## Activating a user - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. - -A deactivated user can be activated from the Admin Area. - -To do this: - -1. Navigate to **Admin Area > Overview > Users**. -1. Click on the **Deactivated** tab. -1. Select a user. -1. Under the **Account** tab, click **Activate user**. - -Users can also be activated using the [GitLab API](../../api/users.md#activate-user). - -NOTE: -Activating a user changes the user's state to active and consumes a -[seat](../../subscriptions/self_managed/index.md#billable-users). - -NOTE: -A deactivated user can also activate their account themselves by logging back in via the UI. diff --git a/doc/user/admin_area/approving_users.md b/doc/user/admin_area/approving_users.md index 9141d7f488de2d..b91fd0fa775100 100644 --- a/doc/user/admin_area/approving_users.md +++ b/doc/user/admin_area/approving_users.md @@ -21,7 +21,7 @@ When a user registers for an account while this setting is enabled: A user pending approval: -- Is functionally identical to a [blocked](blocking_unblocking_users.md) user. +- Is functionally identical to a [blocked](user_moderation.md#blocking-a-user) user. - Cannot sign in. - Cannot access Git repositories or the GitLab API. - Does not receive any notifications from GitLab. diff --git a/doc/user/admin_area/blocking_unblocking_users.md b/doc/user/admin_area/blocking_unblocking_users.md deleted file mode 100644 index 14a5b5085cb069..00000000000000 --- a/doc/user/admin_area/blocking_unblocking_users.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -stage: Manage -group: Access -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: howto ---- - -# Blocking and unblocking users - -GitLab administrators block and unblock users. - -## Blocking a user - -In order to completely prevent access of a user to the GitLab instance, administrators can choose to -block the user. - -Users can be blocked [via an abuse report](review_abuse_reports.md#blocking-users), -or directly from the Admin Area. To do this: - -1. Navigate to **Admin Area > Overview > Users**. -1. Select a user. -1. Under the **Account** tab, click **Block user**. - -A blocked user: - -- Cannot log in. -- Cannot access Git repositories or the API. -- Does not receive any notifications from GitLab. -- Cannot use [slash commands](../../integration/slash_commands.md). - -Personal projects, and group and user history of the blocked user are left intact. - -Users can also be blocked using the [GitLab API](../../api/users.md#block-user). - -NOTE: -A blocked user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). - -## Unblocking a user - -A blocked user can be unblocked from the Admin Area. To do this: - -1. Navigate to **Admin Area > Overview > Users**. -1. Click on the **Blocked** tab. -1. Select a user. -1. Under the **Account** tab, click **Unblock user**. - -Users can also be unblocked using the [GitLab API](../../api/users.md#unblock-user). - -NOTE: -Unblocking a user changes the user's state to active and consumes a -[seat](../../subscriptions/self_managed/index.md#billable-users). diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md index 01926f28937587..949415c3bef9c4 100644 --- a/doc/user/admin_area/index.md +++ b/doc/user/admin_area/index.md @@ -117,8 +117,8 @@ To list users matching a specific criteria, click on one of the following tabs o - **2FA Enabled** - **2FA Disabled** - **External** -- **[Blocked](blocking_unblocking_users.md)** -- **[Deactivated](activating_deactivating_users.md)** +- **[Blocked](user_moderation.md#blocking-a-user)** +- **[Deactivated](user_moderation.md#deactivating-a-user)** - **Without projects** For each user, the following are listed: diff --git a/doc/user/admin_area/user_moderation.md b/doc/user/admin_area/user_moderation.md new file mode 100644 index 00000000000000..8e1f927bc7e918 --- /dev/null +++ b/doc/user/admin_area/user_moderation.md @@ -0,0 +1,164 @@ +--- +stage: Manage +group: Access +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +type: howto +--- + +# User moderation + +GitLab administrators can moderate user access by blocking, banning, or deactivating users. + +## Blocking and unblocking users + +GitLab administrators can block and unblock users. + +### Blocking a user + +In order to completely prevent access of a user to the GitLab instance, +administrators can choose to block the user. + +Users can be blocked [via an abuse report](review_abuse_reports.md#blocking-users), +or directly from the Admin Area. To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Select a user. +1. Under the **Account** tab, click **Block user**. + +A blocked user: + +- Cannot log in. +- Cannot access Git repositories or the API. +- Does not receive any notifications from GitLab. +- Cannot use [slash commands](../../integration/slash_commands.md). + +Personal projects, and group and user history of the blocked user are left intact. + +Users can also be blocked using the [GitLab API](../../api/users.md#block-user). + +NOTE: +A blocked user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). + +### Unblocking a user + +A blocked user can be unblocked from the Admin Area. To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Click on the **Blocked** tab. +1. Select a user. +1. Under the **Account** tab, click **Unblock user**. + +Users can also be unblocked using the [GitLab API](../../api/users.md#unblock-user). + +NOTE: +Unblocking a user changes the user's state to active and consumes a +[seat](../../subscriptions/self_managed/index.md#billable-users). + +## Activating and deactivating users + +GitLab administrators can deactivate and activate users. + +### Deactivating a user + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. + +In order to temporarily prevent access by a GitLab user that has no recent activity, +administrators can choose to deactivate the user. + +Deactivating a user is functionally identical to [blocking a user](#blocking-and-unblocking-users), +with the following differences: + +- It does not prohibit the user from logging back in via the UI. +- Once a deactivated user logs back into the GitLab UI, their account is set to active. + +A deactivated user: + +- Cannot access Git repositories or the API. +- Will not receive any notifications from GitLab. +- Will not be able to use [slash commands](../../integration/slash_commands.md). + +Personal projects, and group and user history of the deactivated user are left intact. + +A user can be deactivated from the Admin Area. To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Select a user. +1. Under the **Account** tab, click **Deactivate user**. + +Please note that for the deactivation option to be visible to an admin, the user: + +- Must be currently active. +- Must not have signed in, or have any activity, in the last 90 days. + +Users can also be deactivated using the [GitLab API](../../api/users.md#deactivate-user). + +NOTE: +A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). + +### Activating a user + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. + +A deactivated user can be activated from the Admin Area. + +To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Click on the **Deactivated** tab. +1. Select a user. +1. Under the **Account** tab, click **Activate user**. + +Users can also be activated using the [GitLab API](../../api/users.md#activate-user). + +NOTE: +Activating a user changes the user's state to active and consumes a +[seat](../../subscriptions/self_managed/index.md#billable-users). + +NOTE: +A deactivated user can also activate their account themselves by logging back in via the UI. + +## Banning and unbanning users + +GitLab administrators can ban users. + +NOTE: +This feature is behind a feature flag that is disabled by default. GitLab administrators +with access to the GitLab Rails console can [enable](../../administration/feature_flags.md) +this feature for your GitLab instance. + +### Banning a user + +In order to completely block a user and hide the user's comments and issues from other users, +administrators can choose to ban the user. + +Users can be banned from the Admin Area. To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Select a user. +1. Under the **Account** tab, click **Ban user**. + +Banning a user is functionally identical to [blocking a user](#blocking-and-unblocking-users), +with the following differences: + +- Comments made by the banned user will be hidden from other users. +- Issues created by the banned user will be hidden from other users. + +Personal projects, and group and user history of the blocked user are left intact. + +NOTE: +This feature is a work in progress. Currently, banning a user +only blocks them and does not hide their comments or issues. +This functionality will be implemented in follow up issues. + +### Unbanning a user + +A banned user can be unbanned from the Admin Area. To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Click on the **Banned** tab. +1. Select a user. +1. Under the **Account** tab, click **Unban user**. + +NOTE: +Unbanning a user changes the user's state to active and consumes a +[seat](../../subscriptions/self_managed/index.md#billable-users). diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md index c0560269f00b0b..d2dac0fe2f645f 100644 --- a/doc/user/profile/account/delete_account.md +++ b/doc/user/profile/account/delete_account.md @@ -69,7 +69,7 @@ username of the original user. When using the **Delete user and contributions** option, **all** associated records are removed. This includes all of the items mentioned above including issues, merge requests, notes/comments, and more. Consider -[blocking a user](../../admin_area/blocking_unblocking_users.md) +[blocking a user](../../admin_area/user_moderation.md#blocking-a-user) or using the **Delete user** option instead. When a user is deleted from an [abuse report](../../admin_area/review_abuse_reports.md) diff --git a/doc/user/upgrade_email_bypass.md b/doc/user/upgrade_email_bypass.md index 199c1a47e04d9b..b5f83c3702689c 100644 --- a/doc/user/upgrade_email_bypass.md +++ b/doc/user/upgrade_email_bypass.md @@ -73,7 +73,7 @@ Your account has been blocked. Fatal: Could not read from remote repository Your primary email address is not confirmed. ``` -You can assure your users that they have not been [Blocked](admin_area/blocking_unblocking_users.md) by an administrator. +You can assure your users that they have not been [Blocked](admin_area/user_moderation.md#blocking-and-unblocking-users) by an administrator. When affected users see this message, they must confirm their email address before they can commit code. ## What do I need to know as an administrator of a GitLab self-managed Instance? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2afaf90e74046c..30ccabd638f0fa 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1373,6 +1373,9 @@ msgstr "" msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates." msgstr "" +msgid "A banned user cannot:" +msgstr "" + msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages" msgstr "" @@ -2435,6 +2438,9 @@ msgstr "" msgid "AdminUsers|(Admin)" msgstr "" +msgid "AdminUsers|(Banned)" +msgstr "" + msgid "AdminUsers|(Blocked)" msgstr "" @@ -2501,6 +2507,21 @@ msgstr "" msgid "AdminUsers|Automatically marked as default internal user" msgstr "" +msgid "AdminUsers|Ban" +msgstr "" + +msgid "AdminUsers|Ban user" +msgstr "" + +msgid "AdminUsers|Ban user %{username}?" +msgstr "" + +msgid "AdminUsers|Banned" +msgstr "" + +msgid "AdminUsers|Banning the user has the following effects:" +msgstr "" + msgid "AdminUsers|Be added to groups and projects" msgstr "" @@ -2588,6 +2609,9 @@ msgstr "" msgid "AdminUsers|It's you!" msgstr "" +msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}" +msgstr "" + msgid "AdminUsers|Log in" msgstr "" @@ -2669,6 +2693,15 @@ msgstr "" msgid "AdminUsers|To confirm, type %{username}" msgstr "" +msgid "AdminUsers|Unban" +msgstr "" + +msgid "AdminUsers|Unban %{username}?" +msgstr "" + +msgid "AdminUsers|Unban user" +msgstr "" + msgid "AdminUsers|Unblock" msgstr "" @@ -2684,6 +2717,9 @@ msgstr "" msgid "AdminUsers|Unlock user %{username}?" msgstr "" +msgid "AdminUsers|User will be blocked" +msgstr "" + msgid "AdminUsers|User will not be able to access git repositories" msgstr "" @@ -2720,6 +2756,9 @@ msgstr "" msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered." msgstr "" +msgid "AdminUsers|You can always ban their account again if needed." +msgstr "" + msgid "AdminUsers|You can always block their account again if needed." msgstr "" @@ -2729,6 +2768,9 @@ msgstr "" msgid "AdminUsers|You can always re-activate their account, their data will remain intact." msgstr "" +msgid "AdminUsers|You can always unban their account. Their data remains intact." +msgstr "" + msgid "AdminUsers|You can always unblock their account, their data will remain intact." msgstr "" @@ -12905,12 +12947,18 @@ msgstr "" msgid "Error occurred. A blocked user must be unblocked to be activated" msgstr "" +msgid "Error occurred. User was not banned" +msgstr "" + msgid "Error occurred. User was not blocked" msgstr "" msgid "Error occurred. User was not confirmed" msgstr "" +msgid "Error occurred. User was not unbanned" +msgstr "" + msgid "Error occurred. User was not unblocked" msgstr "" @@ -31247,6 +31295,9 @@ msgstr "" msgid "Successfully approved" msgstr "" +msgid "Successfully banned" +msgstr "" + msgid "Successfully blocked" msgstr "" @@ -31271,6 +31322,9 @@ msgstr "" msgid "Successfully synced %{synced_timeago}." msgstr "" +msgid "Successfully unbanned" +msgstr "" + msgid "Successfully unblocked" msgstr "" @@ -33377,6 +33431,9 @@ msgstr "" msgid "This user has the %{access} role in the %{name} project." msgstr "" +msgid "This user is banned" +msgstr "" + msgid "This user is blocked" msgstr "" diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index 1afd20f5021e9d..591c9c8740a0a5 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -365,6 +365,28 @@ end end + describe 'PUT ban/:id' do + it 'bans user' do + put :ban, params: { id: user.username } + + user.reload + expect(user.banned?).to be_truthy + expect(flash[:notice]).to eq _('Successfully banned') + end + + context 'when unsuccessful' do + let(:user) { create(:user, :blocked) } + + it 'does not ban user' do + put :ban, params: { id: user.username } + + user.reload + expect(user.banned?).to be_falsey + expect(flash[:alert]).to eq _('Error occurred. User was not banned') + end + end + end + describe 'PUT unlock/:id' do before do request.env["HTTP_REFERER"] = "/" diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 7ac44d55687ecf..476c57f2d80d0a 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -27,6 +27,10 @@ after(:build) { |user, _| user.block_pending_approval! } end + trait :banned do + after(:build) { |user, _| user.ban! } + end + trait :ldap_blocked do after(:build) { |user, _| user.ldap_block! } end diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb index 36907d4aa603d7..d3931373ee3ba0 100644 --- a/spec/features/admin/users/users_spec.rb +++ b/spec/features/admin/users/users_spec.rb @@ -85,6 +85,7 @@ expect(page).to have_link('2FA Disabled', href: admin_users_path(filter: 'two_factor_disabled')) expect(page).to have_link('External', href: admin_users_path(filter: 'external')) expect(page).to have_link('Blocked', href: admin_users_path(filter: 'blocked')) + expect(page).to have_link('Banned', href: admin_users_path(filter: 'banned')) expect(page).to have_link('Deactivated', href: admin_users_path(filter: 'deactivated')) expect(page).to have_link('Without projects', href: admin_users_path(filter: 'wop')) end diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb index 46073b37a3b023..862fd58df04e73 100644 --- a/spec/helpers/users_helper_spec.rb +++ b/spec/helpers/users_helper_spec.rb @@ -136,6 +136,16 @@ def filter_ee_badges(badges) end end + context 'with a banned user' do + it 'returns the banned badge' do + banned_user = create(:user, :banned) + + badges = helper.user_badges_in_admin_section(banned_user) + + expect(filter_ee_badges(badges)).to eq([text: 'Banned', variant: 'danger']) + end + end + context 'with an admin user' do it "returns the admin badge" do admin_user = create(:admin) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0c35b1265ba4f2..e0ef5a20c425e0 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -728,6 +728,7 @@ let_it_be(:blocked_user) { create(:user, :blocked) } let_it_be(:ldap_blocked_user) { create(:omniauth_user, :ldap_blocked) } let_it_be(:blocked_pending_approval_user) { create(:user, :blocked_pending_approval) } + let_it_be(:banned_user) { create(:user, :banned) } describe '.blocked' do subject { described_class.blocked } @@ -735,6 +736,7 @@ it 'returns only blocked users' do expect(subject).to include( blocked_user, + banned_user, ldap_blocked_user ) @@ -749,6 +751,14 @@ expect(subject).to contain_exactly(blocked_pending_approval_user) end end + + describe '.banned' do + subject { described_class.banned } + + it 'returns only banned users' do + expect(subject).to contain_exactly(banned_user) + end + end end describe ".with_two_factor" do @@ -1934,6 +1944,12 @@ expect(described_class.filter_items('blocked')).to include user end + it 'filters by banned' do + expect(described_class).to receive(:banned).and_return([user]) + + expect(described_class.filter_items('banned')).to include user + end + it 'filters by blocked pending approval' do expect(described_class).to receive(:blocked_pending_approval).and_return([user]) diff --git a/spec/services/users/ban_service_spec.rb b/spec/services/users/ban_service_spec.rb new file mode 100644 index 00000000000000..0e6ac615da5f40 --- /dev/null +++ b/spec/services/users/ban_service_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Users::BanService do + let(:current_user) { create(:admin) } + + subject(:service) { described_class.new(current_user) } + + describe '#execute' do + subject(:operation) { service.execute(user) } + + context 'when successful' do + let(:user) { create(:user) } + + it { is_expected.to eq(status: :success) } + + it "bans the user" do + expect { operation }.to change { user.state }.to('banned') + end + + it "blocks the user" do + expect { operation }.to change { user.blocked? }.from(false).to(true) + end + + it 'logs ban in application logs' do + allow(Gitlab::AppLogger).to receive(:info) + + operation + + expect(Gitlab::AppLogger).to have_received(:info).with(message: "User banned", user: "#{user.username}", email: "#{user.email}", banned_by: "#{current_user.username}", ip_address: "#{current_user.current_sign_in_ip}") + end + end + + context 'when failed' do + let(:user) { create(:user, :blocked) } + + it 'returns error result' do + aggregate_failures 'error result' do + expect(operation[:status]).to eq(:error) + expect(operation[:message]).to match(/State cannot transition/) + end + end + + it "does not change the user's state" do + expect { operation }.not_to change { user.state } + end + end + end +end -- GitLab From 2044460b3dd524023c12867f378e8c745f405cf5 Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Wed, 12 May 2021 00:11:11 -0500 Subject: [PATCH 2/9] Apply MR review suggestions Apply TW review suggestions --- app/helpers/users_helper.rb | 6 +- app/views/admin/users/show.html.haml | 2 +- doc/subscriptions/self_managed/index.md | 6 +- .../activating_deactivating_users.md | 68 +++++++++++++++++++ doc/user/admin_area/approving_users.md | 2 +- .../admin_area/blocking_unblocking_users.md | 51 ++++++++++++++ doc/user/admin_area/index.md | 4 +- .../{user_moderation.md => moderate_users.md} | 14 ++-- doc/user/profile/account/delete_account.md | 2 +- doc/user/upgrade_email_bypass.md | 2 +- 10 files changed, 138 insertions(+), 19 deletions(-) create mode 100644 doc/user/admin_area/activating_deactivating_users.md create mode 100644 doc/user/admin_area/blocking_unblocking_users.md rename doc/user/admin_area/{user_moderation.md => moderate_users.md} (94%) diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 845d381892215f..c1d05c2d3cfb8f 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -168,7 +168,7 @@ def user_ban_data(user) method: 'put', modal_attributes: { title: s_('AdminUsers|Ban user %{username}?') % { username: sanitize_name(user.name) }, - message: s_('AdminUsers|You can always unban their account. Their data remains intact.'), + message: s_('AdminUsers|You can unban their account in the future. Their data remains intact.'), okVariant: 'warning', okTitle: s_('AdminUsers|Ban') }.to_json @@ -181,7 +181,7 @@ def user_unban_data(user) method: 'put', modal_attributes: { title: s_('AdminUsers|Unban %{username}?') % { username: sanitize_name(user.name) }, - message: s_('AdminUsers|You can always ban their account again if needed.'), + message: s_('AdminUsers|You ban their account in the future if necessary.'), okVariant: 'info', okTitle: s_('AdminUsers|Unban') }.to_json @@ -195,7 +195,7 @@ def user_ban_effects concat tag.li s_('AdminUsers|User will be blocked') end - link_start = ''.html_safe % { url: help_page_path("user/admin_area/user_moderation", anchor: "banning-a-user") } + link_start = ''.html_safe % { url: help_page_path("user/admin_area/moderate_users", anchor: "ban-a-user") } info = tag.p s_('AdminUsers|Learn more about %{link_start}banned users.%{link_end}').html_safe % { link_start: link_start, link_end: ''.html_safe } header + list + info diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 18756ebc1f1305..19cc29668f59e0 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -185,7 +185,7 @@ %ul %li= _('Log in') %li= _('Access Git repositories') - - link_start = ''.html_safe % { url: help_page_path("user/admin_area/user_moderation", anchor: "banning-a-user") } + - link_start = ''.html_safe % { url: help_page_path("user/admin_area/moderate_users", anchor: "ban-a-user") } = s_('AdminUsers|Learn more about %{link_start}banned users.%{link_end}').html_safe % { link_start: link_start, link_end: ''.html_safe } %p %button.btn.gl-button.btn-info.js-confirm-modal-button{ data: user_unban_data(@user) } diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index 03466785c5164f..648ad0c70a56d2 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -48,8 +48,8 @@ using [Seat Link](#seat-link). A _billable user_ counts against the number of subscription seats. Every user is considered a billable user, with the following exceptions: -- [Deactivated users](../../user/admin_area/user_moderation.md#deactivating-a-user) and - [blocked users](../../user/admin_area/user_moderation.md#blocking-a-user) don't count as billable users in the current subscription. When they are either deactivated or blocked they release a _billable user_ seat. However, they may +- [Deactivated users](../../user/admin_area/moderate_users.md#deactivating-a-user) and + [blocked users](../../user/admin_area/moderate_users.md#blocking-a-user) don't count as billable users in the current subscription. When they are either deactivated or blocked they release a _billable user_ seat. However, they may count toward overages in the subscribed seat count. - Users who are [pending approval](../../user/admin_area/approving_users.md). - Members with Guest permissions on an Ultimate subscription. @@ -183,7 +183,7 @@ Starting 30 days before a subscription expires, GitLab notifies administrators o We recommend following these steps during renewal: -1. Prune any inactive or unwanted users by [blocking them](../../user/admin_area/user_moderation.md#blocking-a-user). +1. Prune any inactive or unwanted users by [blocking them](../../user/admin_area/moderate_users.md#blocking-a-user). 1. Determine if you have a need for user growth in the upcoming subscription. 1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in) and select the **Renew** button beneath your existing subscription. diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md new file mode 100644 index 00000000000000..4ccd7f529fe23f --- /dev/null +++ b/doc/user/admin_area/activating_deactivating_users.md @@ -0,0 +1,68 @@ +--- +stage: Manage +group: Access +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +type: howto +--- + +# Activating and deactivating users + +GitLab administrators can deactivate and activate users. + +## Deactivating a user + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. + +In order to temporarily prevent access by a GitLab user that has no recent activity, administrators +can choose to deactivate the user. + +Deactivating a user is functionally identical to [blocking a user](blocking_unblocking_users.md), +with the following differences: + +- It does not prohibit the user from logging back in via the UI. +- Once a deactivated user logs back into the GitLab UI, their account is set to active. + +A deactivated user: + +- Cannot access Git repositories or the API. +- Will not receive any notifications from GitLab. +- Will not be able to use [slash commands](../../integration/slash_commands.md). + +Personal projects, and group and user history of the deactivated user will be left intact. + +A user can be deactivated from the Admin Area. To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Select a user. +1. Under the **Account** tab, click **Deactivate user**. + +Please note that for the deactivation option to be visible to an admin, the user: + +- Must be currently active. +- Must not have signed in, or have any activity, in the last 90 days. + +Users can also be deactivated using the [GitLab API](../../api/users.md#deactivate-user). +NOTE: +A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). + +## Activating a user + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. + +A deactivated user can be activated from the Admin Area. + +To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Click on the **Deactivated** tab. +1. Select a user. +1. Under the **Account** tab, click **Activate user**. + +Users can also be activated using the [GitLab API](../../api/users.md#activate-user). + +NOTE: +Activating a user changes the user's state to active and consumes a +[seat](../../subscriptions/self_managed/index.md#billable-users). + +NOTE: +A deactivated user can also activate their account themselves by logging back in via the UI. diff --git a/doc/user/admin_area/approving_users.md b/doc/user/admin_area/approving_users.md index b91fd0fa775100..2b3b90cb1a49cc 100644 --- a/doc/user/admin_area/approving_users.md +++ b/doc/user/admin_area/approving_users.md @@ -21,7 +21,7 @@ When a user registers for an account while this setting is enabled: A user pending approval: -- Is functionally identical to a [blocked](user_moderation.md#blocking-a-user) user. +- Is functionally identical to a [blocked](moderate_users.md#blocking-a-user) user. - Cannot sign in. - Cannot access Git repositories or the GitLab API. - Does not receive any notifications from GitLab. diff --git a/doc/user/admin_area/blocking_unblocking_users.md b/doc/user/admin_area/blocking_unblocking_users.md new file mode 100644 index 00000000000000..14a5b5085cb069 --- /dev/null +++ b/doc/user/admin_area/blocking_unblocking_users.md @@ -0,0 +1,51 @@ +--- +stage: Manage +group: Access +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +type: howto +--- + +# Blocking and unblocking users + +GitLab administrators block and unblock users. + +## Blocking a user + +In order to completely prevent access of a user to the GitLab instance, administrators can choose to +block the user. + +Users can be blocked [via an abuse report](review_abuse_reports.md#blocking-users), +or directly from the Admin Area. To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Select a user. +1. Under the **Account** tab, click **Block user**. + +A blocked user: + +- Cannot log in. +- Cannot access Git repositories or the API. +- Does not receive any notifications from GitLab. +- Cannot use [slash commands](../../integration/slash_commands.md). + +Personal projects, and group and user history of the blocked user are left intact. + +Users can also be blocked using the [GitLab API](../../api/users.md#block-user). + +NOTE: +A blocked user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). + +## Unblocking a user + +A blocked user can be unblocked from the Admin Area. To do this: + +1. Navigate to **Admin Area > Overview > Users**. +1. Click on the **Blocked** tab. +1. Select a user. +1. Under the **Account** tab, click **Unblock user**. + +Users can also be unblocked using the [GitLab API](../../api/users.md#unblock-user). + +NOTE: +Unblocking a user changes the user's state to active and consumes a +[seat](../../subscriptions/self_managed/index.md#billable-users). diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md index 949415c3bef9c4..60c1ecbd10f479 100644 --- a/doc/user/admin_area/index.md +++ b/doc/user/admin_area/index.md @@ -117,8 +117,8 @@ To list users matching a specific criteria, click on one of the following tabs o - **2FA Enabled** - **2FA Disabled** - **External** -- **[Blocked](user_moderation.md#blocking-a-user)** -- **[Deactivated](user_moderation.md#deactivating-a-user)** +- **[Blocked](moderate_users.md#blocking-a-user)** +- **[Deactivated](moderate_users.md#deactivating-a-user)** - **Without projects** For each user, the following are listed: diff --git a/doc/user/admin_area/user_moderation.md b/doc/user/admin_area/moderate_users.md similarity index 94% rename from doc/user/admin_area/user_moderation.md rename to doc/user/admin_area/moderate_users.md index 8e1f927bc7e918..4da8e123f2d49c 100644 --- a/doc/user/admin_area/user_moderation.md +++ b/doc/user/admin_area/moderate_users.md @@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w type: howto --- -# User moderation +# Moderate users GitLab administrators can moderate user access by blocking, banning, or deactivating users. @@ -117,7 +117,7 @@ Activating a user changes the user's state to active and consumes a NOTE: A deactivated user can also activate their account themselves by logging back in via the UI. -## Banning and unbanning users +## Ban and unban users GitLab administrators can ban users. @@ -126,12 +126,12 @@ This feature is behind a feature flag that is disabled by default. GitLab admini with access to the GitLab Rails console can [enable](../../administration/feature_flags.md) this feature for your GitLab instance. -### Banning a user +### Ban a user -In order to completely block a user and hide the user's comments and issues from other users, +To completely block a user and hide the user's comments and issues from other users, administrators can choose to ban the user. -Users can be banned from the Admin Area. To do this: +Users can be banned using the Admin Area. To do this: 1. Navigate to **Admin Area > Overview > Users**. 1. Select a user. @@ -150,9 +150,9 @@ This feature is a work in progress. Currently, banning a user only blocks them and does not hide their comments or issues. This functionality will be implemented in follow up issues. -### Unbanning a user +### Unban a user -A banned user can be unbanned from the Admin Area. To do this: +A banned user can be unbanned using the Admin Area. To do this: 1. Navigate to **Admin Area > Overview > Users**. 1. Click on the **Banned** tab. diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md index d2dac0fe2f645f..361353a0f8c092 100644 --- a/doc/user/profile/account/delete_account.md +++ b/doc/user/profile/account/delete_account.md @@ -69,7 +69,7 @@ username of the original user. When using the **Delete user and contributions** option, **all** associated records are removed. This includes all of the items mentioned above including issues, merge requests, notes/comments, and more. Consider -[blocking a user](../../admin_area/user_moderation.md#blocking-a-user) +[blocking a user](../../admin_area/moderate_users.md#blocking-a-user) or using the **Delete user** option instead. When a user is deleted from an [abuse report](../../admin_area/review_abuse_reports.md) diff --git a/doc/user/upgrade_email_bypass.md b/doc/user/upgrade_email_bypass.md index b5f83c3702689c..7d2f2395815cb1 100644 --- a/doc/user/upgrade_email_bypass.md +++ b/doc/user/upgrade_email_bypass.md @@ -73,7 +73,7 @@ Your account has been blocked. Fatal: Could not read from remote repository Your primary email address is not confirmed. ``` -You can assure your users that they have not been [Blocked](admin_area/user_moderation.md#blocking-and-unblocking-users) by an administrator. +You can assure your users that they have not been [Blocked](admin_area/moderate_users.md#blocking-and-unblocking-users) by an administrator. When affected users see this message, they must confirm their email address before they can commit code. ## What do I need to know as an administrator of a GitLab self-managed Instance? -- GitLab From 0e290971e7106744a982f8897724d3d393f806d8 Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Wed, 12 May 2021 00:12:38 -0500 Subject: [PATCH 3/9] Add in accidentally removed blank line --- doc/user/admin_area/activating_deactivating_users.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md index 4ccd7f529fe23f..144ee2dbf98732 100644 --- a/doc/user/admin_area/activating_deactivating_users.md +++ b/doc/user/admin_area/activating_deactivating_users.md @@ -42,6 +42,7 @@ Please note that for the deactivation option to be visible to an admin, the user - Must not have signed in, or have any activity, in the last 90 days. Users can also be deactivated using the [GitLab API](../../api/users.md#deactivate-user). + NOTE: A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). -- GitLab From f1b1e1dfcb97eee24f88dce26b15b0a8628f7568 Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Wed, 12 May 2021 00:36:56 -0500 Subject: [PATCH 4/9] Redirect block and deactivate to moderate Redirect block unblock users and activate deactivate users pages to moderate users --- .../activating_deactivating_users.md | 69 ++----------------- .../admin_area/blocking_unblocking_users.md | 51 ++------------ 2 files changed, 8 insertions(+), 112 deletions(-) diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md index 144ee2dbf98732..1283579356b085 100644 --- a/doc/user/admin_area/activating_deactivating_users.md +++ b/doc/user/admin_area/activating_deactivating_users.md @@ -1,69 +1,8 @@ --- -stage: Manage -group: Access -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: howto +redirect_to: 'moderate_users.md' --- -# Activating and deactivating users +This file was moved to [another location](moderate_users.md). -GitLab administrators can deactivate and activate users. - -## Deactivating a user - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. - -In order to temporarily prevent access by a GitLab user that has no recent activity, administrators -can choose to deactivate the user. - -Deactivating a user is functionally identical to [blocking a user](blocking_unblocking_users.md), -with the following differences: - -- It does not prohibit the user from logging back in via the UI. -- Once a deactivated user logs back into the GitLab UI, their account is set to active. - -A deactivated user: - -- Cannot access Git repositories or the API. -- Will not receive any notifications from GitLab. -- Will not be able to use [slash commands](../../integration/slash_commands.md). - -Personal projects, and group and user history of the deactivated user will be left intact. - -A user can be deactivated from the Admin Area. To do this: - -1. Navigate to **Admin Area > Overview > Users**. -1. Select a user. -1. Under the **Account** tab, click **Deactivate user**. - -Please note that for the deactivation option to be visible to an admin, the user: - -- Must be currently active. -- Must not have signed in, or have any activity, in the last 90 days. - -Users can also be deactivated using the [GitLab API](../../api/users.md#deactivate-user). - -NOTE: -A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). - -## Activating a user - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. - -A deactivated user can be activated from the Admin Area. - -To do this: - -1. Navigate to **Admin Area > Overview > Users**. -1. Click on the **Deactivated** tab. -1. Select a user. -1. Under the **Account** tab, click **Activate user**. - -Users can also be activated using the [GitLab API](../../api/users.md#activate-user). - -NOTE: -Activating a user changes the user's state to active and consumes a -[seat](../../subscriptions/self_managed/index.md#billable-users). - -NOTE: -A deactivated user can also activate their account themselves by logging back in via the UI. + + diff --git a/doc/user/admin_area/blocking_unblocking_users.md b/doc/user/admin_area/blocking_unblocking_users.md index 14a5b5085cb069..1283579356b085 100644 --- a/doc/user/admin_area/blocking_unblocking_users.md +++ b/doc/user/admin_area/blocking_unblocking_users.md @@ -1,51 +1,8 @@ --- -stage: Manage -group: Access -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: howto +redirect_to: 'moderate_users.md' --- -# Blocking and unblocking users +This file was moved to [another location](moderate_users.md). -GitLab administrators block and unblock users. - -## Blocking a user - -In order to completely prevent access of a user to the GitLab instance, administrators can choose to -block the user. - -Users can be blocked [via an abuse report](review_abuse_reports.md#blocking-users), -or directly from the Admin Area. To do this: - -1. Navigate to **Admin Area > Overview > Users**. -1. Select a user. -1. Under the **Account** tab, click **Block user**. - -A blocked user: - -- Cannot log in. -- Cannot access Git repositories or the API. -- Does not receive any notifications from GitLab. -- Cannot use [slash commands](../../integration/slash_commands.md). - -Personal projects, and group and user history of the blocked user are left intact. - -Users can also be blocked using the [GitLab API](../../api/users.md#block-user). - -NOTE: -A blocked user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). - -## Unblocking a user - -A blocked user can be unblocked from the Admin Area. To do this: - -1. Navigate to **Admin Area > Overview > Users**. -1. Click on the **Blocked** tab. -1. Select a user. -1. Under the **Account** tab, click **Unblock user**. - -Users can also be unblocked using the [GitLab API](../../api/users.md#unblock-user). - -NOTE: -Unblocking a user changes the user's state to active and consumes a -[seat](../../subscriptions/self_managed/index.md#billable-users). + + -- GitLab From 8e8c0dbbe539498a1e5aa3446b6eb496eeea2baf Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Wed, 12 May 2021 01:32:48 -0500 Subject: [PATCH 5/9] Add specs for unban and ff disabled Apply MR review suggestions Add version history --- doc/user/admin_area/moderate_users.md | 2 + .../admin/users_controller_spec.rb | 46 +++++++++++++++---- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md index 4da8e123f2d49c..e293117a79178a 100644 --- a/doc/user/admin_area/moderate_users.md +++ b/doc/user/admin_area/moderate_users.md @@ -119,6 +119,8 @@ A deactivated user can also activate their account themselves by logging back in ## Ban and unban users +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327353) in GitLab 13.12. + GitLab administrators can ban users. NOTE: diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index 591c9c8740a0a5..722c9c322cca93 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -366,27 +366,55 @@ end describe 'PUT ban/:id' do - it 'bans user' do - put :ban, params: { id: user.username } + context 'when ban_user_feature_flag is enabled' do + it 'bans user' do + put :ban, params: { id: user.username } - user.reload - expect(user.banned?).to be_truthy - expect(flash[:notice]).to eq _('Successfully banned') + user.reload + expect(user.banned?).to be_truthy + expect(flash[:notice]).to eq _('Successfully banned') + end + + context 'when unsuccessful' do + let(:user) { create(:user, :blocked) } + + it 'does not ban user' do + put :ban, params: { id: user.username } + + user.reload + expect(user.banned?).to be_falsey + expect(flash[:alert]).to eq _('Error occurred. User was not banned') + end + end end - context 'when unsuccessful' do - let(:user) { create(:user, :blocked) } + context 'when ban_user_feature_flag is not enabled' do + before do + stub_feature_flags(ban_user_feature_flag: false) + end - it 'does not ban user' do + it 'does not ban user, renders 404' do put :ban, params: { id: user.username } user.reload expect(user.banned?).to be_falsey - expect(flash[:alert]).to eq _('Error occurred. User was not banned') + expect(response).to have_gitlab_http_status(:not_found) end end end + describe 'PUT unban/:id' do + let(:banned_user) { create(:user, :banned) } + + it 'unbans user' do + put :unban, params: { id: banned_user.username } + + banned_user.reload + expect(banned_user.banned?).to be_falsey + expect(flash[:notice]).to eq _('Successfully unbanned') + end + end + describe 'PUT unlock/:id' do before do request.env["HTTP_REFERER"] = "/" -- GitLab From 4c063349e7c91c4351bf30cf06791f01c006bcde Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Wed, 12 May 2021 01:42:34 -0500 Subject: [PATCH 6/9] Regenerate translation file --- locale/gitlab.pot | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 30ccabd638f0fa..b2c11642456e55 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2756,7 +2756,7 @@ msgstr "" msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered." msgstr "" -msgid "AdminUsers|You can always ban their account again if needed." +msgid "AdminUsers|You ban their account in the future if necessary." msgstr "" msgid "AdminUsers|You can always block their account again if needed." @@ -2768,10 +2768,10 @@ msgstr "" msgid "AdminUsers|You can always re-activate their account, their data will remain intact." msgstr "" -msgid "AdminUsers|You can always unban their account. Their data remains intact." +msgid "AdminUsers|You can always unblock their account, their data will remain intact." msgstr "" -msgid "AdminUsers|You can always unblock their account, their data will remain intact." +msgid "AdminUsers|You can unban their account in the future. Their data remains intact." msgstr "" msgid "AdminUsers|You cannot remove your own admin rights." -- GitLab From 3bcd20f046883a780062c06b4516797366239725 Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Wed, 12 May 2021 02:03:31 -0500 Subject: [PATCH 7/9] Remove banned from blocked scope --- app/models/user.rb | 2 +- spec/models/user_spec.rb | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 40c5fa083d5e96..4ff6221bcab34e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -381,7 +381,7 @@ def blocked? # Scopes scope :admins, -> { where(admin: true) } scope :instance_access_request_approvers_to_be_notified, -> { admins.active.order_recent_sign_in.limit(INSTANCE_ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT) } - scope :blocked, -> { with_states(:blocked, :ldap_blocked, :banned) } + scope :blocked, -> { with_states(:blocked, :ldap_blocked) } scope :blocked_pending_approval, -> { with_states(:blocked_pending_approval) } scope :banned, -> { with_states(:banned) } scope :external, -> { where(external: true) } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index e0ef5a20c425e0..cb34917f07352d 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -736,11 +736,10 @@ it 'returns only blocked users' do expect(subject).to include( blocked_user, - banned_user, ldap_blocked_user ) - expect(subject).not_to include(active_user, blocked_pending_approval_user) + expect(subject).not_to include(active_user, blocked_pending_approval_user, banned_user) end end -- GitLab From 0c8aacb875ea8c6d55731235c6461cda93bb6e8a Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Wed, 12 May 2021 13:27:45 -0500 Subject: [PATCH 8/9] Use gitlab ui utility class --- app/views/admin/users/_ban_user.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/users/_ban_user.html.haml b/app/views/admin/users/_ban_user.html.haml index b8d61b5dead4a3..229c88adb7f7a4 100644 --- a/app/views/admin/users/_ban_user.html.haml +++ b/app/views/admin/users/_ban_user.html.haml @@ -1,6 +1,6 @@ - if ban_feature_available? .card.border-warning - .card-header.bg-warning.text-white + .card-header.bg-warning.gl-text-white = s_('AdminUsers|Ban user') .card-body = user_ban_effects -- GitLab From 19d410d5ff1e6a1aaaf8b22283e2301410a7871e Mon Sep 17 00:00:00 2001 From: Serena Fang Date: Thu, 13 May 2021 12:53:20 -0500 Subject: [PATCH 9/9] Apply MR review suggestions Private method, describe current functionality --- app/services/users/ban_service.rb | 2 ++ doc/user/admin_area/activating_deactivating_users.md | 2 +- doc/user/admin_area/blocking_unblocking_users.md | 2 +- doc/user/admin_area/moderate_users.md | 11 +---------- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/app/services/users/ban_service.rb b/app/services/users/ban_service.rb index 3017afd9c0040d..247ed14966bedb 100644 --- a/app/services/users/ban_service.rb +++ b/app/services/users/ban_service.rb @@ -16,6 +16,8 @@ def execute(user) end end + private + def log_event(user) Gitlab::AppLogger.info(message: "User banned", user: "#{user.username}", email: "#{user.email}", banned_by: "#{current_user.username}", ip_address: "#{current_user.current_sign_in_ip}") end diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md index 1283579356b085..cafc7caf981ea0 100644 --- a/doc/user/admin_area/activating_deactivating_users.md +++ b/doc/user/admin_area/activating_deactivating_users.md @@ -2,7 +2,7 @@ redirect_to: 'moderate_users.md' --- -This file was moved to [another location](moderate_users.md). +This document was moved to [another location](moderate_users.md). diff --git a/doc/user/admin_area/blocking_unblocking_users.md b/doc/user/admin_area/blocking_unblocking_users.md index 1283579356b085..cafc7caf981ea0 100644 --- a/doc/user/admin_area/blocking_unblocking_users.md +++ b/doc/user/admin_area/blocking_unblocking_users.md @@ -2,7 +2,7 @@ redirect_to: 'moderate_users.md' --- -This file was moved to [another location](moderate_users.md). +This document was moved to [another location](moderate_users.md). diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md index e293117a79178a..c04003dd75f4b5 100644 --- a/doc/user/admin_area/moderate_users.md +++ b/doc/user/admin_area/moderate_users.md @@ -130,8 +130,7 @@ this feature for your GitLab instance. ### Ban a user -To completely block a user and hide the user's comments and issues from other users, -administrators can choose to ban the user. +To completely block a user, administrators can choose to ban the user. Users can be banned using the Admin Area. To do this: @@ -139,14 +138,6 @@ Users can be banned using the Admin Area. To do this: 1. Select a user. 1. Under the **Account** tab, click **Ban user**. -Banning a user is functionally identical to [blocking a user](#blocking-and-unblocking-users), -with the following differences: - -- Comments made by the banned user will be hidden from other users. -- Issues created by the banned user will be hidden from other users. - -Personal projects, and group and user history of the blocked user are left intact. - NOTE: This feature is a work in progress. Currently, banning a user only blocks them and does not hide their comments or issues. -- GitLab