@adonisjs/session 6.3.0 → 7.0.0-0

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.
Files changed (56) hide show
  1. package/build/configure.d.ts +5 -0
  2. package/build/configure.js +18 -0
  3. package/build/index.d.ts +12 -0
  4. package/build/index.js +12 -0
  5. package/build/providers/session_provider.d.ts +13 -0
  6. package/build/providers/session_provider.js +43 -0
  7. package/build/src/bindings/api_client.d.ts +2 -0
  8. package/build/src/{Bindings/Tests.js → bindings/api_client.js} +14 -10
  9. package/build/src/bindings/http_context.d.ts +5 -0
  10. package/build/src/bindings/http_context.js +17 -0
  11. package/build/{adonis-typings/tests.d.ts → src/bindings/types.d.ts} +30 -3
  12. package/build/{adonis-typings/session.js → src/bindings/types.js} +2 -1
  13. package/build/src/{Client/index.d.ts → client.d.ts} +7 -15
  14. package/build/src/client.js +100 -0
  15. package/build/src/define_config.d.ts +5 -0
  16. package/build/src/define_config.js +13 -0
  17. package/build/src/{Drivers/Cookie.d.ts → drivers/cookie.d.ts} +4 -6
  18. package/build/src/{Drivers/Cookie.js → drivers/cookie.js} +10 -12
  19. package/build/src/{Drivers/File.d.ts → drivers/file.d.ts} +3 -8
  20. package/build/src/{Drivers/File.js → drivers/file.js} +20 -23
  21. package/build/src/{Drivers/Memory.d.ts → drivers/memory.d.ts} +2 -3
  22. package/build/src/{Drivers/Memory.js → drivers/memory.js} +3 -7
  23. package/build/src/{Drivers/Redis.d.ts → drivers/redis.d.ts} +5 -15
  24. package/build/src/drivers/redis.js +74 -0
  25. package/build/src/{Session/index.d.ts → session.d.ts} +6 -67
  26. package/build/src/session.js +373 -0
  27. package/build/src/session_manager.d.ts +38 -0
  28. package/build/src/session_manager.js +149 -0
  29. package/build/src/session_middleware.d.ts +5 -0
  30. package/build/src/session_middleware.js +20 -0
  31. package/build/src/{Store/index.d.ts → store.d.ts} +3 -7
  32. package/build/src/{Store/index.js → store.js} +18 -18
  33. package/build/src/types.d.ts +61 -0
  34. package/build/src/types.js +1 -0
  35. package/build/{templates/session.txt → stubs/config.stub} +13 -18
  36. package/build/stubs/main.d.ts +1 -0
  37. package/build/{adonis-typings/tests.js → stubs/main.js} +2 -3
  38. package/package.json +96 -132
  39. package/build/adonis-typings/container.d.ts +0 -14
  40. package/build/adonis-typings/container.js +0 -8
  41. package/build/adonis-typings/context.d.ts +0 -14
  42. package/build/adonis-typings/context.js +0 -8
  43. package/build/adonis-typings/index.d.ts +0 -4
  44. package/build/adonis-typings/index.js +0 -12
  45. package/build/adonis-typings/session.d.ts +0 -265
  46. package/build/instructions.md +0 -10
  47. package/build/providers/SessionProvider.d.ts +0 -31
  48. package/build/providers/SessionProvider.js +0 -56
  49. package/build/src/Bindings/Server.d.ts +0 -10
  50. package/build/src/Bindings/Server.js +0 -42
  51. package/build/src/Bindings/Tests.d.ts +0 -7
  52. package/build/src/Client/index.js +0 -93
  53. package/build/src/Drivers/Redis.js +0 -73
  54. package/build/src/Session/index.js +0 -352
  55. package/build/src/SessionManager/index.d.ts +0 -78
  56. package/build/src/SessionManager/index.js +0 -148
@@ -1,29 +1,19 @@
1
1
  /**
2
2
  * @adonisjs/session
3
3
  *
4
- * (c) Harminder Virk <virk@adonisjs.com>
4
+ * (c) AdonisJS
5
5
  *
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
- /// <reference path="../../adonis-typings/index.d.ts" />
10
- import { SessionDriverContract, SessionConfig } from '@ioc:Adonis/Addons/Session';
11
- import { RedisManagerContract } from '@ioc:Adonis/Addons/Redis';
9
+ import type { RedisManagerContract } from '@adonisjs/redis/types';
10
+ import type { SessionDriverContract, SessionConfig } from '../types.js';
12
11
  /**
13
12
  * File driver to read/write session to filesystem
14
13
  */
15
14
  export declare class RedisDriver implements SessionDriverContract {
16
- private config;
17
- private redis;
18
- /**
19
- * Convert milliseconds to seconds
20
- */
21
- private ttl;
22
- constructor(config: SessionConfig, redis: RedisManagerContract);
23
- /**
24
- * Returns instance of the redis connection
25
- */
26
- private getRedisConnection;
15
+ #private;
16
+ constructor(config: SessionConfig, redis: RedisManagerContract<any>);
27
17
  /**
28
18
  * Returns file contents. A new file will be created if it's
29
19
  * missing.
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @adonisjs/session
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import { Exception } from '@poppinss/utils';
10
+ import string from '@poppinss/utils/string';
11
+ import { MessageBuilder } from '@poppinss/utils';
12
+ /**
13
+ * File driver to read/write session to filesystem
14
+ */
15
+ export class RedisDriver {
16
+ #config;
17
+ #redis;
18
+ #ttl;
19
+ constructor(config, redis) {
20
+ this.#config = config;
21
+ this.#redis = redis;
22
+ /**
23
+ * Convert milliseconds to seconds
24
+ */
25
+ this.#ttl = Math.round((typeof this.#config.age === 'string'
26
+ ? string.milliseconds.parse(this.#config.age)
27
+ : this.#config.age) / 1000);
28
+ if (!this.#config.redisConnection) {
29
+ throw new Exception('Missing redisConnection for session redis driver inside "config/session" file', { code: 'E_INVALID_SESSION_DRIVER_CONFIG', status: 500 });
30
+ }
31
+ }
32
+ /**
33
+ * Returns instance of the redis connection
34
+ */
35
+ #getRedisConnection() {
36
+ return this.#redis.connection(this.#config.redisConnection);
37
+ }
38
+ /**
39
+ * Returns file contents. A new file will be created if it's
40
+ * missing.
41
+ */
42
+ async read(sessionId) {
43
+ const contents = await this.#getRedisConnection().get(sessionId);
44
+ if (!contents) {
45
+ return null;
46
+ }
47
+ const verifiedContents = new MessageBuilder().verify(contents, sessionId);
48
+ if (typeof verifiedContents !== 'object') {
49
+ return null;
50
+ }
51
+ return verifiedContents;
52
+ }
53
+ /**
54
+ * Write session values to a file
55
+ */
56
+ async write(sessionId, values) {
57
+ if (typeof values !== 'object') {
58
+ throw new Error('Session file driver expects an object of values');
59
+ }
60
+ await this.#getRedisConnection().setex(sessionId, this.#ttl, new MessageBuilder().build(values, undefined, sessionId));
61
+ }
62
+ /**
63
+ * Cleanup session file by removing it
64
+ */
65
+ async destroy(sessionId) {
66
+ await this.#getRedisConnection().del(sessionId);
67
+ }
68
+ /**
69
+ * Updates the value expiry
70
+ */
71
+ async touch(sessionId) {
72
+ await this.#getRedisConnection().expire(sessionId, this.#ttl);
73
+ }
74
+ }
@@ -1,15 +1,12 @@
1
- /// <reference path="../../adonis-typings/session.d.ts" />
2
- import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
3
- import { SessionConfig, SessionContract, AllowedSessionValues, SessionDriverContract } from '@ioc:Adonis/Addons/Session';
4
- import { Store } from '../Store';
1
+ import type { SessionConfig, SessionDriverContract, AllowedSessionValues } from './types.js';
2
+ import type { HttpContext } from '@adonisjs/core/http';
3
+ import { Store } from './store.js';
5
4
  /**
6
5
  * Session class exposes the API to read/write values to the session for
7
6
  * a given request.
8
7
  */
9
- export declare class Session implements SessionContract {
10
- private ctx;
11
- private config;
12
- private driver;
8
+ export declare class Session {
9
+ #private;
13
10
  /**
14
11
  * Set to true inside the `initiate` method
15
12
  */
@@ -34,21 +31,6 @@ export declare class Session implements SessionContract {
34
31
  * A copy of previously set flash messages
35
32
  */
36
33
  flashMessages: Store;
37
- /**
38
- * Session id for the current request. It will be different
39
- * from the "this.sessionId" when regenerate is called.
40
- */
41
- private currentSessionId;
42
- /**
43
- * A instance of store with values read from the driver. The store
44
- * in initiated inside the [[initiate]] method
45
- */
46
- private store;
47
- /**
48
- * Whether or not to re-generate the session id before comitting
49
- * session values.
50
- */
51
- private regeneratedSessionId;
52
34
  /**
53
35
  * A copy of flash messages. The `input` messages
54
36
  * are overwritten when any of the input related
@@ -57,50 +39,7 @@ export declare class Session implements SessionContract {
57
39
  * The `others` object is expanded with each call.
58
40
  */
59
41
  responseFlashMessages: Store;
60
- /**
61
- * Session key for setting flash messages
62
- */
63
- private flashMessagesKey;
64
- constructor(ctx: HttpContextContract, config: SessionConfig, driver: SessionDriverContract);
65
- /**
66
- * Returns a merged copy of flash messages or null
67
- * when nothing is set
68
- */
69
- private setFlashMessages;
70
- /**
71
- * Returns the existing session id or creates one.
72
- */
73
- private getSessionId;
74
- /**
75
- * Ensures the session store is initialized
76
- */
77
- private ensureIsReady;
78
- /**
79
- * Raises exception when session store is in readonly mode
80
- */
81
- private ensureIsMutable;
82
- /**
83
- * Touches the session cookie
84
- */
85
- private touchSessionCookie;
86
- /**
87
- * Commits the session value to the store
88
- */
89
- private commitValuesToStore;
90
- /**
91
- * Touches the driver to make sure the session values doesn't expire
92
- */
93
- private touchDriver;
94
- /**
95
- * Reading flash messages from the last HTTP request and
96
- * updating the flash messages bag
97
- */
98
- private readLastRequestFlashMessage;
99
- /**
100
- * Share flash messages & read only session's functions with views
101
- * (only when view property exists)
102
- */
103
- private shareLocalsWithView;
42
+ constructor(ctx: HttpContext, config: SessionConfig, driver: SessionDriverContract);
104
43
  /**
105
44
  * Initiating the session by reading it's value from the
106
45
  * driver and feeding it to a store.
@@ -0,0 +1,373 @@
1
+ /*
2
+ * @adonisjs/session
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import { Exception } from '@poppinss/utils';
10
+ import lodash from '@poppinss/utils/lodash';
11
+ import { cuid } from '@adonisjs/core/helpers';
12
+ import { Store } from './store.js';
13
+ /**
14
+ * Session class exposes the API to read/write values to the session for
15
+ * a given request.
16
+ */
17
+ 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
+ #config;
45
+ /**
46
+ * The session driver instance used to read and write session data.
47
+ */
48
+ #driver;
49
+ /**
50
+ * Set to true inside the `initiate` method
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
57
+ */
58
+ fresh = false;
59
+ /**
60
+ * A boolean to know if store is initiated in readonly mode
61
+ * or not. This is done during Websocket requests
62
+ */
63
+ readonly = false;
64
+ /**
65
+ * Session id for the given request. A new session id is only
66
+ * generated when the cookie for the session id is missing
67
+ */
68
+ sessionId;
69
+ /**
70
+ * A copy of previously set flash messages
71
+ */
72
+ flashMessages = new Store({});
73
+ /**
74
+ * A copy of flash messages. The `input` messages
75
+ * are overwritten when any of the input related
76
+ * methods are used.
77
+ *
78
+ * The `others` object is expanded with each call.
79
+ */
80
+ responseFlashMessages = new Store({});
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
+ }
88
+ /**
89
+ * Returns a merged copy of flash messages or null
90
+ * when nothing is set
91
+ */
92
+ #setFlashMessages() {
93
+ if (this.responseFlashMessages.isEmpty) {
94
+ return;
95
+ }
96
+ const { input, ...others } = this.responseFlashMessages.all();
97
+ this.put(this.#flashMessagesKey, { ...input, ...others });
98
+ }
99
+ /**
100
+ * Returns the existing session id or creates one.
101
+ */
102
+ #getSessionId() {
103
+ const sessionId = this.#ctx.request.cookie(this.#config.cookieName);
104
+ if (sessionId) {
105
+ return sessionId;
106
+ }
107
+ this.fresh = true;
108
+ return cuid();
109
+ }
110
+ /**
111
+ * Ensures the session store is initialized
112
+ */
113
+ #ensureIsReady() {
114
+ if (!this.initiated) {
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
+ }
117
+ }
118
+ /**
119
+ * Raises exception when session store is in readonly mode
120
+ */
121
+ #ensureIsMutable() {
122
+ if (this.readonly) {
123
+ throw new Exception('Session store is in readonly mode and cannot be mutated', {
124
+ status: 500,
125
+ code: 'E_RUNTIME_EXCEPTION',
126
+ });
127
+ }
128
+ }
129
+ /**
130
+ * Touches the session cookie
131
+ */
132
+ #touchSessionCookie() {
133
+ this.#ctx.logger.trace('touching session cookie');
134
+ this.#ctx.response.cookie(this.#config.cookieName, this.sessionId, this.#config.cookie);
135
+ }
136
+ /**
137
+ * Commits the session value to the store
138
+ */
139
+ async #commitValuesToStore() {
140
+ this.#ctx.logger.trace('persist session store with driver');
141
+ await this.#driver.write(this.sessionId, this.#store.toJSON());
142
+ }
143
+ /**
144
+ * Touches the driver to make sure the session values doesn't expire
145
+ */
146
+ async #touchDriver() {
147
+ this.#ctx.logger.trace('touch driver for liveliness');
148
+ await this.#driver.touch(this.sessionId);
149
+ }
150
+ /**
151
+ * Reading flash messages from the last HTTP request and
152
+ * updating the flash messages bag
153
+ */
154
+ #readLastRequestFlashMessage() {
155
+ if (this.readonly) {
156
+ return;
157
+ }
158
+ this.flashMessages.update(this.pull(this.#flashMessagesKey, null));
159
+ }
160
+ /**
161
+ * Share flash messages & read only session's functions with views
162
+ * (only when view property exists)
163
+ */
164
+ #shareLocalsWithView() {
165
+ // @ts-ignore may need to expose ./types/extended from adonisjs/view
166
+ if (!this.#ctx['view'] || typeof this.#ctx['view'].share !== 'function') {
167
+ return;
168
+ }
169
+ // @ts-ignore may need to expose ./types/extended from adonisjs/view
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
+ });
178
+ }
179
+ /**
180
+ * Initiating the session by reading it's value from the
181
+ * driver and feeding it to a store.
182
+ *
183
+ * Multiple calls to `initiate` results in a noop.
184
+ */
185
+ async initiate(readonly) {
186
+ if (this.initiated) {
187
+ return;
188
+ }
189
+ this.readonly = readonly;
190
+ const contents = await this.#driver.read(this.sessionId);
191
+ this.#store = new Store(contents);
192
+ this.initiated = true;
193
+ this.#readLastRequestFlashMessage();
194
+ this.#shareLocalsWithView();
195
+ }
196
+ /**
197
+ * Re-generates the session id. This can is used to avoid
198
+ * session fixation attacks.
199
+ */
200
+ regenerate() {
201
+ this.#ctx.logger.trace('explicitly re-generating session id');
202
+ this.sessionId = cuid();
203
+ this.#regeneratedSessionId = true;
204
+ }
205
+ /**
206
+ * Set/update session value
207
+ */
208
+ put(key, value) {
209
+ this.#ensureIsReady();
210
+ this.#ensureIsMutable();
211
+ this.#store.set(key, value);
212
+ }
213
+ /**
214
+ * Find if the value exists in the session
215
+ */
216
+ has(key) {
217
+ this.#ensureIsReady();
218
+ return this.#store.has(key);
219
+ }
220
+ /**
221
+ * Get value from the session. The default value is returned
222
+ * when actual value is `undefined`
223
+ */
224
+ get(key, defaultValue) {
225
+ this.#ensureIsReady();
226
+ return this.#store.get(key, defaultValue);
227
+ }
228
+ /**
229
+ * Returns everything from the session
230
+ */
231
+ all() {
232
+ this.#ensureIsReady();
233
+ return this.#store.all();
234
+ }
235
+ /**
236
+ * Remove value for a given key from the session
237
+ */
238
+ forget(key) {
239
+ this.#ensureIsReady();
240
+ this.#ensureIsMutable();
241
+ this.#store.unset(key);
242
+ }
243
+ /**
244
+ * The method is equivalent to calling `session.get` followed
245
+ * by `session.forget`
246
+ */
247
+ pull(key, defaultValue) {
248
+ this.#ensureIsReady();
249
+ this.#ensureIsMutable();
250
+ return this.#store.pull(key, defaultValue);
251
+ }
252
+ /**
253
+ * Increment value for a number inside the session store. The
254
+ * method raises an error when underlying value is not
255
+ * a number
256
+ */
257
+ increment(key, steps = 1) {
258
+ this.#ensureIsReady();
259
+ this.#ensureIsMutable();
260
+ this.#store.increment(key, steps);
261
+ }
262
+ /**
263
+ * Decrement value for a number inside the session store. The
264
+ * method raises an error when underlying value is not
265
+ * a number
266
+ */
267
+ decrement(key, steps = 1) {
268
+ this.#ensureIsReady();
269
+ this.#ensureIsMutable();
270
+ this.#store.decrement(key, steps);
271
+ }
272
+ /**
273
+ * Remove everything from the session
274
+ */
275
+ clear() {
276
+ this.#ensureIsReady();
277
+ this.#ensureIsMutable();
278
+ this.#store.clear();
279
+ }
280
+ /**
281
+ * Add a new flash message
282
+ */
283
+ flash(key, value) {
284
+ this.#ensureIsReady();
285
+ this.#ensureIsMutable();
286
+ /**
287
+ * Update value
288
+ */
289
+ if (typeof key === 'string') {
290
+ if (value) {
291
+ this.responseFlashMessages.set(key, value);
292
+ }
293
+ }
294
+ else {
295
+ this.responseFlashMessages.merge(key);
296
+ }
297
+ }
298
+ /**
299
+ * Flash all form values
300
+ */
301
+ flashAll() {
302
+ this.#ensureIsReady();
303
+ this.#ensureIsMutable();
304
+ this.responseFlashMessages.set('input', this.#ctx.request.original());
305
+ }
306
+ /**
307
+ * Flash all form values except mentioned keys
308
+ */
309
+ flashExcept(keys) {
310
+ this.#ensureIsReady();
311
+ this.#ensureIsMutable();
312
+ this.responseFlashMessages.set('input', lodash.omit(this.#ctx.request.original(), keys));
313
+ }
314
+ /**
315
+ * Flash only defined keys from the form values
316
+ */
317
+ flashOnly(keys) {
318
+ this.#ensureIsReady();
319
+ this.#ensureIsMutable();
320
+ this.responseFlashMessages.set('input', lodash.pick(this.#ctx.request.original(), keys));
321
+ }
322
+ /**
323
+ * Reflash existing flash messages
324
+ */
325
+ reflash() {
326
+ this.flash(this.flashMessages.all());
327
+ }
328
+ /**
329
+ * Reflash selected keys from the existing flash messages
330
+ */
331
+ reflashOnly(keys) {
332
+ this.flash(lodash.pick(this.flashMessages.all(), keys));
333
+ }
334
+ /**
335
+ * Omit selected keys from the existing flash messages
336
+ * and flash the rest of values
337
+ */
338
+ reflashExcept(keys) {
339
+ this.flash(lodash.omit(this.flashMessages.all(), keys));
340
+ }
341
+ /**
342
+ * Writes value to the underlying session driver.
343
+ */
344
+ async commit() {
345
+ if (!this.initiated) {
346
+ this.#touchSessionCookie();
347
+ await this.#touchDriver();
348
+ return;
349
+ }
350
+ /**
351
+ * Cleanup old session and re-generate new session
352
+ */
353
+ if (this.#regeneratedSessionId) {
354
+ await this.#driver.destroy(this.#currentSessionId);
355
+ }
356
+ /**
357
+ * Touch the session cookie to keep it alive.
358
+ */
359
+ this.#touchSessionCookie();
360
+ this.#setFlashMessages();
361
+ /**
362
+ * Commit values to the store if not empty.
363
+ * Otherwise delete the session store to cleanup
364
+ * the storage space.
365
+ */
366
+ if (!this.#store.isEmpty) {
367
+ await this.#commitValuesToStore();
368
+ }
369
+ else {
370
+ await this.#driver.destroy(this.sessionId);
371
+ }
372
+ }
373
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @adonisjs/session
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import { Session } from './session.js';
10
+ import { HttpContext } from '@adonisjs/core/http';
11
+ import { ExtendCallback, SessionConfig } from './types.js';
12
+ import { RedisManagerContract } from '@adonisjs/redis/types';
13
+ import { Encryption } from '@adonisjs/core/encryption';
14
+ import { SessionClient } from './client.js';
15
+ /**
16
+ * Session manager exposes the API to create session instance for a given
17
+ * request and also add new drivers.
18
+ */
19
+ export declare class SessionManager {
20
+ #private;
21
+ constructor(config: SessionConfig, encryption: Encryption, redis?: RedisManagerContract<any>);
22
+ /**
23
+ * Find if the sessions are enabled
24
+ */
25
+ isEnabled(): boolean;
26
+ /**
27
+ * Creates an instance of the session client
28
+ */
29
+ client(): SessionClient;
30
+ /**
31
+ * Creates a new session instance for a given HTTP request
32
+ */
33
+ create(ctx: HttpContext): Session;
34
+ /**
35
+ * Extend the drivers list by adding a new one.
36
+ */
37
+ extend(driver: string, callback: ExtendCallback): void;
38
+ }