All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 50s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import type { SQLOutputValue } from "node:sqlite";
|
|
import {
|
|
isRole,
|
|
type PublicUser,
|
|
type Role,
|
|
type SelfUser,
|
|
} from "../../shared/user.ts";
|
|
|
|
/** A user as stored: what they see of themselves, plus the password hash. */
|
|
export interface User extends SelfUser {
|
|
passwordHash: string;
|
|
}
|
|
|
|
export function toPublicUser(
|
|
{ passwordHash: _, email: _email, ...user }: User,
|
|
): PublicUser {
|
|
return user;
|
|
}
|
|
|
|
export function toSelfUser({ passwordHash: _, ...user }: User): SelfUser {
|
|
return user;
|
|
}
|
|
|
|
export interface UserRow {
|
|
id: string;
|
|
username: string;
|
|
password_hash: string;
|
|
role: Role;
|
|
created_at: string;
|
|
updated_at: string | null;
|
|
avatar_mime: string | null;
|
|
description: string | null;
|
|
invited_by: string | null;
|
|
// Present only when joined: LEFT JOIN users i ON i.id = u.invited_by
|
|
invited_by_username: string | null;
|
|
email: string;
|
|
[key: string]: SQLOutputValue; // Index signature
|
|
}
|
|
|
|
export function isUserRow(obj: unknown): obj is UserRow {
|
|
return !!obj &&
|
|
typeof obj === "object" &&
|
|
"id" in obj && typeof obj.id === "string" &&
|
|
"username" in obj && typeof obj.username === "string" &&
|
|
"password_hash" in obj && typeof obj.password_hash === "string" &&
|
|
"role" in obj && isRole(obj.role) &&
|
|
"created_at" in obj && typeof obj.created_at === "string" &&
|
|
"updated_at" in obj &&
|
|
(typeof obj.updated_at === "string" || obj.updated_at === null) &&
|
|
"avatar_mime" in obj &&
|
|
(typeof obj.avatar_mime === "string" || obj.avatar_mime === null) &&
|
|
"description" in obj &&
|
|
(typeof obj.description === "string" || obj.description === null) &&
|
|
"invited_by" in obj &&
|
|
(typeof obj.invited_by === "string" || obj.invited_by === null) &&
|
|
"email" in obj && typeof obj.email === "string";
|
|
}
|
|
|
|
export function userRowToApi(row: UserRow): User {
|
|
return {
|
|
id: row.id,
|
|
username: row.username,
|
|
passwordHash: row.password_hash,
|
|
role: row.role,
|
|
createdAt: new Date(row.created_at),
|
|
updatedAt: row.updated_at ? new Date(row.updated_at) : undefined,
|
|
avatarMime: row.avatar_mime ?? undefined,
|
|
description: row.description ?? undefined,
|
|
invitedByUsername: typeof row.invited_by_username === "string"
|
|
? row.invited_by_username
|
|
: undefined,
|
|
email: row.email,
|
|
};
|
|
}
|
|
|
|
export function userApiToRow(user: User): UserRow {
|
|
return {
|
|
id: user.id,
|
|
username: user.username,
|
|
password_hash: user.passwordHash,
|
|
role: user.role,
|
|
created_at: user.createdAt.toISOString(),
|
|
updated_at: user.updatedAt?.toISOString() ?? null,
|
|
avatar_mime: user.avatarMime ?? null,
|
|
description: user.description ?? null,
|
|
invited_by: null,
|
|
invited_by_username: null,
|
|
email: user.email,
|
|
};
|
|
}
|