@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.
@@ -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.uuid('Uuid').notNull();
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":"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"}
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,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACnC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC;YAC7C,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACxC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACpC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACpC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvD,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;YAC3D,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC5B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;YAChE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,CAAC;YAC7C,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAC3F,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpB,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;YAC/B,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACzF,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;QACtH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,qCAAqC;IACrC,gEAAgE;IACzD,KAAK,CAAC,IAAI,CAAC,WAAsB,IAAkB,CAAC;CAC5D,CAAA;AAhCY,0EAA+B;0CAA/B,+BAA+B;IAD3C,IAAA,eAAS,EAAC,SAAS,CAAC;GACR,+BAA+B,CAgC3C"}
@@ -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 JSON string produced by
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
- * @param json - the serialized session data
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(json: string): Map<string, unknown>;
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":"AAwCA;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAGpE"}
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"}
@@ -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 JSON string produced by
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
- * @param json - the serialized session data
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(json) {
56
- const parsed = JSON.parse(json, sessionReviver);
57
- return parsed instanceof Map ? parsed : new Map();
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":";;AA8CA,8CAEC;AAQD,8CAGC;AA3DD,iCAAiC;AACjC,wCAAkG;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,gBAAQ,EAAE,CAAC;QAC5B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,IAAA,eAAY,EAAC,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,gBAAQ,CAAC,OAAO,CAAE,KAAyB,CAAC,KAAe,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,IAAA,cAAW,EAAC,GAAG,EAAE,KAAwB,CAAC,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,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;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,IAAY;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAChD,OAAO,MAAM,YAAY,GAAG,CAAC,CAAC,CAAE,MAA+B,CAAC,CAAC,CAAC,IAAI,GAAG,EAAmB,CAAC;AAC/F,CAAC"}
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.uuid('Uuid').notNull();
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":"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"}
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 JSON string produced by
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
- * @param json - the serialized session data
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(json: string): Map<string, unknown>;
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":"AAwCA;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAGpE"}
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"}
@@ -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 JSON string produced by
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
- * @param json - the serialized session data
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(json) {
52
- const parsed = JSON.parse(json, sessionReviver);
53
- return parsed instanceof Map ? parsed : new Map();
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;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAChD,OAAO,MAAM,YAAY,GAAG,CAAC,CAAC,CAAE,MAA+B,CAAC,CAAC,CAAC,IAAI,GAAG,EAAmB,CAAC;AAC/F,CAAC"}
1
+ {"version":3,"file":"session-codec.js","sourceRoot":"","sources":["../../src/session-codec.ts"],"names":[],"mappings":"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"}