feat(mobile): Auto switching server URLs (#14437)

This commit is contained in:
Alex 2024-12-05 09:11:48 -06:00 committed by GitHub
parent 3c38851d50
commit 055f1fc72f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 1828 additions and 108 deletions

View file

@ -1,19 +1,26 @@
import 'dart:async';
import 'dart:io';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/interfaces/auth.interface.dart';
import 'package:immich_mobile/interfaces/auth_api.interface.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/models/auth/login_response.model.dart';
import 'package:immich_mobile/providers/api.provider.dart';
import 'package:immich_mobile/repositories/auth.repository.dart';
import 'package:immich_mobile/repositories/auth_api.repository.dart';
import 'package:immich_mobile/services/api.service.dart';
import 'package:immich_mobile/services/network.service.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart';
final authServiceProvider = Provider(
(ref) => AuthService(
ref.watch(authApiRepositoryProvider),
ref.watch(authRepositoryProvider),
ref.watch(apiServiceProvider),
ref.watch(networkServiceProvider),
),
);
@ -21,6 +28,7 @@ class AuthService {
final IAuthApiRepository _authApiRepository;
final IAuthRepository _authRepository;
final ApiService _apiService;
final NetworkService _networkService;
final _log = Logger("AuthService");
@ -28,6 +36,7 @@ class AuthService {
this._authApiRepository,
this._authRepository,
this._apiService,
this._networkService,
);
/// Validates the provided server URL by resolving and setting the endpoint.
@ -46,6 +55,28 @@ class AuthService {
return validUrl;
}
Future<bool> validateAuxilaryServerUrl(String url) async {
final httpclient = HttpClient();
final accessToken = _authRepository.getAccessToken();
bool isValid = false;
try {
final uri = Uri.parse('$url/users/me');
final request = await httpclient.getUrl(uri);
request.headers.add('x-immich-user-token', accessToken);
final response = await request.close();
if (response.statusCode == 200) {
isValid = true;
}
} catch (error) {
_log.severe("Error validating auxilary endpoint", error);
} finally {
httpclient.close();
}
return isValid;
}
Future<LoginResponse> login(String email, String password) {
return _authApiRepository.login(email, password);
}
@ -84,6 +115,10 @@ class AuthService {
Store.delete(StoreKey.currentUser),
Store.delete(StoreKey.accessToken),
Store.delete(StoreKey.assetETag),
Store.delete(StoreKey.autoEndpointSwitching),
Store.delete(StoreKey.preferredWifiName),
Store.delete(StoreKey.localEndpoint),
Store.delete(StoreKey.externalEndpointList),
]);
}
@ -95,4 +130,62 @@ class AuthService {
rethrow;
}
}
Future<String?> setOpenApiServiceEndpoint() async {
final enable = _authRepository.getEndpointSwitchingFeature();
if (!enable) {
return null;
}
final wifiName = await _networkService.getWifiName();
final savedWifiName = _authRepository.getPreferredWifiName();
String? endpoint;
if (wifiName == savedWifiName) {
endpoint = await _setLocalConnection();
}
endpoint ??= await _setRemoteConnection();
return endpoint;
}
Future<String?> _setLocalConnection() async {
try {
final localEndpoint = _authRepository.getLocalEndpoint();
if (localEndpoint != null) {
await _apiService.resolveAndSetEndpoint(localEndpoint);
return localEndpoint;
}
} catch (error, stackTrace) {
_log.severe("Cannot set local endpoint", error, stackTrace);
}
return null;
}
Future<String?> _setRemoteConnection() async {
List<AuxilaryEndpoint> endpointList;
try {
endpointList = _authRepository.getExternalEndpointList();
} catch (error, stackTrace) {
_log.severe("Cannot get external endpoint", error, stackTrace);
return null;
}
for (final endpoint in endpointList) {
try {
return await _apiService.resolveAndSetEndpoint(endpoint.url);
} on ApiException catch (error) {
_log.severe("Cannot resolve endpoint", error);
continue;
} catch (_) {
_log.severe("Auxilary server is not valid");
continue;
}
}
return null;
}
}