diff --git a/lib/app.dart b/lib/app.dart index 1b8db99..ba5df67 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -93,27 +93,61 @@ void _authListener( break; case AuthenticationStatus.signUpFailure: context.loaderOverlay.hide(); - // TODO: implement error message + String errorMessage = ''; + switch (state.error) { + case AuthenticationError.userAlreadyRegistered: + errorMessage = + 'Email already registered.\nPlease use a different email or login.'; + break; + case AuthenticationError.invalidCredentials: + errorMessage = 'Invalid data entered.\nPlease try again.'; + break; + case AuthenticationError.unknown: + errorMessage = 'An unknown error occurred.\nPlease try again later.'; + break; + default: + break; + } + final ctx = appRouter.routerDelegate.navigatorKey.currentContext; + if (ctx != null) { + showAuthenticationErrorDialog(ctx, errorMessage); + } break; case AuthenticationStatus.checkInFailure: context.loaderOverlay.hide(); - // TODO: implement error message + String errorMessage = ''; + switch (state.error) { + case AuthenticationError.checkInCodeExpired: + errorMessage = + 'Check-in code has expired.\nPlease request a new code.'; + break; + case AuthenticationError.checkInCodeNotFound: + errorMessage = + 'Check-in code not found.\nPlease verify and scan again.'; + break; + case AuthenticationError.unknown: + errorMessage = 'An unknown error occurred.\nPlease try again later.'; + break; + default: + break; + } + final ctx = appRouter.routerDelegate.navigatorKey.currentContext; + if (ctx != null) { + showAuthenticationErrorDialog(ctx, errorMessage); + } break; case AuthenticationStatus.authenticationFailure: context.loaderOverlay.hide(); String errorMessage = ''; switch (state.error) { - case AuthenticationError.invalidCredentials: - errorMessage = 'Invalid credentials'; - break; case AuthenticationError.userNotFound: - errorMessage = 'User not found'; + errorMessage = 'Email not registered.\nPlease try again.'; break; - case AuthenticationError.missingUserData: - errorMessage = 'Missing user data'; + case AuthenticationError.invalidCredentials: + errorMessage = 'Invalid data entered.\nPlease try again.'; break; case AuthenticationError.unknown: - errorMessage = 'Unknown error'; + errorMessage = 'An unknown error occurred.\nPlease try again later.'; break; default: break; diff --git a/lib/data/errors/authentication_errors.dart b/lib/data/errors/authentication_errors.dart index 055fae7..f312484 100644 --- a/lib/data/errors/authentication_errors.dart +++ b/lib/data/errors/authentication_errors.dart @@ -1,12 +1,15 @@ /// Exception that occurs when the user is already registered class UserAlreadyRegisteredError implements Exception {} +/// Exception that occurs when the user scan an invalid check-in code +class CheckInCodeNotFoundError implements Exception {} + +/// Exception that occurs when the user scan an expired check-in code +class CheckInCodeExpiredError implements Exception {} + /// Exception that occurs when the credentials does not match anything on Firebase Auth class InvalidCredentialsError implements Exception {} -/// Exception that occurs when the user data are missing -class MissingUserDataError implements Exception {} - /// Exception that occurs when a request is made without authentication class UnauthenticatedError implements Exception {} diff --git a/lib/data/repo/authentication_repository.dart b/lib/data/repo/authentication_repository.dart index dfc951c..fd7adb4 100644 --- a/lib/data/repo/authentication_repository.dart +++ b/lib/data/repo/authentication_repository.dart @@ -27,7 +27,7 @@ class AuthenticationRepository { signOut(); switch (response.error.code) { case 'user-not-found': - throw MissingUserDataError(); + throw UserNotFoundError(); default: throw UnknownAuthenticationError(); } @@ -66,7 +66,10 @@ class AuthenticationRepository { if (response.error.code.isNotEmpty) { switch (response.error.code) { - // TODO: handle errors + case 'code-not-found': + throw CheckInCodeNotFoundError(); + case 'code-expired': + throw CheckInCodeExpiredError(); default: throw UnknownAuthenticationError(); } @@ -91,7 +94,9 @@ class AuthenticationRepository { switch (e.code) { case 'user-not-found': throw UserNotFoundError(); + case 'invalid-credential': case 'invalid-email': + case 'invalid-password': case 'wrong-password': throw InvalidCredentialsError(); default: diff --git a/lib/logic/cubit/authentication_cubit.dart b/lib/logic/cubit/authentication_cubit.dart index c8c4fec..f1c0884 100644 --- a/lib/logic/cubit/authentication_cubit.dart +++ b/lib/logic/cubit/authentication_cubit.dart @@ -1,5 +1,6 @@ import 'package:bloc/bloc.dart'; import 'package:devfest_bari_2024/data.dart'; +import 'package:devfest_bari_2024/logic.dart'; import 'package:equatable/equatable.dart'; part 'authentication_state.dart'; @@ -53,9 +54,10 @@ class AuthenticationCubit extends Cubit { ); try { - _checkEmptyData(name, surname, email, password); + _checkSignUpEmptyData(nickname, name, surname, email, password); - _checkEmail(email); + InputValidators.checkEmail(email); + InputValidators.checkPassword(password); await _authRepo.signUp( nickname: nickname, @@ -67,31 +69,44 @@ class AuthenticationCubit extends Cubit { emit(state.copyWith(status: AuthenticationStatus.signUpSuccess)); signInWithEmailAndPassword(email: email, password: password); + } on UserAlreadyRegisteredError { + emit( + state.copyWith( + status: AuthenticationStatus.signUpFailure, + error: AuthenticationError.userAlreadyRegistered, + ), + ); + } on InvalidDataError { + emit( + state.copyWith( + status: AuthenticationStatus.signUpFailure, + error: AuthenticationError.invalidCredentials, + ), + ); } on Exception { - emit(state.copyWith(status: AuthenticationStatus.signUpFailure)); + emit( + state.copyWith( + status: AuthenticationStatus.signUpFailure, + error: AuthenticationError.unknown, + ), + ); } } - void _checkEmptyData( + void _checkSignUpEmptyData( + String nickname, String name, String surname, String email, String password, ) { - final check = name.isNotEmpty && + final check = nickname.isNotEmpty && + name.isNotEmpty && surname.isNotEmpty && email.isNotEmpty && password.isNotEmpty; - if (!check) throw Exception(); - } - - void _checkEmail(String email) { - var check = RegExp( - r"^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$", - ).hasMatch(email); - - if (!check) throw Exception(); + if (!check) throw InvalidDataError(); } Future checkIn(String authorizationCode) async { @@ -108,11 +123,25 @@ class AuthenticationCubit extends Cubit { status: AuthenticationStatus.checkInSuccess, ), ); - } on Exception catch (e) { - print(e); + } on CheckInCodeNotFoundError { + emit( + state.copyWith( + status: AuthenticationStatus.checkInFailure, + error: AuthenticationError.checkInCodeNotFound, + ), + ); + } on CheckInCodeExpiredError { emit( state.copyWith( status: AuthenticationStatus.checkInFailure, + error: AuthenticationError.checkInCodeExpired, + ), + ); + } on Exception { + emit( + state.copyWith( + status: AuthenticationStatus.checkInFailure, + error: AuthenticationError.unknown, ), ); } @@ -132,15 +161,20 @@ class AuthenticationCubit extends Cubit { ); try { - final user = await _authRepo.signInWithEmailAndPassword( + _checkSignInEmptyData(email, password); + + InputValidators.checkEmail(email); + InputValidators.checkPassword(password); + + final userProfile = await _authRepo.signInWithEmailAndPassword( email: email, password: password, ); - if (user.group.groupId.isEmpty) { + if (userProfile.group.groupId.isEmpty) { emit( state.copyWith( - userProfile: user, + userProfile: userProfile, status: AuthenticationStatus.checkInRequired, isAuthenticated: true, ), @@ -148,7 +182,7 @@ class AuthenticationCubit extends Cubit { } else { emit( state.copyWith( - userProfile: user, + userProfile: userProfile, status: AuthenticationStatus.authenticationSuccess, isAuthenticated: true, ), @@ -161,18 +195,18 @@ class AuthenticationCubit extends Cubit { error: AuthenticationError.userNotFound, ), ); - } on InvalidCredentialsError { + } on InvalidDataError { emit( state.copyWith( status: AuthenticationStatus.authenticationFailure, error: AuthenticationError.invalidCredentials, ), ); - } on MissingUserDataError { + } on InvalidCredentialsError { emit( state.copyWith( status: AuthenticationStatus.authenticationFailure, - error: AuthenticationError.missingUserData, + error: AuthenticationError.invalidCredentials, ), ); } on Exception { @@ -185,6 +219,15 @@ class AuthenticationCubit extends Cubit { } } + void _checkSignInEmptyData( + String email, + String password, + ) { + final check = email.isNotEmpty && password.isNotEmpty; + + if (!check) throw InvalidDataError(); + } + Future signOut() async { emit(state.copyWith(status: AuthenticationStatus.signOutInProgress)); await _authRepo.signOut(); diff --git a/lib/logic/cubit/authentication_state.dart b/lib/logic/cubit/authentication_state.dart index 6adeacd..d72c83a 100644 --- a/lib/logic/cubit/authentication_state.dart +++ b/lib/logic/cubit/authentication_state.dart @@ -19,9 +19,11 @@ enum AuthenticationStatus { enum AuthenticationError { none, + userAlreadyRegistered, + checkInCodeNotFound, + checkInCodeExpired, userNotFound, invalidCredentials, - missingUserData, unknown, } diff --git a/lib/logic/input_validators.dart b/lib/logic/input_validators.dart new file mode 100644 index 0000000..50a11ca --- /dev/null +++ b/lib/logic/input_validators.dart @@ -0,0 +1,18 @@ +/// Exception that occurs when the user enter invalid data into the form +class InvalidDataError implements Exception {} + +class InputValidators { + static void checkEmail(String email) { + final check = RegExp( + r"^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$", + ).hasMatch(email); + + if (email.isEmpty || !check) throw InvalidDataError(); + } + + static void checkPassword(String password) { + final check = password.length > 7; + + if (!check) throw InvalidDataError(); + } +}