-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
106 lines (101 loc) · 2.78 KB
/
index.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
const Keygrip = require('./keygrip.js');
const assert = require('assert');
const helper = require('think-helper');
/**
* use cookie to store session
*/
class CookieSession {
/**
* constructor
* @param {Object} options cookie options
* @param {Object} ctx koa ctx
*/
constructor(options = {}, ctx, cookieOptions = {}) {
if (cookieOptions.encrypt) {
assert(cookieOptions.keys && helper.isArray(cookieOptions.keys), '.keys required and must be an array when encrypt is set');
cookieOptions.signed = false; // disable signed when set encrypt
this.keygrip = new Keygrip(cookieOptions.keys);
}
cookieOptions.overwrite = true;
this.options = options;
this.cookieOptions = cookieOptions;
this.ctx = ctx;
this.fresh = true; // session data is fresh
this.data = {}; // session data
this.maxAge = cookieOptions.maxAge || 0;
this.expire = 0;
this.initSessionData();
}
/**
* init session data
*/
initSessionData() {
let data = this.ctx.cookie(this.cookieOptions.name, undefined, this.cookieOptions);
if (data) {
if (this.keygrip) {
data = Buffer.from(data, 'base64');
data = this.keygrip.decrypt(data);
if (data && data[0]) {
data = data[0].toString();
}
}
if (data) {
try {
const result = JSON.parse(data);
this.data = result.data || {};
this.maxAge = result.maxAge || 0;
this.expire = result.expire || 0;
this.fresh = false;
} catch (e) {}
}
}
}
/**
* get session data
* @param {String} name
*/
get(name) {
// auto update cookie when maxAge or expires is set
if (this.maxAge && this.expire && !this.fresh && this.cookieOptions.autoUpdateRate) {
const rate = (this.expire - Date.now()) / this.maxAge;
if (rate < this.cookieOptions.autoUpdateRate) {
this.set();
}
}
if (name) return Promise.resolve(this.data[name]);
return Promise.resolve(this.data);
}
/**
* set session data
* @param {String} name
* @param {Mixed} value
*/
set(name, value) {
if (name) {
this.data[name] = value;
}
let data = JSON.stringify({
maxAge: this.maxAge,
expire: Date.now() + this.maxAge,
data: this.data
});
if (this.keygrip) {
data = this.keygrip.encrypt(data).toString('base64');
}
this.cookieOptions.maxAge = this.maxAge;
this.ctx.cookie(this.cookieOptions.name, data, this.cookieOptions);
return Promise.resolve();
}
/**
* delete session data
*/
delete() {
if (!this.fresh) {
this.ctx.cookie(this.cookieOptions.name, null, this.cookieOptions);
this.data = {};
}
return Promise.resolve();
}
}
CookieSession.onlyCookie = true;
module.exports = CookieSession;