halkyon_base: a Serverpod module for sign-in, accounts and instance basics
What every Halkyon server has, taken from Halkyon Learn's: anonymous, GitHub and email-code sign-in with their endpoints, an account's ways in and its deletion, the pruning of abandoned anonymous people, of sign-up attempts and of expired codes, and the instance's basics (the sign-in ways offered, the source link, the minimum app build, where people's data and its backups are). Endpoints sit under the nickname `base`. A host configures it in one place before its pod starts: its name for the mails, its source link, its minimum build, and hooks that delete its own data with a person. The tables keep Learn's names, columns and indexes, so a host moving onto the module migrates nothing but version rows. Server package under the SSPL, client under the AGPL, as Learn's are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
80fa7b9628
commit
af1de799f4
1 changed files with 17704 additions and 3 deletions
|
|
@ -0,0 +1,76 @@
|
|||
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';
|
||||
|
||||
/// 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(
|
||||
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;
|
||||
}
|
||||
Reference in a new issue