1 | /*!
|
2 | * Connect - session - Session
|
3 | * Copyright(c) 2010 Sencha Inc.
|
4 | * Copyright(c) 2011 TJ Holowaychuk
|
5 | * MIT Licensed
|
6 | */
|
7 |
|
8 | ;
|
9 |
|
10 | /**
|
11 | * Expose Session.
|
12 | */
|
13 |
|
14 | module.exports = Session;
|
15 |
|
16 | /**
|
17 | * Create a new `Session` with the given request and `data`.
|
18 | *
|
19 | * @param {IncomingRequest} req
|
20 | * @param {Object} data
|
21 | * @api private
|
22 | */
|
23 |
|
24 | function Session(req, data) {
|
25 | Object.defineProperty(this, 'req', { value: req });
|
26 | Object.defineProperty(this, 'id', { value: req.sessionID });
|
27 |
|
28 | if (typeof data === 'object' && data !== null) {
|
29 | // merge data into this, ignoring prototype properties
|
30 | for (var prop in data) {
|
31 | if (!(prop in this)) {
|
32 | this[prop] = data[prop]
|
33 | }
|
34 | }
|
35 | }
|
36 | }
|
37 |
|
38 | /**
|
39 | * Update reset `.cookie.maxAge` to prevent
|
40 | * the cookie from expiring when the
|
41 | * session is still active.
|
42 | *
|
43 | * @return {Session} for chaining
|
44 | * @api public
|
45 | */
|
46 |
|
47 | defineMethod(Session.prototype, 'touch', function touch() {
|
48 | return this.resetMaxAge();
|
49 | });
|
50 |
|
51 | /**
|
52 | * Reset `.maxAge` to `.originalMaxAge`.
|
53 | *
|
54 | * @return {Session} for chaining
|
55 | * @api public
|
56 | */
|
57 |
|
58 | defineMethod(Session.prototype, 'resetMaxAge', function resetMaxAge() {
|
59 | this.cookie.maxAge = this.cookie.originalMaxAge;
|
60 | return this;
|
61 | });
|
62 |
|
63 | /**
|
64 | * Save the session data with optional callback `fn(err)`.
|
65 | *
|
66 | * @param {Function} fn
|
67 | * @return {Session} for chaining
|
68 | * @api public
|
69 | */
|
70 |
|
71 | defineMethod(Session.prototype, 'save', function save(fn) {
|
72 | this.req.sessionStore.set(this.id, this, fn || function(){});
|
73 | return this;
|
74 | });
|
75 |
|
76 | /**
|
77 | * Re-loads the session data _without_ altering
|
78 | * the maxAge properties. Invokes the callback `fn(err)`,
|
79 | * after which time if no exception has occurred the
|
80 | * `req.session` property will be a new `Session` object,
|
81 | * although representing the same session.
|
82 | *
|
83 | * @param {Function} fn
|
84 | * @return {Session} for chaining
|
85 | * @api public
|
86 | */
|
87 |
|
88 | defineMethod(Session.prototype, 'reload', function reload(fn) {
|
89 | var req = this.req
|
90 | var store = this.req.sessionStore
|
91 |
|
92 | store.get(this.id, function(err, sess){
|
93 | if (err) return fn(err);
|
94 | if (!sess) return fn(new Error('failed to load session'));
|
95 | store.createSession(req, sess);
|
96 | fn();
|
97 | });
|
98 | return this;
|
99 | });
|
100 |
|
101 | /**
|
102 | * Destroy `this` session.
|
103 | *
|
104 | * @param {Function} fn
|
105 | * @return {Session} for chaining
|
106 | * @api public
|
107 | */
|
108 |
|
109 | defineMethod(Session.prototype, 'destroy', function destroy(fn) {
|
110 | delete this.req.session;
|
111 | this.req.sessionStore.destroy(this.id, fn);
|
112 | return this;
|
113 | });
|
114 |
|
115 | /**
|
116 | * Regenerate this request's session.
|
117 | *
|
118 | * @param {Function} fn
|
119 | * @return {Session} for chaining
|
120 | * @api public
|
121 | */
|
122 |
|
123 | defineMethod(Session.prototype, 'regenerate', function regenerate(fn) {
|
124 | this.req.sessionStore.regenerate(this.req, fn);
|
125 | return this;
|
126 | });
|
127 |
|
128 | /**
|
129 | * Helper function for creating a method on a prototype.
|
130 | *
|
131 | * @param {Object} obj
|
132 | * @param {String} name
|
133 | * @param {Function} fn
|
134 | * @private
|
135 | */
|
136 | function defineMethod(obj, name, fn) {
|
137 | Object.defineProperty(obj, name, {
|
138 | configurable: true,
|
139 | enumerable: false,
|
140 | value: fn,
|
141 | writable: true
|
142 | });
|
143 | };
|