Implement user password reset

pull/116/head
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": "Перезагрузить сервер",
"create_ssh_key": "Создать SSH ключ для {}",
"delete_ssh_key": "Удалить SSH ключ для {}",
"server_jobs": "Задачи на сервере"
"server_jobs": "Задачи на сервере",
"resetUserPassword": "Сбросить пароль пользователя"
},
"validations": {
"required": "Обязательное поле.",

View File

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

View File

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

View File

@ -31,6 +31,17 @@ class CreateUserJob extends ClientJob {
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 {
DeleteUserJob({
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),
ListTile(
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),
title: Text(
'users.reset_password'.tr(),

View File

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