/** * User model for Stack.Gallery Registry */ import * as plugins from '../plugins.ts'; import type { IUser, TUserStatus } from '../interfaces/auth.interfaces.ts'; import { getDb } from './db.ts'; @plugins.smartdata.Collection(() => getDb()) export class User extends plugins.smartdata.SmartDataDbDoc implements IUser { @plugins.smartdata.unI() public id: string = ''; @plugins.smartdata.svDb() @plugins.smartdata.searchable() @plugins.smartdata.index({ unique: true }) public email: string = ''; @plugins.smartdata.svDb() @plugins.smartdata.searchable() @plugins.smartdata.index({ unique: true }) public username: string = ''; @plugins.smartdata.svDb() public passwordHash: string = ''; @plugins.smartdata.svDb() @plugins.smartdata.searchable() public displayName: string = ''; @plugins.smartdata.svDb() public avatarUrl?: string; @plugins.smartdata.svDb() @plugins.smartdata.index() public status: TUserStatus = 'pending_verification'; @plugins.smartdata.svDb() public emailVerified: boolean = false; @plugins.smartdata.svDb() public mfaEnabled: boolean = false; @plugins.smartdata.svDb() public mfaSecret?: string; @plugins.smartdata.svDb() public lastLoginAt?: Date; @plugins.smartdata.svDb() public lastLoginIp?: string; @plugins.smartdata.svDb() public failedLoginAttempts: number = 0; @plugins.smartdata.svDb() public lockedUntil?: Date; @plugins.smartdata.svDb() @plugins.smartdata.index() public isPlatformAdmin: boolean = false; @plugins.smartdata.svDb() @plugins.smartdata.index() public createdAt: Date = new Date(); @plugins.smartdata.svDb() public updatedAt: Date = new Date(); /** * Create a new user instance */ public static async createUser(data: { email: string; username: string; passwordHash: string; displayName?: string; }): Promise { const user = new User(); user.id = await User.getNewId(); user.email = data.email.toLowerCase(); user.username = data.username.toLowerCase(); user.passwordHash = data.passwordHash; user.displayName = data.displayName || data.username; user.status = 'pending_verification'; user.createdAt = new Date(); user.updatedAt = new Date(); await user.save(); return user; } /** * Find user by email */ public static async findByEmail(email: string): Promise { return await User.getInstance({ email: email.toLowerCase() }); } /** * Find user by username */ public static async findByUsername(username: string): Promise { return await User.getInstance({ username: username.toLowerCase() }); } /** * Lifecycle hook: Update timestamps before save */ public async beforeSave(): Promise { this.updatedAt = new Date(); if (!this.id) { this.id = await User.getNewId(); } } }