What every Halkyon app's shell needs, taken from Halkyon Learn's and set on halkyon_base's client: the instances a device keeps an account on, the first start's tiles and where an instance keeps people's data, the account switcher; signing in anonymously, with GitHub or an email code, switching person and the start screen; the gates that build an app's dependencies per instance and per person; and the sync service with its status, Settings card and banner. Texts of its own in English and German take the app's name; what only the app can say, it passes in. Fakes for apps' tests are in testing.dart. An instance's basics now name the app it serves (`app`, set by the host's configuration), and an app accepts only an instance of its own. SerialQueue and CoalescingRunner move into halkyon_core. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
80 lines
2.4 KiB
Dart
80 lines
2.4 KiB
Dart
import 'package:halkyon_base_server/base.dart';
|
|
import 'package:serverpod/serverpod.dart';
|
|
import 'package:serverpod_auth_idp_server/core.dart';
|
|
|
|
import '../test_tools/serverpod_test_tools.dart';
|
|
|
|
/// The app the tests' host is.
|
|
const testAppName = 'Halkyon Test';
|
|
|
|
/// The id of the app the tests' host serves.
|
|
const testApp = 'test';
|
|
|
|
/// Where the tests' host says its project publishes its source.
|
|
const testUpstreamSourceCodeUrl = 'https://code.example.org/halkyon_test';
|
|
|
|
/// The oldest app build the tests' host works with.
|
|
const testMinimumAppBuild = 7;
|
|
|
|
/// Sets the module up on the pod [sessionBuilder]'s sessions run on, as a
|
|
/// host does before its pod starts, with [deletePersonData] as its
|
|
/// deletions, and authentication exactly as hosts run it
|
|
/// (`auth_config.dart`). Not on `Serverpod.instance`: that is the pod made
|
|
/// last, and a test file with several `withServerpod` groups has a pod each.
|
|
void useBase(
|
|
TestSessionBuilder sessionBuilder, {
|
|
List<PersonDataDeletion> deletePersonData = const [],
|
|
}) {
|
|
final pod = sessionBuilder.build().serverpod;
|
|
HalkyonBase.configure(
|
|
pod,
|
|
HalkyonBase(
|
|
app: testApp,
|
|
appName: testAppName,
|
|
upstreamSourceCodeUrl: testUpstreamSourceCodeUrl,
|
|
minimumAppBuild: testMinimumAppBuild,
|
|
deletePersonData: deletePersonData,
|
|
),
|
|
);
|
|
AuthServices.set(
|
|
tokenManagerBuilders: tokenManagerBuilders,
|
|
identityProviderBuilders: identityProviderBuilders(pod),
|
|
);
|
|
}
|
|
|
|
/// Signs [person] in on a new device and returns the new session's id.
|
|
Future<UuidValue> signInNewDevice(
|
|
Session session,
|
|
UuidValue person, {
|
|
Set<Scope> scopes = const {},
|
|
}) async {
|
|
Future<Set<UuidValue>> sessionIds() async => {
|
|
for (final serverSideSession in await ServerSideSession.db.find(
|
|
session,
|
|
where: (t) => t.authUserId.equals(person),
|
|
))
|
|
serverSideSession.id!,
|
|
};
|
|
|
|
final before = await sessionIds();
|
|
await AuthServices.instance.tokenManager.createToken(
|
|
session,
|
|
authUserId: person,
|
|
method: 'test',
|
|
scopes: scopes,
|
|
);
|
|
return (await sessionIds()).difference(before).single;
|
|
}
|
|
|
|
/// A person as an app's first launch creates them: anonymous.
|
|
Future<UuidValue> newAnonymousPerson(
|
|
Session session, {
|
|
DateTime? createdAt,
|
|
}) async {
|
|
final person = (await AuthServices.instance.authUsers.create(session)).id;
|
|
await AnonymousAccount.db.insertRow(
|
|
session,
|
|
AnonymousAccount(authUserId: person, createdAt: createdAt),
|
|
);
|
|
return person;
|
|
}
|