authentication.provider.dart 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter/services.dart';
  3. import 'package:hive/hive.dart';
  4. import 'package:hooks_riverpod/hooks_riverpod.dart';
  5. import 'package:immich_mobile/constants/hive_box.dart';
  6. import 'package:immich_mobile/modules/album/services/album_cache.service.dart';
  7. import 'package:immich_mobile/modules/home/services/asset_cache.service.dart';
  8. import 'package:immich_mobile/modules/login/models/authentication_state.model.dart';
  9. import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
  10. import 'package:immich_mobile/modules/backup/services/backup.service.dart';
  11. import 'package:immich_mobile/shared/providers/api.provider.dart';
  12. import 'package:immich_mobile/shared/services/api.service.dart';
  13. import 'package:immich_mobile/shared/services/device_info.service.dart';
  14. import 'package:openapi/api.dart';
  15. class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
  16. AuthenticationNotifier(
  17. this._deviceInfoService,
  18. this._backupService,
  19. this._apiService,
  20. this._assetCacheService,
  21. this._albumCacheService,
  22. this._sharedAlbumCacheService,
  23. ) : super(
  24. AuthenticationState(
  25. deviceId: "",
  26. deviceType: DeviceTypeEnum.ANDROID,
  27. userId: "",
  28. userEmail: "",
  29. firstName: '',
  30. lastName: '',
  31. profileImagePath: '',
  32. isAdmin: false,
  33. shouldChangePassword: false,
  34. isAuthenticated: false,
  35. deviceInfo: DeviceInfoResponseDto(
  36. id: 0,
  37. userId: "",
  38. deviceId: "",
  39. deviceType: DeviceTypeEnum.ANDROID,
  40. createdAt: "",
  41. isAutoBackup: false,
  42. ),
  43. ),
  44. );
  45. final DeviceInfoService _deviceInfoService;
  46. final BackupService _backupService;
  47. final ApiService _apiService;
  48. final AssetCacheService _assetCacheService;
  49. final AlbumCacheService _albumCacheService;
  50. final SharedAlbumCacheService _sharedAlbumCacheService;
  51. Future<bool> login(
  52. String email,
  53. String password,
  54. String serverEndpoint,
  55. bool isSavedLoginInfo,
  56. ) async {
  57. // Store server endpoint to Hive and test endpoint
  58. if (serverEndpoint[serverEndpoint.length - 1] == "/") {
  59. var validUrl = serverEndpoint.substring(0, serverEndpoint.length - 1);
  60. Hive.box(userInfoBox).put(serverEndpointKey, validUrl);
  61. } else {
  62. Hive.box(userInfoBox).put(serverEndpointKey, serverEndpoint);
  63. }
  64. // Check Server URL validity
  65. try {
  66. _apiService.setEndpoint(Hive.box(userInfoBox).get(serverEndpointKey));
  67. await _apiService.serverInfoApi.pingServer();
  68. } catch (e) {
  69. debugPrint('Invalid Server Endpoint Url $e');
  70. return false;
  71. }
  72. // Make sign-in request
  73. try {
  74. var loginResponse = await _apiService.authenticationApi.login(
  75. LoginCredentialDto(
  76. email: email,
  77. password: password,
  78. ),
  79. );
  80. if (loginResponse == null) {
  81. debugPrint('Login Response is null');
  82. return false;
  83. }
  84. return setSuccessLoginInfo(
  85. accessToken: loginResponse.accessToken,
  86. isSavedLoginInfo: isSavedLoginInfo,
  87. );
  88. } catch (e) {
  89. HapticFeedback.vibrate();
  90. debugPrint("Error logging in $e");
  91. return false;
  92. }
  93. }
  94. Future<bool> logout() async {
  95. Hive.box(userInfoBox).delete(accessTokenKey);
  96. state = state.copyWith(isAuthenticated: false);
  97. _assetCacheService.invalidate();
  98. _albumCacheService.invalidate();
  99. _sharedAlbumCacheService.invalidate();
  100. // Remove login info from local storage
  101. var loginInfo =
  102. Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).get(savedLoginInfoKey);
  103. if (loginInfo != null) {
  104. loginInfo.email = "";
  105. loginInfo.password = "";
  106. loginInfo.isSaveLogin = false;
  107. Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).put(
  108. savedLoginInfoKey,
  109. loginInfo,
  110. );
  111. }
  112. return true;
  113. }
  114. setAutoBackup(bool backupState) async {
  115. var deviceInfo = await _deviceInfoService.getDeviceInfo();
  116. var deviceId = deviceInfo["deviceId"];
  117. DeviceTypeEnum deviceType = deviceInfo["deviceType"];
  118. DeviceInfoResponseDto updatedDeviceInfo =
  119. await _backupService.setAutoBackup(backupState, deviceId, deviceType);
  120. state = state.copyWith(deviceInfo: updatedDeviceInfo);
  121. }
  122. updateUserProfileImagePath(String path) {
  123. state = state.copyWith(profileImagePath: path);
  124. }
  125. Future<bool> changePassword(String newPassword) async {
  126. try {
  127. await _apiService.userApi.updateUser(
  128. UpdateUserDto(
  129. id: state.userId,
  130. password: newPassword,
  131. shouldChangePassword: false,
  132. ),
  133. );
  134. state = state.copyWith(shouldChangePassword: false);
  135. return true;
  136. } catch (e) {
  137. debugPrint("Error changing password $e");
  138. return false;
  139. }
  140. }
  141. Future<bool> setSuccessLoginInfo({
  142. required String accessToken,
  143. required bool isSavedLoginInfo,
  144. }) async {
  145. Hive.box(userInfoBox).put(accessTokenKey, accessToken);
  146. _apiService.setAccessToken(accessToken);
  147. var userResponseDto = await _apiService.userApi.getMyUserInfo();
  148. if (userResponseDto != null) {
  149. var deviceInfo = await _deviceInfoService.getDeviceInfo();
  150. Hive.box(userInfoBox).put(deviceIdKey, deviceInfo["deviceId"]);
  151. state = state.copyWith(
  152. isAuthenticated: true,
  153. userId: userResponseDto.id,
  154. userEmail: userResponseDto.email,
  155. firstName: userResponseDto.firstName,
  156. lastName: userResponseDto.lastName,
  157. profileImagePath: userResponseDto.profileImagePath,
  158. isAdmin: userResponseDto.isAdmin,
  159. shouldChangePassword: userResponseDto.shouldChangePassword,
  160. deviceId: deviceInfo["deviceId"],
  161. deviceType: deviceInfo["deviceType"],
  162. );
  163. if (isSavedLoginInfo) {
  164. // Save login info to local storage
  165. Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).put(
  166. savedLoginInfoKey,
  167. HiveSavedLoginInfo(
  168. email: "",
  169. password: "",
  170. isSaveLogin: true,
  171. serverUrl: Hive.box(userInfoBox).get(serverEndpointKey),
  172. accessToken: accessToken,
  173. ),
  174. );
  175. } else {
  176. Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox)
  177. .delete(savedLoginInfoKey);
  178. }
  179. }
  180. // Register device info
  181. try {
  182. DeviceInfoResponseDto? deviceInfo =
  183. await _apiService.deviceInfoApi.createDeviceInfo(
  184. CreateDeviceInfoDto(
  185. deviceId: state.deviceId,
  186. deviceType: state.deviceType,
  187. ),
  188. );
  189. if (deviceInfo == null) {
  190. debugPrint('Device Info Response is null');
  191. return false;
  192. }
  193. state = state.copyWith(deviceInfo: deviceInfo);
  194. } catch (e) {
  195. debugPrint("ERROR Register Device Info: $e");
  196. return false;
  197. }
  198. return true;
  199. }
  200. }
  201. final authenticationProvider =
  202. StateNotifierProvider<AuthenticationNotifier, AuthenticationState>((ref) {
  203. return AuthenticationNotifier(
  204. ref.watch(deviceInfoServiceProvider),
  205. ref.watch(backupServiceProvider),
  206. ref.watch(apiServiceProvider),
  207. ref.watch(assetCacheServiceProvider),
  208. ref.watch(albumCacheServiceProvider),
  209. ref.watch(sharedAlbumCacheServiceProvider),
  210. );
  211. });