halkyon/packages/halkyon_app/lib/src/base/base_calls.dart

71 lines
2.3 KiB
Dart
Raw Normal View History

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<T> signedOut<T>(Future<T> 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<T> asGrant<T>(
SessionGrant? grant,
Future<T> 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<AuthSuccess?> get() async => _session;
@override
Future<void> set(AuthSuccess? data) async {
_session = data;
}
}