mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[MM-55999] Bring the revoke sessions button to the admin header and improve the styling of the header (#25590)
This commit is contained in:
parent
a09c040a12
commit
5a4dba8809
@ -16,39 +16,47 @@ import {getAdminAccount} from '../../../support/env';
|
||||
describe('System Console > User Management > Users', () => {
|
||||
const admin = getAdminAccount();
|
||||
|
||||
it('MM-T940 Users - Revoke all sessions', () => {
|
||||
it('MM-T940 Users - Revoke all sessions from a button in admin console', () => {
|
||||
// # Login as System Admin
|
||||
cy.apiAdminLogin();
|
||||
|
||||
cy.visit('/admin_console/user_management/users');
|
||||
|
||||
// * Verify the presence of Revoke All Sessions button
|
||||
cy.get('#revoke-all-users').should('be.visible').and('not.have.class', 'btn-danger').click();
|
||||
// * Verify the presence of Revoke All Sessions button and click on it
|
||||
cy.findByText('Revoke All Sessions').should('be.visible').click();
|
||||
|
||||
// * Verify the confirmation message when users clicks on the Revoke All Sessions button
|
||||
cy.get('#confirmModalLabel').should('be.visible').and('have.text', 'Revoke all sessions in the system');
|
||||
cy.get('.modal-body').should('be.visible').and('have.text', 'This action revokes all sessions in the system. All users will be logged out from all devices. Are you sure you want to revoke all sessions?');
|
||||
cy.get('#confirmModalButton').should('be.visible').and('have.class', 'btn-danger');
|
||||
cy.get('#confirmModal').should('be.visible').within(() => {
|
||||
// * Verify the presence of confirmation messages and buttons
|
||||
cy.findByText('Revoke all sessions in the system').should('be.visible');
|
||||
cy.findByText('This action revokes all sessions in the system. All users will be logged out from all devices, including your session. Are you sure you want to revoke all sessions?').should('be.visible');
|
||||
cy.findByText('Cancel').should('be.visible');
|
||||
cy.findByText('Revoke All Sessions').should('be.visible');
|
||||
|
||||
// # Click on Cancel button in the confirmation message
|
||||
cy.get('#cancelModalButton').click();
|
||||
// # Click on Cancel button in the confirmation message
|
||||
cy.findByText('Cancel').click();
|
||||
});
|
||||
|
||||
// * Verify if Confirmation message is closed
|
||||
cy.get('#confirmModal').should('not.exist');
|
||||
|
||||
// * Verify if the Admin's session is still active and user is still in the same page
|
||||
// * Since we have cancelled the confirmation message, verify if the Admin's session is still active and user is still in the same page
|
||||
cy.url().should('contain', '/admin_console/user_management/users');
|
||||
|
||||
// * Verify if the Admin's Session is still active and click on it and then confirm
|
||||
cy.get('#revoke-all-users').should('be.visible').click();
|
||||
cy.get('#confirmModalButton').click();
|
||||
// # Open revoke all sessions modal again
|
||||
cy.findByText('Revoke All Sessions').should('be.visible').click();
|
||||
|
||||
cy.get('#confirmModal').should('be.visible').within(() => {
|
||||
// # Click on Revoke All Sessions button in the confirmation message
|
||||
cy.findByText('Revoke All Sessions').click();
|
||||
});
|
||||
|
||||
// * Verify if Admin User's session is expired and is redirected to login page
|
||||
cy.url({timeout: TIMEOUTS.HALF_MIN}).should('include', '/login');
|
||||
cy.get('.login-body-card', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible');
|
||||
cy.findByText('Log in to your account').should('be.visible');
|
||||
});
|
||||
|
||||
it('Verify for Regular Member', () => {
|
||||
it('MM-T940-1 Users - Revoke all sessions with an API call', () => {
|
||||
// # Login as System Admin
|
||||
cy.apiAdminLogin();
|
||||
|
||||
@ -65,7 +73,7 @@ describe('System Console > User Management > Users', () => {
|
||||
|
||||
// * Verify if the regular member is logged out and redirected to login page
|
||||
cy.url({timeout: TIMEOUTS.HALF_MIN}).should('include', '/login');
|
||||
cy.get('.login-body-card', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible');
|
||||
cy.findByText('Log in to your account').should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -540,7 +540,6 @@ const AdminDefinition: AdminDefinitionType = {
|
||||
searchableStrings: [
|
||||
['admin.system_users.title', {siteName: ''}],
|
||||
],
|
||||
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.USER_MANAGEMENT.USERS)),
|
||||
isHidden: it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.USER_MANAGEMENT.USERS)),
|
||||
schema: {
|
||||
id: 'SystemUsers',
|
||||
@ -549,7 +548,6 @@ const AdminDefinition: AdminDefinitionType = {
|
||||
},
|
||||
system_user_detail: {
|
||||
url: 'user_management/user/:user_id',
|
||||
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.USER_MANAGEMENT.USERS)),
|
||||
isHidden: it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.USER_MANAGEMENT.USERS)),
|
||||
schema: {
|
||||
id: 'SystemUserDetail',
|
||||
|
@ -14,6 +14,7 @@ exports[`components/admin_console/system_users should match default snapshot 1`]
|
||||
}
|
||||
}
|
||||
/>
|
||||
<RevokeSessionsButton />
|
||||
</AdminHeader>
|
||||
<div
|
||||
className="admin-console__wrapper"
|
||||
@ -41,56 +42,6 @@ exports[`components/admin_console/system_users should match default snapshot 1`]
|
||||
usersPerPage={50}
|
||||
/>
|
||||
</div>
|
||||
<Connect(SystemPermissionGate)
|
||||
permissions={
|
||||
Array [
|
||||
"revoke_user_access_token",
|
||||
]
|
||||
}
|
||||
>
|
||||
<ConfirmModal
|
||||
confirmButtonClass="btn btn-danger"
|
||||
confirmButtonText={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Revoke All Sessions"
|
||||
id="admin.system_users.revoke_all_sessions_button"
|
||||
/>
|
||||
}
|
||||
message={
|
||||
<div>
|
||||
<FormattedMarkdownMessage
|
||||
defaultMessage="This action revokes all sessions in the system. All users will be logged out from all devices. Are you sure you want to revoke all sessions?"
|
||||
id="admin.system_users.revoke_all_sessions_modal_message"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
modalClass=""
|
||||
onCancel={[Function]}
|
||||
onConfirm={[Function]}
|
||||
show={false}
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Revoke all sessions in the system"
|
||||
id="admin.system_users.revoke_all_sessions_modal_title"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="pt-3 pb-3"
|
||||
>
|
||||
<button
|
||||
className="btn btn-tertiary"
|
||||
id="revoke-all-users"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage="Revoke All Sessions"
|
||||
id="admin.system_users.revokeAllSessions"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</Connect(SystemPermissionGate)>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -16,7 +16,6 @@ import {
|
||||
getUserAccessToken,
|
||||
getProfiles,
|
||||
searchProfiles,
|
||||
revokeSessionsForAllUsers,
|
||||
getFilteredUsersStats,
|
||||
} from 'mattermost-redux/actions/users';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
@ -106,7 +105,6 @@ function mapDispatchToProps(dispatch: Dispatch<GenericAction>) {
|
||||
loadProfilesWithoutTeam,
|
||||
getProfiles,
|
||||
searchProfiles,
|
||||
revokeSessionsForAllUsers,
|
||||
logError,
|
||||
getFilteredUsersStats,
|
||||
}, dispatch),
|
||||
|
@ -12,7 +12,6 @@ exports[`components/admin_console/system_users/list should match default snapsho
|
||||
"doPasswordReset": [Function],
|
||||
"enableUserAccessTokens": false,
|
||||
"experimentalEnableAuthenticationTransfer": false,
|
||||
"isDisabled": false,
|
||||
"mfaEnabled": false,
|
||||
}
|
||||
}
|
||||
@ -96,7 +95,6 @@ exports[`components/admin_console/system_users/list should match default snapsho
|
||||
"doPasswordReset": [Function],
|
||||
"enableUserAccessTokens": false,
|
||||
"experimentalEnableAuthenticationTransfer": false,
|
||||
"isDisabled": false,
|
||||
"mfaEnabled": false,
|
||||
}
|
||||
}
|
||||
@ -299,7 +297,6 @@ exports[`components/admin_console/system_users/list should match default snapsho
|
||||
"doPasswordReset": [Function],
|
||||
"enableUserAccessTokens": false,
|
||||
"experimentalEnableAuthenticationTransfer": false,
|
||||
"isDisabled": false,
|
||||
"mfaEnabled": true,
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ type Props = {
|
||||
filter: string;
|
||||
term: string;
|
||||
onTermChange: (term: string) => void;
|
||||
isDisabled?: boolean;
|
||||
|
||||
/**
|
||||
* Whether MFA is licensed and enabled.
|
||||
@ -345,7 +344,6 @@ export default class SystemUsersList extends React.PureComponent<Props, State> {
|
||||
doManageTeams: this.doManageTeams,
|
||||
doManageRoles: this.doManageRoles,
|
||||
doManageTokens: this.doManageTokens,
|
||||
isDisabled: this.props.isDisabled,
|
||||
}}
|
||||
nextPage={this.nextPage}
|
||||
previousPage={this.previousPage}
|
||||
|
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useState} from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import {useDispatch} from 'react-redux';
|
||||
|
||||
import type {ServerError} from '@mattermost/types/errors';
|
||||
|
||||
import {revokeSessionsForAllUsers} from 'mattermost-redux/actions/users';
|
||||
import {Permissions} from 'mattermost-redux/constants';
|
||||
import type {ActionResult} from 'mattermost-redux/types/actions';
|
||||
|
||||
import {emitUserLoggedOutEvent} from 'actions/global_actions';
|
||||
|
||||
import ConfirmModal from 'components/confirm_modal';
|
||||
import SystemPermissionGate from 'components/permissions_gates/system_permission_gate';
|
||||
|
||||
function RevokeSessionsButton() {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
|
||||
function handleModalToggle() {
|
||||
setShowModal((showModal) => !showModal);
|
||||
}
|
||||
|
||||
async function handleModalConfirm() {
|
||||
const {data} = await dispatch(revokeSessionsForAllUsers()) as ActionResult<boolean, ServerError>;
|
||||
|
||||
if (data) {
|
||||
emitUserLoggedOutEvent();
|
||||
} else {
|
||||
setShowModal(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<SystemPermissionGate permissions={[Permissions.REVOKE_USER_ACCESS_TOKEN]}>
|
||||
<button
|
||||
className='btn btn-tertiary btn-danger'
|
||||
onClick={handleModalToggle}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.system_users.revokeAllSessions'
|
||||
defaultMessage='Revoke All Sessions'
|
||||
/>
|
||||
</button>
|
||||
<ConfirmModal
|
||||
show={showModal}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='admin.system_users.revoke_all_sessions_modal_title'
|
||||
defaultMessage='Revoke all sessions in the system'
|
||||
/>
|
||||
}
|
||||
message={
|
||||
<FormattedMessage
|
||||
id='admin.system_users.revoke_all_sessions_modal_message'
|
||||
defaultMessage='This action revokes all sessions in the system. All users will be logged out from all devices, including your session. Are you sure you want to revoke all sessions?'
|
||||
/>
|
||||
}
|
||||
confirmButtonClass='btn btn-danger'
|
||||
confirmButtonText={
|
||||
<FormattedMessage
|
||||
id='admin.system_users.revoke_all_sessions_button'
|
||||
defaultMessage='Revoke All Sessions'
|
||||
/>
|
||||
}
|
||||
onConfirm={handleModalConfirm}
|
||||
onCancel={handleModalToggle}
|
||||
/>
|
||||
</SystemPermissionGate>
|
||||
);
|
||||
}
|
||||
|
||||
export default RevokeSessionsButton;
|
@ -36,7 +36,6 @@ describe('components/admin_console/system_users', () => {
|
||||
loadProfilesWithoutTeam: jest.fn().mockResolvedValue({data: true}),
|
||||
getProfiles: jest.fn().mockResolvedValue({data: []}),
|
||||
searchProfiles: jest.fn().mockResolvedValue({data: []}),
|
||||
revokeSessionsForAllUsers: jest.fn().mockResolvedValue({data: true}),
|
||||
logError: jest.fn(),
|
||||
getFilteredUsersStats: jest.fn(),
|
||||
},
|
||||
|
@ -1,8 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import type {ChangeEvent} from 'react';
|
||||
import React, {type ChangeEvent} from 'react';
|
||||
import {FormattedMessage, type IntlShape, injectIntl} from 'react-intl';
|
||||
|
||||
import type {ServerError} from '@mattermost/types/errors';
|
||||
@ -10,21 +9,15 @@ import type {Team} from '@mattermost/types/teams';
|
||||
import type {GetFilteredUsersStatsOpts, UserProfile, UsersStats} from '@mattermost/types/users';
|
||||
|
||||
import {debounce} from 'mattermost-redux/actions/helpers';
|
||||
import {Permissions} from 'mattermost-redux/constants';
|
||||
import type {ActionFunc} from 'mattermost-redux/types/actions';
|
||||
|
||||
import {emitUserLoggedOutEvent} from 'actions/global_actions';
|
||||
|
||||
import ConfirmModal from 'components/confirm_modal';
|
||||
import FormattedMarkdownMessage from 'components/formatted_markdown_message';
|
||||
import SystemPermissionGate from 'components/permissions_gates/system_permission_gate';
|
||||
import AdminHeader from 'components/widgets/admin_console/admin_header';
|
||||
|
||||
import {Constants, UserSearchOptions, SearchUserTeamFilter, UserFilters} from 'utils/constants';
|
||||
import {getUserOptionsFromFilter, searchUserOptionsFromFilter} from 'utils/filter_users';
|
||||
import * as Utils from 'utils/utils';
|
||||
|
||||
import SystemUsersList from './list';
|
||||
import RevokeSessionsButton from './revoke_sessions_button';
|
||||
|
||||
const USER_ID_LENGTH = 26;
|
||||
const USERS_PER_PAGE = 50;
|
||||
@ -62,7 +55,6 @@ type Props = {
|
||||
teamId: string;
|
||||
filter: string;
|
||||
users: Record<string, UserProfile>;
|
||||
isDisabled?: boolean;
|
||||
|
||||
actions: {
|
||||
|
||||
@ -91,11 +83,6 @@ type Props = {
|
||||
setSystemUsersSearch: (searchTerm: string, teamId: string, filter: string) => void;
|
||||
searchProfiles: (term: string, options?: any) => Promise<any> | ActionFunc;
|
||||
|
||||
/**
|
||||
* Function to revoke all sessions in the system
|
||||
*/
|
||||
revokeSessionsForAllUsers: () => any;
|
||||
|
||||
/**
|
||||
* Function to log errors
|
||||
*/
|
||||
@ -110,7 +97,6 @@ type Props = {
|
||||
type State = {
|
||||
loading: boolean;
|
||||
searching: boolean;
|
||||
showRevokeAllSessionsModal: boolean;
|
||||
term?: string;
|
||||
};
|
||||
|
||||
@ -121,7 +107,6 @@ export class SystemUsers extends React.PureComponent<Props, State> {
|
||||
this.state = {
|
||||
loading: true,
|
||||
searching: false,
|
||||
showRevokeAllSessionsModal: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -182,20 +167,6 @@ export class SystemUsers extends React.PureComponent<Props, State> {
|
||||
handleTermChange = (term: string) => {
|
||||
this.props.actions.setSystemUsersSearch(term, this.props.teamId, this.props.filter);
|
||||
};
|
||||
handleRevokeAllSessions = async () => {
|
||||
const {data} = await this.props.actions.revokeSessionsForAllUsers();
|
||||
if (data) {
|
||||
emitUserLoggedOutEvent();
|
||||
} else {
|
||||
this.props.actions.logError({type: 'critical', message: 'Can\'t revoke all sessions'});
|
||||
}
|
||||
};
|
||||
handleRevokeAllSessionsCancel = () => {
|
||||
this.setState({showRevokeAllSessionsModal: false});
|
||||
};
|
||||
handleShowRevokeAllSessionsModal = () => {
|
||||
this.setState({showRevokeAllSessionsModal: true});
|
||||
};
|
||||
|
||||
nextPage = async (page: number) => {
|
||||
const {teamId, filter} = this.props;
|
||||
@ -267,44 +238,6 @@ export class SystemUsers extends React.PureComponent<Props, State> {
|
||||
this.getUserById(id);
|
||||
};
|
||||
|
||||
renderRevokeAllUsersModal = () => {
|
||||
const title = (
|
||||
<FormattedMessage
|
||||
id='admin.system_users.revoke_all_sessions_modal_title'
|
||||
defaultMessage='Revoke all sessions in the system'
|
||||
/>
|
||||
);
|
||||
|
||||
const message = (
|
||||
<div>
|
||||
<FormattedMarkdownMessage
|
||||
id='admin.system_users.revoke_all_sessions_modal_message'
|
||||
defaultMessage='This action revokes all sessions in the system. All users will be logged out from all devices. Are you sure you want to revoke all sessions?'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const confirmButtonClass = 'btn btn-danger';
|
||||
const revokeAllButton = (
|
||||
<FormattedMessage
|
||||
id='admin.system_users.revoke_all_sessions_button'
|
||||
defaultMessage='Revoke All Sessions'
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<ConfirmModal
|
||||
show={this.state.showRevokeAllSessionsModal}
|
||||
title={title}
|
||||
message={message}
|
||||
confirmButtonClass={confirmButtonClass}
|
||||
confirmButtonText={revokeAllButton}
|
||||
onConfirm={this.handleRevokeAllSessions}
|
||||
onCancel={this.handleRevokeAllSessionsCancel}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
renderFilterRow = (doSearch: ((event: React.FormEvent<HTMLInputElement>) => void) | undefined) => {
|
||||
const teams = this.props.teams.map((team) => (
|
||||
<option
|
||||
@ -337,8 +270,8 @@ export class SystemUsers extends React.PureComponent<Props, State> {
|
||||
onChange={this.handleTeamChange}
|
||||
value={this.props.teamId}
|
||||
>
|
||||
<option value={SearchUserTeamFilter.ALL_USERS}>{Utils.localizeMessage('admin.system_users.allUsers', 'All Users')}</option>
|
||||
<option value={SearchUserTeamFilter.NO_TEAM}>{Utils.localizeMessage('admin.system_users.noTeams', 'No Teams')}</option>
|
||||
<option value={SearchUserTeamFilter.ALL_USERS}>{this.props.intl.formatMessage({id: 'admin.system_users.allUsers', defaultMessage: 'All Users'})}</option>
|
||||
<option value={SearchUserTeamFilter.NO_TEAM}>{this.props.intl.formatMessage({id: 'admin.system_users.noTeams', defaultMessage: 'No Teams'})}</option>
|
||||
{teams}
|
||||
</select>
|
||||
</label>
|
||||
@ -355,11 +288,11 @@ export class SystemUsers extends React.PureComponent<Props, State> {
|
||||
value={this.props.filter}
|
||||
onChange={this.handleFilterChange}
|
||||
>
|
||||
<option value=''>{Utils.localizeMessage('admin.system_users.allUsers', 'All Users')}</option>
|
||||
<option value={UserFilters.SYSTEM_ADMIN}>{Utils.localizeMessage('admin.system_users.system_admin', 'System Admin')}</option>
|
||||
<option value={UserFilters.SYSTEM_GUEST}>{Utils.localizeMessage('admin.system_users.guest', 'Guest')}</option>
|
||||
<option value={UserFilters.ACTIVE}>{Utils.localizeMessage('admin.system_users.active', 'Active')}</option>
|
||||
<option value={UserFilters.INACTIVE}>{Utils.localizeMessage('admin.system_users.inactive', 'Inactive')}</option>
|
||||
<option value=''>{this.props.intl.formatMessage({id: 'admin.system_users.allUsers', defaultMessage: 'All Users'})}</option>
|
||||
<option value={UserFilters.SYSTEM_ADMIN}>{this.props.intl.formatMessage({id: 'admin.system_users.system_admin', defaultMessage: 'System Admin'})}</option>
|
||||
<option value={UserFilters.SYSTEM_GUEST}>{this.props.intl.formatMessage({id: 'admin.system_users.guest', defaultMessage: 'Guest'})}</option>
|
||||
<option value={UserFilters.ACTIVE}>{this.props.intl.formatMessage({id: 'admin.system_users.active', defaultMessage: 'Active'})}</option>
|
||||
<option value={UserFilters.INACTIVE}>{this.props.intl.formatMessage({id: 'admin.system_users.inactive', defaultMessage: 'Inactive'})}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
@ -367,8 +300,6 @@ export class SystemUsers extends React.PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const revokeAllUsersModal = this.renderRevokeAllUsersModal();
|
||||
|
||||
return (
|
||||
<div className='wrapper--fixed'>
|
||||
<AdminHeader>
|
||||
@ -379,6 +310,7 @@ export class SystemUsers extends React.PureComponent<Props, State> {
|
||||
siteName: this.props.siteName,
|
||||
}}
|
||||
/>
|
||||
<RevokeSessionsButton/>
|
||||
</AdminHeader>
|
||||
<div className='admin-console__wrapper'>
|
||||
<div className='admin-console__content'>
|
||||
@ -398,26 +330,8 @@ export class SystemUsers extends React.PureComponent<Props, State> {
|
||||
mfaEnabled={this.props.mfaEnabled}
|
||||
enableUserAccessTokens={this.props.enableUserAccessTokens}
|
||||
experimentalEnableAuthenticationTransfer={this.props.experimentalEnableAuthenticationTransfer}
|
||||
isDisabled={this.props.isDisabled}
|
||||
/>
|
||||
</div>
|
||||
<SystemPermissionGate permissions={[Permissions.REVOKE_USER_ACCESS_TOKEN]}>
|
||||
{revokeAllUsersModal}
|
||||
<div className='pt-3 pb-3'>
|
||||
<button
|
||||
id='revoke-all-users'
|
||||
type='button'
|
||||
className='btn btn-tertiary'
|
||||
onClick={() => this.handleShowRevokeAllSessionsModal()}
|
||||
disabled={this.props.isDisabled}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.system_users.revokeAllSessions'
|
||||
defaultMessage='Revoke All Sessions'
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</SystemPermissionGate>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -39,7 +39,6 @@ describe('components/admin_console/system_users/system_users_dropdown/system_use
|
||||
currentUser: otherUser,
|
||||
index: 0,
|
||||
totalUsers: 10,
|
||||
isDisabled: false,
|
||||
actions: {
|
||||
updateUserActive: jest.fn().mockResolvedValue({data: true}),
|
||||
revokeAllSessionsForUser: jest.fn().mockResolvedValue({data: true}),
|
||||
|
@ -42,7 +42,6 @@ export type Props = {
|
||||
config: DeepPartial<AdminConfig>;
|
||||
bots: Record<string, Bot>;
|
||||
isLicensed: boolean;
|
||||
isDisabled: boolean;
|
||||
actions: {
|
||||
updateUserActive: (id: string, active: boolean) => Promise<{error: ServerError}>;
|
||||
revokeAllSessionsForUser: (id: string) => Promise<{error: ServerError; data: any}>;
|
||||
@ -575,13 +574,8 @@ export default class SystemUsersDropdown extends React.PureComponent<Props, Stat
|
||||
render() {
|
||||
const {currentUser, user, isLicensed, config} = this.props;
|
||||
|
||||
let isDisabled = this.props.isDisabled;
|
||||
if (!isDisabled) {
|
||||
// if not already disabled,
|
||||
// disable if SystemAdmin being edited by non SystemAdmin
|
||||
// ie, userManager with EditOtherUsers permissions
|
||||
isDisabled = UserUtils.isSystemAdmin(user.roles) && !UserUtils.isSystemAdmin(currentUser.roles);
|
||||
}
|
||||
// Disable if SystemAdmin being edited by non SystemAdmin eg. userManager with EditOtherUsers permissions
|
||||
const isDisabled = UserUtils.isSystemAdmin(user.roles) && !UserUtils.isSystemAdmin(currentUser.roles);
|
||||
|
||||
const isGuest = UserUtils.isGuest(user.roles);
|
||||
if (!user) {
|
||||
|
@ -33,7 +33,7 @@ type Props = {
|
||||
doManageTeams: (user: UserProfile) => void;
|
||||
doManageRoles: (user: UserProfile) => void;
|
||||
doManageTokens: (user: UserProfile) => void;
|
||||
isDisabled: boolean | undefined;
|
||||
isDisabled?: boolean;
|
||||
};
|
||||
actionUserProps?: {
|
||||
[userId: string]: {
|
||||
|
@ -2423,7 +2423,7 @@
|
||||
"admin.system_users.inactive": "Inactive",
|
||||
"admin.system_users.noTeams": "No Teams",
|
||||
"admin.system_users.revoke_all_sessions_button": "Revoke All Sessions",
|
||||
"admin.system_users.revoke_all_sessions_modal_message": "This action revokes all sessions in the system. All users will be logged out from all devices. Are you sure you want to revoke all sessions?",
|
||||
"admin.system_users.revoke_all_sessions_modal_message": "This action revokes all sessions in the system. All users will be logged out from all devices, including your session. Are you sure you want to revoke all sessions?",
|
||||
"admin.system_users.revoke_all_sessions_modal_title": "Revoke all sessions in the system",
|
||||
"admin.system_users.revokeAllSessions": "Revoke All Sessions",
|
||||
"admin.system_users.system_admin": "System Admin",
|
||||
|
@ -711,19 +711,21 @@ export function revokeAllSessionsForUser(userId: string): ActionFunc {
|
||||
};
|
||||
}
|
||||
|
||||
export function revokeSessionsForAllUsers(): ActionFunc {
|
||||
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
|
||||
export function revokeSessionsForAllUsers(): ActionFunc<boolean, ServerError> {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
await Client4.revokeSessionsForAllUsers();
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch, getState);
|
||||
dispatch(logError(error));
|
||||
return {error};
|
||||
return {error: error as ServerError};
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: UserTypes.REVOKE_SESSIONS_FOR_ALL_USERS_SUCCESS,
|
||||
data: null,
|
||||
});
|
||||
|
||||
return {data: true};
|
||||
};
|
||||
}
|
||||
|
@ -270,6 +270,22 @@ button {
|
||||
color: rgba(var(--center-channel-color-rgb), 0.32);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.btn-danger {
|
||||
background-color: rgba(var(--error-text-color-rgb), 0.08);
|
||||
color: var(--error-text);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(var(--error-text-color-rgb), 0.12);
|
||||
color: var(--error-text);
|
||||
}
|
||||
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: rgba(var(--error-text-color-rgb), 0.16);
|
||||
color: var(--error-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-quaternary {
|
||||
|
@ -406,16 +406,16 @@
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
height: 65px;
|
||||
-webkit-flex: 0 0 65px;
|
||||
flex: 0 0 65px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 20px;
|
||||
padding: 12px 20px;
|
||||
border-bottom: 1px solid alpha-color($black, 0.1);
|
||||
background: white;
|
||||
font-size: 22px;
|
||||
font-weight: normal;
|
||||
line-height: 32px;
|
||||
|
||||
&.with-back {
|
||||
padding: 0;
|
||||
|
Loading…
Reference in New Issue
Block a user