Merge pull request 'web: Modul-Tokens mit explizitem Zielmodul (NEXT_PUBLIC_TOKEN_MODULE)' (#413) from feat/frontends-token-module into main
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Successful in 40s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Successful in 4s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Successful in 4s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Failing after 14s
CI / Web (dms-browser) (push) Failing after 52s
CI / Web (pdf-viewer) (push) Failing after 36s
CI / Web (shl) (push) Failing after 7s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Failing after 3s

This commit was merged in pull request #413.
This commit is contained in:
patrick committed 2026-10-28 16:05:23 +01:00
commit 701fb4e2c4
8 files changed
+15 -9

No files matched your search

+1
View File
@@ -10,6 +10,7 @@ export function getSession(): Session {
}
session = createSession({
coreBase,
module: process.env.NEXT_PUBLIC_TOKEN_MODULE || "dms",
onLoginRequired: () => redirectToLogin(process.env.NEXT_PUBLIC_LOGIN_URL),
});
}
+5 -5
View File
@@ -25,7 +25,7 @@ const json = (body: unknown, status = 200) => new Response(JSON.stringify(body),
beforeEach(() => {
calls = [];
handler = (url) => {
if (url.endsWith("/auth/module-token")) return json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme", role: "user" });
if (url.includes("/auth/module-token")) return json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme", role: "user" });
return json([]);
};
vi.stubGlobal(
@@ -54,7 +54,7 @@ function dmsCalls(): Call[] {
describe("UX-10 AK1: alle DMS-Aufrufe im Token-Modus (Standard)", () => {
it("senden Authorization: Bearer und nie caller/X-User-Id/actor", async () => {
handler = (url) => (url.endsWith("/auth/module-token") ? json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme", role: "user" }) : json({ hits: [], total: 0, limit: 20, offset: 0, took_ms: 1, facets: {} }));
handler = (url) => (url.includes("/auth/module-token") ? json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme", role: "user" }) : json({ hits: [], total: 0, limit: 20, offset: 0, took_ms: 1, facets: {} }));
const attempts: Array<() => Promise<unknown>> = [
() => fetchChildren(null),
() => fetchDocuments("f-1"),
@@ -114,14 +114,14 @@ describe("UX-10 AK2: Fehlerbehandlung", () => {
vi.stubEnv("NEXT_PUBLIC_LOGIN_URL", "/anmelden");
const assign = vi.fn();
vi.stubGlobal("location", { pathname: "/", search: "", assign });
handler = (url) => (url.endsWith("/auth/module-token") ? json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme" }) : new Response("", { status: 401 }));
handler = (url) => (url.includes("/auth/module-token") ? json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme" }) : new Response("", { status: 401 }));
await expect(fetchAllTags()).rejects.toMatchObject({ kind: "unauthenticated" });
expect(assign).toHaveBeenCalledWith("/anmelden?return=%2F");
expect(dmsCalls().every((c) => !/caller=/.test(c.url))).toBe(true);
});
it("Token fremden Mandanten wird vom DMS mit 401 abgewiesen und liefert keine Daten", async () => {
handler = (url) => (url.endsWith("/auth/module-token") ? json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "globex" }) : new Response(JSON.stringify({ error: { code: "unauthenticated" } }), { status: 401 }));
handler = (url) => (url.includes("/auth/module-token") ? json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "globex" }) : new Response(JSON.stringify({ error: { code: "unauthenticated" } }), { status: 401 }));
await expect(fetchFields()).rejects.toMatchObject({ kind: "unauthenticated" });
});
@@ -129,7 +129,7 @@ describe("UX-10 AK2: Fehlerbehandlung", () => {
[403, /Berechtigung/],
[503, /nicht verfügbar/],
])("%i wird als verstaendliche Meldung ausgegeben", async (status, text) => {
handler = (url) => (url.endsWith("/auth/module-token") ? json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme" }) : new Response("", { status }));
handler = (url) => (url.includes("/auth/module-token") ? json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme" }) : new Response("", { status }));
await expect(fetchAllTags()).rejects.toThrow(text);
});
+1
View File
@@ -16,6 +16,7 @@ export function getSession(): Session {
}
session = createSession({
coreBase,
module: process.env.NEXT_PUBLIC_TOKEN_MODULE || "dms",
onLoginRequired: () => redirectToLogin(process.env.NEXT_PUBLIC_LOGIN_URL),
});
}
+4 -4
View File
@@ -17,7 +17,7 @@ beforeEach(() => {
vi.fn(async (input: RequestInfo | URL, init: RequestInit = {}) => {
const url = String(input);
calls.push({ url, init });
if (url.endsWith("/auth/module-token")) return json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme" });
if (url.includes("/auth/module-token")) return json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme" });
return json({ sessionId: "s-1", offset: 0, bytesReceived: 0, status: "uploading", documentId: "d-1", revisionId: "r-1" });
})
);
@@ -46,7 +46,7 @@ describe("UX-10: Upload im Token-Modus", () => {
expect(c.url).not.toMatch(/caller=/);
expect(c.url).not.toContain(TOKEN);
}
expect(calls.filter((c) => c.url.endsWith("/auth/module-token"))).toHaveLength(1);
expect(calls.filter((c) => c.url.includes("/auth/module-token"))).toHaveLength(1);
});
it("401 beim Chunk: Token wird erneuert und der Chunk einmal wiederholt", async () => {
@@ -54,7 +54,7 @@ describe("UX-10: Upload im Token-Modus", () => {
(globalThis.fetch as unknown as ReturnType<typeof vi.fn>).mockImplementation(async (input: RequestInfo | URL, init: RequestInit = {}) => {
const url = String(input);
calls.push({ url, init });
if (url.endsWith("/auth/module-token")) return json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme" });
if (url.includes("/auth/module-token")) return json({ token: TOKEN, token_type: "Bearer", expires_in: 600, tenant: "acme" });
if (first) {
first = false;
return new Response("", { status: 401 });
@@ -62,6 +62,6 @@ describe("UX-10: Upload im Token-Modus", () => {
return json({ bytesReceived: 3 });
});
await uploadChunk("s-1", 0, new Blob(["abc"]));
expect(calls.filter((c) => c.url.endsWith("/auth/module-token"))).toHaveLength(2);
expect(calls.filter((c) => c.url.includes("/auth/module-token"))).toHaveLength(2);
});
});
+1
View File
@@ -16,6 +16,7 @@ export function getSession(): Session {
}
session = createSession({
coreBase,
module: process.env.NEXT_PUBLIC_TOKEN_MODULE || "dms",
onLoginRequired: () => redirectToLogin(process.env.NEXT_PUBLIC_LOGIN_URL),
});
}
+1
View File
@@ -14,6 +14,7 @@ export function getSession(): Session {
}
session = createSession({
coreBase,
module: process.env.NEXT_PUBLIC_TOKEN_MODULE || "dms",
onLoginRequired: () => redirectToLogin(process.env.NEXT_PUBLIC_LOGIN_URL),
});
}
+1
View File
@@ -17,6 +17,7 @@ export function getSession(): Session {
}
session = createSession({
coreBase,
module: process.env.NEXT_PUBLIC_TOKEN_MODULE || "dms",
onLoginRequired: () => redirectToLogin(process.env.NEXT_PUBLIC_LOGIN_URL),
});
}
+1
View File
@@ -16,6 +16,7 @@ export function getSession(): Session {
}
session = createSession({
coreBase,
module: process.env.NEXT_PUBLIC_TOKEN_MODULE || "dms",
onLoginRequired: () => redirectToLogin(process.env.NEXT_PUBLIC_LOGIN_URL),
});
}