From 279be35f97be6bee886b98a743c237f01fa6d588 Mon Sep 17 00:00:00 2001 From: shanghaikid Date: Thu, 27 Jul 2023 19:36:56 +0800 Subject: [PATCH 1/9] assign user role part1 Signed-off-by: shanghaikid --- client/src/http/User.ts | 16 +++++++++ client/src/pages/user/CreateUser.tsx | 49 ++++++++++++++++++++++++-- client/src/pages/user/Types.ts | 12 +++++++ client/src/pages/user/User.tsx | 41 ++++++++++++++++++++-- server/src/users/dto.ts | 16 +++++++++ server/src/users/users.controller.ts | 52 ++++++++++++++++++++++++++-- server/src/users/users.service.ts | 21 +++++++++++ 7 files changed, 200 insertions(+), 7 deletions(-) diff --git a/client/src/http/User.ts b/client/src/http/User.ts index 0cb2b972..45b18c44 100644 --- a/client/src/http/User.ts +++ b/client/src/http/User.ts @@ -4,6 +4,8 @@ import { UpdateUserParams, CreateRoleParams, DeleteRoleParams, + AssignRoleParams, + UnassignRoleParams, } from '../pages/user/Types'; import BaseModel from './BaseModel'; @@ -45,6 +47,20 @@ export class UserHttp extends BaseModel { return super.delete({ path: `${this.USER_URL}/roles/${data.roleName}` }); } + static assignUserRole(data: AssignRoleParams) { + return super.update({ + path: `${this.USER_URL}/${data.username}/role/assign`, + data, + }); + } + + static unassignUserRole(data: UnassignRoleParams) { + return super.update({ + path: `${this.USER_URL}/${data.username}/role/unassign`, + data, + }); + } + get _names() { return this.names; } diff --git a/client/src/pages/user/CreateUser.tsx b/client/src/pages/user/CreateUser.tsx index 615173ba..e96ea1af 100644 --- a/client/src/pages/user/CreateUser.tsx +++ b/client/src/pages/user/CreateUser.tsx @@ -1,4 +1,10 @@ -import { makeStyles, Theme } from '@material-ui/core'; +import { + makeStyles, + Theme, + Checkbox, + FormGroup, + FormControlLabel, +} from '@material-ui/core'; import { FC, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import DialogTemplate from '@/components/customDialog/DialogTemplate'; @@ -12,9 +18,19 @@ const useStyles = makeStyles((theme: Theme) => ({ input: { margin: theme.spacing(3, 0, 0.5), }, + dialogWrapper: { + maxWidth: theme.spacing(70), + '& .MuiFormControlLabel-root': { + width: theme.spacing(20), + }, + }, })); -const CreateUser: FC = ({ handleCreate, handleClose }) => { +const CreateUser: FC = ({ + handleCreate, + handleClose, + roles, +}) => { const { t: commonTrans } = useTranslation(); const { t: userTrans } = useTranslation('user'); const { t: btnTrans } = useTranslation('btn'); @@ -24,10 +40,14 @@ const CreateUser: FC = ({ handleCreate, handleClose }) => { const [form, setForm] = useState({ username: '', password: '', + roles: [], }); + + // selected Role const checkedForm = useMemo(() => { return formatForm(form); }, [form]); + const { validation, checkIsValid, disabled } = useFormValidation(checkedForm); const classes = useStyles(); @@ -87,6 +107,7 @@ const CreateUser: FC = ({ handleCreate, handleClose }) => { confirmLabel={btnTrans('create')} handleConfirm={handleCreateUser} confirmDisabled={disabled} + dialogClass={classes.dialogWrapper} > <> {createConfigs.map(v => ( @@ -98,6 +119,30 @@ const CreateUser: FC = ({ handleCreate, handleClose }) => { key={v.label} /> ))} + + + {roles.map((r: any, index: number) => ( + } + key={index} + label={r.label} + value={r.value} + onChange={(e: React.ChangeEvent<{}>, checked: boolean) => { + let newRoles = [...form.roles]; + + if (!checked) { + newRoles = newRoles.filter( + (n: string | number) => n === r.vlaue + ); + } else { + newRoles.push(r.value); + } + + setForm(v => ({ ...v, roles: [...newRoles] })); + }} + /> + ))} + ); diff --git a/client/src/pages/user/Types.ts b/client/src/pages/user/Types.ts index 4879e154..a938aead 100644 --- a/client/src/pages/user/Types.ts +++ b/client/src/pages/user/Types.ts @@ -1,15 +1,20 @@ +import { Option } from '@/components/customSelector/Types'; + export interface UserData { name: string; + roleName?: string; } export interface CreateUserParams { username: string; password: string; + roles: string[]; } export interface CreateUserProps { handleCreate: (data: CreateUserParams) => void; handleClose: () => void; + roles: Option[] } export interface UpdateUserProps { @@ -41,6 +46,13 @@ export interface DeleteRoleParams { roleName: string; } +export interface AssignRoleParams { + username: string; + roleName: string; +} + +export interface UnassignRoleParams extends AssignRoleParams {} + export interface RoleData { name: string; } diff --git a/client/src/pages/user/User.tsx b/client/src/pages/user/User.tsx index d2b6452e..4bc39a45 100644 --- a/client/src/pages/user/User.tsx +++ b/client/src/pages/user/User.tsx @@ -38,12 +38,36 @@ const Users = () => { const fetchUsers = async () => { const res = await UserHttp.getUsers(); - - setUsers(res.usernames.map((v: string) => ({ name: v }))); + const roles = await UserHttp.getRoles(); + setUsers( + res.usernames.map((v: string) => { + const name = v; + const rolesByName = roles.results.filter((r: any) => + r.users.map((u: any) => u.name).includes(name) + ); + return { + name: v, + role: + v === 'root' + ? 'root' + : rolesByName.map((r: any) => r.role.name).join(','), + }; + }) + ); }; const handleCreate = async (data: CreateUserParams) => { await UserHttp.createUser(data); + console.log(data, data.roles); + // assign user role if + if (data.roles.length > 0) { + console.log('assign roles'); + // await UserHttp.assignUserRole({ + // username: data.username, + // roleName: data.roleName, + // }); + } + fetchUsers(); openSnackBar(successTrans('create', { name: userTrans('user') })); handleCloseDialog(); @@ -72,7 +96,8 @@ const Users = () => { const toolbarConfigs: ToolBarConfig[] = [ { label: userTrans('user'), - onClick: () => { + onClick: async () => { + const roles = await UserHttp.getRoles(); setDialog({ open: true, type: 'custom', @@ -81,6 +106,9 @@ const Users = () => { { + return { label: r.role.name, value: r.role.name }; + })} /> ), }, @@ -124,11 +152,18 @@ const Users = () => { disablePadding: false, label: userTrans('user'), }, + { + id: 'role', + align: 'left', + disablePadding: false, + label: userTrans('role'), + }, { id: 'action', disablePadding: false, label: 'Action', showActionCell: true, + sortBy: 'action', actionBarConfigs: [ { onClick: (e: React.MouseEvent, row: UserData) => { diff --git a/server/src/users/dto.ts b/server/src/users/dto.ts index 4412f250..bb2178c1 100644 --- a/server/src/users/dto.ts +++ b/server/src/users/dto.ts @@ -23,3 +23,19 @@ export class UpdateUserDto { @IsString() readonly newPassword: string; } + +export class AssignUserRoleDto { + @IsString() + readonly username: string; + + @IsString() + readonly roleName: string; +} + +export class UnassignUserRoleDto { + @IsString() + readonly username: string; + + @IsString() + readonly roleName: string; +} diff --git a/server/src/users/users.controller.ts b/server/src/users/users.controller.ts index b27ac8e5..fc7d75ab 100644 --- a/server/src/users/users.controller.ts +++ b/server/src/users/users.controller.ts @@ -2,8 +2,13 @@ import { NextFunction, Request, Response, Router } from 'express'; import { dtoValidationMiddleware } from '../middlewares/validation'; import { UserService } from './users.service'; import { milvusService } from '../milvus'; - -import { CreateUserDto, UpdateUserDto, CreateRoleDto } from './dto'; +import { + CreateUserDto, + UpdateUserDto, + CreateRoleDto, + AssignUserRoleDto, + UnassignUserRoleDto, +} from './dto'; export class UserController { private router: Router; @@ -41,12 +46,25 @@ export class UserController { this.router.delete('/roles/:roleName', this.deleteRole.bind(this)); + this.router.put( + '/:username/role/assign', + dtoValidationMiddleware(AssignUserRoleDto), + this.assignUserRole.bind(this) + ); + + this.router.put( + '/:username/role/unassign', + dtoValidationMiddleware(UnassignUserRoleDto), + this.unassignUserRole.bind(this) + ); + return this.router; } async getUsers(req: Request, res: Response, next: NextFunction) { try { const result = await this.userService.getUsers(); + res.send(result); } catch (error) { next(error); @@ -115,4 +133,34 @@ export class UserController { next(error); } } + + async assignUserRole(req: Request, res: Response, next: NextFunction) { + const { roleName } = req.body; + const { username } = req.params; + + try { + const result = await this.userService.assignUserRole({ + username, + roleName, + }); + res.send(result); + } catch (error) { + next(error); + } + } + + async unassignUserRole(req: Request, res: Response, next: NextFunction) { + const { roleName } = req.body; + const { username } = req.params; + + try { + const result = await this.userService.assignUserRole({ + username, + roleName, + }); + res.send(result); + } catch (error) { + next(error); + } + } } diff --git a/server/src/users/users.service.ts b/server/src/users/users.service.ts index bd87d503..3613ccba 100644 --- a/server/src/users/users.service.ts +++ b/server/src/users/users.service.ts @@ -5,6 +5,9 @@ import { DeleteUserReq, CreateRoleReq, DropRoleReq, + AddUserToRoleReq, + RemoveUserFromRoleReq, + HasRoleReq } from '@zilliz/milvus2-sdk-node'; import { throwErrorFromSDK } from '../utils/Error'; @@ -59,4 +62,22 @@ export class UserService { throwErrorFromSDK(res); return res; } + + async assignUserRole(data: AddUserToRoleReq) { + const res = await this.milvusService.client.addUserToRole(data); + throwErrorFromSDK(res); + return res; + } + + async unassignUserRole(data: RemoveUserFromRoleReq) { + const res = await this.milvusService.client.addUserToRole(data); + throwErrorFromSDK(res); + return res; + } + + async hasRole(data: HasRoleReq) { + const res = await this.milvusService.client.hasRole(data); + throwErrorFromSDK(res.status); + return res; + } } From 7a7a15490f5545c90528b2b49f12bc14b1201ef3 Mon Sep 17 00:00:00 2001 From: shanghaikid Date: Fri, 28 Jul 2023 18:45:23 +0800 Subject: [PATCH 2/9] assign user multiple roles when creating user Signed-off-by: shanghaikid --- client/src/http/User.ts | 4 +-- client/src/i18n/en/user.ts | 3 ++- client/src/pages/user/CreateUser.tsx | 7 ++++- client/src/pages/user/Types.ts | 2 +- client/src/pages/user/User.tsx | 38 +++++++++++++++++++------- server/src/users/dto.ts | 4 +-- server/src/users/users.controller.ts | 40 ++++++++++++++++++++++------ server/src/users/users.service.ts | 17 ++++++++---- 8 files changed, 86 insertions(+), 29 deletions(-) diff --git a/client/src/http/User.ts b/client/src/http/User.ts index 45b18c44..dd682c5e 100644 --- a/client/src/http/User.ts +++ b/client/src/http/User.ts @@ -47,9 +47,9 @@ export class UserHttp extends BaseModel { return super.delete({ path: `${this.USER_URL}/roles/${data.roleName}` }); } - static assignUserRole(data: AssignRoleParams) { + static updateUserRole(data: AssignRoleParams) { return super.update({ - path: `${this.USER_URL}/${data.username}/role/assign`, + path: `${this.USER_URL}/${data.username}/role/update`, data, }); } diff --git a/client/src/i18n/en/user.ts b/client/src/i18n/en/user.ts index 0fe07c77..4b524ef8 100644 --- a/client/src/i18n/en/user.ts +++ b/client/src/i18n/en/user.ts @@ -10,9 +10,10 @@ const userTrans = { update: 'Update password', isNotSame: 'Not same as new password', deleteTip: - 'Please select at least one item to drop and root can not be dropped.', + 'Please select at least one item to drop and the root user can not be dropped.', role: 'Role', + editRole:'Edit Role', roles: 'Roles', createRoleTitle: 'Create Role', }; diff --git a/client/src/pages/user/CreateUser.tsx b/client/src/pages/user/CreateUser.tsx index e96ea1af..78a3c2c3 100644 --- a/client/src/pages/user/CreateUser.tsx +++ b/client/src/pages/user/CreateUser.tsx @@ -4,6 +4,7 @@ import { Checkbox, FormGroup, FormControlLabel, + Typography, } from '@material-ui/core'; import { FC, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -16,7 +17,7 @@ import { CreateUserProps, CreateUserParams } from './Types'; const useStyles = makeStyles((theme: Theme) => ({ input: { - margin: theme.spacing(3, 0, 0.5), + margin: theme.spacing(2, 0, 0.5), }, dialogWrapper: { maxWidth: theme.spacing(70), @@ -120,6 +121,10 @@ const CreateUser: FC = ({ /> ))} + + {userTrans('roles')} + + {roles.map((r: any, index: number) => ( { role: v === 'root' ? 'root' - : rolesByName.map((r: any) => r.role.name).join(','), + : rolesByName.map((r: any) => r.role.name).join(' , '), }; }) ); @@ -60,13 +60,10 @@ const Users = () => { await UserHttp.createUser(data); console.log(data, data.roles); // assign user role if - if (data.roles.length > 0) { - console.log('assign roles'); - // await UserHttp.assignUserRole({ - // username: data.username, - // roleName: data.roleName, - // }); - } + await UserHttp.updateUserRole({ + username: data.username, + roles: data.roles, + }); fetchUsers(); openSnackBar(successTrans('create', { name: userTrans('user') })); @@ -117,6 +114,30 @@ const Users = () => { icon: 'add', }, + { + type: 'iconBtn', + label: userTrans('editRole'), + onClick: async () => { + const roles = await UserHttp.getRoles(); + setDialog({ + open: true, + type: 'custom', + params: { + component: ( + { + return { label: r.role.name, value: r.role.name }; + })} + /> + ), + }, + }); + }, + icon: 'edit', + }, + { type: 'iconBtn', onClick: () => { @@ -140,7 +161,6 @@ const Users = () => { selectedUser.length === 0 || selectedUser.findIndex(v => v.name === 'root') > -1, disabledTooltip: userTrans('deleteTip'), - icon: 'delete', }, ]; diff --git a/server/src/users/dto.ts b/server/src/users/dto.ts index bb2178c1..056da75d 100644 --- a/server/src/users/dto.ts +++ b/server/src/users/dto.ts @@ -28,8 +28,8 @@ export class AssignUserRoleDto { @IsString() readonly username: string; - @IsString() - readonly roleName: string; + @IsString({ each: true }) + readonly roles: string; } export class UnassignUserRoleDto { diff --git a/server/src/users/users.controller.ts b/server/src/users/users.controller.ts index fc7d75ab..dd95fa49 100644 --- a/server/src/users/users.controller.ts +++ b/server/src/users/users.controller.ts @@ -47,9 +47,9 @@ export class UserController { this.router.delete('/roles/:roleName', this.deleteRole.bind(this)); this.router.put( - '/:username/role/assign', + '/:username/role/update', dtoValidationMiddleware(AssignUserRoleDto), - this.assignUserRole.bind(this) + this.updateUserRole.bind(this) ); this.router.put( @@ -134,16 +134,40 @@ export class UserController { } } - async assignUserRole(req: Request, res: Response, next: NextFunction) { - const { roleName } = req.body; + async updateUserRole(req: Request, res: Response, next: NextFunction) { + const { roles } = req.body; const { username } = req.params; + const results = []; + try { - const result = await this.userService.assignUserRole({ + // get user existing roles + const selectUser = await this.userService.selectUser({ username, - roleName, + includeRoleInfo: false, }); - res.send(result); + + const existingRoles = selectUser.results[0].roles; + // remove user existing roles + for (let i = 0; i < existingRoles.length; i++) { + if (existingRoles[i].name.length > 0) { + await this.userService.unassignUserRole({ + username, + roleName: existingRoles[i].name, + }); + } + } + + // assign new user roles + for (let i = 0; i < roles.length; i++) { + const result = await this.userService.assignUserRole({ + username, + roleName: roles[i], + }); + results.push(result); + } + + res.send(results); } catch (error) { next(error); } @@ -154,7 +178,7 @@ export class UserController { const { username } = req.params; try { - const result = await this.userService.assignUserRole({ + const result = await this.userService.unassignUserRole({ username, roleName, }); diff --git a/server/src/users/users.service.ts b/server/src/users/users.service.ts index 3613ccba..5d8d243c 100644 --- a/server/src/users/users.service.ts +++ b/server/src/users/users.service.ts @@ -7,7 +7,9 @@ import { DropRoleReq, AddUserToRoleReq, RemoveUserFromRoleReq, - HasRoleReq + HasRoleReq, + listRoleReq, + SelectUserReq, } from '@zilliz/milvus2-sdk-node'; import { throwErrorFromSDK } from '../utils/Error'; @@ -41,10 +43,15 @@ export class UserService { return res; } - async getRoles() { - const res = await this.milvusService.client.listRoles({ - includeUserInfo: true, - }); + async getRoles(data?: listRoleReq) { + const res = await this.milvusService.client.listRoles(data); + throwErrorFromSDK(res.status); + + return res; + } + + async selectUser(data?: SelectUserReq) { + const res = await this.milvusService.client.selectUser(data); throwErrorFromSDK(res.status); return res; From b6f9a6035bdd7340bb3aba3a67b105df2b331611 Mon Sep 17 00:00:00 2001 From: shanghaikid Date: Fri, 28 Jul 2023 19:27:33 +0800 Subject: [PATCH 3/9] edit user role part1 Signed-off-by: shanghaikid --- client/src/pages/user/Types.ts | 12 ++- client/src/pages/user/UpdateUserRole.tsx | 96 ++++++++++++++++++++++++ client/src/pages/user/User.tsx | 21 +++++- 3 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 client/src/pages/user/UpdateUserRole.tsx diff --git a/client/src/pages/user/Types.ts b/client/src/pages/user/Types.ts index af81430c..6deada12 100644 --- a/client/src/pages/user/Types.ts +++ b/client/src/pages/user/Types.ts @@ -11,10 +11,20 @@ export interface CreateUserParams { roles: string[]; } +export interface UpdateUserRoleParams { + roles: string[]; +} + +export interface UpdateUserRoleProps { + handleUpdate: (data: UpdateUserRoleParams) => void; + handleClose: () => void; + roles: string[]; +} + export interface CreateUserProps { handleCreate: (data: CreateUserParams) => void; handleClose: () => void; - roles: Option[] + roles: Option[]; } export interface UpdateUserProps { diff --git a/client/src/pages/user/UpdateUserRole.tsx b/client/src/pages/user/UpdateUserRole.tsx new file mode 100644 index 00000000..e176c110 --- /dev/null +++ b/client/src/pages/user/UpdateUserRole.tsx @@ -0,0 +1,96 @@ +import { + makeStyles, + Theme, + Checkbox, + FormGroup, + FormControlLabel, +} from '@material-ui/core'; +import { FC, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import DialogTemplate from '@/components/customDialog/DialogTemplate'; +import { useFormValidation } from '@/hooks/Form'; +import { formatForm } from '@/utils/Form'; +import { UpdateUserRoleProps, UpdateUserRoleParams } from './Types'; + +const useStyles = makeStyles((theme: Theme) => ({ + input: { + margin: theme.spacing(2, 0, 0.5), + }, + dialogWrapper: { + maxWidth: theme.spacing(70), + '& .MuiFormControlLabel-root': { + width: theme.spacing(20), + }, + }, +})); + +const UpdateUserRole: FC = ({ + handleUpdate, + handleClose, + roles, +}) => { + const { t: commonTrans } = useTranslation(); + const { t: userTrans } = useTranslation('user'); + const { t: btnTrans } = useTranslation('btn'); + const { t: warningTrans } = useTranslation('warning'); + + const [form, setForm] = useState({ + roles: [], + }); + + // selected Role + const checkedForm = useMemo(() => { + return formatForm(form); + }, [form]); + + const { validation, checkIsValid, disabled } = useFormValidation(checkedForm); + + const classes = useStyles(); + + const handleInputChange = (key: 'username' | 'password', value: string) => { + setForm(v => ({ ...v, [key]: value })); + }; + + const handleCreateUser = () => { + handleUpdate(form); + }; + + return ( + + <> + + {roles.map((r: any, index: number) => ( + } + key={index} + label={r.label} + value={r.value} + onChange={(e: React.ChangeEvent<{}>, checked: boolean) => { + let newRoles = [...form.roles]; + + if (!checked) { + newRoles = newRoles.filter( + (n: string | number) => n === r.vlaue + ); + } else { + newRoles.push(r.value); + } + + setForm(v => ({ ...v, roles: [...newRoles] })); + }} + /> + ))} + + + + ); +}; + +export default UpdateUserRole; diff --git a/client/src/pages/user/User.tsx b/client/src/pages/user/User.tsx index c7a35a9b..e962b4f6 100644 --- a/client/src/pages/user/User.tsx +++ b/client/src/pages/user/User.tsx @@ -9,12 +9,14 @@ import { DeleteUserParams, UpdateUserParams, UserData, + UpdateUserRoleParams, } from './Types'; import DeleteTemplate from '@/components/customDialog/DeleteDialogTemplate'; import { rootContext } from '@/context/Root'; import { useNavigationHook } from '@/hooks/Navigation'; import { ALL_ROUTER_TYPES } from '@/router/Types'; import CreateUser from './CreateUser'; +import UpdateUserRole from './UpdateUserRole'; import UpdateUser from './Update'; const useStyles = makeStyles((theme: Theme) => ({ @@ -70,6 +72,19 @@ const Users = () => { handleCloseDialog(); }; + const handleUpdateUserRole = async (data: UpdateUserRoleParams) => { + // await UserHttp.createUser(data); + // console.log(data, data.roles); + // // assign user role if + // await UserHttp.updateUserRole({ + // username: data.username, + // roles: data.roles, + // }); + // fetchUsers(); + // openSnackBar(successTrans('create', { name: userTrans('user') })); + // handleCloseDialog(); + }; + const handleUpdate = async (data: UpdateUserParams) => { await UserHttp.updateUser(data); fetchUsers(); @@ -124,11 +139,11 @@ const Users = () => { type: 'custom', params: { component: ( - { - return { label: r.role.name, value: r.role.name }; + return r.role.name; })} /> ), From abf71d5cc1f1f35c47aead91426651ca4dc37f5f Mon Sep 17 00:00:00 2001 From: "ruiyi.jiang" Date: Mon, 31 Jul 2023 08:01:59 +0800 Subject: [PATCH 4/9] edit user role Signed-off-by: ruiyi.jiang --- client/src/i18n/en/user.ts | 5 +- client/src/pages/user/CreateUser.tsx | 31 ++--- client/src/pages/user/Types.ts | 5 +- client/src/pages/user/UpdateUserRole.tsx | 79 ++++++------ client/src/pages/user/User.tsx | 40 +++--- server/package.json | 2 +- server/src/users/users.service.ts | 2 +- server/tslint.json | 16 +-- server/yarn.lock | 150 ++++++----------------- 9 files changed, 127 insertions(+), 203 deletions(-) diff --git a/client/src/i18n/en/user.ts b/client/src/i18n/en/user.ts index 4b524ef8..d40e703a 100644 --- a/client/src/i18n/en/user.ts +++ b/client/src/i18n/en/user.ts @@ -1,6 +1,7 @@ const userTrans = { createTitle: 'Create User', updateTitle: 'Update Milvus User', + updateRoleTitle: 'Update User Roles', user: 'User', users: 'Users', deleteWarning: 'You are trying to drop user. This action cannot be undone.', @@ -11,9 +12,9 @@ const userTrans = { isNotSame: 'Not same as new password', deleteTip: 'Please select at least one item to drop and the root user can not be dropped.', - + deleteEditRoleTip: 'root role is not editable.', role: 'Role', - editRole:'Edit Role', + editRole: 'Edit Role', roles: 'Roles', createRoleTitle: 'Create Role', }; diff --git a/client/src/pages/user/CreateUser.tsx b/client/src/pages/user/CreateUser.tsx index 78a3c2c3..a03f3cc1 100644 --- a/client/src/pages/user/CreateUser.tsx +++ b/client/src/pages/user/CreateUser.tsx @@ -128,23 +128,26 @@ const CreateUser: FC = ({ {roles.map((r: any, index: number) => ( } + control={ + , checked: boolean) => { + let newRoles = [...form.roles]; + + if (!checked) { + newRoles = newRoles.filter( + (n: string | number) => n === r.vlaue + ); + } else { + newRoles.push(r.value); + } + + setForm(v => ({ ...v, roles: [...newRoles] })); + }} + /> + } key={index} label={r.label} value={r.value} - onChange={(e: React.ChangeEvent<{}>, checked: boolean) => { - let newRoles = [...form.roles]; - - if (!checked) { - newRoles = newRoles.filter( - (n: string | number) => n === r.vlaue - ); - } else { - newRoles.push(r.value); - } - - setForm(v => ({ ...v, roles: [...newRoles] })); - }} /> ))} diff --git a/client/src/pages/user/Types.ts b/client/src/pages/user/Types.ts index 6deada12..996525c8 100644 --- a/client/src/pages/user/Types.ts +++ b/client/src/pages/user/Types.ts @@ -3,6 +3,7 @@ import { Option } from '@/components/customSelector/Types'; export interface UserData { name: string; roleName?: string; + roles: string[]; } export interface CreateUserParams { @@ -16,9 +17,11 @@ export interface UpdateUserRoleParams { } export interface UpdateUserRoleProps { - handleUpdate: (data: UpdateUserRoleParams) => void; + onUpdate: (data: UpdateUserRoleParams) => void; handleClose: () => void; + username: string; roles: string[]; + allRoles: string[]; } export interface CreateUserProps { diff --git a/client/src/pages/user/UpdateUserRole.tsx b/client/src/pages/user/UpdateUserRole.tsx index e176c110..c2a77bcc 100644 --- a/client/src/pages/user/UpdateUserRole.tsx +++ b/client/src/pages/user/UpdateUserRole.tsx @@ -5,12 +5,11 @@ import { FormGroup, FormControlLabel, } from '@material-ui/core'; -import { FC, useMemo, useState } from 'react'; +import { FC, useState } from 'react'; import { useTranslation } from 'react-i18next'; import DialogTemplate from '@/components/customDialog/DialogTemplate'; -import { useFormValidation } from '@/hooks/Form'; -import { formatForm } from '@/utils/Form'; import { UpdateUserRoleProps, UpdateUserRoleParams } from './Types'; +import { UserHttp } from '@/http/User'; const useStyles = makeStyles((theme: Theme) => ({ input: { @@ -25,66 +24,66 @@ const useStyles = makeStyles((theme: Theme) => ({ })); const UpdateUserRole: FC = ({ - handleUpdate, + onUpdate, handleClose, roles, + allRoles, + username, }) => { - const { t: commonTrans } = useTranslation(); const { t: userTrans } = useTranslation('user'); const { t: btnTrans } = useTranslation('btn'); - const { t: warningTrans } = useTranslation('warning'); const [form, setForm] = useState({ - roles: [], + roles: roles, }); - // selected Role - const checkedForm = useMemo(() => { - return formatForm(form); - }, [form]); - - const { validation, checkIsValid, disabled } = useFormValidation(checkedForm); - const classes = useStyles(); - const handleInputChange = (key: 'username' | 'password', value: string) => { - setForm(v => ({ ...v, [key]: value })); - }; - - const handleCreateUser = () => { - handleUpdate(form); + const handleUpdate = async () => { + await UserHttp.updateUserRole({ + username: username, + roles: form.roles, + }); + onUpdate(form); }; return ( <> - {roles.map((r: any, index: number) => ( + {allRoles.map((r: any, index: number) => ( } - key={index} - label={r.label} - value={r.value} - onChange={(e: React.ChangeEvent<{}>, checked: boolean) => { - let newRoles = [...form.roles]; + control={ + , + checked: boolean + ) => { + let newRoles = [...form.roles]; - if (!checked) { - newRoles = newRoles.filter( - (n: string | number) => n === r.vlaue - ); - } else { - newRoles.push(r.value); - } + if (!checked) { + newRoles = newRoles.filter( + (n: string | number) => n !== r + ); + } else { + newRoles.push(r); + } - setForm(v => ({ ...v, roles: [...newRoles] })); - }} + setForm(v => ({ ...v, roles: [...newRoles] })); + }} + /> + } + key={index} + label={r} + value={r} + checked={form.roles.indexOf(r) !== -1} /> ))} diff --git a/client/src/pages/user/User.tsx b/client/src/pages/user/User.tsx index e962b4f6..08dc2883 100644 --- a/client/src/pages/user/User.tsx +++ b/client/src/pages/user/User.tsx @@ -47,12 +47,12 @@ const Users = () => { const rolesByName = roles.results.filter((r: any) => r.users.map((u: any) => u.name).includes(name) ); + const originRoles = + v === 'root' ? ['root'] : rolesByName.map((r: any) => r.role.name); return { name: v, - role: - v === 'root' - ? 'root' - : rolesByName.map((r: any) => r.role.name).join(' , '), + role: originRoles.join(' , '), + roles: originRoles, }; }) ); @@ -72,17 +72,11 @@ const Users = () => { handleCloseDialog(); }; - const handleUpdateUserRole = async (data: UpdateUserRoleParams) => { - // await UserHttp.createUser(data); - // console.log(data, data.roles); - // // assign user role if - // await UserHttp.updateUserRole({ - // username: data.username, - // roles: data.roles, - // }); - // fetchUsers(); - // openSnackBar(successTrans('create', { name: userTrans('user') })); - // handleCloseDialog(); + const onUpdate = async (data: UpdateUserRoleParams) => { + console.log(data, data.roles); + fetchUsers(); + openSnackBar(successTrans('create', { name: userTrans('user') })); + handleCloseDialog(); }; const handleUpdate = async (data: UpdateUserParams) => { @@ -134,23 +128,31 @@ const Users = () => { label: userTrans('editRole'), onClick: async () => { const roles = await UserHttp.getRoles(); + setDialog({ open: true, type: 'custom', params: { component: ( { - return r.role.name; - })} + roles={ + users.filter(u => u.name === selectedUser[0].name)[0].roles + } + allRoles={roles.results.map((r: any) => r.role.name)} /> ), }, }); }, icon: 'edit', + disabled: () => + selectedUser.length === 0 || + selectedUser.length > 1 || + selectedUser.findIndex(v => v.name === 'root') > -1, + disabledTooltip: userTrans('deleteEditRoleTip'), }, { diff --git a/server/package.json b/server/package.json index 5a419682..405e888b 100644 --- a/server/package.json +++ b/server/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/zilliztech/attu" }, "dependencies": { - "@zilliz/milvus2-sdk-node": "^2.2.19", + "@zilliz/milvus2-sdk-node": "2.2.22-beta.1", "axios": "^1.4.0", "chalk": "^4.1.2", "class-sanitizer": "^1.0.1", diff --git a/server/src/users/users.service.ts b/server/src/users/users.service.ts index 5d8d243c..71d77e06 100644 --- a/server/src/users/users.service.ts +++ b/server/src/users/users.service.ts @@ -77,7 +77,7 @@ export class UserService { } async unassignUserRole(data: RemoveUserFromRoleReq) { - const res = await this.milvusService.client.addUserToRole(data); + const res = await this.milvusService.client.removeUserFromRole(data); throwErrorFromSDK(res); return res; } diff --git a/server/tslint.json b/server/tslint.json index cbb3b93f..367be3ef 100644 --- a/server/tslint.json +++ b/server/tslint.json @@ -1,19 +1,13 @@ { "defaultSeverity": "error", - "extends": [ - "tslint:recommended" - ], + "extends": ["tslint:recommended"], "jsRules": {}, "rules": { - "trailing-comma": [ - false - ], + "trailing-comma": [false], "no-console": false, "max-classes-per-file": false, - "variable-name": [ - false, - "allow-leading-underscore" - ] + "variable-name": [false, "allow-leading-underscore"], + "prefer-for-of": false }, "rulesDirectory": [] -} \ No newline at end of file +} diff --git a/server/yarn.lock b/server/yarn.lock index b5ae2457..67d763e8 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -15,14 +15,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.22.5": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== dependencies: "@babel/highlight" "^7.22.5" -"@babel/compat-data@^7.16.0", "@babel/compat-data@^7.22.9": +"@babel/compat-data@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== @@ -48,7 +48,7 @@ json5 "^2.2.2" semver "^6.3.1" -"@babel/generator@^7.16.0", "@babel/generator@^7.22.7", "@babel/generator@^7.22.9", "@babel/generator@^7.7.2": +"@babel/generator@^7.22.7", "@babel/generator@^7.22.9", "@babel/generator@^7.7.2": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d" integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw== @@ -58,7 +58,7 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.16.0", "@babel/helper-compilation-targets@^7.22.9": +"@babel/helper-compilation-targets@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz#f9d0a7aaaa7cd32a3f31c9316a69f5a9bcacb892" integrity sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw== @@ -74,7 +74,7 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== -"@babel/helper-function-name@^7.16.0", "@babel/helper-function-name@^7.22.5": +"@babel/helper-function-name@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== @@ -82,35 +82,21 @@ "@babel/template" "^7.22.5" "@babel/types" "^7.22.5" -"@babel/helper-get-function-arity@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" - integrity sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-hoist-variables@^7.16.0", "@babel/helper-hoist-variables@^7.22.5": +"@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: "@babel/types" "^7.22.5" -"@babel/helper-member-expression-to-functions@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4" - integrity sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-module-imports@^7.16.0", "@babel/helper-module-imports@^7.22.5": +"@babel/helper-module-imports@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== dependencies: "@babel/types" "^7.22.5" -"@babel/helper-module-transforms@^7.16.0", "@babel/helper-module-transforms@^7.22.9": +"@babel/helper-module-transforms@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz#92dfcb1fbbb2bc62529024f72d942a8c97142129" integrity sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ== @@ -121,36 +107,19 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.5" -"@babel/helper-optimise-call-expression@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" - integrity sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw== - dependencies: - "@babel/types" "^7.16.0" - "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== -"@babel/helper-replace-supers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" - integrity sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.16.0" - "@babel/helper-optimise-call-expression" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/helper-simple-access@^7.16.0", "@babel/helper-simple-access@^7.22.5": +"@babel/helper-simple-access@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== dependencies: "@babel/types" "^7.22.5" -"@babel/helper-split-export-declaration@^7.16.0", "@babel/helper-split-export-declaration@^7.22.6": +"@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== @@ -162,17 +131,17 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== -"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.15.7", "@babel/helper-validator-identifier@^7.22.5": +"@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== -"@babel/helper-validator-option@^7.14.5", "@babel/helper-validator-option@^7.22.5": +"@babel/helper-validator-option@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== -"@babel/helpers@^7.16.0", "@babel/helpers@^7.22.6": +"@babel/helpers@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.6.tgz#8e61d3395a4f0c5a8060f309fb008200969b5ecd" integrity sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA== @@ -181,7 +150,7 @@ "@babel/traverse" "^7.22.6" "@babel/types" "^7.22.5" -"@babel/highlight@^7.14.5", "@babel/highlight@^7.16.0", "@babel/highlight@^7.22.5": +"@babel/highlight@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== @@ -190,7 +159,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.0", "@babel/parser@^7.22.5", "@babel/parser@^7.22.7": +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.22.5", "@babel/parser@^7.22.7": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== @@ -293,7 +262,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/template@^7.16.0", "@babel/template@^7.22.5", "@babel/template@^7.3.3": +"@babel/template@^7.22.5", "@babel/template@^7.3.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== @@ -302,7 +271,7 @@ "@babel/parser" "^7.22.5" "@babel/types" "^7.22.5" -"@babel/traverse@^7.16.0", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": +"@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": version "7.22.8" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== @@ -318,7 +287,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.22.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3": +"@babel/types@^7.0.0", "@babel/types@^7.22.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== @@ -438,15 +407,15 @@ minimatch "^3.0.4" plist "^3.0.4" -"@grpc/grpc-js@^1.8.17": - version "1.8.18" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.8.18.tgz#fdbf2728064fd3db7e72e970372db28bd0f6fafb" - integrity sha512-2uWPtxhsXmVgd8WzDhfamSjHpZDXfMjMDciY6VRTq4Sn7rFzazyf0LLDa0oav+61UHIoEZb4KKaAV6S7NuJFbQ== +"@grpc/grpc-js@1.8.17": + version "1.8.17" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.8.17.tgz#a3a2f826fc033eae7d2f5ee41e0ab39cee948838" + integrity sha512-DGuSbtMFbaRsyffMf+VEkVu8HkSXEUfO3UyGJNtqxW9ABdtTIA+2UXAJpwbJS+xfQxuwqLUeELmL6FuZkOqPxw== dependencies: "@grpc/proto-loader" "^0.7.0" "@types/node" ">=12.12.47" -"@grpc/proto-loader@^0.7.0", "@grpc/proto-loader@^0.7.7": +"@grpc/proto-loader@0.7.7", "@grpc/proto-loader@^0.7.0": version "0.7.7" resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.7.tgz#d33677a77eea8407f7c66e2abd97589b60eb4b21" integrity sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ== @@ -1211,16 +1180,16 @@ resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.9.tgz#b6ef7457e826be8049667ae673eda7876eb049be" integrity sha512-4VSbbcMoxc4KLjb1gs96SRmi7w4h1SF+fCoiK0XaQX62buCc1G5d0DC5bJ9xJBNPDSVCmIrcl8BiYxzjrqaaJA== -"@zilliz/milvus2-sdk-node@^2.2.19": - version "2.2.19" - resolved "https://registry.yarnpkg.com/@zilliz/milvus2-sdk-node/-/milvus2-sdk-node-2.2.19.tgz#423764fb077999366918c66946a62a8717242927" - integrity sha512-kKlQpic5ceVr7OQ0rg+AWHsMUcfoRvzn7BWKPutzU+Sst8cDbLiEaDcSaSR9gUchISBsKh7WwQ7WqK0rYpSYWA== +"@zilliz/milvus2-sdk-node@2.2.21-beta.1": + version "2.2.22-beta.1" + resolved "https://registry.yarnpkg.com/@zilliz/milvus2-sdk-node/-/milvus2-sdk-node-2.2.22-beta.1.tgz#c58456c6c82bd7a5b34b3b3a6360d818233ad618" + integrity sha512-PrG1AWbv8HvHFbfKrXCbSsFFVLoWBfRfNcqJjSH1Lh5Av6RtWOuSz4wfO+7Ko78+vJ1RZtIe4zfFUezp83feEA== dependencies: - "@grpc/grpc-js" "^1.8.17" - "@grpc/proto-loader" "^0.7.7" + "@grpc/grpc-js" "1.8.17" + "@grpc/proto-loader" "0.7.7" dayjs "^1.11.7" lru-cache "^9.1.2" - protobufjs "^7.2.4" + protobufjs "7.2.4" winston "^3.9.0" abbrev@1, abbrev@^1.0.0: @@ -1606,7 +1575,7 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.16.6, browserslist@^4.21.9: +browserslist@^4.21.9: version "4.21.9" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== @@ -1752,7 +1721,7 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== -caniuse-lite@^1.0.30001274, caniuse-lite@^1.0.30001503: +caniuse-lite@^1.0.30001503: version "1.0.30001516" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz#621b1be7d85a8843ee7d210fd9d87b52e3daab3a" integrity sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g== @@ -1860,15 +1829,6 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -2296,7 +2256,7 @@ electron-publish@24.4.0: lazy-val "^1.0.5" mime "^2.5.2" -electron-to-chromium@^1.3.886, electron-to-chromium@^1.4.431: +electron-to-chromium@^1.4.431: version "1.4.464" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.464.tgz#2f94bad78dff34e527aacbfc5d0b1a33cf046507" integrity sha512-guZ84yoou4+ILNdj0XEbmGs6DEWj6zpVOWYpY09GU66yEb0DSYvP/biBPzHn0GuW/3RC/pnaYNUWlQE1fJYtgA== @@ -3549,7 +3509,7 @@ json-stringify-safe@^5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^2.1.2, json5@^2.2.0, json5@^2.2.2, json5@^2.2.3: +json5@^2.2.0, json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -3768,11 +3728,6 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" -mime-db@1.50.0: - version "1.50.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" - integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== - mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -3943,11 +3898,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - negotiator@0.6.3, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -4001,7 +3951,7 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-releases@^2.0.1, node-releases@^2.0.12: +node-releases@^2.0.12: version "2.0.13" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== @@ -4290,7 +4240,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -protobufjs@^7.0.0, protobufjs@^7.2.4: +protobufjs@7.2.4, protobufjs@^7.0.0: version "7.2.4" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.4.tgz#3fc1ec0cdc89dd91aef9ba6037ba07408485c3ae" integrity sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ== @@ -4734,11 +4684,6 @@ source-map-support@^0.5.19: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -5280,11 +5225,6 @@ xmlbuilder@>=11.0.1, xmlbuilder@^15.1.1: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== -xmlbuilder@^9.0.7: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -5300,29 +5240,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - yargs@^17.0.1, yargs@^17.3.1, yargs@^17.6.2, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" From 900482a1023e8d0160b7540896d10c02e8499060 Mon Sep 17 00:00:00 2001 From: shanghaikid Date: Mon, 31 Jul 2023 09:41:43 +0800 Subject: [PATCH 5/9] remove console Signed-off-by: shanghaikid --- client/src/pages/user/User.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/pages/user/User.tsx b/client/src/pages/user/User.tsx index 08dc2883..47f35957 100644 --- a/client/src/pages/user/User.tsx +++ b/client/src/pages/user/User.tsx @@ -60,7 +60,6 @@ const Users = () => { const handleCreate = async (data: CreateUserParams) => { await UserHttp.createUser(data); - console.log(data, data.roles); // assign user role if await UserHttp.updateUserRole({ username: data.username, @@ -73,7 +72,6 @@ const Users = () => { }; const onUpdate = async (data: UpdateUserRoleParams) => { - console.log(data, data.roles); fetchUsers(); openSnackBar(successTrans('create', { name: userTrans('user') })); handleCloseDialog(); From 26bc14c4164bf46bfd78f979305a1c0034e3677c Mon Sep 17 00:00:00 2001 From: shanghaikid Date: Mon, 31 Jul 2023 09:43:47 +0800 Subject: [PATCH 6/9] update tips Signed-off-by: shanghaikid --- client/src/i18n/en/user.ts | 1 + client/src/pages/user/User.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/i18n/en/user.ts b/client/src/i18n/en/user.ts index d40e703a..1a52e9bd 100644 --- a/client/src/i18n/en/user.ts +++ b/client/src/i18n/en/user.ts @@ -17,6 +17,7 @@ const userTrans = { editRole: 'Edit Role', roles: 'Roles', createRoleTitle: 'Create Role', + updateRoleSuccess: 'User Role', }; export default userTrans; diff --git a/client/src/pages/user/User.tsx b/client/src/pages/user/User.tsx index 47f35957..2b52d22d 100644 --- a/client/src/pages/user/User.tsx +++ b/client/src/pages/user/User.tsx @@ -73,7 +73,7 @@ const Users = () => { const onUpdate = async (data: UpdateUserRoleParams) => { fetchUsers(); - openSnackBar(successTrans('create', { name: userTrans('user') })); + openSnackBar(successTrans('update', { name: userTrans('updateRoleSuccess') })); handleCloseDialog(); }; From e122b123d93b2d0054cbff52bf1f073910de732d Mon Sep 17 00:00:00 2001 From: shanghaikid Date: Mon, 31 Jul 2023 11:33:50 +0800 Subject: [PATCH 7/9] fetch all roles should be from the dialog Signed-off-by: shanghaikid --- client/src/pages/user/Types.ts | 1 - client/src/pages/user/UpdateUserRole.tsx | 14 ++++++++++++-- client/src/pages/user/User.tsx | 7 +++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/client/src/pages/user/Types.ts b/client/src/pages/user/Types.ts index 996525c8..cb12fa39 100644 --- a/client/src/pages/user/Types.ts +++ b/client/src/pages/user/Types.ts @@ -21,7 +21,6 @@ export interface UpdateUserRoleProps { handleClose: () => void; username: string; roles: string[]; - allRoles: string[]; } export interface CreateUserProps { diff --git a/client/src/pages/user/UpdateUserRole.tsx b/client/src/pages/user/UpdateUserRole.tsx index c2a77bcc..3dbd9d81 100644 --- a/client/src/pages/user/UpdateUserRole.tsx +++ b/client/src/pages/user/UpdateUserRole.tsx @@ -5,7 +5,7 @@ import { FormGroup, FormControlLabel, } from '@material-ui/core'; -import { FC, useState } from 'react'; +import { FC, useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import DialogTemplate from '@/components/customDialog/DialogTemplate'; import { UpdateUserRoleProps, UpdateUserRoleParams } from './Types'; @@ -27,11 +27,11 @@ const UpdateUserRole: FC = ({ onUpdate, handleClose, roles, - allRoles, username, }) => { const { t: userTrans } = useTranslation('user'); const { t: btnTrans } = useTranslation('btn'); + const [allRoles, setAllRoles] = useState([]); const [form, setForm] = useState({ roles: roles, @@ -47,6 +47,16 @@ const UpdateUserRole: FC = ({ onUpdate(form); }; + const fetchAllRoles = async () => { + const roles = await UserHttp.getRoles(); + + setAllRoles(roles.results.map((r: any) => r.role.name)); + }; + + useEffect(() => { + fetchAllRoles(); + }, []); + return ( { const onUpdate = async (data: UpdateUserRoleParams) => { fetchUsers(); - openSnackBar(successTrans('update', { name: userTrans('updateRoleSuccess') })); + openSnackBar( + successTrans('update', { name: userTrans('updateRoleSuccess') }) + ); handleCloseDialog(); }; @@ -125,8 +127,6 @@ const Users = () => { type: 'iconBtn', label: userTrans('editRole'), onClick: async () => { - const roles = await UserHttp.getRoles(); - setDialog({ open: true, type: 'custom', @@ -139,7 +139,6 @@ const Users = () => { roles={ users.filter(u => u.name === selectedUser[0].name)[0].roles } - allRoles={roles.results.map((r: any) => r.role.name)} /> ), }, From aaff65448081192fec17e6f1f177ded37a841bfc Mon Sep 17 00:00:00 2001 From: shanghaikid Date: Mon, 31 Jul 2023 11:54:53 +0800 Subject: [PATCH 8/9] add more types Signed-off-by: shanghaikid --- client/src/pages/user/CreateUser.tsx | 14 ++++++++------ client/src/pages/user/Types.ts | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/client/src/pages/user/CreateUser.tsx b/client/src/pages/user/CreateUser.tsx index a03f3cc1..1edf4cb5 100644 --- a/client/src/pages/user/CreateUser.tsx +++ b/client/src/pages/user/CreateUser.tsx @@ -14,6 +14,7 @@ import { ITextfieldConfig } from '@/components/customInput/Types'; import { useFormValidation } from '@/hooks/Form'; import { formatForm } from '@/utils/Form'; import { CreateUserProps, CreateUserParams } from './Types'; +import { Option as RoleOption } from '@/components/customSelector/Types'; const useStyles = makeStyles((theme: Theme) => ({ input: { @@ -126,19 +127,20 @@ const CreateUser: FC = ({ - {roles.map((r: any, index: number) => ( + {roles.map((r: RoleOption, index: number) => ( , checked: boolean) => { + onChange={( + e: React.ChangeEvent, + checked: boolean + ) => { let newRoles = [...form.roles]; if (!checked) { - newRoles = newRoles.filter( - (n: string | number) => n === r.vlaue - ); + newRoles = newRoles.filter((n: string) => n === r.value); } else { - newRoles.push(r.value); + newRoles.push(String(r.value)); } setForm(v => ({ ...v, roles: [...newRoles] })); diff --git a/client/src/pages/user/Types.ts b/client/src/pages/user/Types.ts index cb12fa39..cd9768ab 100644 --- a/client/src/pages/user/Types.ts +++ b/client/src/pages/user/Types.ts @@ -1,4 +1,4 @@ -import { Option } from '@/components/customSelector/Types'; +import { Option as RoleOption } from '@/components/customSelector/Types'; export interface UserData { name: string; @@ -26,7 +26,7 @@ export interface UpdateUserRoleProps { export interface CreateUserProps { handleCreate: (data: CreateUserParams) => void; handleClose: () => void; - roles: Option[]; + roles: RoleOption[]; } export interface UpdateUserProps { From 70e1e21dd00718ab84a195b234e710495c5bdef1 Mon Sep 17 00:00:00 2001 From: shanghaikid Date: Mon, 31 Jul 2023 14:19:58 +0800 Subject: [PATCH 9/9] update types Signed-off-by: shanghaikid --- client/src/pages/user/CreateUser.tsx | 4 ++-- client/src/pages/user/Types.ts | 3 ++- client/src/pages/user/UpdateUserRole.tsx | 22 ++++++++++------------ client/src/pages/user/User.tsx | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/client/src/pages/user/CreateUser.tsx b/client/src/pages/user/CreateUser.tsx index 1edf4cb5..e4711a03 100644 --- a/client/src/pages/user/CreateUser.tsx +++ b/client/src/pages/user/CreateUser.tsx @@ -31,7 +31,7 @@ const useStyles = makeStyles((theme: Theme) => ({ const CreateUser: FC = ({ handleCreate, handleClose, - roles, + roleOptions, }) => { const { t: commonTrans } = useTranslation(); const { t: userTrans } = useTranslation('user'); @@ -127,7 +127,7 @@ const CreateUser: FC = ({ - {roles.map((r: RoleOption, index: number) => ( + {roleOptions.map((r: RoleOption, index: number) => ( void; handleClose: () => void; - roles: RoleOption[]; + roleOptions: RoleOption[]; } export interface UpdateUserProps { diff --git a/client/src/pages/user/UpdateUserRole.tsx b/client/src/pages/user/UpdateUserRole.tsx index 3dbd9d81..8692b92c 100644 --- a/client/src/pages/user/UpdateUserRole.tsx +++ b/client/src/pages/user/UpdateUserRole.tsx @@ -31,26 +31,24 @@ const UpdateUserRole: FC = ({ }) => { const { t: userTrans } = useTranslation('user'); const { t: btnTrans } = useTranslation('btn'); - const [allRoles, setAllRoles] = useState([]); + const [roleOptions, setRoleOptions] = useState([]); const [form, setForm] = useState({ + username: username, roles: roles, }); const classes = useStyles(); const handleUpdate = async () => { - await UserHttp.updateUserRole({ - username: username, - roles: form.roles, - }); + await UserHttp.updateUserRole(form); onUpdate(form); }; const fetchAllRoles = async () => { const roles = await UserHttp.getRoles(); - setAllRoles(roles.results.map((r: any) => r.role.name)); + setRoleOptions(roles.results.map((r: any) => r.role.name)); }; useEffect(() => { @@ -68,7 +66,7 @@ const UpdateUserRole: FC = ({ > <> - {allRoles.map((r: any, index: number) => ( + {roleOptions.map((roleOption: string, index: number) => ( = ({ if (!checked) { newRoles = newRoles.filter( - (n: string | number) => n !== r + (n: string | number) => n !== roleOption ); } else { - newRoles.push(r); + newRoles.push(roleOption); } setForm(v => ({ ...v, roles: [...newRoles] })); @@ -91,9 +89,9 @@ const UpdateUserRole: FC = ({ /> } key={index} - label={r} - value={r} - checked={form.roles.indexOf(r) !== -1} + label={roleOption} + value={roleOption} + checked={form.roles.indexOf(roleOption) !== -1} /> ))} diff --git a/client/src/pages/user/User.tsx b/client/src/pages/user/User.tsx index db67cd91..17d5faac 100644 --- a/client/src/pages/user/User.tsx +++ b/client/src/pages/user/User.tsx @@ -112,7 +112,7 @@ const Users = () => { { + roleOptions={roles.results.map((r: any) => { return { label: r.role.name, value: r.role.name }; })} />