Files
pole-book/server/node_modules/grant/lib/session.js

107 lines
2.9 KiB
JavaScript

var crypto = require('crypto')
var cookie = require('cookie')
var signature = require('cookie-signature')
module.exports = ({name, secret, cookie:options, store}) => {
name = name || 'grant'
options = options || {path: '/', httpOnly: true, secure: false, maxAge: null}
if (!secret) {
throw new Error('Grant: cookie secret is required')
}
var embed = !store
return (req) => {
var headers = Object.keys(req.headers)
.filter((key) => /(?:set-)?cookie/i.test(key))
.reduce((all, key) => (all[key.toLowerCase()] = req.headers[key], all), {})
headers['set-cookie'] =
headers['set-cookie'] ||
(req.multiValueHeaders && req.multiValueHeaders['Set-Cookie']) ||
[]
var cookies = {
input:
// vercel - parsed object
typeof req.cookies === 'object' && !(req.cookies instanceof Array) ? req.cookies :
cookie.parse(
headers.cookie ? headers.cookie :
// aws v2 event - array of key=value pairs
req.cookies ? req.cookies.join('; ') :
''
),
output: headers['set-cookie'].reduce((all, str) =>
(all[str.split(';')[0].split('=')[0]] = str, all), {})
}
var encode = (payload, opt = {}) => {
var data = embed
? Buffer.from(JSON.stringify(payload)).toString('base64')
: payload
var value = signature.sign(data, secret)
var output = cookie.serialize(name, value, {...options, ...opt})
cookies.output[name] = output
headers['set-cookie'] = Object.keys(cookies.output)
.map((name) => cookies.output[name])
}
var cookieStore = () => {
var session = (() => {
var payload = signature.unsign(cookies.input[name] || '', secret)
try {
return JSON.parse(Buffer.from(payload, 'base64').toString())
}
catch (err) {
return {grant: {}}
}
})()
var store = {
get: async (sid) => session,
set: async (sid, value) => session = value,
remove: async (sid) => session = {}
}
return {
get: async () => {
return store.get()
},
set: async (value) => {
encode(value)
return store.set(null, value)
},
remove: async () => {
encode('', {maxAge: 0})
await store.remove()
},
cookies,
headers,
}
}
var sessionStore = () => {
var sid = signature.unsign(cookies.input[name] || '', secret)
|| crypto.randomBytes(20).toString('hex')
return {
get: async () => {
return await store.get(sid) || {grant: {}}
},
set: async (value) => {
encode(sid)
return store.set(sid, value)
},
remove: async () => {
encode(sid, {maxAge: 0})
await store.remove(sid)
},
cookies,
headers,
}
}
return embed ? cookieStore() : sessionStore()
}
}