Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/base/src/locale/en-US/dmsUserCenter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ export default {
opPermissions: 'Platform management permissions',
isDisabled: 'Disabled',
disabledTips:
'When the user is disabled, the user will not be able to log in'
'When the user is disabled, the user will not be able to log in',
globalManagementLockedTips:
'Only the built-in admin can grant or revoke the System Administrator permission',
manageTargetForbidden: 'You are not allowed to manage this user'
},
createUser: {
createSuccessTips: 'Add user "{{name}}" successfully'
Expand Down
4 changes: 3 additions & 1 deletion packages/base/src/locale/zh-CN/dmsUserCenter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export default {
userGroups: '所属用户组',
opPermissions: '平台管理权限',
isDisabled: '是否禁用',
disabledTips: '当用户被禁用,该用户将无法登录'
disabledTips: '当用户被禁用,该用户将无法登录',
globalManagementLockedTips: '仅内置管理员可授予或收回「系统管理员」权限',
manageTargetForbidden: '无权管理该用户'
},
createUser: {
createSuccessTips: '添加用户 "{{name}}" 成功'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ exports[`base/Nav/SideMenu/UserMenu/BasicVersionModal render snap when open is t
class="ant-typography css-dev-only-do-not-override-txh9fw"
>
UI:
dev-zjrc-sql-audit-report-summary f4fab7b02
dev-zjrc-user-system-admin f4fab7b02
</article>
</div>
<div
Expand Down Expand Up @@ -345,7 +345,7 @@ exports[`base/Nav/SideMenu/UserMenu/BasicVersionModal render snap when open is t
class="ant-typography css-dev-only-do-not-override-txh9fw"
>
UI:
dev-zjrc-sql-audit-report-summary f4fab7b02
dev-zjrc-user-system-admin f4fab7b02
</article>
</div>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ exports[`base/Nav/SideMenu/UserMenu/VersionModal-ce render snap when open is tru
class="ant-typography css-dev-only-do-not-override-txh9fw"
>
UI:
dev-zjrc-sql-audit-report-summary f4fab7b02
dev-zjrc-user-system-admin f4fab7b02
</article>
</div>
<div
Expand Down Expand Up @@ -1312,7 +1312,7 @@ exports[`base/Nav/SideMenu/UserMenu/VersionModal-ce render snap when open is tru
class="ant-typography css-dev-only-do-not-override-txh9fw"
>
UI:
dev-zjrc-sql-audit-report-summary f4fab7b02
dev-zjrc-user-system-admin f4fab7b02
</article>
</div>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ exports[`base/Nav/SideMenu/UserMenu/VersionModal-ee render snap when open is tru
class="ant-typography css-dev-only-do-not-override-txh9fw"
>
UI:
dev-zjrc-sql-audit-report-summary f4fab7b02
dev-zjrc-user-system-admin f4fab7b02
</article>
</div>
<div
Expand Down Expand Up @@ -352,7 +352,7 @@ exports[`base/Nav/SideMenu/UserMenu/VersionModal-ee render snap when open is tru
class="ant-typography css-dev-only-do-not-override-txh9fw"
>
UI:
dev-zjrc-sql-audit-report-summary f4fab7b02
dev-zjrc-user-system-admin f4fab7b02
</article>
</div>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ModalName } from '../../../../../data/ModalName';
import { selectOptionByIndex } from '@actiontech/shared/lib/testUtil/customQuery';
import EmitterKey from '../../../../../data/EmitterKey';
import { queryBySelector } from '@actiontech/shared/lib/testUtil/customQuery';
import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentUser';

jest.mock('react-redux', () => {
return {
Expand All @@ -23,6 +24,7 @@ describe('base/UserCenter/Modal/AddUser', () => {
let addUserSpy: jest.SpyInstance;
beforeEach(() => {
jest.useFakeTimers();
mockUseCurrentUser({ username: 'admin', uid: '700200' });
addUserSpy = userCenter.addUser();

opPermissionListSpy = userCenter.getOpPermissionsList();
Expand Down
40 changes: 35 additions & 5 deletions packages/base/src/page/UserCenter/Modal/User/AddUser/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { useBoolean } from 'ahooks';
import { Form, message, Space } from 'antd';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { ModalName } from '../../../../../data/ModalName';
import { IReduxState } from '../../../../../store';
import { updateUserManageModalStatus } from '../../../../../store/userCenter';
import { ResponseCode } from '@actiontech/shared/lib/enum';
import { OpPermissionTypeUid, ResponseCode } from '@actiontech/shared/lib/enum';
import EmitterKey from '../../../../../data/EmitterKey';
import UserForm from '../UserForm';
import { IUserFormFields } from '../UserForm/index.type';
import EventEmitter from '../../../../../utils/EventEmitter';
import { BasicDrawer, BasicButton } from '@actiontech/shared';
import User from '@actiontech/shared/lib/api/base/service/User';
import { useCurrentUser } from '@actiontech/shared/lib/global';
import { canEditGlobalManagement } from '../../../utils/systemAdminBoundary';

const AddUser = () => {
const [form] = Form.useForm<IUserFormFields>();
Expand All @@ -27,6 +29,12 @@
(state) => !!state.userCenter.modalStatus[ModalName.DMS_Add_User]
);

const { username, uid } = useCurrentUser();
const allowEditGlobalManagement = useMemo(
() => canEditGlobalManagement({ name: username, uid }),
[username, uid]
);

const [messageApi, contextHolder] = message.useMessage();

const onClose = useCallback(() => {
Expand All @@ -41,6 +49,16 @@

const addUser = useCallback(async () => {
const values = await form.validateFields();
const opPermissionUids = values.opPermissionUids ?? [];

Check warning on line 52 in packages/base/src/page/UserCenter/Modal/User/AddUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
if (
!allowEditGlobalManagement &&
opPermissionUids.includes(OpPermissionTypeUid.global_management)

Check warning on line 55 in packages/base/src/page/UserCenter/Modal/User/AddUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
) {
messageApi.error(
t('dmsUserCenter.user.userForm.globalManagementLockedTips')
);

Check warning on line 59 in packages/base/src/page/UserCenter/Modal/User/AddUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
return;

Check warning on line 60 in packages/base/src/page/UserCenter/Modal/User/AddUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

Check warning on line 61 in packages/base/src/page/UserCenter/Modal/User/AddUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
setTrue();
User.AddUser({
user: {
Expand All @@ -49,7 +67,7 @@
email: values.email ?? '',
phone: values.phone ?? '',
wxid: values.wxid ?? '',
op_permission_uids: values.opPermissionUids ?? []
op_permission_uids: opPermissionUids
}
})
.then((res) => {
Expand All @@ -66,7 +84,15 @@
.finally(() => {
setFalse();
});
}, [onClose, form, setFalse, setTrue, t, messageApi]);
}, [
allowEditGlobalManagement,
onClose,
form,
setFalse,
setTrue,
t,
messageApi
]);

return (
<BasicDrawer
Expand All @@ -86,7 +112,11 @@
}
>
{contextHolder}
<UserForm form={form} visible={visible} />
<UserForm
form={form}
visible={visible}
canEditGlobalManagement={allowEditGlobalManagement}
/>
</BasicDrawer>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { ModalName } from '../../../../../data/ModalName';
import EmitterKey from '../../../../../data/EmitterKey';
import { queryBySelector } from '@actiontech/shared/lib/testUtil/customQuery';
import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentUser';

jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
Expand All @@ -22,6 +23,8 @@ describe('base/UserCenter/Modal/UpdateUser', () => {
const mockUserData = userList[0];
beforeEach(() => {
jest.useFakeTimers();
// UpdateUser 经 useCurrentUser 读当前操作者;需内置 admin 才能编辑系统管理员边界
mockUseCurrentUser({ username: 'admin', uid: '700200' });
updateUserSpy = userCenter.updateUser();
opPermissionListSpy = userCenter.getOpPermissionsList();

Expand Down
42 changes: 39 additions & 3 deletions packages/base/src/page/UserCenter/Modal/User/UpdateUser/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useCallback } from 'react';
import { useEffect, useCallback, useMemo } from 'react';
import { Form, message, Space } from 'antd';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
Expand All @@ -9,7 +9,7 @@
import { IUserFormFields } from '../UserForm/index.type';
import { ModalName } from '../../../../../data/ModalName';
import { updateUserManageModalStatus } from '../../../../../store/userCenter';
import { ResponseCode } from '@actiontech/shared/lib/enum';
import { OpPermissionTypeUid, ResponseCode } from '@actiontech/shared/lib/enum';
import EventEmitter from '../../../../../utils/EventEmitter';
import {
IListUser,
Expand All @@ -19,6 +19,11 @@
import { ListUserStatEnum } from '@actiontech/shared/lib/api/base/service/common.enum';
import { BasicDrawer, BasicButton } from '@actiontech/shared';
import { SystemRole } from '@actiontech/shared/lib/enum';
import { useCurrentUser } from '@actiontech/shared/lib/global';
import {
canEditGlobalManagement,
canManageTarget
} from '../../../utils/systemAdminBoundary';

const UpdateUser = () => {
const [form] = Form.useForm<IUserFormFields>();
Expand All @@ -37,6 +42,16 @@
(state) => state.userCenter.selectUser
);

const { username, uid } = useCurrentUser();
const currentOperator = useMemo(
() => ({ name: username, uid }),
[username, uid]
);
const allowEditGlobalManagement = useMemo(
() => canEditGlobalManagement(currentOperator),
[currentOperator]
);

const [messageApi, contextHolder] = message.useMessage();

const onClose = useCallback(() => {
Expand All @@ -52,12 +67,32 @@
const updateUser = async () => {
const values = await form.validateFields();

if (!canManageTarget(currentOperator, currentUser)) {
messageApi.error(t('dmsUserCenter.user.userForm.manageTargetForbidden'));

Check warning on line 71 in packages/base/src/page/UserCenter/Modal/User/UpdateUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
return;

Check warning on line 72 in packages/base/src/page/UserCenter/Modal/User/UpdateUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

Check warning on line 73 in packages/base/src/page/UserCenter/Modal/User/UpdateUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

const nextOpUids = values.opPermissionUids ?? [];
const prevHadGlobal =
currentUser?.op_permissions?.some(
(p) => p.uid === OpPermissionTypeUid.global_management
) ?? false;
const nextHasGlobal = nextOpUids.includes(
OpPermissionTypeUid.global_management
);
if (!allowEditGlobalManagement && prevHadGlobal !== nextHasGlobal) {

Check warning on line 83 in packages/base/src/page/UserCenter/Modal/User/UpdateUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
messageApi.error(
t('dmsUserCenter.user.userForm.globalManagementLockedTips')
);

Check warning on line 86 in packages/base/src/page/UserCenter/Modal/User/UpdateUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
return;

Check warning on line 87 in packages/base/src/page/UserCenter/Modal/User/UpdateUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

Check warning on line 88 in packages/base/src/page/UserCenter/Modal/User/UpdateUser/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

const userParams: IUpdateUser = {
password: values.passwordConfirm,
email: values.email ?? '',
phone: values.phone ?? '',
wxid: values.wxid ?? '',
op_permission_uids: values.opPermissionUids ?? [],
op_permission_uids: nextOpUids,
is_disabled: values.username !== 'admin' ? !!values.isDisabled : false
};
setTrue();
Expand Down Expand Up @@ -124,6 +159,7 @@
visible={visible}
isUpdate={true}
isAdmin={currentUser?.name === SystemRole.admin}
canEditGlobalManagement={allowEditGlobalManagement}
/>
</BasicDrawer>
);
Expand Down
34 changes: 31 additions & 3 deletions packages/base/src/page/UserCenter/Modal/User/UserForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
import { IUserFormProps } from './index.type';
import { Form, Switch } from 'antd';
import { BasicInput, BasicSelect } from '@actiontech/shared';
import React, { useEffect } from 'react';
import React, { useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Rule } from 'antd/es/form';
import { nameRule, phoneRule } from '@actiontech/shared/lib/utils/FormRule';
import EmptyBox from '@actiontech/shared/lib/components/EmptyBox';
import { BasicToolTips } from '@actiontech/shared';
import useOpPermission from '../../../../../hooks/useOpPermission';
import { ListOpPermissionsFilterByTargetEnum } from '@actiontech/shared/lib/api/base/service/OpPermission/index.enum';
import { OpPermissionTypeUid } from '@actiontech/shared/lib/enum';

const UserForm: React.FC<IUserFormProps> = (props) => {
const { t } = useTranslation();
const canEditGlobalManagement = props.canEditGlobalManagement !== false;

const {
loading: getOpPermissionListLoading,
opPermissionOptions,
updateOpPermissionList
} = useOpPermission();

const permissionOptions = useMemo(() => {
if (canEditGlobalManagement) {
return opPermissionOptions;
}
return opPermissionOptions.map((opt) => {

Check warning on line 28 in packages/base/src/page/UserCenter/Modal/User/UserForm/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
if (opt.value === OpPermissionTypeUid.global_management) {
return { ...opt, disabled: true };

Check warning on line 30 in packages/base/src/page/UserCenter/Modal/User/UserForm/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

Check warning on line 31 in packages/base/src/page/UserCenter/Modal/User/UserForm/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 31 in packages/base/src/page/UserCenter/Modal/User/UserForm/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
return opt;

Check warning on line 32 in packages/base/src/page/UserCenter/Modal/User/UserForm/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
});

Check warning on line 33 in packages/base/src/page/UserCenter/Modal/User/UserForm/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}, [canEditGlobalManagement, opPermissionOptions]);

const userNameRules = (): Rule[] => {
const baseRules = [
{
Expand Down Expand Up @@ -164,7 +178,21 @@
</Form.Item>
<Form.Item
name="opPermissionUids"
label={t('dmsUserCenter.user.userForm.opPermissions')}
label={
canEditGlobalManagement ? (
t('dmsUserCenter.user.userForm.opPermissions')
) : (
<BasicToolTips
suffixIcon
titleWidth={320}
title={t(
'dmsUserCenter.user.userForm.globalManagementLockedTips'
)}
>
{t('dmsUserCenter.user.userForm.opPermissions')}
</BasicToolTips>

Check warning on line 193 in packages/base/src/page/UserCenter/Modal/User/UserForm/index.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
)
}
>
<BasicSelect
mode="multiple"
Expand All @@ -173,7 +201,7 @@
placeholder={t('common.form.placeholder.select', {
name: t('dmsUserCenter.user.userForm.opPermissions')
})}
options={opPermissionOptions}
options={permissionOptions}
optionFilterProp="label"
/>
</Form.Item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ export interface IUserFormProps {
form: FormInstance<IUserFormFields>;
visible: boolean;
isUpdate?: boolean;
/** 目标用户是否为 admin(控制禁用开关展示;勿与「当前操作者是否内置」混淆) */
isAdmin?: boolean;
/** 当前操作者是否可授予/收回「系统管理员」;false 时锁定 700017 选项 */
canEditGlobalManagement?: boolean;
}
Loading
Loading