diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart
index aa1ed36a..bbfc22e8 100644
--- a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart
+++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart
@@ -20,4 +20,6 @@ abstract class AuthFormField {
static const email = 'wyattEmailField';
/// Password field: `wyattPasswordField`
static const password = 'wyattPasswordField';
+ /// Confirm Password field: `wyattConfirmPasswordField`
+ static const confirmPassword = 'wyattConfirmPasswordField';
}
diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart
index 3eca89e0..16f58cf0 100644
--- a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart
+++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart
@@ -22,4 +22,6 @@ abstract class AuthFormName {
static const String signInForm = 'wyattSignInForm';
/// Password reset form: `wyattPasswordResetForm`
static const String passwordResetForm = 'wyattPasswordResetForm';
+ /// Edit account form: `wyattEditAccountForm`
+ static const String editAccountForm = 'wyattEditAccountForm';
}
diff --git a/packages/wyatt_authentication_bloc/lib/src/core/utils/forms.dart b/packages/wyatt_authentication_bloc/lib/src/core/utils/forms.dart
new file mode 100644
index 00000000..f8f8bf17
--- /dev/null
+++ b/packages/wyatt_authentication_bloc/lib/src/core/utils/forms.dart
@@ -0,0 +1,96 @@
+// Copyright (C) 2023 WYATT GROUP
+// Please see the AUTHORS file for details.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
+import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
+
+abstract class Forms {
+ static WyattForm buildSignInForm(
+ FormInputValidator? customEmailValidator,
+ FormInputValidator? customPasswordValidator,
+ ) =>
+ WyattFormImpl(
+ [
+ FormInput(
+ AuthFormField.email,
+ customEmailValidator ?? const Email.pure(),
+ ),
+ FormInput(
+ AuthFormField.password,
+ customPasswordValidator ?? const Password.pure(),
+ )
+ ],
+ name: AuthFormName.signInForm,
+ );
+
+ static WyattForm buildSignUpForm(
+ FormInputValidator? customEmailValidator,
+ FormInputValidator? customPasswordValidator,
+ // ignore: strict_raw_type
+ List? extraSignUpInputs,
+ ) =>
+ WyattFormImpl(
+ [
+ FormInput(
+ AuthFormField.email,
+ customEmailValidator ?? const Email.pure(),
+ ),
+ FormInput(
+ AuthFormField.password,
+ customPasswordValidator ?? const Password.pure(),
+ ),
+ ...extraSignUpInputs ?? []
+ ],
+ name: AuthFormName.signUpForm,
+ );
+
+ static WyattForm buildPasswordResetForm(
+ FormInputValidator? customEmailValidator,
+ ) =>
+ WyattFormImpl(
+ [
+ FormInput(
+ AuthFormField.email,
+ customEmailValidator ?? const Email.pure(),
+ ),
+ ],
+ name: AuthFormName.passwordResetForm,
+ );
+
+ static WyattForm buildEditAccountForm(
+ FormInputValidator? customEmailValidator,
+ FormInputValidator? customPasswordValidator,
+ // ignore: strict_raw_type
+ List? extraEditAccountInputs,
+ ) =>
+ WyattFormImpl(
+ [
+ FormInput(
+ AuthFormField.email,
+ customEmailValidator ?? const Email.pure(),
+ metadata: const FormInputMetadata(isRequired: false),
+ ),
+ FormInput(
+ AuthFormField.password,
+ customPasswordValidator ?? const Password.pure(),
+ metadata: const FormInputMetadata(isRequired: false),
+ ),
+ ...extraEditAccountInputs ?? []
+ ],
+ validationStrategy: const OnlyRequiredInputValidator(),
+ name: AuthFormName.editAccountForm,
+ );
+}
diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart
index 2d75d36a..b2c9d4f2 100644
--- a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart
+++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart
@@ -254,7 +254,11 @@ class AuthenticationFirebaseDataSourceImpl
Future updateEmail({required String email}) async {
try {
await _firebaseAuth.currentUser!.updateEmail(email);
- final account = AccountModel.fromFirebaseUser(_firebaseAuth.currentUser);
+ final jwt = await _firebaseAuth.currentUser!.getIdToken(true);
+ final account = AccountModel.fromFirebaseUser(
+ _firebaseAuth.currentUser,
+ accessToken: jwt,
+ );
return account;
} on FirebaseAuthException catch (e) {
@@ -269,7 +273,11 @@ class AuthenticationFirebaseDataSourceImpl
Future updatePassword({required String password}) async {
try {
await _firebaseAuth.currentUser!.updatePassword(password);
- final account = AccountModel.fromFirebaseUser(_firebaseAuth.currentUser);
+ final jwt = await _firebaseAuth.currentUser!.getIdToken(true);
+ final account = AccountModel.fromFirebaseUser(
+ _firebaseAuth.currentUser,
+ accessToken: jwt,
+ );
return account;
} on FirebaseAuthException catch (e) {
diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart
index 2c25e1bc..4d3a3f4e 100644
--- a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart
+++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart
@@ -15,8 +15,7 @@
// along with this program. If not, see .
import 'package:wyatt_architecture/wyatt_architecture.dart';
-import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart';
-import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart';
+import 'package:wyatt_authentication_bloc/src/core/utils/forms.dart';
import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart';
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
import 'package:wyatt_authentication_bloc/src/domain/entities/session_wrapper.dart';
@@ -31,6 +30,8 @@ class AuthenticationRepositoryImpl
FormRepository? formRepository,
// ignore: strict_raw_type
List? extraSignUpInputs,
+ // ignore: strict_raw_type
+ List? extraEditAccountInputs,
FormInputValidator? customEmailValidator,
FormInputValidator? customPasswordValidator,
}) {
@@ -41,45 +42,26 @@ class AuthenticationRepositoryImpl
}
_formRepository
..registerForm(
- WyattFormImpl(
- [
- FormInput(
- AuthFormField.email,
- customEmailValidator ?? const Email.pure(),
- ),
- FormInput(
- AuthFormField.password,
- customPasswordValidator ?? const Password.pure(),
- )
- ],
- name: AuthFormName.signInForm,
+ Forms.buildSignUpForm(
+ customEmailValidator,
+ customPasswordValidator,
+ extraSignUpInputs,
),
)
..registerForm(
- WyattFormImpl(
- [
- FormInput(
- AuthFormField.email,
- customEmailValidator ?? const Email.pure(),
- ),
- FormInput(
- AuthFormField.password,
- customPasswordValidator ?? const Password.pure(),
- ),
- ...extraSignUpInputs ?? []
- ],
- name: AuthFormName.signUpForm,
+ Forms.buildSignInForm(
+ customEmailValidator,
+ customPasswordValidator,
),
)
..registerForm(
- WyattFormImpl(
- [
- FormInput(
- AuthFormField.email,
- customEmailValidator ?? const Email.pure(),
- ),
- ],
- name: AuthFormName.passwordResetForm,
+ Forms.buildPasswordResetForm(customEmailValidator),
+ )
+ ..registerForm(
+ Forms.buildEditAccountForm(
+ customEmailValidator,
+ customPasswordValidator,
+ extraEditAccountInputs,
),
);
}
diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/base_edit_account_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/base_edit_account_cubit.dart
new file mode 100644
index 00000000..3d6ba12d
--- /dev/null
+++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/base_edit_account_cubit.dart
@@ -0,0 +1,100 @@
+// Copyright (C) 2023 WYATT GROUP
+// Please see the AUTHORS file for details.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+part of 'edit_account_cubit.dart';
+
+/// Abstract edit account cubit useful for implementing a cubit with fine
+/// granularity by adding only the required mixins.
+abstract class BaseEditAccountCubit
+ extends FormDataCubit {
+ BaseEditAccountCubit({
+ required this.authenticationRepository,
+ }) : super(
+ EditAccountState(
+ form: authenticationRepository.formRepository
+ .accessForm(AuthFormName.signInForm),
+ ),
+ );
+ final AuthenticationRepository authenticationRepository;
+ FormRepository get formRepository => authenticationRepository.formRepository;
+
+ @override
+ String get formName => AuthFormName.signInForm;
+
+ @override
+ FutureOr dataChanged(
+ String key,
+ FormInputValidator dirtyValue,
+ ) {
+ final form = formRepository.accessForm(formName).clone();
+
+ try {
+ form.updateValidator(key, dirtyValue);
+ formRepository.updateForm(form);
+ } catch (e) {
+ rethrow;
+ }
+
+ emit(
+ EditAccountState(form: form, status: form.validate()),
+ );
+ }
+
+ @override
+ FutureOr reset() {
+ final form = state.form.reset();
+ formRepository.updateForm(form);
+ emit(
+ EditAccountState(form: form, status: form.validate()),
+ );
+ }
+
+ @override
+ FutureOr update(
+ WyattForm form, {
+ SetOperation operation = SetOperation.replace,
+ }) {
+ final WyattForm current = formRepository.accessForm(formName).clone();
+ final WyattForm newForm = operation.operation.call(current, form);
+ formRepository.updateForm(newForm);
+
+ emit(
+ EditAccountState(form: newForm, status: newForm.validate()),
+ );
+ }
+
+ @override
+ FutureOr validate() {
+ final WyattForm form = formRepository.accessForm(formName);
+ emit(
+ EditAccountState(form: form, status: form.validate()),
+ );
+ }
+
+ @override
+ FutureOr submit() async {
+ final WyattForm form = formRepository.accessForm(formName);
+ const error = '`submit()` is not implemented for BaseEditAccountCubit, '
+ 'please use `updateEmail()` or `updatePassword()`.';
+ emit(
+ EditAccountState(
+ form: form,
+ errorMessage: error,
+ status: FormStatus.submissionFailure,
+ ),
+ );
+ }
+}
diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_cubit.dart
new file mode 100644
index 00000000..b3fcc2b2
--- /dev/null
+++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_cubit.dart
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 WYATT GROUP
+// Please see the AUTHORS file for details.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+import 'dart:async';
+
+import 'package:wyatt_architecture/wyatt_architecture.dart';
+import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart';
+import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart';
+import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
+import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart';
+import 'package:wyatt_authentication_bloc/src/features/edit_account/edit_account.dart';
+import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
+import 'package:wyatt_type_utils/wyatt_type_utils.dart';
+
+part 'base_edit_account_cubit.dart';
+part 'edit_account_state.dart';
+
+/// Fully featured edit account cubit.
+///
+/// Sufficient in most cases. (Where fine granularity is not required.)
+class EditAccountCubit extends BaseEditAccountCubit
+ with UpdateEmail, UpdatePassword {
+ EditAccountCubit({required super.authenticationRepository});
+
+ @override
+ FutureOrResult onEmailUpdated(
+ Result result,
+ WyattForm form,
+ ) =>
+ const Ok(null);
+
+ @override
+ FutureOrResult onPasswordUpdated(
+ Result result,
+ WyattForm form,
+ ) =>
+ const Ok(null);
+}
diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_state.dart
new file mode 100644
index 00000000..0c8fbfba
--- /dev/null
+++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_state.dart
@@ -0,0 +1,48 @@
+// Copyright (C) 2023 WYATT GROUP
+// Please see the AUTHORS file for details.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+part of 'edit_account_cubit.dart';
+
+/// Edit account cubit state to manage the form.
+class EditAccountState extends FormDataState {
+ const EditAccountState({
+ required super.form,
+ super.status = FormStatus.pure,
+ super.errorMessage,
+ });
+ FormInputValidator get email =>
+ form.validatorOf(AuthFormField.email);
+ FormInputValidator get password =>
+ form.validatorOf(AuthFormField.password);
+
+ EditAccountState copyWith({
+ WyattForm? form,
+ FormStatus? status,
+ String? errorMessage,
+ }) =>
+ EditAccountState(
+ form: form ?? this.form,
+ status: status ?? this.status,
+ errorMessage: errorMessage ?? this.errorMessage,
+ );
+
+ @override
+ List