/** * Users as the API shows them, their roles, and the bodies and answers of * sign-up, sign-in, profile edits and invites. * * @module */ /** What a user may do beyond the basics; see `ROLE_PERMISSIONS`. */ export type Role = "user" | "moderator" | "admin"; /** Every {@link Role}, least to most privileged. */ export const ROLES: readonly Role[] = ["user", "moderator", "admin"]; /** Checks whether `value` is a {@link Role}. */ export function isRole(value: unknown): value is Role { return typeof value === "string" && (ROLES as readonly string[]).includes(value); } /** A user as anyone may see them: no password hash, no email. */ export interface PublicUser { /** The user's id. */ id: string; /** The user's name, fixed at sign-up. */ username: string; /** The user's role. */ role: Role; /** When the user signed up. */ createdAt: Date; /** When the user last changed, if ever. */ updatedAt?: Date; /** The avatar's type, undefined without one. */ avatarMime?: string; /** The user's description of themselves, in Markdown. */ description?: string; /** The name of whoever invited them. */ invitedByUsername?: string; } /** A user as they see themselves: everything but the password hash. */ export interface SelfUser extends PublicUser { /** The address password resets are sent to. */ email: string; } /** A match for the @mention autocomplete. */ export interface UserSuggestion { /** The user's id. */ id: string; /** The user's name. */ username: string; /** The avatar's type, null without one. */ avatarMime: string | null; } /** Someone a user invited, directly or down the line. */ export interface Invitee { /** The user's id. */ id: string; /** The user's name. */ username: string; /** The avatar's type, undefined without one. */ avatarMime?: string; /** The id of whoever invited them, to build the tree. */ invitedById: string; /** When they signed up. */ createdAt: Date; } /** The body of `POST /api/users/login`. */ export interface LoginUserRequest { /** The user's name. */ username: string; /** The user's password. */ password: string; } /** The body of `POST /api/users/register`. */ export interface RegisterUserRequest { /** The name to sign up with. */ username: string; /** The password to sign up with. */ password: string; /** The invite's token. */ inviteToken: string; /** The address password resets will be sent to. */ email: string; } /** * Fields of a user to change. `PATCH /api/users/me` takes only `description` * and `email` from it; the role and the password change through their own * endpoints. */ export interface UpdateUserRequest { /** The new name. */ username?: string; /** The new password. */ password?: string; /** The new role. */ role?: Role; /** The new description; `null` removes it. */ description?: string | null; /** The new email address. */ email?: string; } /** The session token, plus the media-only one for file and thumbnail URLs. */ export interface AuthTokens { /** The session token, sent as a bearer token. */ token: string; /** The token media URLs carry as `?token=`, good for nothing else. */ mediaToken: string; } /** What sign-up and sign-in answer: the user and their tokens. */ export interface AuthResponse extends AuthTokens { /** The signed-in user. */ user: SelfUser; } /** `GET /api/users/me/media-token`: a fresh media token. */ export type MediaTokenResponse = Pick; /** `POST /api/invites`: the new invite's token. */ export interface InviteResponse { /** The token, which the invite link carries. */ token: string; }