Use globals object in database rather than /_config/globals.json everywhere
[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 nodemailer_noreply = await env.site.get_nodemailer(
6     '/_config/nodemailer_noreply.json'
7   )
8   let post_request = await _require('/_lib/post_request.jst')
9   let session_cookie = await _require('/_lib/session_cookie.jst')
10   let Problem = await _require('/_lib/Problem.jst')
11
12   await post_request(
13     // env
14     env,
15     // handler
16     async (email, password) => {
17       // coerce and/or validate
18       email = email.slice(0, 256).toLowerCase()
19       password = password.slice(0, 256)
20       if (email.length === 0 || password.length < 8)
21         throw new Problem(
22           'Bad request',
23           'Minimum length check failed',
24           400
25         )
26
27       let transaction = await env.site.database.Transaction()
28       try {
29         // initialize env.session_key, set cookie in env.response
30         await session_cookie(env, transaction)
31
32         let account = await (
33           await (
34             await transaction.get({})
35           ).get('accounts', {})
36         ).get(email)
37         if (account === undefined)
38           throw new Problem(
39             'Account does not exist',
40             `Please create the account for "${email}" before attempting to reset its password.`
41             421
42           )
43
44         let link_code = crypto.randomBytes(16).toString('hex')
45         let expires = new XDate()
46         expires.addDays(1)
47         account.set_json(
48           'verify_password',
49           {password, link_code, expires: expires.getTime()}
50         )
51
52         let globals = await (await transaction.get({})).get('globals')
53         let site_url = await globals.get_json('site_url')
54         let noreply_from = await globals.get_json('noreply_from')
55         let noreply_signature = await globals.get_json('noreply_signature')
56
57         let given_names = await account.get_json('given_names', '')
58         let family_name = await account.get_json('family_name', '')
59         let name =
60           family_name.length ? `${given_names} ${family_name}` : given_names
61
62         await nodemailer_noreply.sendMail(
63           {
64             from: noreply_from,
65             to: `${name} <${email}>`,
66             subject: 'Password reset',
67             text: `Dear ${given_names},
68
69 We have received a request to reset the account password for your email address.
70
71 If this request is valid, please verify the new password by visiting the below link:
72 ${site_url}/my_account/verify_password/index.html?email=${encodeURIComponent(email)}&link_code=${encodeURIComponent(link_code)}
73
74 The link is valid for 24 hours.
75
76 Thanks,
77 ${noreply_signature}
78 `
79           }
80         )
81
82         await transaction.commit()
83       }
84       catch (error) {
85         transaction.rollback()
86         throw error
87       }
88     }
89   )
90 }