added support for multiple accounts with an account switcher in settings

This commit is contained in:
2026-09-27 14:54:10 +02:00
parent 5e65c4671a
commit 27563a6dc1
33 changed files with 1801 additions and 462 deletions
@@ -1,6 +1,8 @@
import 'package:dio/dio.dart';
import '../../auth/token_storage.dart';
import '../../marianumconnect_api.dart';
import '../../marianumconnect_endpoint.dart';
import '../../marianumconnect_query.dart';
/// Revokes the stored MC bearer token both server-side and locally. Best-effort
@@ -24,4 +26,17 @@ class AuthLogout extends MarianumConnectQuery {
await _tokenStorage.clear();
}
}
/// Revokes the token of an inactive account; the stored (active) token is
/// left alone. Best-effort.
static Future<void> revoke(String token) async {
try {
await MarianumConnectApi.plainDio().post<void>(
MarianumConnectEndpoint.resolve('auth/logout'),
options: Options(headers: {'Authorization': 'Bearer $token'}),
);
} on DioException catch (_) {
// ignore
}
}
}
@@ -0,0 +1,40 @@
import 'package:dio/dio.dart';
import '../../../errors/auth_exception.dart';
import '../../auth/token_storage.dart';
import '../../marianumconnect_api.dart';
import '../../marianumconnect_query.dart';
import '../auth_login/auth_login_response.dart';
/// Reads the user behind the stored bearer token, which also probes that the
/// token is still accepted.
///
/// Bypasses the shared dio singleton so the auth interceptor does not react
/// to the 401 this probe is meant to observe.
class AuthMe extends MarianumConnectQuery {
final MarianumConnectTokenStorage _tokenStorage;
AuthMe({
MarianumConnectTokenStorage tokenStorage =
const MarianumConnectTokenStorage(),
Dio? dio,
}) : _tokenStorage = tokenStorage,
super(dio: dio ?? MarianumConnectApi.plainDio());
/// Throws [AuthException] when the token is missing or rejected.
Future<void> run() async {
await user();
}
/// The signed-in user (names, type). Throws like [run].
Future<AuthLoginUser> user() async {
final options = await _tokenStorage.requireBearerOptions('AuthMe');
return guard(() async {
final response = await dio.get<Map<String, dynamic>>(
endpoint('auth/me'),
options: options,
);
return AuthLoginUser.fromJson(response.data!);
});
}
}