@adonisjs/session 7.0.0-0 → 7.0.0-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -38
- package/build/configure.js +29 -2
- package/build/factories/main.d.ts +1 -0
- package/build/factories/main.js +9 -0
- package/build/factories/session_middleware_factory.d.ts +22 -0
- package/build/factories/session_middleware_factory.js +47 -0
- package/build/index.d.ts +5 -3
- package/build/index.js +5 -3
- package/build/providers/session_provider.d.ts +15 -4
- package/build/providers/session_provider.js +37 -20
- package/build/src/client.d.ts +13 -25
- package/build/src/client.js +24 -43
- package/build/src/debug.d.ts +3 -0
- package/build/src/debug.js +10 -0
- package/build/src/define_config.d.ts +6 -3
- package/build/src/define_config.js +34 -5
- package/build/src/drivers/cookie.d.ts +7 -9
- package/build/src/drivers/cookie.js +10 -6
- package/build/src/drivers/file.d.ts +11 -14
- package/build/src/drivers/file.js +90 -34
- package/build/src/drivers/memory.d.ts +4 -8
- package/build/src/drivers/memory.js +0 -3
- package/build/src/drivers/redis.d.ts +4 -6
- package/build/src/drivers/redis.js +25 -29
- package/build/src/drivers_collection.d.ts +22 -0
- package/build/src/drivers_collection.js +38 -0
- package/build/src/edge_plugin_adonisjs_session.d.ts +6 -0
- package/build/src/edge_plugin_adonisjs_session.js +92 -0
- package/build/src/errors.d.ts +8 -0
- package/build/src/errors.js +17 -0
- package/build/src/helpers.d.ts +6 -0
- package/build/src/helpers.js +43 -0
- package/build/src/session.d.ts +86 -59
- package/build/src/session.js +235 -224
- package/build/src/session_middleware.d.ts +19 -2
- package/build/src/session_middleware.js +43 -4
- package/build/src/store.d.ts +48 -35
- package/build/src/store.js +85 -57
- package/build/src/types/extended.d.ts +19 -0
- package/build/src/types/main.d.ts +106 -0
- package/build/src/types/main.js +9 -0
- package/build/stubs/config.stub +28 -92
- package/package.json +37 -26
- package/build/src/bindings/api_client.d.ts +0 -2
- package/build/src/bindings/api_client.js +0 -135
- package/build/src/bindings/http_context.d.ts +0 -5
- package/build/src/bindings/http_context.js +0 -17
- package/build/src/bindings/types.d.ts +0 -77
- package/build/src/session_manager.d.ts +0 -38
- package/build/src/session_manager.js +0 -149
- package/build/src/types.d.ts +0 -61
- package/build/src/types.js +0 -1
- /package/build/src/{bindings/types.js → types/extended.js} +0 -0
package/build/src/session.js
CHANGED
|
@@ -6,368 +6,379 @@
|
|
|
6
6
|
* For the full copyright and license information, please view the LICENSE
|
|
7
7
|
* file that was distributed with this source code.
|
|
8
8
|
*/
|
|
9
|
-
import { Exception } from '@poppinss/utils';
|
|
10
9
|
import lodash from '@poppinss/utils/lodash';
|
|
11
10
|
import { cuid } from '@adonisjs/core/helpers';
|
|
12
|
-
import { Store } from './store.js';
|
|
11
|
+
import { ReadOnlyStore, Store } from './store.js';
|
|
12
|
+
import * as errors from './errors.js';
|
|
13
|
+
import debug from './debug.js';
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
15
|
+
* The session class exposes the API to read and write values to
|
|
16
|
+
* the session store.
|
|
17
|
+
*
|
|
18
|
+
* A session instance is isolated between requests but
|
|
19
|
+
* uses a centralized persistence store and
|
|
16
20
|
*/
|
|
17
21
|
export class Session {
|
|
18
|
-
/**
|
|
19
|
-
* Session id for the current request. It will be different
|
|
20
|
-
* from the "this.sessionId" when regenerate is called.
|
|
21
|
-
*/
|
|
22
|
-
#currentSessionId;
|
|
23
|
-
/**
|
|
24
|
-
* A instance of store with values read from the driver. The store
|
|
25
|
-
* in initiated inside the [[initiate]] method
|
|
26
|
-
*/
|
|
27
|
-
#store;
|
|
28
|
-
/**
|
|
29
|
-
* Whether or not to re-generate the session id before committing
|
|
30
|
-
* session values.
|
|
31
|
-
*/
|
|
32
|
-
#regeneratedSessionId = false;
|
|
33
|
-
/**
|
|
34
|
-
* Session key for setting flash messages
|
|
35
|
-
*/
|
|
36
|
-
#flashMessagesKey = '__flash__';
|
|
37
|
-
/**
|
|
38
|
-
* The HTTP context for the current request.
|
|
39
|
-
*/
|
|
40
|
-
#ctx;
|
|
41
|
-
/**
|
|
42
|
-
* Configuration for the session
|
|
43
|
-
*/
|
|
44
22
|
#config;
|
|
45
|
-
/**
|
|
46
|
-
* The session driver instance used to read and write session data.
|
|
47
|
-
*/
|
|
48
23
|
#driver;
|
|
24
|
+
#emitter;
|
|
25
|
+
#ctx;
|
|
26
|
+
#readonly = false;
|
|
27
|
+
#store;
|
|
49
28
|
/**
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
initiated = false;
|
|
53
|
-
/**
|
|
54
|
-
* A boolean to know if it's a fresh session or not. Fresh
|
|
55
|
-
* sessions are those, whose session id is not present
|
|
56
|
-
* in cookie
|
|
29
|
+
* Session id refers to the session id that will be committed
|
|
30
|
+
* as a cookie during the response.
|
|
57
31
|
*/
|
|
58
|
-
|
|
32
|
+
#sessionId;
|
|
59
33
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
34
|
+
* Session id from cookie refers to the value we read from the
|
|
35
|
+
* cookie during the HTTP request.
|
|
36
|
+
*
|
|
37
|
+
* This only might not exist during the first request. Also during
|
|
38
|
+
* session id re-generation, this value will be different from
|
|
39
|
+
* the session id.
|
|
62
40
|
*/
|
|
63
|
-
|
|
41
|
+
#sessionIdFromCookie;
|
|
64
42
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
43
|
+
* Store of flash messages that be written during the
|
|
44
|
+
* HTTP request
|
|
67
45
|
*/
|
|
68
|
-
|
|
46
|
+
responseFlashMessages = new Store({});
|
|
69
47
|
/**
|
|
70
|
-
*
|
|
48
|
+
* Store of flash messages for the current HTTP request.
|
|
71
49
|
*/
|
|
72
50
|
flashMessages = new Store({});
|
|
73
51
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* methods are used.
|
|
77
|
-
*
|
|
78
|
-
* The `others` object is expanded with each call.
|
|
52
|
+
* The key to use for storing flash messages inside
|
|
53
|
+
* the session store.
|
|
79
54
|
*/
|
|
80
|
-
|
|
81
|
-
constructor(ctx, config, driver) {
|
|
82
|
-
this.#ctx = ctx;
|
|
83
|
-
this.#config = config;
|
|
84
|
-
this.#driver = driver;
|
|
85
|
-
this.sessionId = this.#getSessionId();
|
|
86
|
-
this.#currentSessionId = this.sessionId;
|
|
87
|
-
}
|
|
55
|
+
flashKey = '__flash__';
|
|
88
56
|
/**
|
|
89
|
-
*
|
|
90
|
-
* when nothing is set
|
|
57
|
+
* Session id for the current HTTP request
|
|
91
58
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const { input, ...others } = this.responseFlashMessages.all();
|
|
97
|
-
this.put(this.#flashMessagesKey, { ...input, ...others });
|
|
59
|
+
get sessionId() {
|
|
60
|
+
return this.#sessionId;
|
|
98
61
|
}
|
|
99
62
|
/**
|
|
100
|
-
*
|
|
63
|
+
* A boolean to know if a fresh session is created during
|
|
64
|
+
* the request
|
|
101
65
|
*/
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (sessionId) {
|
|
105
|
-
return sessionId;
|
|
106
|
-
}
|
|
107
|
-
this.fresh = true;
|
|
108
|
-
return cuid();
|
|
66
|
+
get fresh() {
|
|
67
|
+
return this.#sessionIdFromCookie === undefined;
|
|
109
68
|
}
|
|
110
69
|
/**
|
|
111
|
-
*
|
|
70
|
+
* A boolean to know if session is in readonly
|
|
71
|
+
* state
|
|
112
72
|
*/
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
throw new Exception('Session store is not initiated yet. Make sure you are using the session hook', { code: 'E_RUNTIME_EXCEPTION', status: 500 });
|
|
116
|
-
}
|
|
73
|
+
get readonly() {
|
|
74
|
+
return this.#readonly;
|
|
117
75
|
}
|
|
118
76
|
/**
|
|
119
|
-
*
|
|
77
|
+
* A boolean to know if session store has been initiated
|
|
120
78
|
*/
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
throw new Exception('Session store is in readonly mode and cannot be mutated', {
|
|
124
|
-
status: 500,
|
|
125
|
-
code: 'E_RUNTIME_EXCEPTION',
|
|
126
|
-
});
|
|
127
|
-
}
|
|
79
|
+
get initiated() {
|
|
80
|
+
return !!this.#store;
|
|
128
81
|
}
|
|
129
82
|
/**
|
|
130
|
-
*
|
|
83
|
+
* A boolean to know if the session id has been re-generated
|
|
84
|
+
* during the current request
|
|
131
85
|
*/
|
|
132
|
-
|
|
133
|
-
this.#
|
|
134
|
-
this.#ctx.response.cookie(this.#config.cookieName, this.sessionId, this.#config.cookie);
|
|
86
|
+
get hasRegeneratedSession() {
|
|
87
|
+
return !!(this.#sessionIdFromCookie && this.#sessionIdFromCookie !== this.#sessionId);
|
|
135
88
|
}
|
|
136
89
|
/**
|
|
137
|
-
*
|
|
90
|
+
* A boolean to know if the session store is empty
|
|
138
91
|
*/
|
|
139
|
-
|
|
140
|
-
this.#
|
|
141
|
-
await this.#driver.write(this.sessionId, this.#store.toJSON());
|
|
92
|
+
get isEmpty() {
|
|
93
|
+
return this.#store?.isEmpty ?? true;
|
|
142
94
|
}
|
|
143
95
|
/**
|
|
144
|
-
*
|
|
96
|
+
* A boolean to know if the session store has been
|
|
97
|
+
* modified
|
|
145
98
|
*/
|
|
146
|
-
|
|
147
|
-
this.#
|
|
148
|
-
|
|
99
|
+
get hasBeenModified() {
|
|
100
|
+
return this.#store?.hasBeenModified ?? false;
|
|
101
|
+
}
|
|
102
|
+
constructor(config, driver, emitter, ctx) {
|
|
103
|
+
this.#ctx = ctx;
|
|
104
|
+
this.#config = config;
|
|
105
|
+
this.#driver = driver;
|
|
106
|
+
this.#emitter = emitter;
|
|
107
|
+
this.#sessionIdFromCookie = ctx.request.cookie(config.cookieName, undefined);
|
|
108
|
+
this.#sessionId = this.#sessionIdFromCookie || cuid();
|
|
149
109
|
}
|
|
150
110
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
111
|
+
* Returns the flash messages store for a given
|
|
112
|
+
* mode
|
|
153
113
|
*/
|
|
154
|
-
#
|
|
155
|
-
if (this
|
|
156
|
-
|
|
114
|
+
#getFlashStore(mode) {
|
|
115
|
+
if (!this.#store) {
|
|
116
|
+
throw new errors.E_SESSION_NOT_READY();
|
|
157
117
|
}
|
|
158
|
-
|
|
118
|
+
if (mode === 'write' && this.readonly) {
|
|
119
|
+
throw new errors.E_SESSION_NOT_MUTABLE();
|
|
120
|
+
}
|
|
121
|
+
return this.responseFlashMessages;
|
|
159
122
|
}
|
|
160
123
|
/**
|
|
161
|
-
*
|
|
162
|
-
* (only when view property exists)
|
|
124
|
+
* Returns the store instance for a given mode
|
|
163
125
|
*/
|
|
164
|
-
#
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
126
|
+
#getStore(mode) {
|
|
127
|
+
if (!this.#store) {
|
|
128
|
+
throw new errors.E_SESSION_NOT_READY();
|
|
129
|
+
}
|
|
130
|
+
if (mode === 'write' && this.readonly) {
|
|
131
|
+
throw new errors.E_SESSION_NOT_MUTABLE();
|
|
168
132
|
}
|
|
169
|
-
|
|
170
|
-
this.#ctx['view'].share({
|
|
171
|
-
flashMessages: this.flashMessages,
|
|
172
|
-
session: {
|
|
173
|
-
get: this.get.bind(this),
|
|
174
|
-
has: this.has.bind(this),
|
|
175
|
-
all: this.all.bind(this),
|
|
176
|
-
},
|
|
177
|
-
});
|
|
133
|
+
return this.#store;
|
|
178
134
|
}
|
|
179
135
|
/**
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* Multiple calls to `initiate` results in a noop.
|
|
136
|
+
* Initiates the session store. The method results in a noop
|
|
137
|
+
* when called multiple times
|
|
184
138
|
*/
|
|
185
139
|
async initiate(readonly) {
|
|
186
|
-
if (this
|
|
140
|
+
if (this.#store) {
|
|
187
141
|
return;
|
|
188
142
|
}
|
|
189
|
-
|
|
190
|
-
|
|
143
|
+
debug('initiating session (readonly: %s)', readonly);
|
|
144
|
+
this.#readonly = readonly;
|
|
145
|
+
const contents = await this.#driver.read(this.#sessionId);
|
|
191
146
|
this.#store = new Store(contents);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Extract flash messages from the store and keep a local
|
|
149
|
+
* copy of it.
|
|
150
|
+
*/
|
|
151
|
+
if (this.has(this.flashKey)) {
|
|
152
|
+
debug('reading flash data');
|
|
153
|
+
if (this.#readonly) {
|
|
154
|
+
this.flashMessages.update(this.get(this.flashKey, null));
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
this.flashMessages.update(this.pull(this.flashKey, null));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Share session with the templates. We assume the view property
|
|
162
|
+
* is a reference to edge templates
|
|
163
|
+
*/
|
|
164
|
+
if ('view' in this.#ctx) {
|
|
165
|
+
this.#ctx.view.share({
|
|
166
|
+
session: new ReadOnlyStore(this.#store.all()),
|
|
167
|
+
flashMessages: new ReadOnlyStore(this.flashMessages.all()),
|
|
168
|
+
old: function (key, defaultValue) {
|
|
169
|
+
return this.flashMessages.get(key, defaultValue);
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
this.#emitter.emit('session:initiated', { session: this });
|
|
204
174
|
}
|
|
205
175
|
/**
|
|
206
|
-
*
|
|
176
|
+
* Put a key-value pair to the session data store
|
|
207
177
|
*/
|
|
208
178
|
put(key, value) {
|
|
209
|
-
this.#
|
|
210
|
-
this.#ensureIsMutable();
|
|
211
|
-
this.#store.set(key, value);
|
|
179
|
+
this.#getStore('write').set(key, value);
|
|
212
180
|
}
|
|
213
181
|
/**
|
|
214
|
-
*
|
|
182
|
+
* Check if a key exists inside the datastore
|
|
215
183
|
*/
|
|
216
184
|
has(key) {
|
|
217
|
-
this.#
|
|
218
|
-
return this.#store.has(key);
|
|
185
|
+
return this.#getStore('read').has(key);
|
|
219
186
|
}
|
|
220
187
|
/**
|
|
221
|
-
* Get value from the session.
|
|
222
|
-
*
|
|
188
|
+
* Get the value of a key from the session datastore.
|
|
189
|
+
* You can specify a default value to use, when key
|
|
190
|
+
* does not exists or has undefined value.
|
|
223
191
|
*/
|
|
224
192
|
get(key, defaultValue) {
|
|
225
|
-
this.#
|
|
226
|
-
return this.#store.get(key, defaultValue);
|
|
193
|
+
return this.#getStore('read').get(key, defaultValue);
|
|
227
194
|
}
|
|
228
195
|
/**
|
|
229
|
-
*
|
|
196
|
+
* Get everything from the session store
|
|
230
197
|
*/
|
|
231
198
|
all() {
|
|
232
|
-
this.#
|
|
233
|
-
return this.#store.all();
|
|
199
|
+
return this.#getStore('read').all();
|
|
234
200
|
}
|
|
235
201
|
/**
|
|
236
|
-
* Remove
|
|
202
|
+
* Remove a key from the session datastore
|
|
237
203
|
*/
|
|
238
204
|
forget(key) {
|
|
239
|
-
this.#
|
|
240
|
-
this.#ensureIsMutable();
|
|
241
|
-
this.#store.unset(key);
|
|
205
|
+
return this.#getStore('write').unset(key);
|
|
242
206
|
}
|
|
243
207
|
/**
|
|
244
|
-
*
|
|
245
|
-
*
|
|
208
|
+
* Read value for a key from the session datastore
|
|
209
|
+
* and remove it simultaneously.
|
|
246
210
|
*/
|
|
247
211
|
pull(key, defaultValue) {
|
|
248
|
-
this.#
|
|
249
|
-
this.#ensureIsMutable();
|
|
250
|
-
return this.#store.pull(key, defaultValue);
|
|
212
|
+
return this.#getStore('write').pull(key, defaultValue);
|
|
251
213
|
}
|
|
252
214
|
/**
|
|
253
|
-
* Increment value
|
|
254
|
-
*
|
|
255
|
-
*
|
|
215
|
+
* Increment the value of a key inside the session
|
|
216
|
+
* store.
|
|
217
|
+
*
|
|
218
|
+
* A new key will be defined if does not exists already.
|
|
219
|
+
* The value of a new key will be 1
|
|
256
220
|
*/
|
|
257
221
|
increment(key, steps = 1) {
|
|
258
|
-
this.#
|
|
259
|
-
this.#ensureIsMutable();
|
|
260
|
-
this.#store.increment(key, steps);
|
|
222
|
+
return this.#getStore('write').increment(key, steps);
|
|
261
223
|
}
|
|
262
224
|
/**
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
225
|
+
* Increment the value of a key inside the session
|
|
226
|
+
* store.
|
|
227
|
+
*
|
|
228
|
+
* A new key will be defined if does not exists already.
|
|
229
|
+
* The value of a new key will be -1
|
|
266
230
|
*/
|
|
267
231
|
decrement(key, steps = 1) {
|
|
268
|
-
this.#
|
|
269
|
-
this.#ensureIsMutable();
|
|
270
|
-
this.#store.decrement(key, steps);
|
|
232
|
+
return this.#getStore('write').decrement(key, steps);
|
|
271
233
|
}
|
|
272
234
|
/**
|
|
273
|
-
*
|
|
235
|
+
* Empty the session store
|
|
274
236
|
*/
|
|
275
237
|
clear() {
|
|
276
|
-
this.#
|
|
277
|
-
this.#ensureIsMutable();
|
|
278
|
-
this.#store.clear();
|
|
238
|
+
return this.#getStore('write').clear();
|
|
279
239
|
}
|
|
280
240
|
/**
|
|
281
|
-
*
|
|
241
|
+
* Flash validation error messages. Make sure the error
|
|
242
|
+
* is an instance of VineJS ValidationException
|
|
282
243
|
*/
|
|
244
|
+
flashValidationErrors(error) {
|
|
245
|
+
const errorsBag = error.messages.reduce((result, message) => {
|
|
246
|
+
if (result[message.field]) {
|
|
247
|
+
result[message.field].push(message.message);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
result[message.field] = [message.message];
|
|
251
|
+
}
|
|
252
|
+
return result;
|
|
253
|
+
}, {});
|
|
254
|
+
this.flashExcept(['_csrf', '_method']);
|
|
255
|
+
this.flash('errors', errorsBag);
|
|
256
|
+
}
|
|
283
257
|
flash(key, value) {
|
|
284
|
-
this.#ensureIsReady();
|
|
285
|
-
this.#ensureIsMutable();
|
|
286
|
-
/**
|
|
287
|
-
* Update value
|
|
288
|
-
*/
|
|
289
258
|
if (typeof key === 'string') {
|
|
290
259
|
if (value) {
|
|
291
|
-
this.
|
|
260
|
+
this.#getFlashStore('write').set(key, value);
|
|
292
261
|
}
|
|
293
262
|
}
|
|
294
263
|
else {
|
|
295
|
-
this.
|
|
264
|
+
this.#getFlashStore('write').merge(key);
|
|
296
265
|
}
|
|
297
266
|
}
|
|
298
267
|
/**
|
|
299
|
-
* Flash
|
|
268
|
+
* Flash form input data to the flash messages store
|
|
300
269
|
*/
|
|
301
270
|
flashAll() {
|
|
302
|
-
this.#
|
|
303
|
-
this.#ensureIsMutable();
|
|
304
|
-
this.responseFlashMessages.set('input', this.#ctx.request.original());
|
|
271
|
+
return this.#getFlashStore('write').set('input', this.#ctx.request.original());
|
|
305
272
|
}
|
|
306
273
|
/**
|
|
307
|
-
* Flash
|
|
274
|
+
* Flash form input data (except some keys) to the flash messages store
|
|
308
275
|
*/
|
|
309
276
|
flashExcept(keys) {
|
|
310
|
-
this.#
|
|
311
|
-
this.#ensureIsMutable();
|
|
312
|
-
this.responseFlashMessages.set('input', lodash.omit(this.#ctx.request.original(), keys));
|
|
277
|
+
this.#getFlashStore('write').set('input', lodash.omit(this.#ctx.request.original(), keys));
|
|
313
278
|
}
|
|
314
279
|
/**
|
|
315
|
-
* Flash only
|
|
280
|
+
* Flash form input data (only some keys) to the flash messages store
|
|
316
281
|
*/
|
|
317
282
|
flashOnly(keys) {
|
|
318
|
-
this.#
|
|
319
|
-
this.#ensureIsMutable();
|
|
320
|
-
this.responseFlashMessages.set('input', lodash.pick(this.#ctx.request.original(), keys));
|
|
283
|
+
this.#getFlashStore('write').set('input', lodash.pick(this.#ctx.request.original(), keys));
|
|
321
284
|
}
|
|
322
285
|
/**
|
|
323
|
-
* Reflash
|
|
286
|
+
* Reflash messages from the last request in the current response
|
|
324
287
|
*/
|
|
325
288
|
reflash() {
|
|
326
|
-
this.
|
|
289
|
+
this.#getFlashStore('write').set('reflashed', this.flashMessages.all());
|
|
327
290
|
}
|
|
328
291
|
/**
|
|
329
|
-
* Reflash
|
|
292
|
+
* Reflash messages (only some keys) from the last
|
|
293
|
+
* request in the current response
|
|
330
294
|
*/
|
|
331
295
|
reflashOnly(keys) {
|
|
332
|
-
this.
|
|
296
|
+
this.#getFlashStore('write').set('reflashed', lodash.pick(this.flashMessages.all(), keys));
|
|
333
297
|
}
|
|
334
298
|
/**
|
|
335
|
-
*
|
|
336
|
-
*
|
|
299
|
+
* Reflash messages (except some keys) from the last
|
|
300
|
+
* request in the current response
|
|
337
301
|
*/
|
|
338
302
|
reflashExcept(keys) {
|
|
339
|
-
this.
|
|
303
|
+
this.#getFlashStore('write').set('reflashed', lodash.omit(this.flashMessages.all(), keys));
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Re-generate the session id and migrate data to it.
|
|
307
|
+
*/
|
|
308
|
+
regenerate() {
|
|
309
|
+
this.#sessionId = cuid();
|
|
340
310
|
}
|
|
341
311
|
/**
|
|
342
|
-
*
|
|
312
|
+
* Commit session changes. No more mutations will be
|
|
313
|
+
* allowed after commit.
|
|
343
314
|
*/
|
|
344
315
|
async commit() {
|
|
345
|
-
if (!this.
|
|
346
|
-
this.#touchSessionCookie();
|
|
347
|
-
await this.#touchDriver();
|
|
316
|
+
if (!this.#store || this.readonly) {
|
|
348
317
|
return;
|
|
349
318
|
}
|
|
350
319
|
/**
|
|
351
|
-
*
|
|
320
|
+
* If the flash messages store is not empty, we should put
|
|
321
|
+
* its messages inside main session store.
|
|
322
|
+
*/
|
|
323
|
+
if (!this.responseFlashMessages.isEmpty) {
|
|
324
|
+
const { input, reflashed, ...others } = this.responseFlashMessages.all();
|
|
325
|
+
this.put(this.flashKey, { ...reflashed, ...input, ...others });
|
|
326
|
+
}
|
|
327
|
+
debug('committing session data');
|
|
328
|
+
/**
|
|
329
|
+
* Touch the session id cookie to stay alive
|
|
330
|
+
*/
|
|
331
|
+
this.#ctx.response.cookie(this.#config.cookieName, this.#sessionId, this.#config.cookie);
|
|
332
|
+
/**
|
|
333
|
+
* Delete the session data when the session store
|
|
334
|
+
* is empty.
|
|
335
|
+
*
|
|
336
|
+
* Also we only destroy the session id we read from the cookie.
|
|
337
|
+
* If there was no session id in the cookie, there won't be
|
|
338
|
+
* any data inside the store either.
|
|
352
339
|
*/
|
|
353
|
-
if (this
|
|
354
|
-
|
|
340
|
+
if (this.isEmpty) {
|
|
341
|
+
if (this.#sessionIdFromCookie) {
|
|
342
|
+
await this.#driver.destroy(this.#sessionIdFromCookie);
|
|
343
|
+
}
|
|
344
|
+
this.#emitter.emit('session:committed', { session: this });
|
|
345
|
+
return;
|
|
355
346
|
}
|
|
356
347
|
/**
|
|
357
|
-
* Touch the
|
|
348
|
+
* Touch the store expiry when the session store was
|
|
349
|
+
* not modified.
|
|
358
350
|
*/
|
|
359
|
-
this
|
|
360
|
-
|
|
351
|
+
if (!this.hasBeenModified) {
|
|
352
|
+
if (this.#sessionIdFromCookie && this.#sessionIdFromCookie !== this.#sessionId) {
|
|
353
|
+
await this.#driver.destroy(this.#sessionIdFromCookie);
|
|
354
|
+
await this.#driver.write(this.#sessionId, this.#store.toJSON());
|
|
355
|
+
this.#emitter.emit('session:migrated', {
|
|
356
|
+
fromSessionId: this.#sessionIdFromCookie,
|
|
357
|
+
toSessionId: this.sessionId,
|
|
358
|
+
session: this,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
await this.#driver.touch(this.#sessionId);
|
|
363
|
+
}
|
|
364
|
+
this.#emitter.emit('session:committed', { session: this });
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
361
367
|
/**
|
|
362
|
-
*
|
|
363
|
-
* Otherwise delete the session store to cleanup
|
|
364
|
-
* the storage space.
|
|
368
|
+
* Otherwise commit to the session store
|
|
365
369
|
*/
|
|
366
|
-
if (
|
|
367
|
-
await this.#
|
|
370
|
+
if (this.#sessionIdFromCookie && this.#sessionIdFromCookie !== this.#sessionId) {
|
|
371
|
+
await this.#driver.destroy(this.#sessionIdFromCookie);
|
|
372
|
+
await this.#driver.write(this.#sessionId, this.#store.toJSON());
|
|
373
|
+
this.#emitter.emit('session:migrated', {
|
|
374
|
+
fromSessionId: this.#sessionIdFromCookie,
|
|
375
|
+
toSessionId: this.sessionId,
|
|
376
|
+
session: this,
|
|
377
|
+
});
|
|
368
378
|
}
|
|
369
379
|
else {
|
|
370
|
-
await this.#driver.
|
|
380
|
+
await this.#driver.write(this.#sessionId, this.#store.toJSON());
|
|
371
381
|
}
|
|
382
|
+
this.#emitter.emit('session:committed', { session: this });
|
|
372
383
|
}
|
|
373
384
|
}
|
|
@@ -1,5 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { EmitterService } from '@adonisjs/core/types';
|
|
2
2
|
import type { NextFn } from '@adonisjs/core/types/http';
|
|
3
|
+
import { HttpContext } from '@adonisjs/core/http';
|
|
4
|
+
import { Session } from './session.js';
|
|
5
|
+
import type { SessionConfig } from './types/main.js';
|
|
6
|
+
/**
|
|
7
|
+
* HttpContext augmentations
|
|
8
|
+
*/
|
|
9
|
+
declare module '@adonisjs/http-server' {
|
|
10
|
+
interface HttpContext {
|
|
11
|
+
session: Session;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Session middleware is used to initiate the session store
|
|
16
|
+
* and commit its values during an HTTP request
|
|
17
|
+
*/
|
|
3
18
|
export default class SessionMiddleware {
|
|
4
|
-
|
|
19
|
+
#private;
|
|
20
|
+
constructor(config: SessionConfig, emitter: EmitterService);
|
|
21
|
+
handle(ctx: HttpContext, next: NextFn): Promise<any>;
|
|
5
22
|
}
|