1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2024-12-28 22:51:59 +00:00

fix(mobile): ios random logout (#8997)

* fix(mobile): random logout

* move logout mechanism to the end

* More logs

* wording

* more logs

* fixed

* Better check
This commit is contained in:
Alex 2024-04-23 16:09:10 -05:00 committed by GitHub
parent 70c78a09a4
commit 48b0b7e8bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 70 additions and 25 deletions

View file

@ -155,7 +155,7 @@ SPEC CHECKSUMS:
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
flutter_udid: a2482c67a61b9c806ef59dd82ed8d007f1b7ac04
flutter_web_auth: c25208760459cec375a3c39f6a8759165ca0fa4d
fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c
fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
geolocator_apple: 9157311f654584b9bb72686c55fc02a97b73f461
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
@ -180,4 +180,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 64c9b5291666c0ca3caabdfe9865c141ac40321d
COCOAPODS: 1.12.1
COCOAPODS: 1.15.2

View file

@ -181,10 +181,21 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
UserResponseDto? userResponseDto;
try {
userResponseDto = await _apiService.userApi.getMyUserInfo();
} on ApiException catch (e) {
if (e.innerException is SocketException) {
} 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) {

View file

@ -3,6 +3,7 @@ import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/modules/login/providers/oauth.provider.dart';
@ -86,6 +87,7 @@ class LoginForm extends HookConsumerWidget {
context: context,
msg: e.message ?? 'login_form_api_exception'.tr(),
toastType: ToastType.error,
gravity: ToastGravity.TOP,
);
isOauthEnable.value = false;
isPasswordLoginEnable.value = true;
@ -96,6 +98,7 @@ class LoginForm extends HookConsumerWidget {
context: context,
msg: 'login_form_handshake_exception'.tr(),
toastType: ToastType.error,
gravity: ToastGravity.TOP,
);
isOauthEnable.value = false;
isPasswordLoginEnable.value = true;
@ -106,6 +109,7 @@ class LoginForm extends HookConsumerWidget {
context: context,
msg: 'login_form_server_error'.tr(),
toastType: ToastType.error,
gravity: ToastGravity.TOP,
);
isOauthEnable.value = false;
isPasswordLoginEnable.value = true;
@ -174,6 +178,7 @@ class LoginForm extends HookConsumerWidget {
context: context,
msg: "login_form_failed_login".tr(),
toastType: ToastType.error,
gravity: ToastGravity.TOP,
);
}
} finally {
@ -197,6 +202,7 @@ class LoginForm extends HookConsumerWidget {
context: context,
msg: "login_form_failed_get_oauth_server_config".tr(),
toastType: ToastType.error,
gravity: ToastGravity.TOP,
);
isLoading.value = false;
return;
@ -225,6 +231,7 @@ class LoginForm extends HookConsumerWidget {
context: context,
msg: "login_form_failed_login".tr(),
toastType: ToastType.error,
gravity: ToastGravity.TOP,
);
}
}
@ -235,6 +242,7 @@ class LoginForm extends HookConsumerWidget {
context: context,
msg: "login_form_failed_get_oauth_server_disable".tr(),
toastType: ToastType.info,
gravity: ToastGravity.TOP,
);
isLoading.value = false;
return;

View file

@ -7,6 +7,7 @@ import 'package:immich_mobile/shared/services/server_info.service.dart';
import 'package:immich_mobile/shared/models/server_info/server_config.model.dart';
import 'package:immich_mobile/shared/models/server_info/server_features.model.dart';
import 'package:immich_mobile/shared/models/server_info/server_version.model.dart';
import 'package:logging/logging.dart';
import 'package:package_info_plus/package_info_plus.dart';
class ServerInfoNotifier extends StateNotifier<ServerInfo> {
@ -47,6 +48,7 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
);
final ServerInfoService _serverInfoService;
final _log = Logger("ServerInfoNotifier");
Future<void> getServerInfo() async {
await getServerVersion();
@ -55,17 +57,25 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
}
getServerVersion() async {
final serverVersion = await _serverInfoService.getServerVersion();
try {
final serverVersion = await _serverInfoService.getServerVersion();
if (serverVersion == null) {
if (serverVersion == null) {
state = state.copyWith(
isVersionMismatch: true,
versionMismatchErrorMessage: "common_server_error".tr(),
);
return;
}
await _checkServerVersionMismatch(serverVersion);
} catch (e, stackTrace) {
_log.severe("Failed to get server version", e, stackTrace);
state = state.copyWith(
isVersionMismatch: true,
versionMismatchErrorMessage: "common_server_error".tr(),
);
return;
}
await _checkServerVersionMismatch(serverVersion);
}
_checkServerVersionMismatch(ServerVersion serverVersion) async {

View file

@ -5,6 +5,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/utils/url_helper.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart';
import 'package:http/http.dart';
@ -34,6 +35,7 @@ class ApiService {
}
}
String? _accessToken;
final _log = Logger("ApiService");
setEndpoint(String endpoint) {
_apiClient = ApiClient(basePath: endpoint);
@ -95,14 +97,17 @@ class ApiService {
serverUrl += '/api';
}
// Throw Socket or Timeout exceptions,
// we do not care if the endpoints hits an HTTP error
try {
await client
.get(
Uri.parse(serverUrl),
)
final response = await client
.get(Uri.parse("$serverUrl/server-info/ping"))
.timeout(const Duration(seconds: 5));
if (response.statusCode != 200) {
_log.severe(
"Server Gateway Error: ${response.body} - Cannot communicate to the server",
);
return false;
}
} on TimeoutException catch (_) {
return false;
} on SocketException catch (_) {

View file

@ -25,20 +25,30 @@ class SplashScreenPage extends HookConsumerWidget {
void performLoggingIn() async {
bool isSuccess = false;
bool deviceIsOffline = false;
if (accessToken != null && serverUrl != null) {
try {
// Resolve API server endpoint from user provided serverUrl
await apiService.resolveAndSetEndpoint(serverUrl);
} on ApiException catch (e) {
} on ApiException catch (error, stackTrace) {
log.severe(
"Failed to resolve endpoint [ApiException]",
error,
stackTrace,
);
// okay, try to continue anyway if offline
if (e.code == 503) {
if (error.code == 503) {
deviceIsOffline = true;
log.fine("Device seems to be offline upon launch");
log.warning("Device seems to be offline upon launch");
} else {
log.severe("Failed to resolve endpoint", e);
log.severe("Failed to resolve endpoint", error);
}
} catch (e) {
log.severe("Failed to resolve endpoint", e);
} catch (error, stackTrace) {
log.severe(
"Failed to resolve endpoint [Catch All]",
error,
stackTrace,
);
}
try {
@ -50,15 +60,11 @@ class SplashScreenPage extends HookConsumerWidget {
offlineLogin: deviceIsOffline,
);
} catch (error, stackTrace) {
ref.read(authenticationProvider.notifier).logout();
log.severe(
'Cannot set success login info',
error,
stackTrace,
);
context.pushRoute(const LoginRoute());
}
}
@ -76,6 +82,11 @@ class SplashScreenPage extends HookConsumerWidget {
}
context.replaceRoute(const TabControllerRoute());
} else {
log.severe(
'Unable to login through offline or online methods - logging out completely',
);
ref.read(authenticationProvider.notifier).logout();
// User was unable to login through either offline or online methods
context.replaceRoute(const LoginRoute());
}