Refactor FieldCubit creation for user forms
Move all cubit fields to a special factory which encapsulates all logic related to their default properties, which leaves possibility for future dependency inversion on that factory or future factories of other cubit fields (in case we will have to replace it with other implementations).pull/89/head
parent
4c99579f13
commit
4c7cf05578
|
@ -66,7 +66,6 @@ class ServerApi extends ApiMap {
|
|||
|
||||
Future<ApiResponse<User>> createUser(User user) async {
|
||||
var client = await getClient();
|
||||
// POST request with JSON body containing username and password
|
||||
|
||||
var makeErrorApiReponse = (int status) {
|
||||
return ApiResponse(
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||
|
||||
class FieldCubitFactory {
|
||||
FieldCubitFactory(this.context);
|
||||
|
||||
/* A common user login field.
|
||||
* - Available characters are lowercase a-z, digits and underscore _
|
||||
* - Must start with either a-z or underscore
|
||||
* - Must be no longer than 'userMaxLength' characters
|
||||
* - Must not be empty
|
||||
* - Must not be a reserved root login
|
||||
* - Must be unique
|
||||
*/
|
||||
FieldCubit<String> createUserLoginField() {
|
||||
final userAllowedRegExp = RegExp(r"^[a-z_][a-z0-9_]+$");
|
||||
const userMaxLength = 31;
|
||||
return FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
ValidationModel<String>(
|
||||
(s) => s.toLowerCase() == 'root', 'validations.root_name'.tr()),
|
||||
ValidationModel(
|
||||
(login) => context.read<UsersCubit>().state.isLoginRegistered(login),
|
||||
'validations.user_already_exist'.tr(),
|
||||
),
|
||||
RequiredStringValidation('validations.required'.tr()),
|
||||
LengthStringLongerValidation(userMaxLength),
|
||||
ValidationModel<String>((s) => !userAllowedRegExp.hasMatch(s),
|
||||
'validations.invalid_format'.tr()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/* A common user password field.
|
||||
* - Must fail on the regural expression of invalid matches: [\n\r\s]+
|
||||
* - Must not be empty
|
||||
*/
|
||||
FieldCubit<String> createUserPasswordField() {
|
||||
var passwordForbiddenRegExp = RegExp(r"[\n\r\s]+");
|
||||
return FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
RequiredStringValidation('validations.required'.tr()),
|
||||
ValidationModel<String>(
|
||||
(password) => passwordForbiddenRegExp.hasMatch(password),
|
||||
'validations.invalid_format'.tr()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
final BuildContext context;
|
||||
}
|
|
@ -2,33 +2,14 @@ import 'dart:async';
|
|||
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
||||
import 'package:selfprivacy/logic/models/user.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
||||
class RootUserFormCubit extends FormCubit {
|
||||
RootUserFormCubit(this.initializingCubit) {
|
||||
var userRegExp = RegExp(r"\W");
|
||||
var passwordRegExp = RegExp(r"[\n\r\s]+");
|
||||
|
||||
userName = FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
ValidationModel<String>(
|
||||
(s) => s.toLowerCase() == 'root', 'validations.root_name'.tr()),
|
||||
RequiredStringValidation('validations.required'.tr()),
|
||||
ValidationModel<String>(
|
||||
(s) => userRegExp.hasMatch(s), 'validations.invalid_format'.tr()),
|
||||
],
|
||||
);
|
||||
|
||||
password = FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
RequiredStringValidation('validations.required'.tr()),
|
||||
ValidationModel<String>((s) => passwordRegExp.hasMatch(s),
|
||||
'validations.invalid_format'.tr()),
|
||||
],
|
||||
);
|
||||
RootUserFormCubit(
|
||||
this.initializingCubit, final FieldCubitFactory fieldFactory) {
|
||||
userName = fieldFactory.createUserLoginField();
|
||||
password = fieldFactory.createUserPasswordField();
|
||||
|
||||
isVisible = FieldCubit(initalValue: false);
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/job.dart';
|
||||
import 'package:selfprivacy/logic/models/user.dart';
|
||||
|
@ -11,41 +10,16 @@ import 'package:selfprivacy/utils/password_generator.dart';
|
|||
class UserFormCubit extends FormCubit {
|
||||
UserFormCubit({
|
||||
required this.jobsCubit,
|
||||
required List<User> users,
|
||||
required FieldCubitFactory fieldFactory,
|
||||
User? user,
|
||||
}) {
|
||||
var isEdit = user != null;
|
||||
|
||||
var userAllowedRegExp = RegExp(r"^[a-z_][a-z0-9_]+$");
|
||||
const userMaxLength = 31;
|
||||
|
||||
var passwordForbiddenRegExp = RegExp(r"[\n\r\s]+");
|
||||
|
||||
login = FieldCubit(
|
||||
initalValue: isEdit ? user!.login : '',
|
||||
validations: [
|
||||
ValidationModel<String>(
|
||||
(s) => s.toLowerCase() == 'root', 'validations.root_name'.tr()),
|
||||
ValidationModel(
|
||||
(login) => users.any((user) => user.login == login),
|
||||
'validations.user_already_exist'.tr(),
|
||||
),
|
||||
RequiredStringValidation('validations.required'.tr()),
|
||||
LengthStringLongerValidation(userMaxLength),
|
||||
ValidationModel<String>((s) => !userAllowedRegExp.hasMatch(s),
|
||||
'validations.invalid_format'.tr()),
|
||||
],
|
||||
);
|
||||
|
||||
password = FieldCubit(
|
||||
initalValue:
|
||||
isEdit ? (user?.password ?? '') : StringGenerators.userPassword(),
|
||||
validations: [
|
||||
RequiredStringValidation('validations.required'.tr()),
|
||||
ValidationModel<String>((s) => passwordForbiddenRegExp.hasMatch(s),
|
||||
'validations.invalid_format'.tr()),
|
||||
],
|
||||
);
|
||||
login = fieldFactory.createUserLoginField();
|
||||
login.setValue(isEdit ? user!.login : '');
|
||||
password = fieldFactory.createUserPasswordField();
|
||||
password.setValue(
|
||||
isEdit ? (user?.password ?? '') : StringGenerators.userPassword());
|
||||
|
||||
super.addFields([login, password]);
|
||||
}
|
||||
|
|
|
@ -22,5 +22,11 @@ class UsersState extends AppConfigDependendState {
|
|||
);
|
||||
}
|
||||
|
||||
bool isLoginRegistered(String login) {
|
||||
return users.any((user) => user.login == login) ||
|
||||
login == rootUser.login ||
|
||||
login == primaryUser.login;
|
||||
}
|
||||
|
||||
bool get isEmpty => users.isEmpty;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/backblaze_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/cloudflare_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/domain_cloudflare.dart';
|
||||
|
@ -352,7 +353,8 @@ class InitializingPage extends StatelessWidget {
|
|||
|
||||
Widget _stepUser(AppConfigCubit initializingCubit) {
|
||||
return BlocProvider(
|
||||
create: (context) => RootUserFormCubit(initializingCubit),
|
||||
create: (context) =>
|
||||
RootUserFormCubit(initializingCubit, FieldCubitFactory(context)),
|
||||
child: Builder(builder: (context) {
|
||||
var formCubitState = context.watch<RootUserFormCubit>().state;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ class _NewUser extends StatelessWidget {
|
|||
}
|
||||
return UserFormCubit(
|
||||
jobsCubit: jobCubit,
|
||||
users: users,
|
||||
fieldFactory: FieldCubitFactory(context),
|
||||
);
|
||||
},
|
||||
child: Builder(builder: (context) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:selfprivacy/config/brand_colors.dart';
|
|||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/config/text_themes.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/user/user_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||
|
|
Loading…
Reference in New Issue