Add expiry on sign up draft (to prevent leakage of personal information)
[ndcode_site.git] / _lib / session_cookie.jst
1 let logjson = (await import('@ndcode/logjson')).default
2 let cookie = require('cookie')
3 let crypto = require('crypto')
4 let XDate = require('xdate')
5
6 return async (env, transaction) => {
7   let sessions = await (
8     await transaction.get({})
9   ).get('sessions', {})
10
11   // do not generate a new session key for multiple calls per request
12   if (env.session_key !== undefined)
13     return /*await*/ sessions.get(env.session_key, {})
14
15   let cookies = cookie.parse(env.request.headers.cookie || '')
16   let now = Date.now()
17
18   let session, expires = new XDate(now)
19   if (
20     Object.prototype.hasOwnProperty.call(cookies, 'session_key') &&
21       (
22         session = await sessions.get(env.session_key = cookies.session_key)
23       ) !== undefined &&
24       now < await session.get('expires', 0)
25   )
26     // if session key is already in database, we know the requester supports
27     // cookies, therefore each access extends the session expiry by 1 month
28     expires.addMonths(1)
29   else {
30     // first request for session, maybe a bot, retain session for only 1 day
31     expires.addDays(1)
32     do {
33       env.session_key = crypto.randomBytes(16).toString('hex')
34     } while (sessions.has(env.session_key))
35     session = transaction.LazyObject()
36     sessions.set(env.session_key, session)
37   }
38
39   await session.set('expires', expires.getTime())
40   env.response.setHeader(
41     'Set-Cookie',
42     `session_key=${env.session_key}; expires=${expires.toUTCString()}; path=/;`
43   )
44
45   env.signed_in_as = await logjson.logjson_to_json(
46     await session.get('signed_in_as', null)
47   )
48   return session
49 }