import { DateTime } from 'luxon'; import { BaseModel, beforeSave, column, hasMany } from '@adonisjs/lucid/orm'; import hash from '@adonisjs/core/services/hash'; import emitter from '@adonisjs/core/services/emitter'; import moment from 'moment'; import Encryption from '@ioc:Adonis/Core/Encryption'; import randtoken from 'rand-token'; import Token from './Token.js'; import Workspace from './Workspace.js'; import Service from './Service.js'; import mail from '@adonisjs/mail/services/main'; import { url } from '#config/app'; import { mailFrom } from '#config/dashboard'; import { HasMany } from '@adonisjs/lucid/types/relations'; export default class User extends BaseModel { @column({ isPrimary: true }) public id: number; @column() public email: string; @column() public username: string; @column() public password: string; @column() public lastname: string; // TODO: Type the settings object. @column() public settings: object; @column.dateTime({ autoCreate: true }) public created_at: DateTime; @column.dateTime({ autoCreate: true, autoUpdate: true }) public updated_at: DateTime; @beforeSave() public static async hashPassword(user: User) { if (user.$dirty.password) { user.password = await hash.make(user.password); } } @hasMany(() => Token, { foreignKey: 'user_id', }) public tokens: HasMany; @hasMany(() => Service, { foreignKey: 'userId', }) public services: HasMany; @hasMany(() => Workspace, { foreignKey: 'userId', }) public workspaces: HasMany; public async forgotPassword(): Promise { const token = await this.generateToken(this, 'forgot_password'); await mail.send(message => { message .from(mailFrom) .to(this.email) .subject('[Ferdium] Password Recovery') .htmlView('emails/reset_password', { username: this.username, appUrl: url, token: token, }); }); await emitter.emit('forgot:password', { user: this, token, }); } private async generateToken(user: User, type: string): Promise { const query = user .related('tokens') .query() .where('type', type) .where('is_revoked', false) .where( 'updated_at', '>=', moment().subtract(24, 'hours').format('YYYY-MM-DD HH:mm:ss'), ); const row = await query.first(); if (row) { return row.token; } const token = Encryption.encrypt(randtoken.generate(16)); await user.related('tokens').create({ type, token }); return token; } }