Use (Transaction|LazyValue).get_json() instead of logjson.logjson_to_json() and ...
[ndcode_site.git] / api / account / password_reset.json.jst
1 let crypto = require('crypto')
2 let XDate = require('xdate')
3
4 return async env => {
5   let globals = await env.site.get_json('/_config/globals.json')
6   let nodemailer_noreply = await env.site.get_nodemailer(
7     '/_config/nodemailer_noreply.json'
8   )
9   let post_request = await _require('/_lib/post_request.jst')
10   let session_cookie = await _require('/_lib/session_cookie.jst')
11   let Problem = await _require('/_lib/Problem.jst')
12
13   await post_request(
14     // env
15     env,
16     // handler
17     async (email, password) => {
18       // coerce and/or validate
19       email = email.slice(0, 256).toLowerCase()
20       password = password.slice(0, 256)
21       if (email.length === 0 || password.length < 8)
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 reset its password.`
42             421
43           )
44
45         let link_code = crypto.randomBytes(16).toString('hex')
46         let expires = new XDate()
47         expires.addDays(1)
48         account.set_json(
49           'verify_password',
50           {password, link_code, expires: expires.getTime()}
51         )
52
53         let given_names = await account.get_json('given_names', '')
54         let family_name = await account.get_json('family_name', '')
55         let name =
56           family_name.length ? `${given_names} ${family_name}` : given_names
57
58         await nodemailer_noreply.sendMail(
59           {
60             from: globals.noreply_from,
61             to: `${name} <${email}>`,
62             subject: 'Password reset',
63             text: `Dear ${given_names},
64
65 We have received a request to reset the account password for your email address.
66
67 If this request is valid, please verify the new password by visiting the below link:
68 ${globals.site_url}/my_account/verify_password/index.html?email=${encodeURIComponent(email)}&link_code=${encodeURIComponent(link_code)}
69
70 The link is valid for 24 hours.
71
72 Thanks,
73 ${globals.noreply_signature}
74 `
75           }
76         )
77
78         await transaction.commit()
79       }
80       catch (error) {
81         transaction.rollback()
82         throw error
83       }
84     }
85   )
86 }