90 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'package:moneymgr_mobile/services/api/api_client.dart';
 | 
						|
import 'package:moneymgr_mobile/services/api/api_token.dart';
 | 
						|
import 'package:moneymgr_mobile/services/api/auth_api.dart';
 | 
						|
import 'package:moneymgr_mobile/services/storage/prefs.dart';
 | 
						|
import 'package:moneymgr_mobile/services/storage/secure_storage.dart';
 | 
						|
import 'package:riverpod_annotation/riverpod_annotation.dart';
 | 
						|
 | 
						|
import '../services/router/routes_list.dart';
 | 
						|
 | 
						|
part 'auth_state.g.dart';
 | 
						|
 | 
						|
/// The current authentication state of the app.
 | 
						|
///
 | 
						|
/// This notifier is responsible for saving/removing the token and profile info
 | 
						|
/// to the storage through the [setAuthToken] and [logout] methods.
 | 
						|
@riverpod
 | 
						|
class CurrentAuthState extends _$CurrentAuthState {
 | 
						|
  @override
 | 
						|
  AuthState build() {
 | 
						|
    final secureStorage = ref.watch(secureStorageProvider).requireValue;
 | 
						|
    final token = secureStorage.token();
 | 
						|
    return token != null ? AuthState.authenticated : AuthState.unauthenticated;
 | 
						|
  }
 | 
						|
 | 
						|
  /// Attempts to authenticate with [token] and saves the token and profile info to storage.
 | 
						|
  /// Will invalidate the state if success and throw an exception in case of failure
 | 
						|
  Future<void> setAuthToken(ApiToken token) async {
 | 
						|
    // Attempt to use provided token
 | 
						|
    await ApiClient(
 | 
						|
      token: token,
 | 
						|
      prefs: await ref.watch(prefsProvider.future),
 | 
						|
    ).authInfo();
 | 
						|
 | 
						|
    final secureStorage = ref.read(secureStorageProvider).requireValue;
 | 
						|
    await secureStorage.setToken(token);
 | 
						|
 | 
						|
    ref
 | 
						|
        // Invalidate the state so the auth state will be updated to authenticated.
 | 
						|
        .invalidateSelf();
 | 
						|
  }
 | 
						|
 | 
						|
  /// Logs out, deletes the saved token and profile info from storage, and invalidates
 | 
						|
  /// the state.
 | 
						|
  Future<void> logout() async {
 | 
						|
    final prefs = ref.read(prefsProvider).requireValue;
 | 
						|
 | 
						|
    final secureStorage = ref.read(secureStorageProvider).requireValue;
 | 
						|
    await secureStorage.removeToken();
 | 
						|
 | 
						|
    prefs.clearServerConfig();
 | 
						|
    prefs.clearAuthInfo();
 | 
						|
 | 
						|
    ref
 | 
						|
    // Invalidate the state so the auth state will be updated to authenticated.
 | 
						|
        .invalidateSelf();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/// The possible authentication states of the app.
 | 
						|
enum AuthState {
 | 
						|
  unknown(redirectPath: homePage, allowedPaths: [homePage]),
 | 
						|
  unauthenticated(
 | 
						|
    redirectPath: authPage,
 | 
						|
    allowedPaths: [authPage, qrAuthPath, manualAuthPage, settingsPage],
 | 
						|
  ),
 | 
						|
  authenticated(
 | 
						|
    redirectPath: homePage,
 | 
						|
    allowedPaths: null,
 | 
						|
    forbiddenPaths: [authPage, manualAuthPage],
 | 
						|
  );
 | 
						|
 | 
						|
  const AuthState({
 | 
						|
    required this.redirectPath,
 | 
						|
    required this.allowedPaths,
 | 
						|
    this.forbiddenPaths,
 | 
						|
  });
 | 
						|
 | 
						|
  /// The target path to redirect when the current route is not allowed in this
 | 
						|
  /// auth state.
 | 
						|
  final String redirectPath;
 | 
						|
 | 
						|
  /// List of paths allowed when the app is in this auth state. May be set to null if there is no
 | 
						|
  /// restriction applicable
 | 
						|
  final List<String>? allowedPaths;
 | 
						|
 | 
						|
  /// List of paths not allowed when the app is in this auth state. May be set to null if there is no
 | 
						|
  /// restriction applicable
 | 
						|
  final List<String>? forbiddenPaths;
 | 
						|
}
 |