Files
AutoJudge-Flutter/lib/utils/session_manager.dart

264 lines
7.6 KiB
Dart
Raw Normal View History

2025-11-13 09:14:49 +08:00
import 'package:flutter/foundation.dart';
import '../models/user_credentials.dart';
import '../providers/auth_provider.dart';
/// Session manager for handling app startup and session restoration
///
/// Provides utilities for:
/// - Checking if saved credentials exist
/// - Attempting to restore previous session
/// - Handling session expiration
///
/// Usage example:
/// ```dart
/// final sessionManager = SessionManager(authProvider: authProvider);
///
/// // Check if session can be restored
/// final canRestore = await sessionManager.canRestoreSession();
///
/// // Attempt to restore session
/// final restored = await sessionManager.restoreSession();
///
/// // Handle session expiration
/// await sessionManager.handleSessionExpired();
/// ```
class SessionManager {
final AuthProvider _authProvider;
SessionManager({required AuthProvider authProvider})
: _authProvider = authProvider;
/// Check if saved credentials exist
///
/// Returns true if credentials are stored, false otherwise
/// Does not validate if the session is still active
Future<bool> hasSavedCredentials() async {
try {
final credentials = await UserCredentials.loadSecurely();
return credentials != null;
} catch (e) {
debugPrint('Error checking saved credentials: $e');
return false;
}
}
/// Check if session can be restored
///
/// Checks if saved credentials exist and are valid
/// Returns true if session restoration should be attempted
Future<bool> canRestoreSession() async {
return await hasSavedCredentials();
}
/// Attempt to restore session from saved credentials
///
/// Loads credentials from secure storage and attempts login
/// Returns SessionRestoreResult with status and details
Future<SessionRestoreResult> restoreSession() async {
try {
// Check if credentials exist
final hasCredentials = await hasSavedCredentials();
if (!hasCredentials) {
return SessionRestoreResult(
success: false,
reason: SessionRestoreFailureReason.noCredentials,
message: '未找到保存的登录凭证',
);
}
// Attempt to restore session using AuthProvider
final restored = await _authProvider.restoreSession();
if (restored) {
return SessionRestoreResult(success: true, message: '会话恢复成功');
} else {
// Check the error message from auth provider
final errorMessage = _authProvider.errorMessage;
final reason = _determineFailureReason(errorMessage);
return SessionRestoreResult(
success: false,
reason: reason,
message: errorMessage ?? '会话恢复失败',
);
}
} catch (e) {
debugPrint('Error restoring session: $e');
return SessionRestoreResult(
success: false,
reason: SessionRestoreFailureReason.unknown,
message: '会话恢复出错: $e',
);
}
}
/// Handle session expiration
///
/// Clears current session and credentials
/// Should be called when session is detected as expired
Future<void> handleSessionExpired() async {
try {
await _authProvider.logout();
debugPrint('Session expired and cleared');
} catch (e) {
debugPrint('Error handling session expiration: $e');
}
}
/// Clear saved session data
///
/// Removes all saved credentials and session information
/// Useful for logout or when user wants to clear data
Future<void> clearSession() async {
try {
await _authProvider.logout();
debugPrint('Session cleared successfully');
} catch (e) {
debugPrint('Error clearing session: $e');
}
}
/// Validate current session
///
/// Checks if the current session is still valid
/// Returns true if session is active and healthy
Future<bool> validateSession() async {
try {
if (!_authProvider.isAuthenticated) {
return false;
}
return await _authProvider.checkSession();
} catch (e) {
debugPrint('Error validating session: $e');
return false;
}
}
/// Get session status
///
/// Returns current session status information
SessionStatus getSessionStatus() {
return SessionStatus(
isAuthenticated: _authProvider.isAuthenticated,
authState: _authProvider.state,
hasConnection: _authProvider.connection != null,
errorMessage: _authProvider.errorMessage,
);
}
/// Determine failure reason from error message
SessionRestoreFailureReason _determineFailureReason(String? errorMessage) {
if (errorMessage == null) {
return SessionRestoreFailureReason.unknown;
}
if (errorMessage.contains('密码错误') || errorMessage.contains('凭证')) {
return SessionRestoreFailureReason.invalidCredentials;
} else if (errorMessage.contains('网络') || errorMessage.contains('连接')) {
return SessionRestoreFailureReason.networkError;
} else if (errorMessage.contains('过期')) {
return SessionRestoreFailureReason.sessionExpired;
} else {
return SessionRestoreFailureReason.unknown;
}
}
}
/// Result of session restoration attempt
class SessionRestoreResult {
final bool success;
final SessionRestoreFailureReason? reason;
final String message;
SessionRestoreResult({
required this.success,
this.reason,
required this.message,
});
@override
String toString() {
return 'SessionRestoreResult(success: $success, reason: $reason, message: $message)';
}
}
/// Reasons why session restoration might fail
enum SessionRestoreFailureReason {
/// No saved credentials found
noCredentials,
/// Saved credentials are invalid
invalidCredentials,
/// Session has expired
sessionExpired,
/// Network connection error
networkError,
/// Unknown error
unknown,
}
/// Current session status information
class SessionStatus {
final bool isAuthenticated;
final AuthState authState;
final bool hasConnection;
final String? errorMessage;
SessionStatus({
required this.isAuthenticated,
required this.authState,
required this.hasConnection,
this.errorMessage,
});
/// Check if session is healthy
bool get isHealthy =>
isAuthenticated && hasConnection && errorMessage == null;
@override
String toString() {
return 'SessionStatus('
'isAuthenticated: $isAuthenticated, '
'authState: $authState, '
'hasConnection: $hasConnection, '
'errorMessage: $errorMessage'
')';
}
}
/// Extension methods for SessionRestoreFailureReason
extension SessionRestoreFailureReasonExtension on SessionRestoreFailureReason {
/// Get user-friendly message for the failure reason
String get userMessage {
switch (this) {
case SessionRestoreFailureReason.noCredentials:
return '未找到保存的登录信息,请重新登录';
case SessionRestoreFailureReason.invalidCredentials:
return '登录凭证无效,请重新登录';
case SessionRestoreFailureReason.sessionExpired:
return '会话已过期,请重新登录';
case SessionRestoreFailureReason.networkError:
return '网络连接失败,请检查网络后重试';
case SessionRestoreFailureReason.unknown:
return '会话恢复失败,请重新登录';
}
}
/// Check if user should be prompted to login again
bool get shouldPromptLogin {
switch (this) {
case SessionRestoreFailureReason.noCredentials:
case SessionRestoreFailureReason.invalidCredentials:
case SessionRestoreFailureReason.sessionExpired:
return true;
case SessionRestoreFailureReason.networkError:
case SessionRestoreFailureReason.unknown:
return false; // User might want to retry
}
}
}