import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, Index, ManyToOne, JoinColumn, } from 'typeorm'; import { User } from './user.entity.js'; import { Session } from './session.entity.js'; export enum CodeType { TOTP_SETUP = 'totp_setup', SMS = 'sms', EMAIL = 'email', BACKUP = 'backup', } @Entity({ schema: 'auth', name: 'verification_codes' }) @Index('idx_verification_codes_user', ['userId', 'codeType'], { where: 'used_at IS NULL', }) @Index('idx_verification_codes_expires', ['expiresAt'], { where: 'used_at IS NULL', }) export class VerificationCode { @PrimaryGeneratedColumn('uuid') id: string; // Relaciones @Column({ type: 'uuid', nullable: false, name: 'user_id' }) userId: string; @Column({ type: 'uuid', nullable: true, name: 'session_id' }) sessionId: string | null; // Tipo de código @Column({ type: 'enum', enum: CodeType, nullable: false, name: 'code_type', }) codeType: CodeType; // Código (hash SHA-256) @Column({ type: 'varchar', length: 64, nullable: false, name: 'code_hash' }) codeHash: string; @Column({ type: 'integer', default: 6, nullable: false, name: 'code_length' }) codeLength: number; // Destino (para SMS/Email) @Column({ type: 'varchar', length: 256, nullable: true }) destination: string | null; // Intentos @Column({ type: 'integer', default: 0, nullable: false }) attempts: number; @Column({ type: 'integer', default: 5, nullable: false, name: 'max_attempts' }) maxAttempts: number; // Validez @CreateDateColumn({ name: 'created_at', type: 'timestamptz' }) createdAt: Date; @Column({ type: 'timestamptz', nullable: false, name: 'expires_at' }) expiresAt: Date; @Column({ type: 'timestamptz', nullable: true, name: 'used_at' }) usedAt: Date | null; // Metadata @Column({ type: 'inet', nullable: true, name: 'ip_address' }) ipAddress: string | null; @Column({ type: 'text', nullable: true, name: 'user_agent' }) userAgent: string | null; // Relaciones @ManyToOne(() => User, { onDelete: 'CASCADE' }) @JoinColumn({ name: 'user_id' }) user: User; @ManyToOne(() => Session, { onDelete: 'CASCADE', nullable: true }) @JoinColumn({ name: 'session_id' }) session: Session | null; }