@cosmicdrift/kumiko-bundled-features 0.171.2 → 0.173.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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-bundled-features",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.173.0",
|
|
4
4
|
"description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -119,12 +119,12 @@
|
|
|
119
119
|
"./step-dispatcher": "./src/step-dispatcher/index.ts"
|
|
120
120
|
},
|
|
121
121
|
"dependencies": {
|
|
122
|
-
"@cosmicdrift/kumiko-dispatcher-live": "0.
|
|
123
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
124
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
125
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
126
|
-
"@cosmicdrift/kumiko-renderer-web": "0.
|
|
127
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
122
|
+
"@cosmicdrift/kumiko-dispatcher-live": "0.173.0",
|
|
123
|
+
"@cosmicdrift/kumiko-framework": "0.173.0",
|
|
124
|
+
"@cosmicdrift/kumiko-headless": "0.173.0",
|
|
125
|
+
"@cosmicdrift/kumiko-renderer": "0.173.0",
|
|
126
|
+
"@cosmicdrift/kumiko-renderer-web": "0.173.0",
|
|
127
|
+
"@cosmicdrift/kumiko-types": "0.173.0",
|
|
128
128
|
"@mollie/api-client": "^4.5.0",
|
|
129
129
|
"imapflow": "^1.3.3",
|
|
130
130
|
"mailparser": "^3.9.8",
|
|
@@ -245,7 +245,6 @@ describe("audit: list query", () => {
|
|
|
245
245
|
);
|
|
246
246
|
expect(untilBefore.rows).toHaveLength(1);
|
|
247
247
|
const untilRow = untilBefore.rows[0];
|
|
248
|
-
expect(untilRow).toBeDefined();
|
|
249
248
|
if (!untilRow) throw new Error("expected untilBefore row");
|
|
250
249
|
expect((untilRow.payload as { name?: string }).name).toBe("before-window");
|
|
251
250
|
});
|
|
@@ -55,8 +55,7 @@ describe("login.write gates (fw#1284)", () => {
|
|
|
55
55
|
["User"],
|
|
56
56
|
"Asia/Tokyo",
|
|
57
57
|
);
|
|
58
|
-
expect(g.
|
|
59
|
-
if (g.ok) expect(g.value.session.timezone).toBe("Asia/Tokyo");
|
|
58
|
+
expect(g.session.timezone).toBe("Asia/Tokyo");
|
|
60
59
|
});
|
|
61
60
|
|
|
62
61
|
test("gateBuildSession omits timezone when the user never set one (fw#1636)", async () => {
|
|
@@ -67,7 +66,6 @@ describe("login.write gates (fw#1284)", () => {
|
|
|
67
66
|
["User"],
|
|
68
67
|
null,
|
|
69
68
|
);
|
|
70
|
-
expect(g.
|
|
71
|
-
if (g.ok) expect(g.value.session.timezone).toBeUndefined();
|
|
69
|
+
expect(g.session.timezone).toBeUndefined();
|
|
72
70
|
});
|
|
73
71
|
});
|
|
@@ -206,16 +206,16 @@ export async function gateEnforceMfa(
|
|
|
206
206
|
userId: string,
|
|
207
207
|
tenantId: TenantId,
|
|
208
208
|
mergedRoles: readonly string[],
|
|
209
|
-
): Promise<
|
|
210
|
-
if (!opts.mfaStatusChecker) return
|
|
209
|
+
): Promise<LoginResult | undefined> {
|
|
210
|
+
if (!opts.mfaStatusChecker) return undefined;
|
|
211
211
|
const mfaStatus = await opts.mfaStatusChecker(ctx, userId, tenantId, mergedRoles);
|
|
212
212
|
if ("challengeToken" in mfaStatus) {
|
|
213
|
-
return
|
|
213
|
+
return { kind: "mfa-challenge", challengeToken: mfaStatus.challengeToken };
|
|
214
214
|
}
|
|
215
215
|
if ("setupRequired" in mfaStatus) {
|
|
216
|
-
return
|
|
216
|
+
return { kind: "mfa-setup-required", preauthSetupToken: mfaStatus.preauthSetupToken };
|
|
217
217
|
}
|
|
218
|
-
return
|
|
218
|
+
return undefined;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
/** Auth-claims hooks → session. */
|
|
@@ -225,7 +225,7 @@ export async function gateBuildSession(
|
|
|
225
225
|
tenantId: TenantId,
|
|
226
226
|
mergedRoles: readonly string[],
|
|
227
227
|
timezone?: string | null,
|
|
228
|
-
): Promise<
|
|
228
|
+
): Promise<{ readonly kind: "auth-session"; readonly session: SessionUser }> {
|
|
229
229
|
const baseSession: SessionUser = {
|
|
230
230
|
id: userId,
|
|
231
231
|
tenantId,
|
|
@@ -235,7 +235,7 @@ export async function gateBuildSession(
|
|
|
235
235
|
const claims = await ctx.resolveAuthClaims(baseSession);
|
|
236
236
|
const session: SessionUser =
|
|
237
237
|
Object.keys(claims).length > 0 ? { ...baseSession, claims } : baseSession;
|
|
238
|
-
return
|
|
238
|
+
return { kind: "auth-session", session };
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
// Login — unauthenticated entry point. The route is wired public (no JWT
|
|
@@ -291,20 +291,18 @@ export function createLoginHandler(opts: LoginHandlerOptions = {}) {
|
|
|
291
291
|
const { chosen, mergedRoles } = membershipGate.value;
|
|
292
292
|
|
|
293
293
|
const mfaGate = await gateEnforceMfa(ctx, opts, found.id, chosen.tenantId, mergedRoles);
|
|
294
|
-
if (
|
|
295
|
-
|
|
296
|
-
return { isSuccess: true, data: mfaGate.value };
|
|
294
|
+
if (mfaGate !== undefined) {
|
|
295
|
+
return { isSuccess: true, data: mfaGate };
|
|
297
296
|
}
|
|
298
297
|
|
|
299
|
-
const
|
|
298
|
+
const session = await gateBuildSession(
|
|
300
299
|
ctx,
|
|
301
300
|
found.id,
|
|
302
301
|
chosen.tenantId,
|
|
303
302
|
mergedRoles,
|
|
304
303
|
found.timezone,
|
|
305
304
|
);
|
|
306
|
-
|
|
307
|
-
return { isSuccess: true, data: sessionGate.value };
|
|
305
|
+
return { isSuccess: true, data: session };
|
|
308
306
|
},
|
|
309
307
|
});
|
|
310
308
|
}
|
|
@@ -129,8 +129,6 @@ describe("my-audit-log", () => {
|
|
|
129
129
|
// ihre Payload, bob nur seine.
|
|
130
130
|
const aliceRow = aliceLog.rows[0];
|
|
131
131
|
const bobRow = bobLog.rows[0];
|
|
132
|
-
expect(aliceRow).toBeDefined();
|
|
133
|
-
expect(bobRow).toBeDefined();
|
|
134
132
|
if (!aliceRow || !bobRow) throw new Error("expected audit rows");
|
|
135
133
|
expect((aliceRow.payload as { foo: string }).foo).toBe("alice");
|
|
136
134
|
expect((bobRow.payload as { foo: string }).foo).toBe("bob");
|