aboutsummaryrefslogtreecommitdiffstats
path: root/app/Models/User.ts
blob: 0ed4627c24cc478c07dd84210e180aad0ae6705d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import { DateTime } from 'luxon';
import {
  BaseModel,
  beforeSave,
  column,
  HasMany,
  hasMany,
} from '@ioc:Adonis/Lucid/Orm';
import Hash from '@ioc:Adonis/Core/Hash';
import Event from '@ioc:Adonis/Core/Event';
import moment from 'moment';
import Encryption from '@ioc:Adonis/Core/Encryption';
import randtoken from 'rand-token';
import Token from './Token';
import Workspace from './Workspace';
import Service from './Service';

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<typeof Token>;

  @hasMany(() => Service, {
    foreignKey: 'userId',
  })
  public services: HasMany<typeof Service>;

  @hasMany(() => Workspace, {
    foreignKey: 'userId',
  })
  public workspaces: HasMany<typeof Workspace>;

  public async forgotPassword(): Promise<void> {
    const token = await this.generateToken(this, 'forgot_password');

    await Event.emit('forgot:password', {
      user: this,
      token,
    });
  }

  private async generateToken(user: User, type: string): Promise<string> {
    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;
  }
}