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