-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathutils.ts
83 lines (75 loc) · 2.9 KB
/
utils.ts
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
import { components } from './generated/api-types'
import { decodeAddress, cryptoWaitReady, signatureVerify } from '@polkadot/util-crypto'
import { BadRequestError } from './errors'
import { config, ConfigVariable } from '../utils/config'
import { JOYSTREAM_ADDRESS_PREFIX } from '@joystream/types'
import { Account, Token, TokenType } from '../model'
import { EntityManager } from 'typeorm'
import { uniqueId } from '../utils/crypto'
import { sgSendMail } from '../utils/mail'
import { formatDate } from '../utils/date'
import { registerEmailContent } from './emails'
export async function verifyActionExecutionRequest(
em: EntityManager,
{ payload, signature }: components['schemas']['ActionExecutionRequestData']
): Promise<void> {
await cryptoWaitReady()
const signatureVerifyResult = signatureVerify(
JSON.stringify(payload),
signature,
decodeAddress(payload.joystreamAccountId, false, JOYSTREAM_ADDRESS_PREFIX)
)
if (!signatureVerifyResult.isValid || signatureVerifyResult.crypto !== 'sr25519') {
throw new BadRequestError('Payload signature is invalid.')
}
const appName = await config.get(ConfigVariable.AppName, em)
const proofExpiryTimeSeconds = await config.get(
ConfigVariable.AccountOwnershipProofExpiryTimeSeconds,
em
)
if (payload.gatewayName !== appName) {
throw new BadRequestError('Payload gatewayName does not match the app name.')
}
if (payload.timestamp < Date.now() - proofExpiryTimeSeconds * 1000) {
throw new BadRequestError(
`Payload timestamp cannot be older than ${proofExpiryTimeSeconds} seconds.`
)
}
if (payload.timestamp > Date.now()) {
throw new BadRequestError('Payload timestamp is in the future.')
}
}
export async function issueEmailConfirmationToken(
account: Account,
em: EntityManager
): Promise<Token> {
const issuedAt = new Date()
const lifetimeMs =
(await config.get(ConfigVariable.EmailConfirmationTokenExpiryTimeHours, em)) * 3_600_000
const expiry = new Date(issuedAt.getTime() + lifetimeMs)
const token = new Token({
id: uniqueId(),
type: TokenType.EMAIL_CONFIRMATION,
expiry,
issuedAt,
issuedForId: account.id,
})
return em.save(token)
}
export async function sendWelcomeEmail(account: Account, em: EntityManager): Promise<void> {
const emailConfirmationToken = await issueEmailConfirmationToken(account, em)
const appName = await config.get(ConfigVariable.AppName, em)
const confirmEmailRoute = await config.get(ConfigVariable.EmailConfirmationRoute, em)
const emailConfirmationLink = confirmEmailRoute.replace('{token}', emailConfirmationToken.id)
const emailContent = registerEmailContent({
link: emailConfirmationLink,
linkExpiryDate: formatDate(emailConfirmationToken.expiry),
appName,
})
await sgSendMail({
from: await config.get(ConfigVariable.SendgridFromEmail, em),
to: account.email,
subject: `Welcome to ${appName}!`,
content: emailContent,
})
}