Use jst_server.Problem everywhere, make /_lib/post_request.jst use jst_server's new...
[ndcode_site.git] / api / account / verify_password.json.jst
1 let crypto = require('crypto')
2 let jst_server = (await import('@ndcode/jst_server')).default
3 let XDate = require('xdate')
4
5 return async env => {
6   let post_request = await _require('/_lib/post_request.jst')
7
8   await post_request(
9     // env
10     env,
11     // handler
12     async (email, link_code) => {
13       // coerce and/or validate
14       email = email.slice(0, 256).toLowerCase()
15       link_code = link_code.slice(0, 256).toLowerCase()
16       if (email.length === 0 || link_code.length < 32)
17         throw new jst_server.Problem(
18           'Bad request',
19           'Minimum length check failed',
20           400
21         )
22
23       let transaction = await env.site.database.Transaction()
24       try {
25         let root = await transaction.get({})
26         let accounts = await root.get('accounts', {})
27         let account = await accounts.get(email)
28         if (account === undefined)
29           throw new jst_server.Problem(
30             'Account does not exist',
31             `Please create the account for "${email}" before attempting to verify the password reset link.`
32             421
33           )
34
35         let verify_password = await account.get('verify_password')
36         if (
37           verify_password === undefined ||
38             XDate.now() >= await verify_password.get_json('expires')
39         )
40           throw new jst_server.Problem(
41             'Link code missing',
42             `Password reset link code for account "${email}" does not exist or has expired.`,
43             423
44           )
45         if (link_code !== await verify_password.get_json('link_code'))
46           throw new jst_server.Problem(
47             'Link code mismatch',
48             `Provided password reset link code "${link_code}" does not match expected value.`,
49             423
50           )
51
52         await account.delete('verify_password')
53         await account.set('password', await verify_password.get('password'))
54
55         await transaction.commit()
56       }
57       catch (error) {
58         transaction.rollback()
59         throw error
60       }
61     }
62   )
63 }