d5b87a635fa474c567de87410d2fb84631d03673
[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 cookies = cookie.parse(env.request.headers.cookie || '')
8   let now = Date.now()
9
10   let sessions = await (
11     await transaction.get({})
12   ).get('sessions', {})
13
14   let session, expires = new XDate(now)
15   if (
16     Object.prototype.hasOwnProperty.call(cookies, 'session_key') &&
17       (
18         session = await sessions.get(env.session_key = cookies.session_key)
19       ) !== undefined &&
20       now < await session.get('expires', 0)
21   )
22     // if session key is already in database, we know the requester supports
23     // cookies, therefore each access extends the session expiry by 1 month
24     expires.addMonths(1)
25   else {
26     // first request for session, maybe a bot, retain session for only 1 day
27     expires.addDays(1)
28     do {
29       env.session_key = crypto.randomBytes(16).toString('hex')
30     } while (sessions.has(env.session_key))
31     session = transaction.LazyObject()
32     sessions.set(env.session_key, session)
33   }
34
35   await session.set('expires', expires.getTime())
36   env.response.setHeader(
37     'Set-Cookie',
38     `session_key=${env.session_key}; expires=${expires.toUTCString()}; path=/;`
39   )
40
41   env.signed_in_as = await logjson.logjson_to_json(
42     await session.get('signed_in_as', null)
43   )
44   return session
45 }