init
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
import 'api/support_api.dart';
|
||||
import 'models/account.dart';
|
||||
import 'models/api_exception.dart';
|
||||
|
||||
class SessionStore {
|
||||
SessionStore({FlutterSecureStorage? storage})
|
||||
: _storage = storage ?? const FlutterSecureStorage();
|
||||
|
||||
static const tokenKey = 'auth_token';
|
||||
static const accountKey = 'account_json';
|
||||
static const fcmTokenKey = 'fcm_token';
|
||||
|
||||
final FlutterSecureStorage _storage;
|
||||
|
||||
Future<String?> readToken() => _storage.read(key: tokenKey);
|
||||
|
||||
Future<Account?> readAccount() async {
|
||||
final raw = await _storage.read(key: accountKey);
|
||||
if (raw == null || raw.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
final decoded = jsonDecode(raw);
|
||||
if (decoded is! Map) {
|
||||
return null;
|
||||
}
|
||||
return Account.fromJson(Map<String, dynamic>.from(decoded));
|
||||
}
|
||||
|
||||
Future<String?> readFcmToken() => _storage.read(key: fcmTokenKey);
|
||||
|
||||
Future<void> writeSession(String token, Account account) async {
|
||||
await _storage.write(key: tokenKey, value: token);
|
||||
await _storage.write(key: accountKey, value: jsonEncode(account.toJson()));
|
||||
}
|
||||
|
||||
Future<void> writeFcmToken(String token) {
|
||||
return _storage.write(key: fcmTokenKey, value: token);
|
||||
}
|
||||
|
||||
Future<void> clear() async {
|
||||
await _storage.delete(key: tokenKey);
|
||||
await _storage.delete(key: accountKey);
|
||||
await _storage.delete(key: fcmTokenKey);
|
||||
}
|
||||
}
|
||||
|
||||
class SessionController extends ChangeNotifier {
|
||||
SessionController({required this.store, required this.api});
|
||||
|
||||
final SessionStore store;
|
||||
final SupportApi api;
|
||||
|
||||
Account? account;
|
||||
String? token;
|
||||
String? fcmToken;
|
||||
String? pendingTicketId;
|
||||
bool ready = false;
|
||||
|
||||
bool get isSignedIn =>
|
||||
token != null && account != null && account!.canReadSupport;
|
||||
|
||||
Future<void> restore() async {
|
||||
try {
|
||||
token = await store.readToken();
|
||||
account = await store.readAccount();
|
||||
fcmToken = await store.readFcmToken();
|
||||
if (token == null || account == null || !account!.canReadSupport) {
|
||||
token = null;
|
||||
account = null;
|
||||
}
|
||||
api.authToken = token;
|
||||
} finally {
|
||||
ready = true;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an error message, or null when the inbox can open.
|
||||
Future<String?> signIn(String username, String password) async {
|
||||
try {
|
||||
final result = await api.login(username.trim(), password);
|
||||
if (!result.account.canReadSupport) {
|
||||
return 'This account does not have support access';
|
||||
}
|
||||
await store.writeSession(result.token, result.account);
|
||||
token = result.token;
|
||||
account = result.account;
|
||||
api.authToken = token;
|
||||
notifyListeners();
|
||||
return null;
|
||||
} on ApiException catch (error) {
|
||||
return error.message;
|
||||
} on Object {
|
||||
return 'Could not save this session.';
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveFcmToken(String value) async {
|
||||
fcmToken = value;
|
||||
await store.writeFcmToken(value);
|
||||
}
|
||||
|
||||
Future<void> signOut() async {
|
||||
final deviceToken = fcmToken;
|
||||
if (deviceToken != null && deviceToken.isNotEmpty && token != null) {
|
||||
try {
|
||||
await api.unregisterDevice(deviceToken);
|
||||
} on ApiException {
|
||||
// Local logout still proceeds when the device delete fails.
|
||||
}
|
||||
}
|
||||
token = null;
|
||||
account = null;
|
||||
fcmToken = null;
|
||||
api.authToken = null;
|
||||
await store.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void handleUnauthorized() {
|
||||
if (token == null && account == null) {
|
||||
return;
|
||||
}
|
||||
token = null;
|
||||
account = null;
|
||||
fcmToken = null;
|
||||
api.authToken = null;
|
||||
notifyListeners();
|
||||
unawaited(store.clear());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user