Update Saqel Platform: 2026-08-31 01:52:23
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import '../../data/models/user_model.dart';
|
||||
import '../utils/app_logger.dart';
|
||||
|
||||
/// Resilient Storage Service for JWT Tokens, Device ID, and User Data
|
||||
/// Supports macOS Keychain + In-Memory Fallback to prevent -34018 crashes
|
||||
class StorageService {
|
||||
final FlutterSecureStorage _storage;
|
||||
static final Map<String, String> _memoryFallback = {};
|
||||
|
||||
StorageService({FlutterSecureStorage? storage})
|
||||
: _storage = storage ??
|
||||
const FlutterSecureStorage(
|
||||
mOptions: MacOsOptions(
|
||||
accessibility: KeychainAccessibility.first_unlock,
|
||||
),
|
||||
aOptions: AndroidOptions(
|
||||
encryptedSharedPreferences: true,
|
||||
),
|
||||
);
|
||||
|
||||
static const String _keyToken = 'saqel_jwt_token';
|
||||
static const String _keyUser = 'saqel_user_data';
|
||||
static const String _keyRole = 'saqel_active_role';
|
||||
static const String _keyIdentityToken = 'saqel_identity_token';
|
||||
static const String _keyDeviceId = 'saqel_device_id';
|
||||
|
||||
Future<void> _writeSafe(String key, String value) async {
|
||||
_memoryFallback[key] = value;
|
||||
try {
|
||||
await _storage.write(key: key, value: value);
|
||||
} on PlatformException catch (e) {
|
||||
AppLogger.log('Keychain write notice ($key): ${e.message} (Using secure memory fallback)', tag: 'STORAGE');
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
Future<String?> _readSafe(String key) async {
|
||||
try {
|
||||
final val = await _storage.read(key: key);
|
||||
if (val != null) return val;
|
||||
} on PlatformException catch (e) {
|
||||
AppLogger.log('Keychain read notice ($key): ${e.message}', tag: 'STORAGE');
|
||||
} catch (_) {}
|
||||
return _memoryFallback[key];
|
||||
}
|
||||
|
||||
Future<void> _deleteSafe(String key) async {
|
||||
_memoryFallback.remove(key);
|
||||
try {
|
||||
await _storage.delete(key: key);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
Future<void> saveToken(String token) async {
|
||||
await _writeSafe(_keyToken, token);
|
||||
}
|
||||
|
||||
Future<String?> getToken() async {
|
||||
return await _readSafe(_keyToken);
|
||||
}
|
||||
|
||||
Future<void> saveIdentityToken(String token) async {
|
||||
await _writeSafe(_keyIdentityToken, token);
|
||||
}
|
||||
|
||||
Future<String?> getIdentityToken() async {
|
||||
return await _readSafe(_keyIdentityToken);
|
||||
}
|
||||
|
||||
Future<void> saveUser(UserModel user) async {
|
||||
await _writeSafe(_keyUser, jsonEncode(user.toJson()));
|
||||
}
|
||||
|
||||
Future<UserModel?> getUser() async {
|
||||
final raw = await _readSafe(_keyUser);
|
||||
if (raw == null || raw.isEmpty) return null;
|
||||
try {
|
||||
final json = jsonDecode(raw);
|
||||
return UserModel.fromJson(json);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveActiveRole(String role) async {
|
||||
await _writeSafe(_keyRole, role);
|
||||
}
|
||||
|
||||
Future<String?> getActiveRole() async {
|
||||
return await _readSafe(_keyRole);
|
||||
}
|
||||
|
||||
Future<void> saveDeviceId(String deviceId) async {
|
||||
await _writeSafe(_keyDeviceId, deviceId);
|
||||
}
|
||||
|
||||
Future<String?> getDeviceId() async {
|
||||
return await _readSafe(_keyDeviceId);
|
||||
}
|
||||
|
||||
Future<void> clearSession() async {
|
||||
await _deleteSafe(_keyToken);
|
||||
await _deleteSafe(_keyUser);
|
||||
await _deleteSafe(_keyRole);
|
||||
await _deleteSafe(_keyIdentityToken);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user