aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared/server-commands/users/two-factor-command.ts
blob: 5542acfdad994a99883e4431ff42bdd73353da33 (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
import { TOTP } from 'otpauth'
import { HttpStatusCode, TwoFactorEnableResult } from '@shared/models'
import { unwrapBody } from '../requests'
import { AbstractCommand, OverrideCommandOptions } from '../shared'

export class TwoFactorCommand extends AbstractCommand {

  static buildOTP (options: {
    secret: string
  }) {
    const { secret } = options

    return new TOTP({
      issuer: 'PeerTube',
      algorithm: 'SHA1',
      digits: 6,
      period: 30,
      secret
    })
  }

  request (options: OverrideCommandOptions & {
    userId: number
    currentPassword?: string
  }) {
    const { currentPassword, userId } = options

    const path = '/api/v1/users/' + userId + '/two-factor/request'

    return unwrapBody<TwoFactorEnableResult>(this.postBodyRequest({
      ...options,

      path,
      fields: { currentPassword },
      implicitToken: true,
      defaultExpectedStatus: HttpStatusCode.OK_200
    }))
  }

  confirmRequest (options: OverrideCommandOptions & {
    userId: number
    requestToken: string
    otpToken: string
  }) {
    const { userId, requestToken, otpToken } = options

    const path = '/api/v1/users/' + userId + '/two-factor/confirm-request'

    return this.postBodyRequest({
      ...options,

      path,
      fields: { requestToken, otpToken },
      implicitToken: true,
      defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
    })
  }

  disable (options: OverrideCommandOptions & {
    userId: number
    currentPassword?: string
  }) {
    const { userId, currentPassword } = options
    const path = '/api/v1/users/' + userId + '/two-factor/disable'

    return this.postBodyRequest({
      ...options,

      path,
      fields: { currentPassword },
      implicitToken: true,
      defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
    })
  }

  async requestAndConfirm (options: OverrideCommandOptions & {
    userId: number
    currentPassword?: string
  }) {
    const { userId, currentPassword } = options

    const { otpRequest } = await this.request({ userId, currentPassword })

    await this.confirmRequest({
      userId,
      requestToken: otpRequest.requestToken,
      otpToken: TwoFactorCommand.buildOTP({ secret: otpRequest.secret }).generate()
    })

    return otpRequest
  }
}