@spinajs/rbac 2.0.489 → 2.0.491
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/lib/cjs/migrations/RBACInitial_2022_06_28_01_13_00.js +1 -1
- package/lib/cjs/migrations/RBACInitial_2022_06_28_01_13_00.js.map +1 -1
- package/lib/cjs/session-codec.d.ts +30 -4
- package/lib/cjs/session-codec.d.ts.map +1 -1
- package/lib/cjs/session-codec.js +102 -6
- package/lib/cjs/session-codec.js.map +1 -1
- package/lib/mjs/migrations/RBACInitial_2022_06_28_01_13_00.js +1 -1
- package/lib/mjs/migrations/RBACInitial_2022_06_28_01_13_00.js.map +1 -1
- package/lib/mjs/session-codec.d.ts +30 -4
- package/lib/mjs/session-codec.d.ts.map +1 -1
- package/lib/mjs/session-codec.js +102 -6
- package/lib/mjs/session-codec.js.map +1 -1
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +11 -11
|
@@ -13,7 +13,7 @@ let RBACInitial_2022_06_28_01_13_00 = class RBACInitial_2022_06_28_01_13_00 exte
|
|
|
13
13
|
async up(connection) {
|
|
14
14
|
await connection.schema().createTable('users', (table) => {
|
|
15
15
|
table.int('Id').primaryKey().autoIncrement();
|
|
16
|
-
table.
|
|
16
|
+
table.string('Uuid', 36).notNull();
|
|
17
17
|
table.string('Email', 64).unique().notNull();
|
|
18
18
|
table.string('Password', 128).notNull();
|
|
19
19
|
table.string('Login', 64).notNull();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RBACInitial_2022_06_28_01_13_00.js","sourceRoot":"","sources":["../../../src/migrations/RBACInitial_2022_06_28_01_13_00.ts"],"names":[],"mappings":";;;;;;;;;AAAA,sDAAsD;AACtD,sCAAkE;AAI3D,IAAM,+BAA+B,GAArC,MAAM,+BAAgC,SAAQ,kBAAY;IACxD,KAAK,CAAC,EAAE,CAAC,UAAqB;QACnC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACvD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,CAAC;YAC7C,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"RBACInitial_2022_06_28_01_13_00.js","sourceRoot":"","sources":["../../../src/migrations/RBACInitial_2022_06_28_01_13_00.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,10 +6,36 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function encodeSessionData(data: Map<string, unknown>): string;
|
|
8
8
|
/**
|
|
9
|
-
* Restores a session `Data` map from a
|
|
10
|
-
* {@link encodeSessionData}.
|
|
9
|
+
* Restores a session `Data` map from whatever a store hands back for the payload
|
|
10
|
+
* written by {@link encodeSessionData}.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* TWO representations reach this function, and both are legitimate:
|
|
13
|
+
*
|
|
14
|
+
* - a **string** - what {@link encodeSessionData} produces, and what every
|
|
15
|
+
* text-ish column and every non-SQL store (redis, dynamodb) returns. Parsed
|
|
16
|
+
* with {@link sessionReviver}, the JSON.parse path.
|
|
17
|
+
* - an **object** - a MySQL `json` column, which mysql2 parses for us before
|
|
18
|
+
* the ORM ever sees it. Walked with {@link reviveSessionValue}: the value is
|
|
19
|
+
* already an object graph, so round-tripping it back through
|
|
20
|
+
* `JSON.stringify` + `JSON.parse` purely to reach the reviver would be
|
|
21
|
+
* pointless work on every single session read.
|
|
22
|
+
*
|
|
23
|
+
* Both branches are kept deliberately. `user_sessions.Data` is a `json` column
|
|
24
|
+
* on fresh installs and on every install that has run the converging migration,
|
|
25
|
+
* but a driver, a column type or a store that still yields a string must keep
|
|
26
|
+
* decoding - and the sqlite driver used by the tests is exactly that case.
|
|
27
|
+
*
|
|
28
|
+
* ANYTHING ELSE THROWS. The object branch is narrowed to a real object
|
|
29
|
+
* (`!== null && typeof === 'object'`) rather than being the `else` of the string
|
|
30
|
+
* test, because widening the parameter to `unknown` otherwise turns `null`,
|
|
31
|
+
* `undefined` and a stray number into a silently EMPTY session: every request
|
|
32
|
+
* carrying that session reads as authenticated-but-anonymous, and a store that
|
|
33
|
+
* started handing back the wrong shape would log out its entire user base
|
|
34
|
+
* without a single error line. A missing or malformed payload is a defect in the
|
|
35
|
+
* store, not a session with no data, and it is raised as one.
|
|
36
|
+
*
|
|
37
|
+
* @param data - the serialized session data, as string or as parsed object
|
|
38
|
+
* @throws `InvalidArgument` when `data` is neither a string nor a non-null object
|
|
13
39
|
*/
|
|
14
|
-
export declare function decodeSessionData(
|
|
40
|
+
export declare function decodeSessionData(data: string | unknown): Map<string, unknown>;
|
|
15
41
|
//# sourceMappingURL=session-codec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-codec.d.ts","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-codec.d.ts","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":"AAkHA;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAc9E"}
|
package/lib/cjs/session-codec.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.encodeSessionData = encodeSessionData;
|
|
4
4
|
exports.decodeSessionData = decodeSessionData;
|
|
5
5
|
const luxon_1 = require("luxon");
|
|
6
|
+
const exceptions_1 = require("@spinajs/exceptions");
|
|
6
7
|
const util_1 = require("@spinajs/util");
|
|
7
8
|
/**
|
|
8
9
|
* Shared session-data serialization codec (fixes B5 — symmetric write/read).
|
|
@@ -37,6 +38,68 @@ function sessionReviver(key, value) {
|
|
|
37
38
|
}
|
|
38
39
|
return (0, util_1.reviver)(key, value);
|
|
39
40
|
}
|
|
41
|
+
const MAP_TAG = 'Map';
|
|
42
|
+
const SET_TAG = 'Set';
|
|
43
|
+
/**
|
|
44
|
+
* Object-graph twin of {@link sessionReviver}: turns the same tags back into the
|
|
45
|
+
* same instances, but reads a value that is ALREADY a parsed object graph
|
|
46
|
+
* instead of JSON text.
|
|
47
|
+
*
|
|
48
|
+
* It exists because a MySQL `json` column comes back from mysql2 already parsed.
|
|
49
|
+
* Re-serializing that object only to hand it straight back to `JSON.parse` would
|
|
50
|
+
* be a pure waste - and passing it to the decoder untransformed is worse than
|
|
51
|
+
* wasteful: the payload's top level is the tagged wrapper
|
|
52
|
+
* `{ dataType: 'Map', value: [...] }`, so without this walk `parsed instanceof Map`
|
|
53
|
+
* is false and the session decodes as silently EMPTY.
|
|
54
|
+
*
|
|
55
|
+
* Kept byte-for-byte semantically equal to the reviver:
|
|
56
|
+
*
|
|
57
|
+
* - `JSON.parse` calls its reviver bottom-up (children before parents), so the
|
|
58
|
+
* walk recurses into children BEFORE inspecting the node's own tag,
|
|
59
|
+
* - the DateTime tag is checked before the shared Map/Set tags, matching
|
|
60
|
+
* {@link sessionReviver}'s order,
|
|
61
|
+
* - properties are installed with `defineProperty` so a payload carrying a
|
|
62
|
+
* literal `__proto__` key becomes an own data property (what `JSON.parse`
|
|
63
|
+
* does) rather than mutating the result's prototype.
|
|
64
|
+
*
|
|
65
|
+
* Values that are already live instances (`Map` / `Set` / `DateTime`) are passed
|
|
66
|
+
* through untouched: a caller may legitimately hand over data that never went
|
|
67
|
+
* through a database at all.
|
|
68
|
+
*/
|
|
69
|
+
function reviveSessionValue(value) {
|
|
70
|
+
if (value === null || typeof value !== 'object') {
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
if (Array.isArray(value)) {
|
|
74
|
+
return value.map(reviveSessionValue);
|
|
75
|
+
}
|
|
76
|
+
// already-materialized structural types - nothing to rebuild
|
|
77
|
+
if (value instanceof Map || value instanceof Set || luxon_1.DateTime.isDateTime(value)) {
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
const tag = value.dataType;
|
|
81
|
+
if (tag === DATETIME_TAG) {
|
|
82
|
+
return luxon_1.DateTime.fromISO(value.value);
|
|
83
|
+
}
|
|
84
|
+
if (tag === MAP_TAG) {
|
|
85
|
+
const entries = (value.value ?? []);
|
|
86
|
+
return new Map(entries.map(([k, v]) => [reviveSessionValue(k), reviveSessionValue(v)]));
|
|
87
|
+
}
|
|
88
|
+
if (tag === SET_TAG) {
|
|
89
|
+
const members = (value.value ?? []);
|
|
90
|
+
return new Set(members.map(reviveSessionValue));
|
|
91
|
+
}
|
|
92
|
+
const out = {};
|
|
93
|
+
for (const [k, v] of Object.entries(value)) {
|
|
94
|
+
Object.defineProperty(out, k, {
|
|
95
|
+
value: reviveSessionValue(v),
|
|
96
|
+
enumerable: true,
|
|
97
|
+
writable: true,
|
|
98
|
+
configurable: true,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
40
103
|
/**
|
|
41
104
|
* Serializes a session `Data` map to a JSON string, preserving `Map` / `Set` /
|
|
42
105
|
* `DateTime` values.
|
|
@@ -47,13 +110,46 @@ function encodeSessionData(data) {
|
|
|
47
110
|
return JSON.stringify({ dataType: 'Map', value: Array.from(data.entries()) }, sessionReplacer);
|
|
48
111
|
}
|
|
49
112
|
/**
|
|
50
|
-
* Restores a session `Data` map from a
|
|
51
|
-
* {@link encodeSessionData}.
|
|
113
|
+
* Restores a session `Data` map from whatever a store hands back for the payload
|
|
114
|
+
* written by {@link encodeSessionData}.
|
|
115
|
+
*
|
|
116
|
+
* TWO representations reach this function, and both are legitimate:
|
|
52
117
|
*
|
|
53
|
-
*
|
|
118
|
+
* - a **string** - what {@link encodeSessionData} produces, and what every
|
|
119
|
+
* text-ish column and every non-SQL store (redis, dynamodb) returns. Parsed
|
|
120
|
+
* with {@link sessionReviver}, the JSON.parse path.
|
|
121
|
+
* - an **object** - a MySQL `json` column, which mysql2 parses for us before
|
|
122
|
+
* the ORM ever sees it. Walked with {@link reviveSessionValue}: the value is
|
|
123
|
+
* already an object graph, so round-tripping it back through
|
|
124
|
+
* `JSON.stringify` + `JSON.parse` purely to reach the reviver would be
|
|
125
|
+
* pointless work on every single session read.
|
|
126
|
+
*
|
|
127
|
+
* Both branches are kept deliberately. `user_sessions.Data` is a `json` column
|
|
128
|
+
* on fresh installs and on every install that has run the converging migration,
|
|
129
|
+
* but a driver, a column type or a store that still yields a string must keep
|
|
130
|
+
* decoding - and the sqlite driver used by the tests is exactly that case.
|
|
131
|
+
*
|
|
132
|
+
* ANYTHING ELSE THROWS. The object branch is narrowed to a real object
|
|
133
|
+
* (`!== null && typeof === 'object'`) rather than being the `else` of the string
|
|
134
|
+
* test, because widening the parameter to `unknown` otherwise turns `null`,
|
|
135
|
+
* `undefined` and a stray number into a silently EMPTY session: every request
|
|
136
|
+
* carrying that session reads as authenticated-but-anonymous, and a store that
|
|
137
|
+
* started handing back the wrong shape would log out its entire user base
|
|
138
|
+
* without a single error line. A missing or malformed payload is a defect in the
|
|
139
|
+
* store, not a session with no data, and it is raised as one.
|
|
140
|
+
*
|
|
141
|
+
* @param data - the serialized session data, as string or as parsed object
|
|
142
|
+
* @throws `InvalidArgument` when `data` is neither a string nor a non-null object
|
|
54
143
|
*/
|
|
55
|
-
function decodeSessionData(
|
|
56
|
-
|
|
57
|
-
|
|
144
|
+
function decodeSessionData(data) {
|
|
145
|
+
if (typeof data === 'string') {
|
|
146
|
+
const parsed = JSON.parse(data, sessionReviver);
|
|
147
|
+
return parsed instanceof Map ? parsed : new Map();
|
|
148
|
+
}
|
|
149
|
+
if (data !== null && typeof data === 'object') {
|
|
150
|
+
const revived = reviveSessionValue(data);
|
|
151
|
+
return revived instanceof Map ? revived : new Map();
|
|
152
|
+
}
|
|
153
|
+
throw new exceptions_1.InvalidArgument(`Cannot decode session data: expected a JSON string or an already-parsed object, got ${data === null ? 'null' : typeof data}`, 'data');
|
|
58
154
|
}
|
|
59
155
|
//# sourceMappingURL=session-codec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-codec.js","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"session-codec.js","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ let RBACInitial_2022_06_28_01_13_00 = class RBACInitial_2022_06_28_01_13_00 exte
|
|
|
10
10
|
async up(connection) {
|
|
11
11
|
await connection.schema().createTable('users', (table) => {
|
|
12
12
|
table.int('Id').primaryKey().autoIncrement();
|
|
13
|
-
table.
|
|
13
|
+
table.string('Uuid', 36).notNull();
|
|
14
14
|
table.string('Email', 64).unique().notNull();
|
|
15
15
|
table.string('Password', 128).notNull();
|
|
16
16
|
table.string('Login', 64).notNull();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RBACInitial_2022_06_28_01_13_00.js","sourceRoot":"","sources":["../../../src/migrations/RBACInitial_2022_06_28_01_13_00.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAsD;AACtD,OAAO,EAAE,YAAY,EAAa,SAAS,EAAE,MAAM,cAAc,CAAC;AAI3D,IAAM,+BAA+B,GAArC,MAAM,+BAAgC,SAAQ,YAAY;IACxD,KAAK,CAAC,EAAE,CAAC,UAAqB;QACnC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACvD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,CAAC;YAC7C,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"RBACInitial_2022_06_28_01_13_00.js","sourceRoot":"","sources":["../../../src/migrations/RBACInitial_2022_06_28_01_13_00.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,10 +6,36 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function encodeSessionData(data: Map<string, unknown>): string;
|
|
8
8
|
/**
|
|
9
|
-
* Restores a session `Data` map from a
|
|
10
|
-
* {@link encodeSessionData}.
|
|
9
|
+
* Restores a session `Data` map from whatever a store hands back for the payload
|
|
10
|
+
* written by {@link encodeSessionData}.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* TWO representations reach this function, and both are legitimate:
|
|
13
|
+
*
|
|
14
|
+
* - a **string** - what {@link encodeSessionData} produces, and what every
|
|
15
|
+
* text-ish column and every non-SQL store (redis, dynamodb) returns. Parsed
|
|
16
|
+
* with {@link sessionReviver}, the JSON.parse path.
|
|
17
|
+
* - an **object** - a MySQL `json` column, which mysql2 parses for us before
|
|
18
|
+
* the ORM ever sees it. Walked with {@link reviveSessionValue}: the value is
|
|
19
|
+
* already an object graph, so round-tripping it back through
|
|
20
|
+
* `JSON.stringify` + `JSON.parse` purely to reach the reviver would be
|
|
21
|
+
* pointless work on every single session read.
|
|
22
|
+
*
|
|
23
|
+
* Both branches are kept deliberately. `user_sessions.Data` is a `json` column
|
|
24
|
+
* on fresh installs and on every install that has run the converging migration,
|
|
25
|
+
* but a driver, a column type or a store that still yields a string must keep
|
|
26
|
+
* decoding - and the sqlite driver used by the tests is exactly that case.
|
|
27
|
+
*
|
|
28
|
+
* ANYTHING ELSE THROWS. The object branch is narrowed to a real object
|
|
29
|
+
* (`!== null && typeof === 'object'`) rather than being the `else` of the string
|
|
30
|
+
* test, because widening the parameter to `unknown` otherwise turns `null`,
|
|
31
|
+
* `undefined` and a stray number into a silently EMPTY session: every request
|
|
32
|
+
* carrying that session reads as authenticated-but-anonymous, and a store that
|
|
33
|
+
* started handing back the wrong shape would log out its entire user base
|
|
34
|
+
* without a single error line. A missing or malformed payload is a defect in the
|
|
35
|
+
* store, not a session with no data, and it is raised as one.
|
|
36
|
+
*
|
|
37
|
+
* @param data - the serialized session data, as string or as parsed object
|
|
38
|
+
* @throws `InvalidArgument` when `data` is neither a string nor a non-null object
|
|
13
39
|
*/
|
|
14
|
-
export declare function decodeSessionData(
|
|
40
|
+
export declare function decodeSessionData(data: string | unknown): Map<string, unknown>;
|
|
15
41
|
//# sourceMappingURL=session-codec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-codec.d.ts","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-codec.d.ts","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":"AAkHA;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAc9E"}
|
package/lib/mjs/session-codec.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DateTime } from 'luxon';
|
|
2
|
+
import { InvalidArgument } from '@spinajs/exceptions';
|
|
2
3
|
import { replacer as baseReplacer, reviver as baseReviver } from '@spinajs/util';
|
|
3
4
|
/**
|
|
4
5
|
* Shared session-data serialization codec (fixes B5 — symmetric write/read).
|
|
@@ -33,6 +34,68 @@ function sessionReviver(key, value) {
|
|
|
33
34
|
}
|
|
34
35
|
return baseReviver(key, value);
|
|
35
36
|
}
|
|
37
|
+
const MAP_TAG = 'Map';
|
|
38
|
+
const SET_TAG = 'Set';
|
|
39
|
+
/**
|
|
40
|
+
* Object-graph twin of {@link sessionReviver}: turns the same tags back into the
|
|
41
|
+
* same instances, but reads a value that is ALREADY a parsed object graph
|
|
42
|
+
* instead of JSON text.
|
|
43
|
+
*
|
|
44
|
+
* It exists because a MySQL `json` column comes back from mysql2 already parsed.
|
|
45
|
+
* Re-serializing that object only to hand it straight back to `JSON.parse` would
|
|
46
|
+
* be a pure waste - and passing it to the decoder untransformed is worse than
|
|
47
|
+
* wasteful: the payload's top level is the tagged wrapper
|
|
48
|
+
* `{ dataType: 'Map', value: [...] }`, so without this walk `parsed instanceof Map`
|
|
49
|
+
* is false and the session decodes as silently EMPTY.
|
|
50
|
+
*
|
|
51
|
+
* Kept byte-for-byte semantically equal to the reviver:
|
|
52
|
+
*
|
|
53
|
+
* - `JSON.parse` calls its reviver bottom-up (children before parents), so the
|
|
54
|
+
* walk recurses into children BEFORE inspecting the node's own tag,
|
|
55
|
+
* - the DateTime tag is checked before the shared Map/Set tags, matching
|
|
56
|
+
* {@link sessionReviver}'s order,
|
|
57
|
+
* - properties are installed with `defineProperty` so a payload carrying a
|
|
58
|
+
* literal `__proto__` key becomes an own data property (what `JSON.parse`
|
|
59
|
+
* does) rather than mutating the result's prototype.
|
|
60
|
+
*
|
|
61
|
+
* Values that are already live instances (`Map` / `Set` / `DateTime`) are passed
|
|
62
|
+
* through untouched: a caller may legitimately hand over data that never went
|
|
63
|
+
* through a database at all.
|
|
64
|
+
*/
|
|
65
|
+
function reviveSessionValue(value) {
|
|
66
|
+
if (value === null || typeof value !== 'object') {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(value)) {
|
|
70
|
+
return value.map(reviveSessionValue);
|
|
71
|
+
}
|
|
72
|
+
// already-materialized structural types - nothing to rebuild
|
|
73
|
+
if (value instanceof Map || value instanceof Set || DateTime.isDateTime(value)) {
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
const tag = value.dataType;
|
|
77
|
+
if (tag === DATETIME_TAG) {
|
|
78
|
+
return DateTime.fromISO(value.value);
|
|
79
|
+
}
|
|
80
|
+
if (tag === MAP_TAG) {
|
|
81
|
+
const entries = (value.value ?? []);
|
|
82
|
+
return new Map(entries.map(([k, v]) => [reviveSessionValue(k), reviveSessionValue(v)]));
|
|
83
|
+
}
|
|
84
|
+
if (tag === SET_TAG) {
|
|
85
|
+
const members = (value.value ?? []);
|
|
86
|
+
return new Set(members.map(reviveSessionValue));
|
|
87
|
+
}
|
|
88
|
+
const out = {};
|
|
89
|
+
for (const [k, v] of Object.entries(value)) {
|
|
90
|
+
Object.defineProperty(out, k, {
|
|
91
|
+
value: reviveSessionValue(v),
|
|
92
|
+
enumerable: true,
|
|
93
|
+
writable: true,
|
|
94
|
+
configurable: true,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
36
99
|
/**
|
|
37
100
|
* Serializes a session `Data` map to a JSON string, preserving `Map` / `Set` /
|
|
38
101
|
* `DateTime` values.
|
|
@@ -43,13 +106,46 @@ export function encodeSessionData(data) {
|
|
|
43
106
|
return JSON.stringify({ dataType: 'Map', value: Array.from(data.entries()) }, sessionReplacer);
|
|
44
107
|
}
|
|
45
108
|
/**
|
|
46
|
-
* Restores a session `Data` map from a
|
|
47
|
-
* {@link encodeSessionData}.
|
|
109
|
+
* Restores a session `Data` map from whatever a store hands back for the payload
|
|
110
|
+
* written by {@link encodeSessionData}.
|
|
111
|
+
*
|
|
112
|
+
* TWO representations reach this function, and both are legitimate:
|
|
48
113
|
*
|
|
49
|
-
*
|
|
114
|
+
* - a **string** - what {@link encodeSessionData} produces, and what every
|
|
115
|
+
* text-ish column and every non-SQL store (redis, dynamodb) returns. Parsed
|
|
116
|
+
* with {@link sessionReviver}, the JSON.parse path.
|
|
117
|
+
* - an **object** - a MySQL `json` column, which mysql2 parses for us before
|
|
118
|
+
* the ORM ever sees it. Walked with {@link reviveSessionValue}: the value is
|
|
119
|
+
* already an object graph, so round-tripping it back through
|
|
120
|
+
* `JSON.stringify` + `JSON.parse` purely to reach the reviver would be
|
|
121
|
+
* pointless work on every single session read.
|
|
122
|
+
*
|
|
123
|
+
* Both branches are kept deliberately. `user_sessions.Data` is a `json` column
|
|
124
|
+
* on fresh installs and on every install that has run the converging migration,
|
|
125
|
+
* but a driver, a column type or a store that still yields a string must keep
|
|
126
|
+
* decoding - and the sqlite driver used by the tests is exactly that case.
|
|
127
|
+
*
|
|
128
|
+
* ANYTHING ELSE THROWS. The object branch is narrowed to a real object
|
|
129
|
+
* (`!== null && typeof === 'object'`) rather than being the `else` of the string
|
|
130
|
+
* test, because widening the parameter to `unknown` otherwise turns `null`,
|
|
131
|
+
* `undefined` and a stray number into a silently EMPTY session: every request
|
|
132
|
+
* carrying that session reads as authenticated-but-anonymous, and a store that
|
|
133
|
+
* started handing back the wrong shape would log out its entire user base
|
|
134
|
+
* without a single error line. A missing or malformed payload is a defect in the
|
|
135
|
+
* store, not a session with no data, and it is raised as one.
|
|
136
|
+
*
|
|
137
|
+
* @param data - the serialized session data, as string or as parsed object
|
|
138
|
+
* @throws `InvalidArgument` when `data` is neither a string nor a non-null object
|
|
50
139
|
*/
|
|
51
|
-
export function decodeSessionData(
|
|
52
|
-
|
|
53
|
-
|
|
140
|
+
export function decodeSessionData(data) {
|
|
141
|
+
if (typeof data === 'string') {
|
|
142
|
+
const parsed = JSON.parse(data, sessionReviver);
|
|
143
|
+
return parsed instanceof Map ? parsed : new Map();
|
|
144
|
+
}
|
|
145
|
+
if (data !== null && typeof data === 'object') {
|
|
146
|
+
const revived = reviveSessionValue(data);
|
|
147
|
+
return revived instanceof Map ? revived : new Map();
|
|
148
|
+
}
|
|
149
|
+
throw new InvalidArgument(`Cannot decode session data: expected a JSON string or an already-parsed object, got ${data === null ? 'null' : typeof data}`, 'data');
|
|
54
150
|
}
|
|
55
151
|
//# sourceMappingURL=session-codec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-codec.js","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,OAAO,IAAI,WAAW,EAAmB,MAAM,eAAe,CAAC;AAElG;;;;;;;;;;GAUG;AAEH,MAAM,YAAY,GAAG,UAAU,CAAC;AAEhC;;;;GAIG;AACH,SAAS,eAAe,CAAgC,GAAW,EAAE,KAAc;IACjF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,GAAW,EAAE,KAAgC;IACnE,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,KAAyB,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC/F,OAAO,QAAQ,CAAC,OAAO,CAAE,KAAyB,CAAC,KAAe,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,WAAW,CAAC,GAAG,EAAE,KAAwB,CAAC,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA0B;IAC1D,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC;AACjG,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"session-codec.js","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,OAAO,IAAI,WAAW,EAAmB,MAAM,eAAe,CAAC;AAElG;;;;;;;;;;GAUG;AAEH,MAAM,YAAY,GAAG,UAAU,CAAC;AAEhC;;;;GAIG;AACH,SAAS,eAAe,CAAgC,GAAW,EAAE,KAAc;IACjF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,GAAW,EAAE,KAAgC;IACnE,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,KAAyB,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC/F,OAAO,QAAQ,CAAC,OAAO,CAAE,KAAyB,CAAC,KAAe,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,WAAW,CAAC,GAAG,EAAE,KAAwB,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,OAAO,GAAG,KAAK,CAAC;AACtB,MAAM,OAAO,GAAG,KAAK,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAS,kBAAkB,CAAC,KAAc;IACxC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACvC,CAAC;IAED,6DAA6D;IAC7D,IAAI,KAAK,YAAY,GAAG,IAAI,KAAK,YAAY,GAAG,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,GAAG,GAAI,KAAyB,CAAC,QAAQ,CAAC;IAEhD,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;QACzB,OAAO,QAAQ,CAAC,OAAO,CAAE,KAAyB,CAAC,KAAe,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,CAAE,KAAyB,CAAC,KAAK,IAAI,EAAE,CAAyB,CAAC;QACjF,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAuB,CAAC,CAAC,CAAC;IAChH,CAAC;IAED,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,CAAE,KAAyB,CAAC,KAAK,IAAI,EAAE,CAAc,CAAC;QACtE,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,GAAG,GAA4B,EAAE,CAAC;IAExC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QACtE,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,EAAE;YAC5B,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC;YAC5B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA0B;IAC1D,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC;AACjG,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAsB;IACtD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAEhD,OAAO,MAAM,YAAY,GAAG,CAAC,CAAC,CAAE,MAA+B,CAAC,CAAC,CAAC,IAAI,GAAG,EAAmB,CAAC;IAC/F,CAAC;IAED,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAEzC,OAAO,OAAO,YAAY,GAAG,CAAC,CAAC,CAAE,OAAgC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAmB,CAAC;IACjG,CAAC;IAED,MAAM,IAAI,eAAe,CAAC,uFAAuF,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;AACnK,CAAC"}
|