1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-06 11:56:46 +01:00
immich/mobile/lib/modules/login/providers/authentication.provider.dart

235 lines
6.8 KiB
Dart
Raw Normal View History

import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
2022-02-03 17:06:44 +01:00
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_udid/flutter_udid.dart';
2022-02-03 17:06:44 +01:00
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/providers/album.provider.dart';
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
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';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
import 'package:immich_mobile/utils/db.dart';
import 'package:immich_mobile/utils/hash.dart';
import 'package:isar/isar.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart';
2022-02-03 17:06:44 +01:00
class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
AuthenticationNotifier(
this._apiService,
this._db,
this._ref,
) : super(
2022-02-03 17:06:44 +01:00
AuthenticationState(
deviceId: "",
userId: "",
userEmail: "",
name: '',
profileImagePath: '',
isAdmin: false,
shouldChangePassword: false,
isAuthenticated: false,
2022-02-03 17:06:44 +01:00
),
);
final ApiService _apiService;
final Isar _db;
final StateNotifierProviderRef<AuthenticationNotifier, AuthenticationState>
_ref;
final _log = Logger("AuthenticationNotifier");
Future<bool> login(
String email,
String password,
String serverUrl,
) async {
2022-02-05 00:20:23 +01:00
try {
// Resolve API server endpoint from user provided serverUrl
await _apiService.resolveAndSetEndpoint(serverUrl);
await _apiService.serverInfoApi.pingServer();
2022-02-05 00:20:23 +01:00
} catch (e) {
debugPrint('Invalid Server Endpoint Url $e');
2022-02-03 17:06:44 +01:00
return false;
}
// Make sign-in request
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 {
var loginResponse = await _apiService.authenticationApi.login(
LoginCredentialDto(
email: email,
password: password,
),
);
2022-02-03 17:06:44 +01:00
if (loginResponse == null) {
debugPrint('Login Response is null');
return false;
}
2022-02-03 17:06:44 +01:00
return setSuccessLoginInfo(
accessToken: loginResponse.accessToken,
serverUrl: serverUrl,
2022-02-03 17:06:44 +01:00
);
} catch (e) {
HapticFeedback.vibrate();
debugPrint("Error logging in $e");
2022-02-03 17:06:44 +01:00
return false;
}
}
Future<void> logout() async {
var log = Logger('AuthenticationNotifier');
try {
String? userEmail = Store.tryGet(StoreKey.currentUser)?.email;
_apiService.authenticationApi
.logout()
.then((_) => log.info("Logout was successful for $userEmail"))
.onError(
(error, stackTrace) =>
log.severe("Error logging out $userEmail", error, stackTrace),
);
await Future.wait([
clearAssetsAndAlbums(_db),
Store.delete(StoreKey.currentUser),
Store.delete(StoreKey.accessToken),
]);
_ref.invalidate(albumProvider);
_ref.invalidate(sharedAlbumProvider);
state = state.copyWith(
deviceId: "",
userId: "",
userEmail: "",
name: '',
profileImagePath: '',
isAdmin: false,
shouldChangePassword: false,
isAuthenticated: false,
);
} catch (e) {
log.severe("Error logging out $e");
}
2022-02-03 17:06:44 +01:00
}
updateUserProfileImagePath(String path) {
state = state.copyWith(profileImagePath: path);
}
Future<bool> changePassword(String newPassword) async {
try {
await _apiService.userApi.updateUser(
UpdateUserDto(
id: state.userId,
password: newPassword,
shouldChangePassword: false,
),
);
state = state.copyWith(shouldChangePassword: false);
return true;
} catch (e) {
debugPrint("Error changing password $e");
return false;
}
}
Future<bool> setSuccessLoginInfo({
required String accessToken,
required String serverUrl,
bool offlineLogin = false,
}) async {
_apiService.setAccessToken(accessToken);
// Get the deviceid from the store if it exists, otherwise generate a new one
String deviceId =
Store.tryGet(StoreKey.deviceId) ?? await FlutterUdid.consistentUdid;
bool shouldChangePassword = false;
User? user;
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 {
UserResponseDto? userResponseDto;
try {
userResponseDto = await _apiService.userApi.getMyUserInfo();
} on ApiException catch (e) {
if (e.innerException is SocketException) {
state = state.copyWith(isAuthenticated: true);
}
}
if (userResponseDto != null) {
Store.put(StoreKey.deviceId, deviceId);
Store.put(StoreKey.deviceIdHash, fastHash(deviceId));
Store.put(
StoreKey.currentUser,
User.fromUserDto(userResponseDto),
);
Store.put(StoreKey.serverUrl, serverUrl);
Store.put(StoreKey.accessToken, accessToken);
shouldChangePassword = userResponseDto.shouldChangePassword;
user = User.fromUserDto(userResponseDto);
retResult = true;
} else {
_log.severe("Unable to get user information from the server.");
return false;
}
}
state = state.copyWith(
isAuthenticated: true,
userId: user.id,
userEmail: user.email,
name: user.name,
profileImagePath: user.profileImagePath,
isAdmin: user.isAdmin,
shouldChangePassword: shouldChangePassword,
deviceId: deviceId,
);
return retResult;
}
2022-02-03 17:06:44 +01:00
}
final authenticationProvider =
StateNotifierProvider<AuthenticationNotifier, AuthenticationState>((ref) {
return AuthenticationNotifier(
ref.watch(apiServiceProvider),
ref.watch(dbProvider),
ref,
);
2022-02-03 17:06:44 +01:00
});