}
' '
if (env.signed_in_as !== null)
- a#sign-in(href="" hidden="") {'Sign in'}
+ a#sign-in(href="#" style="display: none;") {'Sign in'}
else
- a#sign-in(href="") {'Sign in'}
+ a#sign-in(href="#") {'Sign in'}
' '
if (env.signed_in_as !== null)
- a#sign-out(href="") {'Sign out'}
+ a#sign-out(href="#") {'Sign out'}
else
- a#sign-out(href="" hidden="") {'Sign out'}
+ a#sign-out(href="#" style="display: none;") {'Sign out'}
}
- form/*.form-inline*/(action="/search/index.html") {
+ form(action="/search/index.html") {
div.input-group {
input.form-control(name="query" type="text" placeholder="Search" aria-describedby="search-button") {}
div.input-group-append {
}
ul.navbar-nav.ml-auto {
li.nav-item {
- a.nav-link#give-feedback(href="") {'Give feedback'}
+ a.nav-link#give-feedback(href="#") {'Give feedback'}
}
}
}
}
// hidden part
- //div#sign-in-modal.modal.fade(role="dialog") {
- // div.modal-dialog {
- // div.modal-content {
- // div.modal-header {
- // span.h4.modal-title {'Sign in'}
- // }
- // div.modal-body {
- // form#sign-in-form(method="post" action="/sign_in.json" role="form") {
- // div.row {
- // div.col-md-12 {
- // div.form-group {
- // label(for="sign-in-form-email") {'Email'}
- // input.form-control#sign-in-form-email(type="text" name="email" placeholder="Please enter your email address" required="required" data-error="Email address is required.") {}
- // div.help-block.with-errors {}
- // }
- // }
- // }
- // div.row {
- // div.col-md-12 {
- // div.form-group {
- // label(for="sign-in-form-password") {'Password'}
- // input.form-control#sign-in-form-password(type="password" name="password" required="required" placeholder="Please enter your password" data-error="Password is required.") {}
- // div.help-block.with-errors {}
- // }
- // }
- // }
- // input.btn.btn-success.btn-send(style="display: none;" type="submit" value="Sign in") {}
- // }
+ div#sign-in-modal.modal.fade(role="dialog") {
+ div.modal-dialog {
+ div.modal-content {
+ div.modal-header {
+ span.h4.modal-title {'Sign in'}
+ }
+ div.modal-body {
+ form#sign-in-form {
+ div.row {
+ div.col-md-12 {
+ div.form-group {
+ label.form-label(for="sign-in-form-email") {'Email'}
+ input.form-control#sign-in-form-email(type="text" name="email" placeholder="Account email address" required="required" maxlength=256) {}
+ }
+ }
+ }
+ div.row {
+ div.col-md-12 {
+ div.form-group {
+ label.form-label(for="sign-in-form-password") {'Password'}
+ input.form-control#sign-in-form-password(type="password" name="password" placeholder="Account password" required="required" minlength=8 maxlength=256) {}
+ }
+ }
+ }
+ input.btn.btn-success.btn-send(style="display: none;" type="submit" value="Sign in") {}
+ }
- // p {
- // 'No account yet? '
- // a(href="/my_account/sign_up/index.html") {'Sign up'}
- // }
+ p.mt-2 {
+ 'No account yet? '
+ a(href="/my_account/sign_up/index.html") {'Sign up'}
+ }
- // p {
- // 'Forgot password? '
- // a(href="/my_account/password_reset/index.html") {'Password reset'}
- // }
- // }
- // div.modal-footer {
- // button.btn.btn-primary(type="submit" form="sign-in-form") {
- // 'Sign in'
- // }
- // button.btn.btn-outline-secondary(type="button" data-dismiss="modal") {
- // 'Cancel'
- // }
- // }
- // }
- // }
- //}
+ p {
+ 'Forgot password? '
+ a(href="/my_account/password_reset/index.html") {'Password reset'}
+ }
+ }
+ div.modal-footer {
+ button.btn.btn-outline-secondary(type="button" data-dismiss="modal") {
+ 'Cancel'
+ }
+ button.btn.btn-primary(type="submit" form="sign-in-form") {
+ 'Sign in'
+ }
+ }
+ }
+ }
+ }
div#feedback-modal.modal.fade(role="dialog") {
div.modal-dialog {
p {
'Did you notice something not quite right, or just want to share your impression of this page?'
}
- form#feedback-form(method="post" action="/feedback.html" role="form") {
+ form#feedback-form {
div.row {
div.col-md-12 {
div.form-group {
}
}
div.modal-footer {
- button.btn.btn-primary(type="submit" form="feedback-form") {
- 'Submit'
- }
button.btn.btn-outline-secondary(type="button" data-dismiss="modal") {
'Cancel'
}
+ button.btn.btn-primary(type="submit" form="feedback-form") {
+ 'Submit'
+ }
}
}
}
div.modal-header {
span.h4.modal-title {'Message'}
}
- div.modal-body {
- p#message-modal-message {}
+ div.modal-body#message-modal-message {
}
div.modal-footer {
button.btn.btn-outline-secondary(type="button" data-dismiss="modal") {
},
// scripts
async _out => {
- //script(src="/js/sha256.js") {}
+ script(src="/js/api_call.js") {}
script {
- //function get_cookie(name) {
- // let entries = document.cookie.split(';');
- // for (let i = 0; i < entries.length; ++i) {
- // let fields = entries[i].split('=');
- // if (fields[0].trim() === name)
- // return decodeURIComponent(fields[1]);
- // }
- // return undefined;
- //}
+ let sign_in = async (...arguments) => api_call(
+ '/api/sign_in.json',
+ ...arguments
+ )
+ let sign_out = async (...arguments) => api_call(
+ '/api/sign_out.json',
+ ...arguments
+ )
- //// this function can be overridden in a further script
- //function sign_in_out(status) {
- //}
+ // this function can be overridden in a further script
+ function sign_in_out(status) {
+ }
- $(document).ready(
+ document.addEventListener(
+ 'DOMContentLoaded',
() => {
- //// sign in form
- //$('#sign-in').click(
- // () => {
- // $('#sign-in-form-email').text('')
- // $('#sign-in-form-password').text('')
- // $('#sign-in-modal').modal('show')
- // return false
- // }
- //)
- //$('#sign-in-modal').on(
- // 'shown.bs.modal',
- // () => {
- // $('#sign-in-form-email').focus()
- // }
- //)
- //// when sign in form is submitted, do not reload the page
- //$(document).on(
- // 'submit',
- // '#sign-in-form',
- // e => {
- // e.preventDefault()
- // $.ajax(
- // {
- // url: '/my_account/sign_in.json',
- // type: 'POST',
- // data: {
- // email: $('#sign-in-form-email').val(),
- // password: sha256(
- // get_cookie('session_key') +
- // $('#sign-in-form-password').val()
- // ).toString('hex')
- // },
- // success: (data, textStatus, jqXHR) => {
- // $('#sign-in-modal').modal('hide')
- // switch (data.result) {
- // case 1: // success
- // $('#signed-in-status').text(data.signed_in_status)
- // $('#sign-in').hide()
- // $('#sign-out').show()
- // sign_in_out(true) // notify navbar caller
- // break
- // case 2: // redirect
- // location.href = data.redirect_href
- // break
- // }
- // $('#message-modal-message').text(data.message)
- // $('#message-modal').modal('show')
- // },
- // error: (jqXHR, textStatus, errorThrown) => {
- // $('#sign-in-modal').modal('hide')
- // $('#message-modal-message').text(errorThrown)
- // $('#message-modal').modal('show')
- // }
- // }
- // )
- // }
- //)
+ // sign in form
+ document.getElementById('sign-in').addEventListener(
+ 'click',
+ () => {
+ document.getElementById('sign-in-form-email').value = ''
+ document.getElementById('sign-in-form-password').value = ''
+ $('#sign-in-modal').modal('show')
+ }
+ )
- //// sign out button
- //$('#sign-out').click(
- // () => {
- // $.ajax(
- // {
- // url: '/my_account/sign_out.json',
- // type: 'GET',
- // success: (data, textStatus, jqXHR) => {
- // if (data.result) {
- // $('#signed-in-status').text(data.signed_in_status)
- // $('#sign-in').show()
- // $('#sign-out').hide()
- // sign_in_out(false) // notify navbar caller
- // }
- // $('#message-modal-message').text(data.message)
- // $('#message-modal').modal('show')
- // },
- // error: (jqXHR, textStatus, errorThrown) => {
- // $('#message-modal-message').text(errorThrown)
- // $('#message-modal').modal('show')
- // }
- // }
- // )
- // return false
- // }
- //)
+ $('#sign-in-modal').on(
+ 'shown.bs.modal',
+ () => {
+ console.log('bloo')
+ $('#sign-in-form-email').focus()
+ }
+ )
+
+ $(document).on(
+ 'submit',
+ '#sign-in-form',
+ async e => {
+ e.preventDefault()
+ let email
+ try {
+ email = document.getElementById('sign-in-form-email').value.slice(0, 256).toLowerCase()
+ await sign_in(
+ email,
+ document.getElementById('sign-in-form-password').value.slice(0, 256)
+ )
+ }
+ catch (error) {
+ document.getElementById('message-modal-message').textContent = error.message
+ $('#sign-in-modal').modal('hide')
+ $('#message-modal').modal('show')
+ return
+ }
+
+ document.getElementById('signed-in-status').textContent = `Signed in as ${email}.`
+ $('#sign-in').hide()
+ $('#sign-out').show()
+ sign_in_out(true)
+
+ document.getElementById('message-modal-message').textContent = `You are now signed in as "${email}".`
+ $('#sign-in-modal').modal('hide')
+ $('#message-modal').modal('show')
+ }
+ )
+
+ // sign out button
+ document.getElementById('sign-out').addEventListener(
+ 'click',
+ async () => {
+ try {
+ await sign_out()
+ }
+ catch (error) {
+ document.getElementById('message-modal-message').textContent = error.message
+ $('#sign-in-modal').modal('hide')
+ $('#message-modal').modal('show')
+ return
+ }
+
+ document.getElementById('signed-in-status').textContent = 'Browsing as guest.'
+ $('#sign-in').show()
+ $('#sign-out').hide()
+ sign_in_out(false)
+
+ document.getElementById('message-modal-message').textContent = `You are now signed out.`
+ $('#sign-in-modal').modal('hide')
+ $('#message-modal').modal('show')
+ }
+ )
// feedback form
- $('#give-feedback').click(
+ document.getElementById('give-feedback').addEventListener(
+ 'click',
() => {
$('#feedback-form-message').text('')
$('#feedback-modal').modal('show')
return false
}
)
+
$('#feedback-modal').on(
'shown.bs.modal',
() => {
$('#feedback-form-message').focus()
}
)
- // when feedback form is submitted, do not reload the page
+
$(document).on(
'submit',
'#feedback-form',
e.preventDefault()
$.ajax(
{
- url: '/feedback.html',
+ url: '/api/feedback.html',
type: 'POST',
data: {
page: window.location.href,
},
success: (data, textStatus, jqXHR) => {
$('#feedback-modal').modal('hide')
+ document.getElementById('message-modal-message').textContent = data
$('#message-modal-message').text(data)
$('#message-modal').modal('show')
},
error: (jqXHR, textStatus, errorThrown) => {
$('#feedback-modal').modal('hide')
- $('#message-modal-message').text(errorThrown)
+ document.getElementById('message-modal-message').textContent = errorThrown
$('#message-modal').modal('show')
}
}
--- /dev/null
+let logjson = (await import('@ndcode/logjson')).default
+
+return async env => {
+ let globals = await env.site.get_json('/_config/globals.json')
+ let nodemailer_noreply = await env.site.get_nodemailer(
+ '/_config/nodemailer_noreply.json'
+ )
+ 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,
+ // endpoint
+ '/api/sign_in.json',
+ // handler
+ async (email, password) => {
+ // coerce and/or validate
+ email = email.slice(0, 256).toLowerCase()
+ password = password.slice(0, 256)
+ if (email.length === 0 || password.length < 8)
+ throw new Problem(
+ 'Bad request',
+ 'Minimum length check failed',
+ 400
+ )
+
+ 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 account = await (
+ await (
+ await transaction.get({})
+ ).get('accounts', {})
+ ).get(email)
+ if (
+ account === undefined ||
+ password !== await logjson.logjson_to_json(
+ await account.get('password')
+ )
+ )
+ throw new Problem(
+ 'Unauthorized',
+ 'Email and password combination was incorrect.'
+ 401
+ )
+
+ if (
+ !await logjson.logjson_to_json(
+ await account.get('email_verified')
+ )
+ )
+ throw new Problem(
+ 'Email not yet verified',
+ 'Please verify your email address via email link before trying to sign in.',
+ 425
+ )
+
+ session.set('signed_in_as', transaction.json_to_logjson(email))
+
+ await transaction.commit()
+ }
+ catch (error) {
+ transaction.rollback()
+ throw error
+ }
+ }
+ )
+}