From d3aacbe74bda91841b74b8e25bd3586521dc3fa4 Mon Sep 17 00:00:00 2001 From: Zack Pollard Date: Mon, 29 Jul 2024 19:02:04 +0100 Subject: [PATCH] refactor: authentication provider always try network calls and only fail if 401 or no local user --- .../lib/pages/common/splash_screen.page.dart | 13 +-- .../providers/authentication.provider.dart | 98 +++++++++---------- 2 files changed, 53 insertions(+), 58 deletions(-) diff --git a/mobile/lib/pages/common/splash_screen.page.dart b/mobile/lib/pages/common/splash_screen.page.dart index 2de8bb4364..42bb081816 100644 --- a/mobile/lib/pages/common/splash_screen.page.dart +++ b/mobile/lib/pages/common/splash_screen.page.dart @@ -24,19 +24,17 @@ class SplashScreenPage extends HookConsumerWidget { final log = Logger("SplashScreenPage"); void performLoggingIn() async { - bool isSuccess = false; - bool deviceIsOffline = false; + bool isAuthSuccess = false; if (accessToken != null && serverUrl != null && endpoint != null) { apiService.setEndpoint(endpoint); try { - isSuccess = await ref + isAuthSuccess = await ref .read(authenticationProvider.notifier) .setSuccessLoginInfo( accessToken: accessToken, serverUrl: serverUrl, - offlineLogin: deviceIsOffline, ); } catch (error, stackTrace) { log.severe( @@ -46,14 +44,13 @@ class SplashScreenPage extends HookConsumerWidget { ); } } else { + isAuthSuccess = false; log.severe( - 'Missing authentication and server information from the local storage', + 'Missing authentication, server, or endpoint info from the local store', ); - - isSuccess = false; } - if (!isSuccess) { + if (!isAuthSuccess) { log.severe( 'Unable to login using offline or online methods - Logging out completely', ); diff --git a/mobile/lib/providers/authentication.provider.dart b/mobile/lib/providers/authentication.provider.dart index 3d98cb0e20..991ff4a50a 100644 --- a/mobile/lib/providers/authentication.provider.dart +++ b/mobile/lib/providers/authentication.provider.dart @@ -156,7 +156,6 @@ class AuthenticationNotifier extends StateNotifier { Future setSuccessLoginInfo({ required String accessToken, required String serverUrl, - bool offlineLogin = false, }) async { _apiService.setAccessToken(accessToken); @@ -165,57 +164,56 @@ class AuthenticationNotifier extends StateNotifier { Store.tryGet(StoreKey.deviceId) ?? await FlutterUdid.consistentUdid; bool shouldChangePassword = false; - User? user; + User? user = Store.tryGet(StoreKey.currentUser); - bool retResult = false; - User? offlineUser = Store.tryGet(StoreKey.currentUser); - - // If the user is offline and there is a user saved on the device, - // if not try an online login - if (offlineLogin && offlineUser != null) { - user = offlineUser; - retResult = false; - } else { - UserAdminResponseDto? userResponseDto; - UserPreferencesResponseDto? userPreferences; - try { - userResponseDto = await _apiService.usersApi.getMyUser(); - userPreferences = await _apiService.usersApi.getMyPreferences(); - } on ApiException catch (error, stackTrace) { - _log.severe( - "Error getting user information from the server [API EXCEPTION]", - error, - stackTrace, - ); - if (error.innerException is SocketException) { - state = state.copyWith(isAuthenticated: true); - } - } catch (error, stackTrace) { - _log.severe( - "Error getting user information from the server [CATCH ALL]", - error, - stackTrace, - ); - } - - if (userResponseDto != null) { - Store.put(StoreKey.deviceId, deviceId); - Store.put(StoreKey.deviceIdHash, fastHash(deviceId)); - Store.put( - StoreKey.currentUser, - User.fromUserDto(userResponseDto, userPreferences), - ); - Store.put(StoreKey.serverUrl, serverUrl); - Store.put(StoreKey.accessToken, accessToken); - - shouldChangePassword = userResponseDto.shouldChangePassword; - user = User.fromUserDto(userResponseDto, userPreferences); - - retResult = true; - } else { - _log.severe("Unable to get user information from the server."); + UserAdminResponseDto? userResponse; + UserPreferencesResponseDto? userPreferences; + try { + var responses = await Future.wait([ + _apiService.usersApi.getMyUser(), + _apiService.usersApi.getMyPreferences(), + ]); + userResponse = responses[0] as UserAdminResponseDto; + userPreferences = responses[1] as UserPreferencesResponseDto; + } on ApiException catch (error, stackTrace) { + if (error.code == 401) { + _log.severe("Unauthorized access, token likely expired. Logging out."); return false; } + _log.severe( + "Error getting user information from the server [API EXCEPTION]", + stackTrace, + ); + } catch (error, stackTrace) { + _log.severe( + "Error getting user information from the server [CATCH ALL]", + error, + stackTrace, + ); + } + + // If the user information is successfully retrieved, update the store + // Due to the flow of the code, this will always happen on first login + if (userResponse != null) { + Store.put(StoreKey.deviceId, deviceId); + Store.put(StoreKey.deviceIdHash, fastHash(deviceId)); + Store.put( + StoreKey.currentUser, + User.fromUserDto(userResponse, userPreferences), + ); + Store.put(StoreKey.serverUrl, serverUrl); + Store.put(StoreKey.accessToken, accessToken); + + shouldChangePassword = userResponse.shouldChangePassword; + user = User.fromUserDto(userResponse, userPreferences); + } else { + _log.severe("Unable to get user information from the server."); + } + + // If the user is null, the login was not successful + // and we don't have a local copy of the user from a prior successful login + if (user == null) { + return false; } state = state.copyWith( @@ -229,7 +227,7 @@ class AuthenticationNotifier extends StateNotifier { deviceId: deviceId, ); - return retResult; + return true; } }