100 lines
2.9 KiB
Dart
100 lines
2.9 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import '../models/user_profile.dart';
|
|
import '../services/api_client.dart';
|
|
import '../services/token_store.dart';
|
|
|
|
enum SessionStatus { loading, signedOut, signedIn }
|
|
|
|
class SessionController extends ChangeNotifier {
|
|
SessionController(this.api, this.tokens);
|
|
final ApiClient api;
|
|
final TokenStore tokens;
|
|
SessionStatus status = SessionStatus.loading;
|
|
UserProfile? user;
|
|
String? organizationId;
|
|
|
|
OrganizationMembership? get membership {
|
|
final matches = user?.approvedMemberships.where(
|
|
(item) => item.organization.id == organizationId,
|
|
);
|
|
return matches == null || matches.isEmpty ? null : matches.first;
|
|
}
|
|
|
|
Future<void> initialize() async {
|
|
final minimumSplash = Future<void>.delayed(
|
|
const Duration(milliseconds: 1100),
|
|
);
|
|
final token = await tokens.read();
|
|
if (token == null) {
|
|
status = SessionStatus.signedOut;
|
|
} else {
|
|
try {
|
|
user = await api.me();
|
|
await _selectInitialOrganization();
|
|
if (organizationId == null) {
|
|
throw StateError('No approved organization membership');
|
|
}
|
|
status = SessionStatus.signedIn;
|
|
} catch (_) {
|
|
await tokens.clear();
|
|
status = SessionStatus.signedOut;
|
|
}
|
|
}
|
|
await minimumSplash;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> login(String username, String password) async {
|
|
final result = await api.login(username, password);
|
|
await tokens.write(result.token);
|
|
user = result.user;
|
|
await _selectInitialOrganization();
|
|
status = SessionStatus.signedIn;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<String> register(Map<String, dynamic> input) => api.register(input);
|
|
|
|
Future<void> _selectInitialOrganization() async {
|
|
final approved = user?.approvedMemberships ?? const [];
|
|
final saved = await tokens.readOrganization();
|
|
final selected = approved.where((item) => item.organization.id == saved);
|
|
organizationId = selected.isNotEmpty
|
|
? selected.first.organization.id
|
|
: (approved.isEmpty ? null : approved.first.organization.id);
|
|
if (organizationId != null) {
|
|
await tokens.writeOrganization(organizationId!);
|
|
}
|
|
}
|
|
|
|
Future<void> selectOrganization(String id) async {
|
|
if (!(user?.approvedMemberships.any((item) => item.organization.id == id) ??
|
|
false)) {
|
|
return;
|
|
}
|
|
organizationId = id;
|
|
await tokens.writeOrganization(id);
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> refreshProfile() async {
|
|
user = await api.me();
|
|
await _selectInitialOrganization();
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> logout() async {
|
|
await tokens.clear();
|
|
await tokens.clearOrganization();
|
|
user = null;
|
|
organizationId = null;
|
|
status = SessionStatus.signedOut;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> deleteAccount(String password) async {
|
|
await api.deleteAccount(password);
|
|
await logout();
|
|
}
|
|
}
|