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
|
// TODO: use Redis for in-memory caching of sessions
// this was originally a Proxy<Map<String, Session>> but was replaced because of a nodejs bug
// XXX: maybe we should use an already-existing Express session manager // NIH syndrome
const timeout_symbol = Symbol("timeout");
const hydrate_symbol = Symbol("hydrate");
const container_symbol = Symbol("container");
const session_handler = {
[container_symbol]: new Map(),
[hydrate_symbol] (key, obj) {
if (obj === null || obj === undefined)
return obj;
let minutes = 30;
if (Reflect.has(obj, timeout_symbol)) {
clearTimeout(obj[timeout_symbol]);
minutes = 360; // 6 hours
}
let expires = new Date();
expires.setUTCMinutes(expires.getUTCMinutes() + minutes);
obj.expires = expires // this could also be a symbol
obj[timeout_symbol] = setTimeout(() => session_handler.delete(key), minutes * 60000);
return obj;
},
has (key) {
return session_handler[container_symbol].has(key);
},
get (key) {
return session_handler[hydrate_symbol](key, session_handler[container_symbol].get(key));
},
set (key, obj) {
return session_handler[container_symbol].set(key, session_handler[hydrate_symbol](key, obj));
},
delete (key) {
if (session_handler[container_symbol].get(key) && session_handler[container_symbol].get(key)[timeout_symbol])
clearTimeout(session_handler[container_symbol].get(key)[timeout_symbol]);
return session_handler[container_symbol].delete(key);
},
[Symbol.iterator]: function* () {
for (const [key, obj] of session_handler[container_symbol]) {
yield [key, obj];
}
},
};
// TODO: DRY this shit
const identity_handler = {
[container_symbol]: new Map(),
[hydrate_symbol] (key, obj) {
if (obj === null || obj === undefined)
return obj;
if (Reflect.has(obj, timeout_symbol))
clearTimeout(obj[timeout_symbol]);
let expires = new Date();
expires.setUTCMinutes(expires.getUTCMinutes() + 30);
obj.expires = expires // this could also be a symbol
obj[timeout_symbol] = setTimeout(() => identity_handler.delete(key), 30 * 60000); // 30 minutes
return obj;
},
has (key) {
return identity_handler[container_symbol].has(key);
},
get (key) {
return identity_handler[container_symbol].get(key);
},
set (key, obj) {
return identity_handler[container_symbol].set(key, identity_handler[hydrate_symbol](key, obj));
},
delete (key) {
if (identity_handler[container_symbol].get(key) && identity_handler[container_symbol].get(key)[timeout_symbol])
clearTimeout(identity_handler[container_symbol].get(key)[timeout_symbol]);
return identity_handler[container_symbol].delete(key);
},
[Symbol.iterator]: function* () {
for (const [key, obj] of identity_handler[container_symbol]) {
yield [key, obj];
}
},
};
module.exports = {
session_handler,
identity_handler,
}
|