diff --git a/lib/logic/api_maps/server.dart b/lib/logic/api_maps/server.dart index 1d2c3bce..6302611e 100644 --- a/lib/logic/api_maps/server.dart +++ b/lib/logic/api_maps/server.dart @@ -66,7 +66,6 @@ class ServerApi extends ApiMap { Future> createUser(User user) async { var client = await getClient(); - // POST request with JSON body containing username and password var makeErrorApiReponse = (int status) { return ApiResponse( diff --git a/lib/logic/cubit/forms/factories/field_cubit_factory.dart b/lib/logic/cubit/forms/factories/field_cubit_factory.dart new file mode 100644 index 00000000..c1b8abe7 --- /dev/null +++ b/lib/logic/cubit/forms/factories/field_cubit_factory.dart @@ -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 createUserLoginField() { + final userAllowedRegExp = RegExp(r"^[a-z_][a-z0-9_]+$"); + const userMaxLength = 31; + return FieldCubit( + initalValue: '', + validations: [ + ValidationModel( + (s) => s.toLowerCase() == 'root', 'validations.root_name'.tr()), + ValidationModel( + (login) => context.read().state.isLoginRegistered(login), + 'validations.user_already_exist'.tr(), + ), + RequiredStringValidation('validations.required'.tr()), + LengthStringLongerValidation(userMaxLength), + ValidationModel((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 createUserPasswordField() { + var passwordForbiddenRegExp = RegExp(r"[\n\r\s]+"); + return FieldCubit( + initalValue: '', + validations: [ + RequiredStringValidation('validations.required'.tr()), + ValidationModel( + (password) => passwordForbiddenRegExp.hasMatch(password), + 'validations.invalid_format'.tr()), + ], + ); + } + + final BuildContext context; +} diff --git a/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart b/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart index 41b26582..102d7ac7 100644 --- a/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart @@ -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( - (s) => s.toLowerCase() == 'root', 'validations.root_name'.tr()), - RequiredStringValidation('validations.required'.tr()), - ValidationModel( - (s) => userRegExp.hasMatch(s), 'validations.invalid_format'.tr()), - ], - ); - - password = FieldCubit( - initalValue: '', - validations: [ - RequiredStringValidation('validations.required'.tr()), - ValidationModel((s) => passwordRegExp.hasMatch(s), - 'validations.invalid_format'.tr()), - ], - ); + RootUserFormCubit( + this.initializingCubit, final FieldCubitFactory fieldFactory) { + userName = fieldFactory.createUserLoginField(); + password = fieldFactory.createUserPasswordField(); isVisible = FieldCubit(initalValue: false); diff --git a/lib/logic/cubit/forms/user/user_form_cubit.dart b/lib/logic/cubit/forms/user/user_form_cubit.dart index 4f0e6488..b65cfb47 100644 --- a/lib/logic/cubit/forms/user/user_form_cubit.dart +++ b/lib/logic/cubit/forms/user/user_form_cubit.dart @@ -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 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( - (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((s) => !userAllowedRegExp.hasMatch(s), - 'validations.invalid_format'.tr()), - ], - ); - - password = FieldCubit( - initalValue: - isEdit ? (user?.password ?? '') : StringGenerators.userPassword(), - validations: [ - RequiredStringValidation('validations.required'.tr()), - ValidationModel((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]); } diff --git a/lib/logic/cubit/users/users_state.dart b/lib/logic/cubit/users/users_state.dart index 1ee1903f..d15789c9 100644 --- a/lib/logic/cubit/users/users_state.dart +++ b/lib/logic/cubit/users/users_state.dart @@ -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; } diff --git a/lib/ui/pages/initializing/initializing.dart b/lib/ui/pages/initializing/initializing.dart index 95ba575c..d30569ca 100644 --- a/lib/ui/pages/initializing/initializing.dart +++ b/lib/ui/pages/initializing/initializing.dart @@ -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().state; diff --git a/lib/ui/pages/users/new_user.dart b/lib/ui/pages/users/new_user.dart index 4f6da178..58559c8f 100644 --- a/lib/ui/pages/users/new_user.dart +++ b/lib/ui/pages/users/new_user.dart @@ -24,7 +24,7 @@ class _NewUser extends StatelessWidget { } return UserFormCubit( jobsCubit: jobCubit, - users: users, + fieldFactory: FieldCubitFactory(context), ); }, child: Builder(builder: (context) { diff --git a/lib/ui/pages/users/users.dart b/lib/ui/pages/users/users.dart index 72c519a0..013f65b0 100644 --- a/lib/ui/pages/users/users.dart +++ b/lib/ui/pages/users/users.dart @@ -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';