Change /_lib/session_cookie.jst to /_lib/get_session.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 post_request = await _require('/_lib/post_request.jst')
7   let get_session = await _require('/_lib/get_session.jst')
8   let Problem = await _require('/_lib/Problem.jst')
9
10   await post_request(
11     // env
12     env,
13     // handler
14     async (email, password) => {
15       // coerce and/or validate
16       email = email.slice(0, 256).toLowerCase()
17       password = password.slice(0, 256)
18       if (email.length === 0 || password.length < 8)
19         throw new Problem(
20           'Bad request',
21           'Minimum length check failed',
22           400
23         )
24
25       let transaction = await env.site.database.Transaction()
26       let link_code
27       let nodemailer_noreply, noreply_from, noreply_signature
28       let given_names, family_name
29       try {
30         // initialize env.session_key, set cookie in env.response
31         await get_session(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         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 root = await transaction.get({})
54         nodemailer_noreply = nodemailer.createTransport(
55           await (await root.get('nodemailer')).get_json('noreply')
56         )
57         let globals = await root.get('globals')
58         site_url = await globals.get_json('site_url')
59         noreply_from = await globals.get_json('noreply_from')
60         noreply_signature = await globals.get_json('noreply_signature')
61
62         given_names = await account.get_json('given_names', '')
63         family_name = await account.get_json('family_name', '')
64
65         await transaction.commit()
66       }
67       catch (error) {
68         transaction.rollback()
69         throw error
70       }
71
72       let name =
73         family_name.length ? `${given_names} ${family_name}` : given_names
74       await nodemailer_noreply.sendMail(
75         {
76           from: noreply_from,
77           to: `${name} <${email}>`,
78           subject: 'Password reset',
79           text: `Dear ${given_names},
80
81 We have received a request to reset the account password for your email address.
82
83 If this request is valid, please verify the new password by visiting the below link:
84 ${site_url}/my_account/verify_password/index.html?email=${encodeURIComponent(email)}&link_code=${encodeURIComponent(link_code)}
85
86 The link is valid for 24 hours.
87
88 Thanks,
89 ${noreply_signature}
90 `
91         }
92       )
93     }
94   )
95 }