From c943d7ed3a8929055d76ff3da4b55f08335601cf Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sun, 16 Jan 2022 22:05:39 +1100 Subject: [PATCH] Move account-related APIs down one level into /api/account and the former /api/sign_up to /api/account/sign_up, improve error checking and refactor code a bit --- _lib/navbar.jst | 6 +-- _lib/post_request.jst | 8 ++-- api/{ => account}/password_reset.json.jst | 2 - api/{ => account}/sign_in.json.jst | 2 - api/{ => account}/sign_out.json.jst | 2 - .../sign_up/create_account.json.jst | 4 +- api/{ => account}/sign_up/get_draft.json.jst | 2 - .../send_email_verification_link.json.jst | 15 ++++-- api/{ => account}/sign_up/set_draft.json.jst | 3 -- .../sign_up/verify_email.json.jst | 2 - api/{ => account}/verify_password.json.jst | 2 - api/feedback.json.jst | 2 - my_account/password_reset/index.html.jst | 2 +- .../send_verification_email/index.html.jst | 2 +- my_account/sign_up/index.html.jst | 48 ++++++++++--------- my_account/verify_email/index.html.jst | 2 +- my_account/verify_password/index.html.jst | 2 +- 17 files changed, 50 insertions(+), 56 deletions(-) rename api/{ => account}/password_reset.json.jst (98%) rename api/{ => account}/sign_in.json.jst (97%) rename api/{ => account}/sign_out.json.jst (95%) rename api/{ => account}/sign_up/create_account.json.jst (95%) rename api/{ => account}/sign_up/get_draft.json.jst (93%) rename api/{ => account}/sign_up/send_email_verification_link.json.jst (88%) rename api/{ => account}/sign_up/set_draft.json.jst (90%) rename api/{ => account}/sign_up/verify_email.json.jst (97%) rename api/{ => account}/verify_password.json.jst (97%) diff --git a/_lib/navbar.jst b/_lib/navbar.jst index a993c46..db455b4 100644 --- a/_lib/navbar.jst +++ b/_lib/navbar.jst @@ -294,15 +294,15 @@ return async (env, head, body, scripts) => { script { let sign_in = async (...arguments) => api_call( - '/api/sign_in.json', + '/api/account/sign_in.json', ...arguments ) let sign_out = async (...arguments) => api_call( - '/api/sign_out.json', + '/api/account/sign_out.json', ...arguments ) let feedback = async (...arguments) => api_call( - '/api/feedback.json', + '/api/account/feedback.json', ...arguments ) diff --git a/_lib/post_request.jst b/_lib/post_request.jst index 59c780e..73fa773 100644 --- a/_lib/post_request.jst +++ b/_lib/post_request.jst @@ -1,6 +1,6 @@ let stream_buffers = require('stream-buffers') -return async (env, endpoint, handler) => { +return async (env, handler) => { let Problem = await _require('/_lib/Problem.jst') let result @@ -24,12 +24,12 @@ return async (env, endpoint, handler) => { ) env.request.pipe(write_stream) let arguments = JSON.parse((await data).toString()) - console.log('endpoint', endpoint, 'arguments', JSON.stringify(arguments)) + console.log('endpoint', env.parsed_url.path, 'arguments', JSON.stringify(arguments)) result = await handler(...arguments) if (result === undefined) result = null - console.log('endpoint', endpoint, 'result', JSON.stringify(result)) + console.log('endpoint', env.parsed_url.path, 'result', JSON.stringify(result)) } catch (error) { let problem = @@ -43,7 +43,7 @@ return async (env, endpoint, handler) => { // status 500 ) - console.log('endpoint', endpoint, 'problem', problem.detail) + console.log('endpoint', env.parsed_url.path, 'problem', problem.detail) env.mime_type = 'application/problem+json; charset=utf-8' env.site.serve( diff --git a/api/password_reset.json.jst b/api/account/password_reset.json.jst similarity index 98% rename from api/password_reset.json.jst rename to api/account/password_reset.json.jst index b439a17..cb11270 100644 --- a/api/password_reset.json.jst +++ b/api/account/password_reset.json.jst @@ -14,8 +14,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/password_reset.json', // handler async (email, password) => { // coerce and/or validate diff --git a/api/sign_in.json.jst b/api/account/sign_in.json.jst similarity index 97% rename from api/sign_in.json.jst rename to api/account/sign_in.json.jst index bf3b02e..b963f97 100644 --- a/api/sign_in.json.jst +++ b/api/account/sign_in.json.jst @@ -12,8 +12,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/sign_in.json', // handler async (email, password) => { // coerce and/or validate diff --git a/api/sign_out.json.jst b/api/account/sign_out.json.jst similarity index 95% rename from api/sign_out.json.jst rename to api/account/sign_out.json.jst index 264fb3c..3ddf3c8 100644 --- a/api/sign_out.json.jst +++ b/api/account/sign_out.json.jst @@ -12,8 +12,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/sign_out.json', // handler async () => { let transaction = await env.site.database.Transaction() diff --git a/api/sign_up/create_account.json.jst b/api/account/sign_up/create_account.json.jst similarity index 95% rename from api/sign_up/create_account.json.jst rename to api/account/sign_up/create_account.json.jst index bb96f5c..85c4ef7 100644 --- a/api/sign_up/create_account.json.jst +++ b/api/account/sign_up/create_account.json.jst @@ -8,8 +8,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/sign_up/create_account.json', // handler async (verification_code, details) => { // coerce and/or validate @@ -41,7 +39,7 @@ return async env => { if (captcha === undefined || XDate.now() >= captcha.get('expires')) throw new Problem( 'No verification image in session', - `Please call the "/api/verification_image.png" endpoint to create a verification image, in same session as the "/api/sign_up/create_account.json" call and less than one hour prior.`, + `Please call the "/api/verification_image.png" endpoint to create a verification image, in same session as the "/api/account/sign_up/create_account.json" call and less than one hour prior.`, 418 ) diff --git a/api/sign_up/get_draft.json.jst b/api/account/sign_up/get_draft.json.jst similarity index 93% rename from api/sign_up/get_draft.json.jst rename to api/account/sign_up/get_draft.json.jst index 44f20f0..197fd24 100644 --- a/api/sign_up/get_draft.json.jst +++ b/api/account/sign_up/get_draft.json.jst @@ -9,8 +9,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/sign_up/get_draft.json', // handler async () => { let transaction = await env.site.database.Transaction() diff --git a/api/sign_up/send_email_verification_link.json.jst b/api/account/sign_up/send_email_verification_link.json.jst similarity index 88% rename from api/sign_up/send_email_verification_link.json.jst rename to api/account/sign_up/send_email_verification_link.json.jst index 08f0db6..ee1b7b4 100644 --- a/api/sign_up/send_email_verification_link.json.jst +++ b/api/account/sign_up/send_email_verification_link.json.jst @@ -14,8 +14,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/sign_up/send_verification_email.json', // handler async email => { // coerce and/or validate @@ -40,10 +38,21 @@ return async env => { if (account === undefined) throw new Problem( 'Account does not exist', - `Please create the account for "${email}" before attempting to send a email verification link.` + `Please create the account for "${email}" before attempting to send an email verification link.` 421 ) + if ( + await logjson.logjson_to_json( + await account.get('email_verified') + ) + ) + throw new Problem( + 'Email already verified', + `Your email "${email}" is already verified. You can now sign in.` + 422 + ) + let link_code = crypto.randomBytes(16).toString('hex') let expires = new XDate() expires.addDays(1) diff --git a/api/sign_up/set_draft.json.jst b/api/account/sign_up/set_draft.json.jst similarity index 90% rename from api/sign_up/set_draft.json.jst rename to api/account/sign_up/set_draft.json.jst index e7d2457..f7ca03b 100644 --- a/api/sign_up/set_draft.json.jst +++ b/api/account/sign_up/set_draft.json.jst @@ -8,8 +8,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/sign_up/set_draft.json', // handler async details => { // coerce and/or validate @@ -17,7 +15,6 @@ return async env => { email: details.email.slice(0, 256).toLowerCase(), given_names: details.given_names.slice(0, 256), family_name: details.family_name.slice(0, 256), - password: details.password.slice(0, 256), contact_me: details.contact_me ? true : false } diff --git a/api/sign_up/verify_email.json.jst b/api/account/sign_up/verify_email.json.jst similarity index 97% rename from api/sign_up/verify_email.json.jst rename to api/account/sign_up/verify_email.json.jst index 8ff628a..1fe908c 100644 --- a/api/sign_up/verify_email.json.jst +++ b/api/account/sign_up/verify_email.json.jst @@ -10,8 +10,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/sign_up/verify_email.json', // handler async (email, link_code) => { // coerce and/or validate diff --git a/api/verify_password.json.jst b/api/account/verify_password.json.jst similarity index 97% rename from api/verify_password.json.jst rename to api/account/verify_password.json.jst index bb36a53..0d5359d 100644 --- a/api/verify_password.json.jst +++ b/api/account/verify_password.json.jst @@ -10,8 +10,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/verify_password.json', // handler async (email, link_code) => { // coerce and/or validate diff --git a/api/feedback.json.jst b/api/feedback.json.jst index 860f3e2..30761c6 100644 --- a/api/feedback.json.jst +++ b/api/feedback.json.jst @@ -12,8 +12,6 @@ return async env => { await post_request( // env env, - // endpoint - '/api/feedback.json', // handler async (page, message) => { // coerce and/or validate diff --git a/my_account/password_reset/index.html.jst b/my_account/password_reset/index.html.jst index 0e74ab5..ffae545 100644 --- a/my_account/password_reset/index.html.jst +++ b/my_account/password_reset/index.html.jst @@ -101,7 +101,7 @@ return async env => { script { let password_reset = async (...arguments) => api_call( - '/api/password_reset.json', + '/api/account/password_reset.json', ...arguments ) diff --git a/my_account/send_verification_email/index.html.jst b/my_account/send_verification_email/index.html.jst index cc03ade..32f6c75 100644 --- a/my_account/send_verification_email/index.html.jst +++ b/my_account/send_verification_email/index.html.jst @@ -95,7 +95,7 @@ return async env => { script { let sign_up_send_email_verification_link = async (...arguments) => api_call( - '/api/sign_up/send_email_verification_link.json', + '/api/account/sign_up/send_email_verification_link.json', ...arguments ) diff --git a/my_account/sign_up/index.html.jst b/my_account/sign_up/index.html.jst index 9f10481..228b5b0 100644 --- a/my_account/sign_up/index.html.jst +++ b/my_account/sign_up/index.html.jst @@ -78,7 +78,7 @@ return async env => { div.col-md-6 { div.form-group { label.form-label(for="password") {'Password *'} - input.form-control#password(type="password" value=details.password || '' placeholder="New password" required="required" minlength=8 maxlength=256) {} + input.form-control#password(type="password" placeholder="New password" required="required" minlength=8 maxlength=256) {} } } } @@ -182,36 +182,33 @@ return async env => { script { let sign_up_create_account = async (...arguments) => api_call( - '/api/sign_up/create_account.json', + '/api/account/sign_up/create_account.json', ...arguments ) //let sign_up_get_draft = async (...arguments) => api_call( - // '/api/sign_up/get_draft.json', + // '/api/account/sign_up/get_draft.json', // ...arguments //) let sign_up_set_draft = async (...arguments) => api_call( - '/api/sign_up/set_draft.json', + '/api/account/sign_up/set_draft.json', ...arguments ) let sign_up_send_email_verification_link = async (...arguments) => api_call( - '/api/sign_up/send_email_verification_link.json', + '/api/account/sign_up/send_email_verification_link.json', ...arguments ) - let coerce_details = () => { - return { - email: document.getElementById('email').value.slice(0, 256).toLowerCase(), - given_names: document.getElementById('given-names').value.slice(0, 256), - family_name: document.getElementById('family-name').value.slice(0, 256), - password: document.getElementById('password').value.slice(0, 256), - contact_me: document.getElementById('contact-me').checked ? true : false - } - } - let draft_timeout_running = false let draft_timeout_handler = async () => { draft_timeout_running = false - await sign_up_set_draft(coerce_details()) + await sign_up_set_draft( + { + email: document.getElementById('email').value.slice(0, 256).toLowerCase(), + given_names: document.getElementById('given-names').value.slice(0, 256), + family_name: document.getElementById('family-name').value.slice(0, 256), + contact_me: document.getElementById('contact-me').checked ? true : false + } + ) //console.log('draft', await sign_up_get_draft()) } let draft_change_handler = () => { @@ -221,6 +218,7 @@ return async env => { } } + let details let step_1 = async () => { if ( !document.getElementById('given-names').reportValidity() || @@ -237,10 +235,17 @@ return async env => { $('#step-1-tick').show() $('#step-1-cross').hide() //$('#step-1-spinner').hide() + + details = { + email: document.getElementById('email').value.slice(0, 256).toLowerCase(), + given_names: document.getElementById('given-names').value.slice(0, 256), + family_name: document.getElementById('family-name').value.slice(0, 256), + password: document.getElementById('password').value.slice(0, 256), + contact_me: document.getElementById('contact-me').checked ? true : false + } return true } - let step_2_details = '' let step_2 = async () => { $('#step-2-tick').hide() $('#step-2-cross').hide() @@ -248,12 +253,11 @@ return async env => { document.getElementById('step-2').scrollIntoView() try { - step_2_details = coerce_details() await sign_up_create_account( // verification_code document.getElementById('verification-code').value.slice(0, 6).toLowerCase(), // details - step_2_details + details ) } catch (error) { @@ -280,7 +284,7 @@ return async env => { $('#step-2-tick').show() $('#step-2-cross').hide() $('#step-2-spinner').hide() - document.getElementById('step-2-message').textContent = `Your account with email "${step_2_details.email}" has been created.` + document.getElementById('step-2-message').textContent = `Your account with email "${details.email}" has been created.` return true } @@ -291,7 +295,7 @@ return async env => { document.getElementById('step-3').scrollIntoView() try { - await sign_up_send_email_verification_link(step_2_details.email) + await sign_up_send_email_verification_link(details.email) } catch (error) { let problem = @@ -318,7 +322,7 @@ return async env => { $('#step-3-cross').hide() $('#step-3-spinner').hide() - document.getElementById('step-3-message').textContent = `Email verification link has been sent to "${step_2_details.email}". Please check your email for next steps.` + document.getElementById('step-3-message').textContent = `Email verification link has been sent to "${details.email}". Please check your email for next steps.` return true } diff --git a/my_account/verify_email/index.html.jst b/my_account/verify_email/index.html.jst index e61683d..142e10e 100644 --- a/my_account/verify_email/index.html.jst +++ b/my_account/verify_email/index.html.jst @@ -109,7 +109,7 @@ return async env => { script { let sign_up_verify_email = async (...arguments) => api_call( - '/api/sign_up/verify_email.json', + '/api/account/sign_up/verify_email.json', ...arguments ) diff --git a/my_account/verify_password/index.html.jst b/my_account/verify_password/index.html.jst index a61916d..7fecc81 100644 --- a/my_account/verify_password/index.html.jst +++ b/my_account/verify_password/index.html.jst @@ -109,7 +109,7 @@ return async env => { script { let verify_password = async (...arguments) => api_call( - '/api/verify_password.json', + '/api/account/verify_password.json', ...arguments ) -- 2.34.1