Added the catalogue models and seed to support phase 5 of the POC prototype in the Persistence package.
This commit is contained in:
1 parent
9403931109
commit
89a7a7b8e5
19 files changed
+990
-15
No files matched your search
@@ -117,6 +117,63 @@ public struct AccountRepository: Sendable {
|
||||
.update()
|
||||
}
|
||||
|
||||
/// Adds a passkey to an account. Only ever for the account's own session: holding one is the proof of who is asking.
|
||||
public func addPasskey(
|
||||
to user: User,
|
||||
credentialID: String,
|
||||
publicKey: [UInt8],
|
||||
signCount: UInt32
|
||||
) async throws {
|
||||
try await PasskeyRecord(
|
||||
userID: user.id,
|
||||
credentialID: credentialID,
|
||||
publicKey: publicKey,
|
||||
signCount: signCount,
|
||||
at: .init()
|
||||
).save(on: fluent.db())
|
||||
}
|
||||
|
||||
/// Fetches the passkeys registered to an account, the oldest first, with when each was created.
|
||||
public func passkeys(
|
||||
of user: User
|
||||
) async throws -> [(passkey: Passkey, createdAt: Date)] {
|
||||
try await PasskeyRecord.query(on: fluent.db())
|
||||
.filter(\.$user.$id == user.id)
|
||||
.sort(\.$createdAt)
|
||||
.with(\.$user)
|
||||
.all()
|
||||
.map { (try $0.snapshot, $0.createdAt) }
|
||||
}
|
||||
|
||||
/// Changes an account's display name.
|
||||
/// - Returns: the account, renamed.
|
||||
public func rename(
|
||||
_ user: User,
|
||||
to displayName: String
|
||||
) async throws -> User {
|
||||
try await UserRecord.query(on: fluent.db())
|
||||
.filter(\.$id == user.id)
|
||||
.set(\.$displayName, to: displayName)
|
||||
.update()
|
||||
|
||||
return .init(
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
displayName: displayName
|
||||
)
|
||||
}
|
||||
|
||||
/// Revokes one of an account's passkeys, taking effect at once.
|
||||
public func revokePasskey(
|
||||
_ credentialID: String,
|
||||
of user: User
|
||||
) async throws {
|
||||
try await PasskeyRecord.query(on: fluent.db())
|
||||
.filter(\.$credentialID == credentialID)
|
||||
.filter(\.$user.$id == user.id)
|
||||
.delete()
|
||||
}
|
||||
|
||||
/// Fetches the account with the given email, creating it when there is none: one step both signs in and joins.
|
||||
///
|
||||
/// A new account is named after the email's local part until its owner picks a display name.
|
||||
@@ -125,11 +182,16 @@ public struct AccountRepository: Sendable {
|
||||
public func account(
|
||||
email: String
|
||||
) async throws -> User {
|
||||
if let record = try await UserRecord.query(on: fluent.db())
|
||||
.filter(\.$email == email)
|
||||
.first()
|
||||
{
|
||||
return try record.snapshot
|
||||
try await signIn(email: email).user
|
||||
}
|
||||
|
||||
/// Fetches the account with the given email, creating it when there is none, and says which happened.
|
||||
/// - Returns: the account, and whether this step created it.
|
||||
public func signIn(
|
||||
email: String
|
||||
) async throws -> (user: User, isNew: Bool) {
|
||||
if let user = try await existingAccount(email: email) {
|
||||
return (user, false)
|
||||
}
|
||||
|
||||
let record = UserRecord(
|
||||
@@ -139,7 +201,7 @@ public struct AccountRepository: Sendable {
|
||||
|
||||
try await record.save(on: fluent.db())
|
||||
|
||||
return try record.snapshot
|
||||
return (try record.snapshot, true)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user