From 28e93fe9435451471acefc6e61f054dee5f2c05c Mon Sep 17 00:00:00 2001 From: Jared Date: Wed, 18 Jun 2025 16:33:35 +0200 Subject: [PATCH 1/6] vorgang accessible via url --- src/lib/minio.ts | 1 + src/lib/server/vorgangService.ts | 11 +++++------ .../list/[vorgang]/+page.server.ts | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 src/routes/(token-based)/list/[vorgang]/+page.server.ts diff --git a/src/lib/minio.ts b/src/lib/minio.ts index 6824b78..f2ac969 100644 --- a/src/lib/minio.ts +++ b/src/lib/minio.ts @@ -8,3 +8,4 @@ import config from '$lib/config'; export const client = new Client(config.minio); export const BUCKET = 'tatort'; +export const TOKENFILENAME = '__perm__'; diff --git a/src/lib/server/vorgangService.ts b/src/lib/server/vorgangService.ts index c24a37c..c4439bd 100644 --- a/src/lib/server/vorgangService.ts +++ b/src/lib/server/vorgangService.ts @@ -1,5 +1,5 @@ import { fail, redirect } from '@sveltejs/kit'; -import { BUCKET, client } from '$lib/minio'; +import { BUCKET, client, TOKENFILENAME } from '$lib/minio'; import { checkIfExactDirectoryExists } from './s3ClientService'; /** @@ -38,7 +38,7 @@ export const redirectIfVorgangExists = async (request: Request) => { }); } - redirect(303, `/list/${caseId}`); + redirect(303, `/list/${caseId}?token=${caseToken}`); }; export const getVorgangByCaseId = ({ params }) => { @@ -76,14 +76,13 @@ export const getVorgangByCaseId = ({ params }) => { }); }; -const hasValidToken = async (caseId: string, caseToken: string) => { - const tokenFileName = '__perm__'; - const objPath = `${caseId}/${tokenFileName}`; +export const hasValidToken = async (caseId: string, caseToken: string) => { + const objPath = `${caseId}/${TOKENFILENAME}`; try { if (!caseToken) return false; - const res = await client.getObject('tatort', objPath); + const res = await client.getObject(BUCKET, objPath); const savedToken = await new Response(res).text(); diff --git a/src/routes/(token-based)/list/[vorgang]/+page.server.ts b/src/routes/(token-based)/list/[vorgang]/+page.server.ts new file mode 100644 index 0000000..f4fe251 --- /dev/null +++ b/src/routes/(token-based)/list/[vorgang]/+page.server.ts @@ -0,0 +1,18 @@ +import { hasValidToken } from '$lib/server/vorgangService'; +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from '../../view/$types'; + +export const load: PageServerLoad = ({params, url}) => { + const caseID = params.vorgang; + const token = url.searchParams.get('token'); + + let isTokenValid + + if (typeof token === 'string' && caseID) { + isTokenValid = hasValidToken(caseID, token); + } + + if(!isTokenValid) { + redirect(303, '/anmeldung'); + } +}; -- 2.43.0 From a2ac88af50a290510f5810c4758ab97c36d9fc2c Mon Sep 17 00:00:00 2001 From: Jared Date: Thu, 19 Jun 2025 10:31:31 +0200 Subject: [PATCH 2/6] revised backend service getObjects --- src/lib/server/vorgangService.ts | 137 ++++++++++++++++----------- src/routes/anmeldung/+page.server.ts | 14 ++- src/routes/anmeldung/+page.svelte | 2 +- 3 files changed, 95 insertions(+), 58 deletions(-) diff --git a/src/lib/server/vorgangService.ts b/src/lib/server/vorgangService.ts index c4439bd..a4dcad4 100644 --- a/src/lib/server/vorgangService.ts +++ b/src/lib/server/vorgangService.ts @@ -1,17 +1,73 @@ -import { fail, redirect } from '@sveltejs/kit'; +import { fail } from '@sveltejs/kit'; import { BUCKET, client, TOKENFILENAME } from '$lib/minio'; import { checkIfExactDirectoryExists } from './s3ClientService'; +export const getVorgangByCaseId = async (caseId: string, token: string) => { + const isValidCase = await checkIfVorgangExists(caseId); + const isValidToken = await hasValidToken(caseId, token); + + // const prefix = params.vorgang ? `${params.vorgang}/` : ''; + + // const stream = client.listObjectsV2(BUCKET, caseId, false, ''); + // let files: any[] = []; + + return new Promise((resolve, reject) => { + const stream = client.listObjectsV2(BUCKET, caseId, false, ''); + const result = []; + + stream.on('data', (item) => { + result.push(item); + }); + + stream.on('end', () => { + resolve(result); + }); + + stream.on('error', (err) => { + reject(err); + }); + }); + + // const readableStream = new ReadableStream({ + // start(controller) { + // stream.on('data', (data) => { + // if (caseId === '') { + // if (data.prefix) + // controller.enqueue(`${JSON.stringify({ ...data, name: data.prefix.slice(0, -1) })}\n`); + // return; + // } + + // const name = data?.name?.slice(caseId.length); + // if (name === 'config.json') return; + // // zugangscode datei + // if (name === '__perm__') return; + + // controller.enqueue(`${JSON.stringify({ ...data, name, caseId })}\n`); + // }); + // stream.on('end', () => { + // controller.close(); + // }); + // }, + // cancel() { + // stream.destroy(); + // } + // }); + + // return files; + + // return new Response(result, { + // headers: { + // 'content-type': 'text/event-stream' + // } + // }); +}; + /** * Checks if Vorgang exists and token is valid. * @param request * @returns redirect to /list/caseId or error */ -export const redirectIfVorgangExists = async (request: Request) => { - const data = await request.formData(); - const caseId = data.get('case-id'); - const caseToken = data.get('case-token'); - +const checkIfVorgangExists = async (caseId) => { if (!caseId) { return fail(400, { success: false, @@ -28,55 +84,22 @@ export const redirectIfVorgangExists = async (request: Request) => { }); } - const isTokenValid = await hasValidToken(caseId, caseToken); + return true; - if (!isTokenValid) { - return fail(400, { - success: false, - caseId, - error: { message: 'Der Token ist ungültig.' } - }); - } + // const isTokenValid = await hasValidToken(caseId, caseToken); - redirect(303, `/list/${caseId}?token=${caseToken}`); + // if (!isTokenValid) { + // return fail(400, { + // success: false, + // caseId, + // error: { message: 'Der Token ist ungültig.' } + // }); + // } + + // redirect(303, `/list/${caseId}?token=${caseToken}`); }; -export const getVorgangByCaseId = ({ params }) => { - const prefix = params.vorgang ? `${params.vorgang}/` : ''; - const stream = client.listObjectsV2(BUCKET, prefix, false, ''); - const result = new ReadableStream({ - start(controller) { - stream.on('data', (data) => { - if (prefix === '') { - if (data.prefix) - controller.enqueue(`${JSON.stringify({ ...data, name: data.prefix.slice(0, -1) })}\n`); - return; - } - - const name = data.name.slice(prefix.length); - if (name === 'config.json') return; - // zugangscode datei - if (name === '__perm__') return; - - controller.enqueue(`${JSON.stringify({ ...data, name, prefix })}\n`); - }); - stream.on('end', () => { - controller.close(); - }); - }, - cancel() { - stream.destroy(); - } - }); - - return new Response(result, { - headers: { - 'content-type': 'text/event-stream' - } - }); -}; - -export const hasValidToken = async (caseId: string, caseToken: string) => { +const hasValidToken = async (caseId: string, caseToken: string) => { const objPath = `${caseId}/${TOKENFILENAME}`; try { @@ -84,9 +107,17 @@ export const hasValidToken = async (caseId: string, caseToken: string) => { const res = await client.getObject(BUCKET, objPath); - const savedToken = await new Response(res).text(); + const token = await new Response(res).text(); - return savedToken === caseToken ? true : false; + if (!token) { + return fail(400, { + success: false, + caseId, + error: { message: 'Der Token ist ungültig.' } + }); + } + + return token === caseToken ? true : false; } catch (error) { if (error.name == 'S3Error') { console.log(error); diff --git a/src/routes/anmeldung/+page.server.ts b/src/routes/anmeldung/+page.server.ts index be19d11..362a0ca 100644 --- a/src/routes/anmeldung/+page.server.ts +++ b/src/routes/anmeldung/+page.server.ts @@ -1,9 +1,15 @@ import { loginUser, logoutUser } from '$lib/server/authService'; -import { redirectIfVorgangExists } from '$lib/server/vorgangService.js'; - +import { getVorgangByCaseId } from '$lib/server/vorgangService.js'; export const actions = { - login: ({ request, cookies }) => loginUser({request, cookies}), + login: ({ request, cookies }) => loginUser({ request, cookies }), logout: (event) => logoutUser(event), - redirectToVorgang: ({request}) => redirectIfVorgangExists(request) + getVorgangById: async ({ request }) => { + const data = await request.formData(); + const caseId = data.get('case-id'); + const caseToken = data.get('case-token'); + const result = await getVorgangByCaseId(caseId, caseToken); + + console.log(result); + } } as const; diff --git a/src/routes/anmeldung/+page.svelte b/src/routes/anmeldung/+page.svelte index f68f9ea..f937a51 100644 --- a/src/routes/anmeldung/+page.svelte +++ b/src/routes/anmeldung/+page.svelte @@ -24,7 +24,7 @@
-
+ Date: Thu, 19 Jun 2025 16:01:07 +0200 Subject: [PATCH 3/6] change case loading in server side mode, made case list functional --- src/lib/minio.ts | 1 + src/lib/server/s3ClientService.ts | 10 +- src/lib/server/vorgangService.ts | 122 +++++++----------- src/routes/(angemeldet)/list/+page.server.ts | 10 ++ .../list/+page.svelte | 33 +---- .../list/[vorgang]/+page.server.ts | 32 +++-- .../(token-based)/list/[vorgang]/+page.svelte | 58 ++------- src/routes/anmeldung/+page.server.ts | 12 +- 8 files changed, 110 insertions(+), 168 deletions(-) create mode 100644 src/routes/(angemeldet)/list/+page.server.ts rename src/routes/{(token-based) => (angemeldet)}/list/+page.svelte (73%) diff --git a/src/lib/minio.ts b/src/lib/minio.ts index f2ac969..49ef470 100644 --- a/src/lib/minio.ts +++ b/src/lib/minio.ts @@ -9,3 +9,4 @@ export const client = new Client(config.minio); export const BUCKET = 'tatort'; export const TOKENFILENAME = '__perm__'; +export const CONFIGFILENAME = 'config.json'; diff --git a/src/lib/server/s3ClientService.ts b/src/lib/server/s3ClientService.ts index 2a46c87..dc497b1 100644 --- a/src/lib/server/s3ClientService.ts +++ b/src/lib/server/s3ClientService.ts @@ -1,6 +1,5 @@ import { BUCKET, client } from '$lib/minio'; - export const checkIfExactDirectoryExists = (dir: string): Promise => { return new Promise((resolve, reject) => { const prefix = dir.endsWith('/') ? dir : `${dir}/`; @@ -18,4 +17,11 @@ export const checkIfExactDirectoryExists = (dir: string): Promise => { stream.on('end', () => resolve(false)); }); -} +}; + +export const getContentofTextObject = async (bucket: string, objPath: string) => { + const res = await client.getObject(bucket, objPath); + + const text = await new Response(res).text(); + return text; +}; diff --git a/src/lib/server/vorgangService.ts b/src/lib/server/vorgangService.ts index a4dcad4..65ae4fc 100644 --- a/src/lib/server/vorgangService.ts +++ b/src/lib/server/vorgangService.ts @@ -1,73 +1,49 @@ import { fail } from '@sveltejs/kit'; -import { BUCKET, client, TOKENFILENAME } from '$lib/minio'; -import { checkIfExactDirectoryExists } from './s3ClientService'; +import { BUCKET, client, CONFIGFILENAME, TOKENFILENAME } from '$lib/minio'; +import { checkIfExactDirectoryExists, getContentofTextObject } from './s3ClientService'; -export const getVorgangByCaseId = async (caseId: string, token: string) => { - const isValidCase = await checkIfVorgangExists(caseId); - const isValidToken = await hasValidToken(caseId, token); +/** + * Get Vorgang and list of tatorte + * @param caseId + * @returns + */ +export const getVorgangByCaseId = async (caseId: string) => { + const prefix = `${caseId}/`; - // const prefix = params.vorgang ? `${params.vorgang}/` : ''; + const stream = client.listObjectsV2(BUCKET, prefix, false, ''); - // const stream = client.listObjectsV2(BUCKET, caseId, false, ''); - // let files: any[] = []; + const list = []; + for await (const chunk of stream) { + const splittedNameParts = chunk.name.split('/'); + const prefix = splittedNameParts[0]; + const name = splittedNameParts[1]; + if (name === CONFIGFILENAME || name === TOKENFILENAME) continue; + list.push({ ...chunk, name: name, prefix: prefix, show_button: true }); + } + return list; +}; - return new Promise((resolve, reject) => { - const stream = client.listObjectsV2(BUCKET, caseId, false, ''); - const result = []; +export const getListOfVorgänge = async () => { + const stream = client.listObjectsV2(BUCKET, '', false, ''); + + const list = []; + for await (const chunk of stream) { + const objPath = `${chunk.prefix}${TOKENFILENAME}`; - stream.on('data', (item) => { - result.push(item); - }); + const token = await getContentofTextObject(BUCKET, objPath); - stream.on('end', () => { - resolve(result); - }); - - stream.on('error', (err) => { - reject(err); - }); - }); - - // const readableStream = new ReadableStream({ - // start(controller) { - // stream.on('data', (data) => { - // if (caseId === '') { - // if (data.prefix) - // controller.enqueue(`${JSON.stringify({ ...data, name: data.prefix.slice(0, -1) })}\n`); - // return; - // } - - // const name = data?.name?.slice(caseId.length); - // if (name === 'config.json') return; - // // zugangscode datei - // if (name === '__perm__') return; - - // controller.enqueue(`${JSON.stringify({ ...data, name, caseId })}\n`); - // }); - // stream.on('end', () => { - // controller.close(); - // }); - // }, - // cancel() { - // stream.destroy(); - // } - // }); - - // return files; - - // return new Response(result, { - // headers: { - // 'content-type': 'text/event-stream' - // } - // }); + const cleanedChunkPrefix = chunk.prefix.replace(/\/$/, ''); + list.push({ name: cleanedChunkPrefix, token: token }); + } + return list; }; /** - * Checks if Vorgang exists and token is valid. + * Checks if Vorgang exists * @param request - * @returns redirect to /list/caseId or error + * @returns fail or true */ -const checkIfVorgangExists = async (caseId) => { +export const checkIfVorgangExists = async (caseId: string) => { if (!caseId) { return fail(400, { success: false, @@ -85,31 +61,23 @@ const checkIfVorgangExists = async (caseId) => { } return true; - - // const isTokenValid = await hasValidToken(caseId, caseToken); - - // if (!isTokenValid) { - // return fail(400, { - // success: false, - // caseId, - // error: { message: 'Der Token ist ungültig.' } - // }); - // } - - // redirect(303, `/list/${caseId}?token=${caseToken}`); }; -const hasValidToken = async (caseId: string, caseToken: string) => { +export const hasValidToken = async (caseId: string, caseToken: string) => { const objPath = `${caseId}/${TOKENFILENAME}`; try { - if (!caseToken) return false; + if (!caseToken) { + return fail(400, { + success: false, + caseId, + error: { message: 'Bitte Zugangscode eingeben!' } + }); + } - const res = await client.getObject(BUCKET, objPath); + const token = await getContentofTextObject(BUCKET, objPath); - const token = await new Response(res).text(); - - if (!token) { + if (!token || token !== caseToken) { return fail(400, { success: false, caseId, @@ -117,7 +85,7 @@ const hasValidToken = async (caseId: string, caseToken: string) => { }); } - return token === caseToken ? true : false; + return true; } catch (error) { if (error.name == 'S3Error') { console.log(error); diff --git a/src/routes/(angemeldet)/list/+page.server.ts b/src/routes/(angemeldet)/list/+page.server.ts new file mode 100644 index 0000000..4d78120 --- /dev/null +++ b/src/routes/(angemeldet)/list/+page.server.ts @@ -0,0 +1,10 @@ +import { getListOfVorgänge } from '$lib/server/vorgangService'; +import type { PageServerLoad } from '../../(token-based)/view/$types'; + +export const load: PageServerLoad = async () => { + const caseList = await getListOfVorgänge(); + + return { + caseList + }; +}; diff --git a/src/routes/(token-based)/list/+page.svelte b/src/routes/(angemeldet)/list/+page.svelte similarity index 73% rename from src/routes/(token-based)/list/+page.svelte rename to src/routes/(angemeldet)/list/+page.svelte index 323bc3e..b730a95 100644 --- a/src/routes/(token-based)/list/+page.svelte +++ b/src/routes/(angemeldet)/list/+page.svelte @@ -1,34 +1,11 @@ diff --git a/src/routes/anmeldung/+page.server.ts b/src/routes/anmeldung/+page.server.ts index 210da49..167b8ef 100644 --- a/src/routes/anmeldung/+page.server.ts +++ b/src/routes/anmeldung/+page.server.ts @@ -15,7 +15,6 @@ export const actions = { const isTokenValid = await hasValidToken(caseId, caseToken); if ( isTokenValid !== true) return isTokenValid; - throw redirect(303, `/list/${caseId}?token=${caseToken}`); } } as const; -- 2.43.0