-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsessions.js
92 lines (84 loc) · 3.22 KB
/
sessions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
const oneOf = (...items) => items.find(item => item != null);
const getCookies = req => {
if (!req.cookies && req.headers.cookie) {
const c = {};
req.cookies = c;
const {cookie} = req.headers;
if (cookie) {
for (const item of cookie.split('; ')) {
const e = item.indexOf('=');
if (e > 0) {
c[item.substr(0, e).trim()] = item.substr(e + 1).trim();
}
}
}
return c;
}
return req.cookies || {};
};
const getSession = (req, res, context, options) => {
const createSession = options === true || (options && options.new);
let alreadyCreated = req._givenSession;
if (alreadyCreated) {
if (alreadyCreated.data || !createSession) {
return alreadyCreated.data;
}
} else {
alreadyCreated = {};
req._givenSession = alreadyCreated;
}
const cookies = getCookies(req);
const params = options || {};
const tokenName = params.token || context.token || 'token';
const csrfTokenName = params.csrfToken || context.csrfToken || 'csrf-token';
let existingToken = cookies[tokenName];
let existingCsrfToken = cookies[csrfTokenName];
if (existingToken || createSession) {
if (!context.sessions) {
const sessions = {};
context.sessionsInterval = setInterval(() => {
const now = Date.now();
for (const [token, item] of Object.entries(sessions)) {
if (item.expires < now) {
delete sessions[token];
}
}
}, 60000);
context.on('unregister', () => {
clearInterval(context.sessionsInterval);
});
context.sessions = sessions;
}
let item = existingToken ? context.sessions[existingToken] : null;
if (item) {
delete context.sessions[existingToken];
}
const now = Date.now();
if (item && (item.expires < now || item.csrfToken !== existingCsrfToken)) {
item = null;
}
const token = alreadyCreated.token || (item || createSession ? Math.round(Math.random()*10000000000).toString(16) : null);
const csrfToken = alreadyCreated.csrfToken || (token ? Math.round(Math.random()*10000000000).toString(16) : null);
if (token && !alreadyCreated.token) {
const secure = Boolean(oneOf(params.secure, context.secure, true));
res.cookie(tokenName, token, {secure});
res.cookie(csrfTokenName, csrfToken, {secure, httpOnly: true});
alreadyCreated.token = token;
alreadyCreated.csrfToken = csrfToken;
}
if (!item && createSession) {
item = {data: {}};
}
if (item) {
const sessionTimeout = params.timeout || context.timeout || 4*3600*1000;
context.sessions[token] = item;
item.expires = now + sessionTimeout;
item.csrfToken = csrfToken;
alreadyCreated.data = item.data;
alreadyCreated.created = true;
return item.data;
}
}
return null;
};
module.exports = {getCookies, getSession};