Implement user password reset

Inex Code 2022-09-18 23:25:26 +03:00
parent a0b365f496
commit 900e07f364
7 changed files with 150 additions and 17 deletions

View File

@ -483,7 +483,8 @@
"rebootServer": "Перезагрузить сервер", "rebootServer": "Перезагрузить сервер",
"create_ssh_key": "Создать SSH ключ для {}", "create_ssh_key": "Создать SSH ключ для {}",
"delete_ssh_key": "Удалить SSH ключ для {}", "delete_ssh_key": "Удалить SSH ключ для {}",
"server_jobs": "Задачи на сервере" "server_jobs": "Задачи на сервере",
"resetUserPassword": "Сбросить пароль пользователя"
}, },
"validations": { "validations": {
"required": "Обязательное поле.", "required": "Обязательное поле.",

View File

@ -121,6 +121,9 @@ class JobsCubit extends Cubit<JobsState> {
if (job is DeleteSSHKeyJob) { if (job is DeleteSSHKeyJob) {
await usersCubit.deleteSshKey(job.user, job.publicKey); await usersCubit.deleteSshKey(job.user, job.publicKey);
} }
if (job is ResetUserPasswordJob) {
await usersCubit.changeUserPassword(job.user, job.user.password!);
}
} }
await api.pullConfigurationUpdate(); await api.pullConfigurationUpdate();

View File

@ -11,28 +11,50 @@ class UserFormCubit extends FormCubit {
UserFormCubit({ UserFormCubit({
required this.jobsCubit, required this.jobsCubit,
required final FieldCubitFactory fieldFactory, required final FieldCubitFactory fieldFactory,
final User? user, final this.initialUser,
}) { }) {
final bool isEdit = user != null; if (initialUser == null) {
login = fieldFactory.createUserLoginField();
login.setValue('');
password = fieldFactory.createUserPasswordField();
password.setValue(
StringGenerators.userPassword(),
);
login = fieldFactory.createUserLoginField(); super.addFields([login, password]);
login.setValue(isEdit ? user.login : ''); } else {
password = fieldFactory.createUserPasswordField(); login = fieldFactory.createRequiredStringField();
password.setValue( login.setValue(initialUser!.login);
isEdit ? (user.password ?? '') : StringGenerators.userPassword(), password = fieldFactory.createUserPasswordField();
); password.setValue(
initialUser?.password ?? '',
);
super.addFields([login, password]); super.addFields([login, password]);
}
} }
@override @override
FutureOr<void> onSubmit() { FutureOr<void> onSubmit() {
final User user = User( print('onSubmit');
login: login.state.value, print('initialUser: $initialUser');
type: UserType.normal, print('login: ${login.state.value}');
password: password.state.value, print('password: ${password.state.value}');
); if (initialUser == null) {
jobsCubit.addJob(CreateUserJob(user: user)); final User user = User(
login: login.state.value,
type: UserType.normal,
password: password.state.value,
);
jobsCubit.addJob(CreateUserJob(user: user));
} else {
final User user = User(
login: initialUser?.login ?? login.state.value,
type: initialUser?.type ?? UserType.normal,
password: password.state.value,
);
jobsCubit.addJob(ResetUserPasswordJob(user: user));
}
} }
late FieldCubit<String> login; late FieldCubit<String> login;
@ -43,4 +65,5 @@ class UserFormCubit extends FormCubit {
} }
final JobsCubit jobsCubit; final JobsCubit jobsCubit;
final User? initialUser;
} }

View File

@ -31,6 +31,17 @@ class CreateUserJob extends ClientJob {
List<Object> get props => [id, title, user]; List<Object> get props => [id, title, user];
} }
class ResetUserPasswordJob extends ClientJob {
ResetUserPasswordJob({
required this.user,
}) : super(title: '${"jobs.resetUserPassword".tr()} ${user.login}');
final User user;
@override
List<Object> get props => [id, title, user];
}
class DeleteUserJob extends ClientJob { class DeleteUserJob extends ClientJob {
DeleteUserJob({ DeleteUserJob({
required this.user, required this.user,

View File

@ -0,0 +1,84 @@
part of 'users.dart';
class ResetPassword extends StatelessWidget {
const ResetPassword({
required this.user,
final super.key,
});
final User user;
@override
Widget build(final BuildContext context) => BrandBottomSheet(
child: BlocProvider(
create: (final BuildContext context) => UserFormCubit(
jobsCubit: context.read<JobsCubit>(),
fieldFactory: FieldCubitFactory(context),
initialUser: user,
),
child: Builder(
builder: (final BuildContext context) {
final FormCubitState formCubitState =
context.watch<UserFormCubit>().state;
return BlocListener<UserFormCubit, FormCubitState>(
listener:
(final BuildContext context, final FormCubitState state) {
if (state.isSubmitted) {
Navigator.pop(context);
}
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
BrandHeader(
title: 'users.reset_password'.tr(),
),
const SizedBox(width: 14),
Padding(
padding: paddingH15V0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CubitFormTextField(
formFieldCubit:
context.read<UserFormCubit>().password,
decoration: InputDecoration(
alignLabelWithHint: false,
labelText: 'basis.password'.tr(),
suffixIcon: Padding(
padding: const EdgeInsets.only(right: 8),
child: IconButton(
icon: Icon(
BrandIcons.refresh,
color:
Theme.of(context).colorScheme.secondary,
),
onPressed: context
.read<UserFormCubit>()
.genNewPassword,
),
),
),
),
const SizedBox(height: 30),
BrandButton.rised(
onPressed: formCubitState.isSubmitting
? null
: () =>
context.read<UserFormCubit>().trySubmit(),
text: 'basis.apply'.tr(),
),
const SizedBox(height: 30),
],
),
),
],
),
);
},
),
),
);
}

View File

@ -43,7 +43,17 @@ class UserDetails extends StatelessWidget {
const SizedBox(height: 8), const SizedBox(height: 8),
ListTile( ListTile(
iconColor: Theme.of(context).colorScheme.onBackground, iconColor: Theme.of(context).colorScheme.onBackground,
onTap: () => {}, onTap: () => {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (final BuildContext context) => Padding(
padding: MediaQuery.of(context).viewInsets,
child: ResetPassword(user: user),
),
),
},
leading: const Icon(Icons.lock_reset_outlined), leading: const Icon(Icons.lock_reset_outlined),
title: Text( title: Text(
'users.reset_password'.tr(), 'users.reset_password'.tr(),

View File

@ -31,6 +31,7 @@ part 'new_user.dart';
part 'user.dart'; part 'user.dart';
part 'user_details.dart'; part 'user_details.dart';
part 'add_user_fab.dart'; part 'add_user_fab.dart';
part 'reset_password.dart';
class UsersPage extends StatelessWidget { class UsersPage extends StatelessWidget {
const UsersPage({final super.key}); const UsersPage({final super.key});