Implement feedback as a JSON API, fix missing await on all post_request() calls
[ndcode_site.git] / api / account / sign_up / send_email_verification_link.json.jst
1 let crypto = require('crypto')
2 let logjson = (await import('@ndcode/logjson')).default
3 let XDate = require('xdate')
4
5 return async env => {
6   let globals = await env.site.get_json('/_config/globals.json')
7   let nodemailer_noreply = await env.site.get_nodemailer(
8     '/_config/nodemailer_noreply.json'
9   )
10   let post_request = await _require('/_lib/post_request.jst')
11   let session_cookie = await _require('/_lib/session_cookie.jst')
12   let Problem = await _require('/_lib/Problem.jst')
13
14   await post_request(
15     // env
16     env,
17     // handler
18     async email => {
19       // coerce and/or validate
20       email = email.slice(0, 256).toLowerCase()
21       if (email.length === 0)
22         throw new Problem(
23           'Bad request',
24           'Minimum length check failed',
25           400
26         )
27
28       let transaction = await env.site.database.Transaction()
29       try {
30         // initialize env.session_key, set cookie in env.response
31         await session_cookie(env, transaction)
32
33         let account = await (
34           await (
35             await transaction.get({})
36           ).get('accounts', {})
37         ).get(email)
38         if (account === undefined)
39           throw new Problem(
40             'Account does not exist',
41             `Please create the account for "${email}" before attempting to send an email verification link.`
42             421
43           )
44
45         if (
46           await logjson.logjson_to_json(
47             await account.get('email_verified')
48           )
49         )
50           throw new Problem(
51             'Email already verified',
52             `Your email "${email}" is already verified. You can now sign in.`
53             422
54           )
55
56         let link_code = crypto.randomBytes(16).toString('hex')
57         let expires = new XDate()
58         expires.addDays(1)
59         account.set(
60           'verify_email',
61           transaction.json_to_logjson({link_code, expires: expires.getTime()})
62         )
63
64         let given_names = await logjson.logjson_to_json(
65           await account.get('given_names', '')
66         )
67         let family_name = await logjson.logjson_to_json(
68           await account.get('family_name', '')
69         )
70         let name =
71           family_name.length ? `${given_names} ${family_name}` : given_names
72
73         await nodemailer_noreply.sendMail(
74           {
75             from: globals.noreply_from,
76             to: `${name} <${email}>`,
77             subject: 'Email address verification',
78             text: `Dear ${given_names},
79
80 We have received a request to sign up using your email address.
81
82 If this request is valid, please verify your email address by visiting the below link:
83 ${globals.site_url}/my_account/verify_email/index.html?email=${encodeURIComponent(email)}&link_code=${encodeURIComponent(link_code)}
84
85 The link is valid for 24 hours.
86
87 Thanks,
88 ${globals.noreply_signature}
89 `
90           }
91         )
92
93         await transaction.commit()
94       }
95       catch (error) {
96         transaction.rollback()
97         throw error
98       }
99     }
100   )
101 }