Commit 9d154fd7 authored by Dmytro Zaporozhets (DZ)'s avatar Dmytro Zaporozhets (DZ)

Merge branch 'peterhegman/add-ban-action-to-user-admin-dropdown' into 'master'

Add Ban/Unban actions to user administration dropdown in the admin area

See merge request gitlab-org/gitlab!64742
parents 4d2b560a 325583db
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { sprintf, s__ } from '~/locale';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
const messageHtml = `
<p>${s__('AdminUsers|When banned, users:')}</p>
<ul>
<li>${s__("AdminUsers|Can't log in.")}</li>
<li>${s__("AdminUsers|Can't access Git repositories.")}</li>
</ul>
<p>${s__('AdminUsers|You can unban their account in the future. Their data remains intact.')}</p>
<p>${sprintf(
s__('AdminUsers|Learn more about %{link_start}banned users.%{link_end}'),
{
link_start: `<a href="${helpPagePath('user/admin_area/moderate_users', {
anchor: 'ban-a-user',
})}" target="_blank">`,
link_end: '</a>',
},
false,
)}</p>
`;
export default {
components: {
GlDropdownItem,
},
props: {
username: {
type: String,
required: true,
},
path: {
type: String,
required: true,
},
},
computed: {
modalAttributes() {
return {
'data-path': this.path,
'data-method': 'put',
'data-modal-attributes': JSON.stringify({
title: sprintf(s__('AdminUsers|Ban user %{username}?'), {
username: this.username,
}),
okVariant: 'warning',
okTitle: s__('AdminUsers|Ban user'),
messageHtml,
}),
};
},
},
};
</script>
<template>
<div class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
<gl-dropdown-item>
<slot></slot>
</gl-dropdown-item>
</div>
</template>
import Activate from './activate.vue'; import Activate from './activate.vue';
import Approve from './approve.vue'; import Approve from './approve.vue';
import Ban from './ban.vue';
import Block from './block.vue'; import Block from './block.vue';
import Deactivate from './deactivate.vue'; import Deactivate from './deactivate.vue';
import Delete from './delete.vue'; import Delete from './delete.vue';
import DeleteWithContributions from './delete_with_contributions.vue'; import DeleteWithContributions from './delete_with_contributions.vue';
import Reject from './reject.vue'; import Reject from './reject.vue';
import Unban from './unban.vue';
import Unblock from './unblock.vue'; import Unblock from './unblock.vue';
import Unlock from './unlock.vue'; import Unlock from './unlock.vue';
export default { export default {
Activate, Activate,
Approve, Approve,
Ban,
Block, Block,
Deactivate, Deactivate,
Delete, Delete,
DeleteWithContributions, DeleteWithContributions,
Unban,
Unblock, Unblock,
Unlock, Unlock,
Reject, Reject,
......
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
const messageHtml = `<p>${s__(
'AdminUsers|You can ban their account in the future if necessary.',
)}</p>`;
export default {
components: {
GlDropdownItem,
},
props: {
username: {
type: String,
required: true,
},
path: {
type: String,
required: true,
},
},
computed: {
modalAttributes() {
return {
'data-path': this.path,
'data-method': 'put',
'data-modal-attributes': JSON.stringify({
title: sprintf(s__('AdminUsers|Unban user %{username}?'), {
username: this.username,
}),
okVariant: 'info',
okTitle: s__('AdminUsers|Unban user'),
messageHtml,
}),
};
},
},
};
</script>
<template>
<div class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
<gl-dropdown-item>
<slot></slot>
</gl-dropdown-item>
</div>
</template>
...@@ -17,4 +17,6 @@ export const I18N_USER_ACTIONS = { ...@@ -17,4 +17,6 @@ export const I18N_USER_ACTIONS = {
ldapBlocked: s__('AdminUsers|Cannot unblock LDAP blocked users'), ldapBlocked: s__('AdminUsers|Cannot unblock LDAP blocked users'),
delete: s__('AdminUsers|Delete user'), delete: s__('AdminUsers|Delete user'),
deleteWithContributions: s__('AdminUsers|Delete user and contributions'), deleteWithContributions: s__('AdminUsers|Delete user and contributions'),
ban: s__('AdminUsers|Ban user'),
unban: s__('AdminUsers|Unban user'),
}; };
...@@ -15,6 +15,7 @@ module Admin ...@@ -15,6 +15,7 @@ module Admin
deactivate_actions deactivate_actions
unlock_actions unlock_actions
delete_actions delete_actions
ban_actions
@actions @actions
end end
...@@ -28,7 +29,7 @@ module Admin ...@@ -28,7 +29,7 @@ module Admin
@actions << 'approve' @actions << 'approve'
@actions << 'reject' @actions << 'reject'
elsif @user.blocked? elsif @user.blocked?
@actions << 'unblock' @actions << 'unblock' unless @user.banned?
else else
@actions << 'block' @actions << 'block'
end end
...@@ -52,5 +53,19 @@ module Admin ...@@ -52,5 +53,19 @@ module Admin
@actions << 'delete' @actions << 'delete'
@actions << 'delete_with_contributions' @actions << 'delete_with_contributions'
end end
def ban_actions
return unless ban_feature_available?
return if @user.internal?
if @user.banned?
@actions << 'unban'
return
end
unless @user.blocked?
@actions << 'ban'
end
end
end end
end end
...@@ -270,7 +270,9 @@ module UsersHelper ...@@ -270,7 +270,9 @@ module UsersHelper
unlock: unlock_admin_user_path(:id), unlock: unlock_admin_user_path(:id),
delete: admin_user_path(:id), delete: admin_user_path(:id),
delete_with_contributions: admin_user_path(:id), delete_with_contributions: admin_user_path(:id),
admin_user: admin_user_path(:id) admin_user: admin_user_path(:id),
ban: ban_admin_user_path(:id),
unban: unban_admin_user_path(:id)
} }
end end
......
...@@ -2551,6 +2551,12 @@ msgstr "" ...@@ -2551,6 +2551,12 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:" msgid "AdminUsers|Blocking user has the following effects:"
msgstr "" msgstr ""
msgid "AdminUsers|Can't access Git repositories."
msgstr ""
msgid "AdminUsers|Can't log in."
msgstr ""
msgid "AdminUsers|Cannot sign in or access instance information" msgid "AdminUsers|Cannot sign in or access instance information"
msgstr "" msgstr ""
...@@ -2710,6 +2716,9 @@ msgstr "" ...@@ -2710,6 +2716,9 @@ msgstr ""
msgid "AdminUsers|Unban user" msgid "AdminUsers|Unban user"
msgstr "" msgstr ""
msgid "AdminUsers|Unban user %{username}?"
msgstr ""
msgid "AdminUsers|Unblock" msgid "AdminUsers|Unblock"
msgstr "" msgstr ""
...@@ -2755,6 +2764,9 @@ msgstr "" ...@@ -2755,6 +2764,9 @@ msgstr ""
msgid "AdminUsers|What does this mean?" msgid "AdminUsers|What does this mean?"
msgstr "" msgstr ""
msgid "AdminUsers|When banned, users:"
msgstr ""
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account" msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr "" msgstr ""
...@@ -2785,6 +2797,9 @@ msgstr "" ...@@ -2785,6 +2797,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact." msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr "" msgstr ""
msgid "AdminUsers|You can ban their account in the future if necessary."
msgstr ""
msgid "AdminUsers|You can unban their account in the future. Their data remains intact." msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
msgstr "" msgstr ""
......
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
"unlock": { "type": "string" }, "unlock": { "type": "string" },
"delete": { "type": "string" }, "delete": { "type": "string" },
"delete_with_contributions": { "type": "string" }, "delete_with_contributions": { "type": "string" },
"admin_user": { "type": "string" } "admin_user": { "type": "string" },
"ban": { "type": "string" },
"unban": { "type": "string" }
}, },
"required": [ "required": [
"edit", "edit",
...@@ -24,7 +26,9 @@ ...@@ -24,7 +26,9 @@
"unlock", "unlock",
"delete", "delete",
"delete_with_contributions", "delete_with_contributions",
"admin_user" "admin_user",
"ban",
"unban"
], ],
"additionalProperties": false "additionalProperties": false
} }
...@@ -7,6 +7,8 @@ const ACTIVATE = 'activate'; ...@@ -7,6 +7,8 @@ const ACTIVATE = 'activate';
const DEACTIVATE = 'deactivate'; const DEACTIVATE = 'deactivate';
const REJECT = 'reject'; const REJECT = 'reject';
const APPROVE = 'approve'; const APPROVE = 'approve';
const BAN = 'ban';
const UNBAN = 'unban';
export const EDIT = 'edit'; export const EDIT = 'edit';
...@@ -14,6 +16,6 @@ export const LDAP = 'ldapBlocked'; ...@@ -14,6 +16,6 @@ export const LDAP = 'ldapBlocked';
export const LINK_ACTIONS = [APPROVE, REJECT]; export const LINK_ACTIONS = [APPROVE, REJECT];
export const CONFIRMATION_ACTIONS = [ACTIVATE, BLOCK, DEACTIVATE, UNLOCK, UNBLOCK]; export const CONFIRMATION_ACTIONS = [ACTIVATE, BLOCK, DEACTIVATE, UNLOCK, UNBLOCK, BAN, UNBAN];
export const DELETE_ACTIONS = [DELETE, DELETE_WITH_CONTRIBUTIONS]; export const DELETE_ACTIONS = [DELETE, DELETE_WITH_CONTRIBUTIONS];
...@@ -30,6 +30,8 @@ export const paths = { ...@@ -30,6 +30,8 @@ export const paths = {
delete: '/admin/users/id', delete: '/admin/users/id',
deleteWithContributions: '/admin/users/id', deleteWithContributions: '/admin/users/id',
adminUser: '/admin/users/id', adminUser: '/admin/users/id',
ban: '/admin/users/id/ban',
unban: '/admin/users/id/unban',
}; };
export const createGroupCountResponse = (groupCounts) => ({ export const createGroupCountResponse = (groupCounts) => ({
......
...@@ -29,13 +29,13 @@ RSpec.describe Admin::UserActionsHelper do ...@@ -29,13 +29,13 @@ RSpec.describe Admin::UserActionsHelper do
context 'the user is a standard user' do context 'the user is a standard user' do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
it { is_expected.to contain_exactly("edit", "block", "deactivate", "delete", "delete_with_contributions") } it { is_expected.to contain_exactly("edit", "block", "ban", "deactivate", "delete", "delete_with_contributions") }
end end
context 'the user is an admin user' do context 'the user is an admin user' do
let_it_be(:user) { create(:user, :admin) } let_it_be(:user) { create(:user, :admin) }
it { is_expected.to contain_exactly("edit", "block", "deactivate", "delete", "delete_with_contributions") } it { is_expected.to contain_exactly("edit", "block", "ban", "deactivate", "delete", "delete_with_contributions") }
end end
context 'the user is blocked by LDAP' do context 'the user is blocked by LDAP' do
...@@ -59,7 +59,7 @@ RSpec.describe Admin::UserActionsHelper do ...@@ -59,7 +59,7 @@ RSpec.describe Admin::UserActionsHelper do
context 'the user is deactivated' do context 'the user is deactivated' do
let_it_be(:user) { create(:user, :deactivated) } let_it_be(:user) { create(:user, :deactivated) }
it { is_expected.to contain_exactly("edit", "block", "activate", "delete", "delete_with_contributions") } it { is_expected.to contain_exactly("edit", "block", "ban", "activate", "delete", "delete_with_contributions") }
end end
context 'the user is locked' do context 'the user is locked' do
...@@ -73,6 +73,7 @@ RSpec.describe Admin::UserActionsHelper do ...@@ -73,6 +73,7 @@ RSpec.describe Admin::UserActionsHelper do
is_expected.to contain_exactly( is_expected.to contain_exactly(
"edit", "edit",
"block", "block",
"ban",
"deactivate", "deactivate",
"unlock", "unlock",
"delete", "delete",
...@@ -81,6 +82,12 @@ RSpec.describe Admin::UserActionsHelper do ...@@ -81,6 +82,12 @@ RSpec.describe Admin::UserActionsHelper do
} }
end end
context 'the user is banned' do
let_it_be(:user) { create(:user, :banned) }
it { is_expected.to contain_exactly("edit", "unban", "delete", "delete_with_contributions") }
end
context 'the current_user does not have permission to delete the user' do context 'the current_user does not have permission to delete the user' do
let_it_be(:user) { build(:user) } let_it_be(:user) { build(:user) }
...@@ -88,7 +95,7 @@ RSpec.describe Admin::UserActionsHelper do ...@@ -88,7 +95,7 @@ RSpec.describe Admin::UserActionsHelper do
allow(helper).to receive(:can?).with(current_user, :destroy_user, user).and_return(false) allow(helper).to receive(:can?).with(current_user, :destroy_user, user).and_return(false)
end end
it { is_expected.to contain_exactly("edit", "block", "deactivate") } it { is_expected.to contain_exactly("edit", "block", "ban", "deactivate") }
end end
context 'the user is a sole owner of a group' do context 'the user is a sole owner of a group' do
...@@ -99,7 +106,31 @@ RSpec.describe Admin::UserActionsHelper do ...@@ -99,7 +106,31 @@ RSpec.describe Admin::UserActionsHelper do
group.add_owner(user) group.add_owner(user)
end end
it { is_expected.to contain_exactly("edit", "block", "deactivate") } it { is_expected.to contain_exactly("edit", "block", "ban", "deactivate") }
end
context 'the user is a bot' do
let_it_be(:user) { create(:user, :bot) }
it { is_expected.to match_array([]) }
end
context 'when `ban_user_feature_flag` is disabled' do
before do
stub_feature_flags(ban_user_feature_flag: false)
end
context 'the user is a standard user' do
let_it_be(:user) { create(:user) }
it { is_expected.not_to include("ban") }
end
context 'the user is banned' do
let_it_be(:user) { create(:user, :banned) }
it { is_expected.not_to include("unban") }
end
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment