diff --git a/webapp/packages/authentication/locales/en.json b/webapp/packages/authentication/locales/en.json index b616fe5737..cd3bd8728f 100644 --- a/webapp/packages/authentication/locales/en.json +++ b/webapp/packages/authentication/locales/en.json @@ -4,5 +4,8 @@ "authentication_create_user_dialog_create": "Create", "authentication_user_name": "User name", "authentication_user_password": "User password", - "authentication_user_role": "User role" + "authentication_user_password_repeat": "Repeat password", + "authentication_user_role": "User role", + "authentication_user_passwords_not_match": "Passwords don't match", + "authentication_user_user_created": "User was created successfully" } \ No newline at end of file diff --git a/webapp/packages/authentication/locales/ru.json b/webapp/packages/authentication/locales/ru.json index c711def40c..60468d55eb 100644 --- a/webapp/packages/authentication/locales/ru.json +++ b/webapp/packages/authentication/locales/ru.json @@ -4,5 +4,8 @@ "authentication_create_user_dialog_create": "Создать", "authentication_user_name": "Имя", "authentication_user_password": "Пароль", - "authentication_user_role": "Роль" + "authentication_user_password_repeat": "Повторите пароль", + "authentication_user_role": "Роль", + "authentication_user_passwords_not_match": "Пароли не совпадают", + "authentication_user_user_created": "Пользователь создан успешно" } \ No newline at end of file diff --git a/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialog.tsx b/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialog.tsx index 4e3b534e7e..c494af0f9e 100644 --- a/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialog.tsx +++ b/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialog.tsx @@ -11,7 +11,7 @@ import { useCallback } from 'react'; import styled, { css } from 'reshadow'; import { - SubmittingForm, ErrorMessage, InputField + SubmittingForm, ErrorMessage, InputField, Checkbox } from '@dbeaver/core/blocks'; import { useController } from '@dbeaver/core/di'; import { DialogComponent, CommonDialogWrapper } from '@dbeaver/core/dialogs'; @@ -37,7 +37,6 @@ const styles = composes( } SubmittingForm { overflow: auto; - margin: auto; margin-top: 20px; margin-bottom: 20px; } @@ -70,8 +69,12 @@ export const CreateUserDialog: DialogComponent = observer( (value: string) => controller.credentials.password = value, [] ); + const handlePasswordRepeatChange = useCallback( + (value: string) => controller.credentials.passwordRepeat = value, + [] + ); const handleRoleChange = useCallback( - (value: string) => controller.credentials.roles = value, + (roleId: string, value: boolean) => controller.credentials.roles.set(roleId, value), [] ); @@ -82,6 +85,7 @@ export const CreateUserDialog: DialogComponent = observer( footer={( )} @@ -115,17 +119,31 @@ export const CreateUserDialog: DialogComponent = observer( - {translate('authentication_user_role')} + {translate('authentication_user_password_repeat')} + {controller.roles.map((role, i) => ( + + handleRoleChange(role.roleId, checked)} + checked={controller.credentials.roles.get(role.roleId)} + disabled={controller.isCreating} + mod='surface' + > + {i === 0 && translate('authentication_user_role')} + + + ))} {controller.error.responseMessage && ( diff --git a/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialogController.ts b/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialogController.ts index 3095a430d0..02bf0b1186 100644 --- a/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialogController.ts +++ b/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialogController.ts @@ -24,11 +24,12 @@ export class CreateUserDialogController implements IInitializableController, IDe @observable credentials = { login: '', password: '', - roles: '', + passwordRepeat: '', + roles: new Map(), }; @computed get roles() { - return this.rolesManagerService.roles.data.map(role => role.roleId); + return this.rolesManagerService.roles.data; } readonly error = new GQLErrorCatcher(); private isDistructed = false; @@ -54,6 +55,10 @@ export class CreateUserDialogController implements IInitializableController, IDe if (this.isCreating) { return; } + if (this.credentials.password !== this.credentials.passwordRepeat) { + this.notificationService.logError({ title: 'authentication_user_passwords_not_match' }); + return; + } this.isCreating = true; let isUserCreated = false; @@ -61,17 +66,13 @@ export class CreateUserDialogController implements IInitializableController, IDe const user = await this.usersManagerService.create(this.credentials.login, false); isUserCreated = !!user; await this.usersManagerService.updateCredentials(user.userId, { password: this.credentials.password }); - if (this.credentials.roles) { - const roles = this.credentials.roles - .trim() - .replace(/\s+/g, ' ') - .split(' '); - - for (const role of roles) { - await this.usersManagerService.grantRole(user.userId, role); + for (const [roleId, checked] of this.credentials.roles) { + if (checked) { + await this.usersManagerService.grantRole(user.userId, roleId); } } await this.usersManagerService.users.refresh(user.userId); + this.notificationService.logInfo({ title: 'authentication_user_user_created' }); this.close(); } catch (exception) { if (isUserCreated) { diff --git a/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialogFooter.tsx b/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialogFooter.tsx index a85f5677ff..f43f745195 100644 --- a/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialogFooter.tsx +++ b/webapp/packages/authentication/src/Administration/Users/CreateUserDialog/CreateUserDialogFooter.tsx @@ -21,22 +21,37 @@ const styles = css` margin: auto; justify-content: flex-end; } + + fill { + flex: 1; + } `; export type Props = { isCreating: boolean; + onCancel(): void; onCreate(): void; } export const CreateUserDialogFooter = observer( function CreateUserDialogFooter({ isCreating, + onCancel, onCreate, }: Props) { const translate = useTranslate(); return styled(styles)( + +