import 'package:halkyon_app/src/auth/model/session_grant.dart'; import 'package:halkyon_app/src/base/base_client.dart'; import 'package:halkyon_base_client/halkyon_base_client.dart' as protocol; import 'package:http/http.dart' as http; import 'package:serverpod_auth_idp_flutter/serverpod_auth_idp_flutter.dart'; /// The calls a gateway makes on an instance's halkyon_base for someone /// other than the device's person: without a session, through a client of /// halkyon_base holding none (Serverpod issues no session for another /// person inside a signed-in call), and with a session granted but not yet /// the device's, through a client holding that one. Each client is the /// call's own, closed after. final class BaseCalls( final ServerpodClientShared _client, { /// The module's endpoints on the app's client, as the device's person. required final protocol.Caller _base, /// What the clients it makes for itself send through; tests give a fake. final http.Client Function()? _httpClient, }) { /// What [call] gives on a client of halkyon_base without a session. Future signedOut(Future Function(BaseClient base) call) async { final client = BaseClient( _client.host, httpClientOverride: _httpClient?.call(), ); try { return await call(client); } finally { client.close(); } } /// What [call] gives on the device's session, or on [grant]'s, kept in /// memory by a client of its own. Future asGrant( SessionGrant? grant, Future Function(protocol.Caller base) call, ) async { if (grant == null) { return await call(_base); } final sessionManager = FlutterAuthSessionManager( storage: _MemorySessionStorage(), ); final client = BaseClient( _client.host, httpClientOverride: _httpClient?.call(), )..authSessionManager = sessionManager; try { await sessionManager.updateSignedInUser(grant.session as AuthSuccess); return await call(client.modules); } finally { client.close(); } } } /// Keeps one session in memory, for a client used once. final class _MemorySessionStorage() implements ClientAuthSuccessStorage { AuthSuccess? _session; @override Future get() async => _session; @override Future set(AuthSuccess? data) async { _session = data; } }