Skip to content

Commit

Permalink
authentication errors handled
Browse files Browse the repository at this point in the history
  • Loading branch information
fedecarroz committed Oct 3, 2024
1 parent d5b76f3 commit 53362af
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 38 deletions.
52 changes: 43 additions & 9 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 6 additions & 3 deletions lib/data/errors/authentication_errors.dart
Original file line number Diff line number Diff line change
@@ -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 {}

Expand Down
9 changes: 7 additions & 2 deletions lib/data/repo/authentication_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class AuthenticationRepository {
signOut();
switch (response.error.code) {
case 'user-not-found':
throw MissingUserDataError();
throw UserNotFoundError();
default:
throw UnknownAuthenticationError();
}
Expand Down Expand Up @@ -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();
}
Expand All @@ -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:
Expand Down
89 changes: 66 additions & 23 deletions lib/logic/cubit/authentication_cubit.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -53,9 +54,10 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
);

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,
Expand All @@ -67,31 +69,44 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {

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<void> checkIn(String authorizationCode) async {
Expand All @@ -108,11 +123,25 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
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,
),
);
}
Expand All @@ -132,23 +161,28 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
);

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,
),
);
} else {
emit(
state.copyWith(
userProfile: user,
userProfile: userProfile,
status: AuthenticationStatus.authenticationSuccess,
isAuthenticated: true,
),
Expand All @@ -161,18 +195,18 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
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 {
Expand All @@ -185,6 +219,15 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
}
}

void _checkSignInEmptyData(
String email,
String password,
) {
final check = email.isNotEmpty && password.isNotEmpty;

if (!check) throw InvalidDataError();
}

Future<void> signOut() async {
emit(state.copyWith(status: AuthenticationStatus.signOutInProgress));
await _authRepo.signOut();
Expand Down
4 changes: 3 additions & 1 deletion lib/logic/cubit/authentication_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ enum AuthenticationStatus {

enum AuthenticationError {
none,
userAlreadyRegistered,
checkInCodeNotFound,
checkInCodeExpired,
userNotFound,
invalidCredentials,
missingUserData,
unknown,
}

Expand Down
18 changes: 18 additions & 0 deletions lib/logic/input_validators.dart
Original file line number Diff line number Diff line change
@@ -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();
}
}

0 comments on commit 53362af

Please sign in to comment.