let assert = require('assert')
+let cookie = require('cookie')
+let crypto = require('crypto')
let logjson = (await import('@ndcode/logjson')).default
//let NodeMailerCache = require('@ndcode/nodemailer_cache')
let XDate = require('xdate')
return /*await*/ this.zettair_cache.get(this.root + pathname)
}
+ // customize template serving to initialize env.now, env.session_key first
+ async serve_jst(env, pathname, ...args) {
+ let template
+ try {
+ template = await this.jst_cache.get(pathname)
+ }
+ catch (err) {
+ if (!(err instanceof Error) || err.code !== 'ENOENT')
+ throw err
+ return false
+ }
+ env.site = this
+
+ // added part
+ env.now = XDate.now()
+ let transaction = await this.database.Transaction()
+ try {
+ let sessions = await (
+ await transaction.get({})
+ ).get('sessions', {})
+
+ let cookies = cookie.parse(env.request.headers.cookie || '')
+ let session, expires = new XDate(env.now)
+ if (
+ Object.prototype.hasOwnProperty.call(cookies, 'session_key') &&
+ (
+ session = await sessions.get(
+ env.session_key = cookies.session_key
+ )
+ ) !== undefined &&
+ env.now < await session.get('expires', 0)
+ )
+ // if session key is already in database, the requester supports
+ // cookies, and each access extends the session expiry by 1 month
+ expires.addMonths(1)
+ else {
+ // first request for session, maybe a bot, retain for only 1 day
+ expires.addDays(1)
+
+ do {
+ env.session_key = crypto.randomBytes(16).toString('hex')
+ } while (sessions.has(env.session_key))
+ session = transaction.LazyObject()
+ sessions.set(env.session_key, session)
+ }
+
+ await session.set('expires', expires.getTime())
+ env.response.setHeader(
+ 'Set-Cookie',
+ `session_key=${env.session_key}; expires=${expires.toUTCString()}; path=/;`
+ )
+
+ await transaction.commit()
+ }
+ catch (error) {
+ transaction.rollback()
+ throw error
+ }
+
+ await template(env, ...args)
+ return true
+ }
+
// customize the file search/serving algorithm for this particular website
async respond(env) {
if (
-let cookie = require('cookie')
-let crypto = require('crypto')
let XDate = require('xdate')
-// note: this routine is "almost" idempotent
-// it will return the same session key each time
-// expiry may be increased slightly at each call
return async (env, transaction) => {
let sessions = await (
await transaction.get({})
).get('sessions', {})
- let cookies = cookie.parse(env.request.headers.cookie || '')
- let now = Date.now()
-
- let session, expires = new XDate(now)
- if (
- Object.prototype.hasOwnProperty.call(cookies, 'session_key') &&
- (session = await sessions.get(cookies.session_key)) !== undefined &&
- now < await session.get('expires', 0)
- ) {
- // if session key is already in database, we know the requester supports
- // cookies, therefore each access extends the session expiry by 1 month
- env.session_key = cookies.session_key
- expires.addMonths(1)
- }
- else {
- // first request for session, maybe a bot, retain session for only 1 day
- if (!Object.prototype.hasOwnProperty.call(env, 'session_key')) {
- do {
- env.session_key = crypto.randomBytes(16).toString('hex')
- } while (sessions.has(env.session_key))
- }
- session = await sessions.get(env.session_key, {})
+ let session = await sessions.get(env.session_key)
+ if (session === undefined) {
+ // this should never happen, but could happen if we take more than a day
+ // to process an incoming request, and database is cleaned in the meantime
+ let expires = new XDate(env.now)
expires.addDays(1)
+ session = Transaction.json_to_logjson({expires: expires.getTime()})
+ sessions.set(env.session_key, session)
}
- await session.set('expires', expires.getTime())
- env.response.setHeader(
- 'Set-Cookie',
- `session_key=${env.session_key}; expires=${expires.toUTCString()}; path=/;`
- )
-
env.signed_in_as = await session.get_json('signed_in_as', null)
return session
}