--- /dev/null
+class Problem {
+ constructor(title, detail, status) {
+ this.title = title
+ this.detail = detail
+ this.status = status
+ }
+}
+
+return Problem
let icon_search_mono = await env.site.get_min_svg('/_svg/icon_search_mono.svg')
let logo_large = await env.site.get_min_svg('/_svg/logo_large.svg')
let menu = await env.site.get_menu('/_menu.json')
- let page = await _require('/page.jst')
+ let page = await _require('/_lib/page.jst')
//let session = await _require('/session.jst')
// initialize env.sessions, env.session_key, env.session
return async (env, head, body, scripts) => {
let favicons = await env.site.get_min_html('/_favicon/favicons.html')
let globals = await env.site.get_json('/_config/globals.json')
- let session_cookie = await _require('/session_cookie.jst')
+ let session_cookie = await _require('/_lib/session_cookie.jst')
// initialize env.session_key, set cookie in env.response
let transaction = await env.site.database.Transaction()
--- /dev/null
+let stream_buffers = require('stream-buffers')
+
+return async (env, api, func) => {
+ let Problem = await _require('/_lib/Problem.jst')
+
+ let result
+ try {
+ if (env.request.method !== 'POST') {
+ env.response.setHeader('Allow', 'POST')
+ throw new Problem(
+ 'Method not allowed',
+ `The endpoint "${env.parsed_url.path}" requires a POST request.`,
+ 405
+ )
+ }
+
+ let write_stream = new stream_buffers.WritableStreamBuffer()
+ let data = new Promise(
+ (resolve, reject) => {
+ write_stream.
+ on('finish', () => {resolve(write_stream.getContents())}).
+ on('error', () => {reject()})
+ }
+ )
+ env.request.pipe(write_stream)
+ let arguments = JSON.parse((await data).toString())
+ console.log('api', api, 'arguments', arguments)
+
+ result = await func(...arguments)
+ if (result === undefined)
+ result = null
+ console.log('api', api, 'result', result)
+ }
+ catch (error) {
+ let problem =
+ error instanceof Problem ?
+ error :
+ new Problem(
+ // title
+ 'Internal server error',
+ // details
+ error.message,
+ // status
+ 500
+ )
+ console.log('api', api, 'problem', problem.detail)
+
+ env.mime_type = 'application/problem+json; charset=utf-8'
+ env.site.serve(
+ env,
+ problem.status,
+ Buffer.from(
+ JSON.stringify(
+ {
+ title: problem.title,
+ detail: problem.detail,
+ status: problem.status
+ },
+ null,
+ 2
+ ) + '\n',
+ 'utf-8'
+ ),
+ 'post_request.jst'
+ )
+ return
+ }
+
+ env.site.serve(
+ env,
+ 200,
+ Buffer.from(JSON.stringify(result, null, 2) + '\n', 'utf-8'),
+ 'post_request.jst'
+ )
+}
"417": "Expectation failed",
"418": "No verification image in session",
"419": "Verification code mismatch",
- "420": "Account already exists"
+ "420": "Account already exists",
+ "500": "Internal server error",
+ "501": "Not implemented",
+ "502": "Bad gateway",
+ "503": "Service unavailable",
+ "504": "Gateway timeout",
+ "505": "HTTP version not supported"
}
+++ /dev/null
-/*let*/ sign_up = async (
- email,
- verification_code,
- given_names,
- family_name,
- password,
- contact_me
-) => {
- let response = await fetch(
- '/api/sign_up.json',
- {
- method: 'POST',
- body: JSON.stringify(
- {
- email,
- verification_code,
- given_names,
- family_name,
- password,
- contact_me
- }
- )
- }
- )
- if (!response.ok)
- throw new Error((await response.json()).detail)
- return /*await*/ response.json()
-}
+++ /dev/null
-let stream_buffers = require('stream-buffers')
-let XDate = require('xdate')
-
-return async env => {
- let session_cookie = await _require('/session_cookie.jst')
-
- if (env.request.method !== 'POST') {
- env.response.setHeader('Allow', 'POST')
- env.mime_type = 'application/problem+json; charset=utf-8'
- env.site.serve(
- env,
- 405,
- Buffer.from(
- JSON.stringify(
- {
- title: 'Method not allowed',
- detail: `The endpoint "${env.parsed_url.path}" requires a POST request.`,
- status: 405
- },
- null,
- 2
- ) + '\n',
- 'utf-8'
- ),
- 'sign_up.json.jst'
- )
- return
- }
-
- let write_stream = new stream_buffers.WritableStreamBuffer()
- let data = new Promise(
- (resolve, reject) => {
- write_stream.
- on('finish', () => {resolve(write_stream.getContents())}).
- on('error', () => {reject()})
- }
- )
- env.request.pipe(write_stream)
- let query = JSON.parse((await data).toString())
- let email = query.email.toLowerCase()
- console.log('sign up', email)
-
- // initialize env.session_key, set cookie in env.response
- let transaction = await env.site.database.Transaction()
- let session = await session_cookie(env, transaction)
-
- let captcha = await session.get('captcha')
- if (captcha === undefined || XDate.now() >= captcha.get('expires')) {
- transaction.rollback()
-
- env.mime_type = 'application/problem+json; charset=utf-8'
- env.site.serve(
- env,
- 418,
- Buffer.from(
- JSON.stringify(
- {
- title: 'No verification image in session',
- detail: `Please call the "/api/verification_image.png" endpoint to create a verification image, in same session as the "/api/sign_up.json" call and less than one hour prior.`,
- status: 418
- },
- null,
- 2
- ) + '\n',
- 'utf-8'
- ),
- 'sign_up.json.jst'
- )
- return
- }
-
-
- let verification_code = query.verification_code.toLowerCase()
- let captcha_text = await captcha.get('text')
- if (verification_code !== captcha_text) {
- console.log(`verification code mismatch, \"${verification_code}\" should be \"${captcha_text}\"`)
- transaction.rollback()
-
- env.mime_type = 'application/problem+json; charset=utf-8'
- env.site.serve(
- env,
- 419,
- Buffer.from(
- JSON.stringify(
- {
- title: 'Verification code mismatch',
- detail: `The provided verification code "${verification_code}" did not match the verification image.`,
- status: 419
- },
- null,
- 2
- ) + '\n',
- 'utf-8'
- ),
- 'sign_up.json.jst'
- )
- return
- }
-
- let accounts = await (
- await transaction.get({})
- ).get('accounts', {})
-
- if (accounts.has(email)) {
- transaction.rollback()
-
- env.mime_type = 'application/problem+json; charset=utf-8'
- env.site.serve(
- env,
- 420,
- Buffer.from(
- JSON.stringify(
- {
- title: 'Account already exists',
- detail: `The email "${email}" already has an account registered.`,
- status: 420
- },
- null,
- 2
- ) + '\n',
- 'utf-8'
- ),
- 'sign_up.json.jst'
- )
- return
- }
- accounts.set(
- email,
- transaction.json_to_logjson(
- {
- given_names: query.given_names || '',
- family_name: query.family_name || '',
- password: query.password || '',
- contact_me: query.contact_me || false,
- email_verified: false
- }
- )
- )
-
- await transaction.commit()
-
- env.site.serve(
- env,
- 200,
- Buffer.from(
- JSON.stringify(
- null,
- null,
- 2
- ) + '\n',
- 'utf-8'
- ),
- 'sign_up.json.jst'
- )
-}
--- /dev/null
+let XDate = require('xdate')
+
+return async env => {
+ let post_request = await _require('/_lib/post_request.jst')
+ let session_cookie = await _require('/_lib/session_cookie.jst')
+ let Problem = await _require('/_lib/Problem.jst')
+
+ post_request(
+ // env
+ env,
+ // api
+ '/api/sign_up/create_account',
+ // func
+ async (verification_code, details) => {
+ // coerce and/or validate
+ verification_code = verification_code.slice(0, 6).toLowerCase()
+ details = {
+ 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
+ }
+
+ let transaction = await env.site.database.Transaction()
+ try {
+ // initialize env.session_key, set cookie in env.response
+ let session = await session_cookie(env, transaction)
+
+ let captcha = await session.get('captcha')
+ 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.json" call and less than one hour prior.`,
+ 418
+ )
+
+ let captcha_text = await captcha.get('text')
+ if (verification_code !== captcha_text) {
+ console.log(`verification code mismatch, \"${verification_code}\" should be \"${captcha_text}\"`)
+
+ throw new Problem(
+ 'Verification code mismatch',
+ `The provided verification code "${verification_code}" did not match the verification image.`,
+ 419
+ )
+ }
+
+ let accounts = await (
+ await transaction.get({})
+ ).get('accounts', {})
+
+ if (accounts.has(details.email))
+ throw new Problem(
+ 'Account already exists',
+ `The email "${details.email}" already has an account registered.`,
+ 420
+ )
+ accounts.set(details.email, transaction.json_to_logjson(details))
+
+ await transaction.commit()
+ }
+ catch (error) {
+ transaction.rollback()
+ throw error
+ }
+ }
+ )
+}
let XDate = require('xdate')
return async env => {
- let session_cookie = await _require('/session_cookie.jst')
+ let session_cookie = await _require('/_lib/session_cookie.jst')
let captcha = captchagen.create()
captcha.generate()
let XDate = require('xdate')
return async env => {
- let breadcrumbs = await _require('/breadcrumbs.jst')
+ let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
let globals = await env.site.get_json('/_config/globals.json')
- let navbar = await _require('/navbar.jst')
+ let navbar = await _require('/_lib/navbar.jst')
await navbar(
env,
return async env => {
- let breadcrumbs = await _require('/breadcrumbs.jst')
+ let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
let icon_jst = await env.site.get_min_svg('/_svg/icon_jst.svg')
- let navbar = await _require('/navbar.jst')
+ let navbar = await _require('/_lib/navbar.jst')
let icon_pitree = await env.site.get_min_svg('/_svg/icon_pitree.svg')
await navbar(
--- /dev/null
+api_call = async (endpoint, ...arguments) => {
+ let response = await fetch(
+ endpoint,
+ {
+ method: 'POST',
+ body: JSON.stringify(arguments)
+ }
+ )
+ if (!response.ok)
+ throw new Error((await response.json()).detail)
+ return /*await*/ response.json()
+}
}
// insert title and body into our navbar
- let navbar = await _require('/navbar.jst')
+ let navbar = await _require('/_lib/navbar.jst')
await navbar(
env,
// head
return async env => {
//let account = await _require('/account.jst')
- let breadcrumbs = await _require('/breadcrumbs.jst')
+ let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
let menu = await env.site.get_menu('/my_account/_menu.json')
- let navbar = await _require('/navbar.jst')
+ let navbar = await _require('/_lib/navbar.jst')
await navbar(
env,
return async env => {
- let breadcrumbs = await _require('/breadcrumbs.jst')
+ let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
let icon_cross = await env.site.get_min_svg('/_svg/icon_cross.svg')
let icon_tick = await env.site.get_min_svg('/_svg/icon_tick.svg')
- let navbar = await _require('/navbar.jst')
+ let navbar = await _require('/_lib/navbar.jst')
await navbar(
env,
},
// scripts
async _out => {
- script(src="/api/sign_up.js") {}
+ script(src="/js/api_call.js") {}
script {
+ let sign_up_create_account = async (...arguments) => api_call(
+ '/api/sign_up/create_account.json',
+ ...arguments
+ )
+
$(document).ready(
() => {
$('#step-1-continue').click(
$('#step-2-cross').hide()
$('#step-2-spinner').show()
try {
- await sign_up(
- document.getElementById('email').value,
- document.getElementById('verification-code').value
- document.getElementById('given-names').value,
- document.getElementById('family-name').value,
- document.getElementById('password').value
+ await sign_up_create_account(
+ // verification_code
+ document.getElementById('verification-code').value,
+ // details
+ {
+ email: document.getElementById('email').value,
+ given_names: document.getElementById('given-names').value,
+ family_name: document.getElementById('family-name').value,
+ password: document.getElementById('password').value,
+ contact_me: document.getElementById('contact-me').value
+ }
)
}
catch (e) {
let querystring = require('querystring')
return async env => {
- let breadcrumbs = await _require('/breadcrumbs.jst')
- let navbar = await _require('/navbar.jst')
+ let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
+ let navbar = await _require('/_lib/navbar.jst')
let zet_site = await env.site.get_zettair('/_zet/site')
let query = env.parsed_url.query.query
}
// insert head before/after stylesheet and body into our navbar
- let navbar = await _require('/navbar.jst')
+ let navbar = await _require('/_lib/navbar.jst')
await navbar(
env,
// head