2023-03-15 22:29:07 +01:00
|
|
|
import 'dart:io';
|
|
|
|
|
2023-04-26 04:19:23 +02:00
|
|
|
import 'package:device_info_plus/device_info_plus.dart';
|
2022-02-03 17:06:44 +01:00
|
|
|
import 'package:flutter/material.dart';
|
2022-10-14 23:13:35 +02:00
|
|
|
import 'package:flutter/services.dart';
|
2023-04-28 22:01:03 +02:00
|
|
|
import 'package:flutter_udid/flutter_udid.dart';
|
2022-02-03 17:06:44 +01:00
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
2023-02-09 18:32:08 +01:00
|
|
|
import 'package:immich_mobile/shared/models/store.dart';
|
2022-02-03 17:06:44 +01:00
|
|
|
import 'package:immich_mobile/modules/login/models/authentication_state.model.dart';
|
2023-03-03 23:38:30 +01:00
|
|
|
import 'package:immich_mobile/shared/models/user.dart';
|
2022-08-03 07:04:34 +02:00
|
|
|
import 'package:immich_mobile/shared/providers/api.provider.dart';
|
2023-05-17 19:36:02 +02:00
|
|
|
import 'package:immich_mobile/shared/providers/db.provider.dart';
|
2022-07-13 14:23:48 +02:00
|
|
|
import 'package:immich_mobile/shared/services/api.service.dart';
|
2023-05-17 19:36:02 +02:00
|
|
|
import 'package:immich_mobile/utils/db.dart';
|
2023-03-03 23:38:30 +01:00
|
|
|
import 'package:immich_mobile/utils/hash.dart';
|
2023-05-17 19:36:02 +02:00
|
|
|
import 'package:isar/isar.dart';
|
2023-07-16 03:52:41 +02:00
|
|
|
import 'package:logging/logging.dart';
|
2022-07-13 14:23:48 +02:00
|
|
|
import 'package:openapi/api.dart';
|
2022-02-03 17:06:44 +01:00
|
|
|
|
|
|
|
class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
2022-06-25 20:46:51 +02:00
|
|
|
AuthenticationNotifier(
|
2022-07-13 14:23:48 +02:00
|
|
|
this._apiService,
|
2023-05-17 19:36:02 +02:00
|
|
|
this._db,
|
2022-07-13 14:23:48 +02:00
|
|
|
) : super(
|
2022-02-03 17:06:44 +01:00
|
|
|
AuthenticationState(
|
|
|
|
deviceId: "",
|
|
|
|
userId: "",
|
|
|
|
userEmail: "",
|
2022-05-29 05:35:45 +02:00
|
|
|
firstName: '',
|
|
|
|
lastName: '',
|
|
|
|
profileImagePath: '',
|
|
|
|
isAdmin: false,
|
2022-06-27 22:13:07 +02:00
|
|
|
shouldChangePassword: false,
|
2022-05-29 05:35:45 +02:00
|
|
|
isAuthenticated: false,
|
2022-02-03 17:06:44 +01:00
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2022-07-13 14:23:48 +02:00
|
|
|
final ApiService _apiService;
|
2023-05-17 19:36:02 +02:00
|
|
|
final Isar _db;
|
2022-07-13 14:23:48 +02:00
|
|
|
|
|
|
|
Future<bool> login(
|
|
|
|
String email,
|
|
|
|
String password,
|
2023-01-19 16:45:37 +01:00
|
|
|
String serverUrl,
|
2022-07-13 14:23:48 +02:00
|
|
|
) async {
|
2022-02-05 00:20:23 +01:00
|
|
|
try {
|
2023-01-19 16:45:37 +01:00
|
|
|
// Resolve API server endpoint from user provided serverUrl
|
|
|
|
await _apiService.resolveAndSetEndpoint(serverUrl);
|
2022-07-13 14:23:48 +02:00
|
|
|
await _apiService.serverInfoApi.pingServer();
|
2022-02-05 00:20:23 +01:00
|
|
|
} catch (e) {
|
2022-07-13 14:23:48 +02:00
|
|
|
debugPrint('Invalid Server Endpoint Url $e');
|
2022-02-03 17:06:44 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sign-in request
|
2023-04-26 04:19:23 +02:00
|
|
|
DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
|
|
|
|
|
|
|
|
if (Platform.isIOS) {
|
|
|
|
var iosInfo = await deviceInfoPlugin.iosInfo;
|
|
|
|
_apiService.authenticationApi.apiClient
|
|
|
|
.addDefaultHeader('deviceModel', iosInfo.utsname.machine ?? '');
|
|
|
|
_apiService.authenticationApi.apiClient
|
|
|
|
.addDefaultHeader('deviceType', 'iOS');
|
|
|
|
} else {
|
|
|
|
var androidInfo = await deviceInfoPlugin.androidInfo;
|
|
|
|
_apiService.authenticationApi.apiClient
|
|
|
|
.addDefaultHeader('deviceModel', androidInfo.model);
|
|
|
|
_apiService.authenticationApi.apiClient
|
|
|
|
.addDefaultHeader('deviceType', 'Android');
|
|
|
|
}
|
|
|
|
|
2022-02-03 17:06:44 +01:00
|
|
|
try {
|
2022-07-13 14:23:48 +02:00
|
|
|
var loginResponse = await _apiService.authenticationApi.login(
|
|
|
|
LoginCredentialDto(
|
|
|
|
email: email,
|
|
|
|
password: password,
|
|
|
|
),
|
|
|
|
);
|
2022-02-03 17:06:44 +01:00
|
|
|
|
2022-07-13 14:23:48 +02:00
|
|
|
if (loginResponse == null) {
|
|
|
|
debugPrint('Login Response is null');
|
|
|
|
return false;
|
|
|
|
}
|
2022-02-03 17:06:44 +01:00
|
|
|
|
2022-11-20 18:43:10 +01:00
|
|
|
return setSuccessLoginInfo(
|
|
|
|
accessToken: loginResponse.accessToken,
|
2023-01-19 16:45:37 +01:00
|
|
|
serverUrl: serverUrl,
|
2022-02-03 17:06:44 +01:00
|
|
|
);
|
|
|
|
} catch (e) {
|
2022-10-14 23:13:35 +02:00
|
|
|
HapticFeedback.vibrate();
|
2022-07-13 14:23:48 +02:00
|
|
|
debugPrint("Error logging in $e");
|
2022-02-03 17:06:44 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-16 03:52:41 +02:00
|
|
|
Future<void> logout() async {
|
|
|
|
var log = Logger('AuthenticationNotifier');
|
2023-02-21 04:43:39 +01:00
|
|
|
try {
|
2023-07-16 03:52:41 +02:00
|
|
|
|
|
|
|
String? userEmail = Store.tryGet(StoreKey.currentUser)?.email;
|
|
|
|
|
|
|
|
_apiService.authenticationApi
|
|
|
|
.logout()
|
|
|
|
.then((_) => log.info("Logout was successfull for $userEmail"))
|
|
|
|
.onError(
|
|
|
|
(error, stackTrace) =>
|
|
|
|
log.severe("Error logging out $userEmail", error, stackTrace),
|
|
|
|
);
|
|
|
|
|
2023-02-21 04:43:39 +01:00
|
|
|
await Future.wait([
|
2023-05-17 19:36:02 +02:00
|
|
|
clearAssetsAndAlbums(_db),
|
2023-03-03 23:38:30 +01:00
|
|
|
Store.delete(StoreKey.currentUser),
|
2023-03-23 02:36:44 +01:00
|
|
|
Store.delete(StoreKey.accessToken),
|
2023-02-21 04:43:39 +01:00
|
|
|
]);
|
2022-10-24 21:45:58 +02:00
|
|
|
|
2023-02-21 04:43:39 +01:00
|
|
|
state = state.copyWith(isAuthenticated: false);
|
|
|
|
} catch (e) {
|
2023-07-16 03:52:41 +02:00
|
|
|
log.severe("Error logging out $e");
|
2023-02-21 04:43:39 +01:00
|
|
|
}
|
2022-02-03 17:06:44 +01:00
|
|
|
}
|
|
|
|
|
2022-05-29 05:35:45 +02:00
|
|
|
updateUserProfileImagePath(String path) {
|
|
|
|
state = state.copyWith(profileImagePath: path);
|
|
|
|
}
|
2022-06-27 22:13:07 +02:00
|
|
|
|
|
|
|
Future<bool> changePassword(String newPassword) async {
|
2022-07-13 14:23:48 +02:00
|
|
|
try {
|
|
|
|
await _apiService.userApi.updateUser(
|
|
|
|
UpdateUserDto(
|
|
|
|
id: state.userId,
|
|
|
|
password: newPassword,
|
|
|
|
shouldChangePassword: false,
|
|
|
|
),
|
|
|
|
);
|
2022-06-27 22:13:07 +02:00
|
|
|
|
|
|
|
state = state.copyWith(shouldChangePassword: false);
|
2022-07-13 14:23:48 +02:00
|
|
|
|
2022-06-27 22:13:07 +02:00
|
|
|
return true;
|
2022-07-13 14:23:48 +02:00
|
|
|
} catch (e) {
|
|
|
|
debugPrint("Error changing password $e");
|
2022-06-27 22:13:07 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2022-11-20 18:43:10 +01:00
|
|
|
|
|
|
|
Future<bool> setSuccessLoginInfo({
|
|
|
|
required String accessToken,
|
2022-11-21 12:29:43 +01:00
|
|
|
required String serverUrl,
|
2022-11-20 18:43:10 +01:00
|
|
|
}) async {
|
|
|
|
_apiService.setAccessToken(accessToken);
|
2023-03-15 22:29:07 +01:00
|
|
|
UserResponseDto? userResponseDto;
|
|
|
|
try {
|
|
|
|
userResponseDto = await _apiService.userApi.getMyUserInfo();
|
|
|
|
} on ApiException catch (e) {
|
|
|
|
if (e.innerException is SocketException) {
|
|
|
|
state = state.copyWith(isAuthenticated: true);
|
|
|
|
}
|
|
|
|
}
|
2022-11-20 18:43:10 +01:00
|
|
|
|
|
|
|
if (userResponseDto != null) {
|
2023-04-28 22:01:03 +02:00
|
|
|
final deviceId = await FlutterUdid.consistentUdid;
|
|
|
|
Store.put(StoreKey.deviceId, deviceId);
|
|
|
|
Store.put(StoreKey.deviceIdHash, fastHash(deviceId));
|
2023-03-03 23:38:30 +01:00
|
|
|
Store.put(StoreKey.currentUser, User.fromDto(userResponseDto));
|
2023-03-23 02:36:44 +01:00
|
|
|
Store.put(StoreKey.serverUrl, serverUrl);
|
|
|
|
Store.put(StoreKey.accessToken, accessToken);
|
2022-11-20 18:43:10 +01:00
|
|
|
|
|
|
|
state = state.copyWith(
|
|
|
|
isAuthenticated: true,
|
|
|
|
userId: userResponseDto.id,
|
|
|
|
userEmail: userResponseDto.email,
|
|
|
|
firstName: userResponseDto.firstName,
|
|
|
|
lastName: userResponseDto.lastName,
|
|
|
|
profileImagePath: userResponseDto.profileImagePath,
|
|
|
|
isAdmin: userResponseDto.isAdmin,
|
|
|
|
shouldChangePassword: userResponseDto.shouldChangePassword,
|
2023-04-28 22:01:03 +02:00
|
|
|
deviceId: deviceId,
|
2022-11-20 18:43:10 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2022-02-03 17:06:44 +01:00
|
|
|
}
|
|
|
|
|
2022-06-25 20:46:51 +02:00
|
|
|
final authenticationProvider =
|
|
|
|
StateNotifierProvider<AuthenticationNotifier, AuthenticationState>((ref) {
|
|
|
|
return AuthenticationNotifier(
|
2022-07-13 14:23:48 +02:00
|
|
|
ref.watch(apiServiceProvider),
|
2023-05-17 19:36:02 +02:00
|
|
|
ref.watch(dbProvider),
|
2022-06-25 20:46:51 +02:00
|
|
|
);
|
2022-02-03 17:06:44 +01:00
|
|
|
});
|