9 Commits

9 changed files with 122 additions and 38 deletions

View File

@@ -51,6 +51,7 @@
"minio": "^8.0.5",
"postcss": "^8.5.4",
"sqlite3": "^5.1.7",
"tailwindcss": "^3.4.17"
"tailwindcss": "^3.4.17",
"uuid": "^11.1.0"
}
}

View File

@@ -19,21 +19,27 @@ let check_ins_stmt = `INSERT INTO users (name, pw) SELECT 'admin', '${hashed_pw}
db.exec(check_ins_stmt);
let users_stmt = `SELECT * FROM USERS`;
const stmt = db.prepare(users_stmt);
let stmt = db.prepare(users_stmt);
console.log(`\n`, `*** Users table`);
for (const usr of stmt.iterate()) {
console.log(`xxx ${usr.name} + ${usr.pw}`)
};
console.log(`[r] ${usr.name} + ${usr.pw}`);
}
// cases table
create_stmt = `CREATE TABLE IF NOT EXISTS cases
(id INTEGER PRIMARY KEY AUTOINCREMENT,
token TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
pw TEXT NOT NULL,
created_by INTEGER NOT NULL,
FOREIGN KEY(created_by) REFERENCES users(id))`;
token TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
pw TEXT NOT NULL)`;
db.exec(create_stmt);
let cases_stmt = `SELECT * FROM cases`;
stmt = db.prepare(cases_stmt);
console.log(`\n`, `*** Cases table`);
for (const usr of stmt.iterate()) {
console.log(`[r] ${usr.name} + ${usr.token} + ${usr.pw}`);
}
db.close();

View File

@@ -2,6 +2,9 @@ import { fail } from '@sveltejs/kit';
import { BUCKET, client, CONFIGFILENAME, TOKENFILENAME } from '$lib/minio';
import { checkIfExactDirectoryExists, getContentOfTextObject } from './s3ClientService';
import Database from 'better-sqlite3';
const db = new Database('./src/lib/data/tatort.db');
/**
* Get Vorgang and corresponend list of tatorte
* @param caseId
@@ -17,13 +20,25 @@ export const getVorgangByCaseId = async (caseId: string) => {
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;
};
/**
* Get Vorgang
* @param caseId
* @returns caseObj with keys `token`, `name`, `pw` || undefined
*/
export const getVorgang = function (caseId: string) {
let getVorgang_stmt = `SELECT token, name, pw FROM cases WHERE token = ?`;
const stmt = db.prepare(getVorgang_stmt);
const res = stmt.get(caseId);
return res;
};
/**
* Fetches list of vorgänge from s3 bucket
@@ -31,7 +46,7 @@ export const getVorgangByCaseId = async (caseId: string) => {
*/
export const getListOfVorgänge = async () => {
const stream = client.listObjectsV2(BUCKET, '', false, '');
const list = [];
for await (const chunk of stream) {
const objPath = `${chunk.prefix}${TOKENFILENAME}`;
@@ -44,6 +59,23 @@ export const getListOfVorgänge = async () => {
return list;
};
/**
* Fetches list of vorgänge from database
* @returns list with of available cases
*/
export const getVorgaenge = function () {
let getVorgaenge_stmt = `SELECT token, name, pw from cases`;
const stmt = db.prepare(getVorgaenge_stmt);
const res = stmt.all();
const vorgaenge_list = [];
for (const r of res) {
const vorg = { token: r.token, name: r.name, pw: r.pw };
vorgaenge_list.push(vorg);
}
return vorgaenge_list;
};
/**
* Checks if Vorgang exists
* @param request
@@ -69,6 +101,23 @@ export const checkIfVorgangExists = async (caseId: string | null) => {
return true;
};
export const vorgangExists = function (caseId: string | null) {
if (!caseId) {
return fail(400, {
success: false,
caseId,
error: { message: 'Die Vorgangsnummer darf nicht leer sein.' }
});
}
let vorgaenge = getVorgaenge();
const vorgaenge_tokens = vorgaenge.map((vorg) => vorg.token);
const found = vorgaenge_tokens.indexOf(caseId) != -1;
return found;
};
export const hasValidToken = async (caseId: string, caseToken: string) => {
const objPath = `${caseId}/${TOKENFILENAME}`;
@@ -90,3 +139,17 @@ export const hasValidToken = async (caseId: string, caseToken: string) => {
}
}
};
export const tokenValid = function (caseId, caseToken) {
if (!caseToken) {
return false;
}
const vorg = getVorgang(caseId);
if (!vorg || vorg.pw !== caseToken) {
return false;
}
return true;
};

View File

@@ -1,10 +1,11 @@
import { getListOfVorgänge } from '$lib/server/vorgangService';
import { getListOfVorgänge, getVorgaenge } from '$lib/server/vorgangService';
import type { PageServerLoad } from '../../(token-based)/view/$types';
export const load: PageServerLoad = async () => {
const caseList = await getListOfVorgänge();
// const caseList = await getListOfVorgänge();
const caseList = getVorgaenge();
return {
caseList
};
return {
caseList
};
};

View File

@@ -46,7 +46,7 @@
<ul role="list" class="divide-y divide-gray-100">
{#each caseList as item}
<li>
<a href="/list/{item.name}?token={item.token}" class="flex justify-between gap-x-6 py-5">
<a href="/list/{item.token}?token={item.pw}" class="flex justify-between gap-x-6 py-5">
<div class="flex gap-x-4">
<!-- Ordner -->
<Folder />

View File

@@ -2,6 +2,9 @@ import { Buffer } from 'buffer';
import { Readable } from 'stream';
import { client } from '$lib/minio';
import { fail } from '@sveltejs/kit';
import { v4 as uuidv4 } from 'uuid';
import Database from 'better-sqlite3';
const isRequiredFieldValid = (value: unknown) => {
if (value == null) return false;
@@ -9,10 +12,10 @@ const isRequiredFieldValid = (value: unknown) => {
if (typeof value === 'string' || value instanceof String) return value.trim() !== '';
return true;
}
};
export const actions = {
url: async ({ request }: {request: Request}) => {
url: async ({ request }: { request: Request }) => {
const data = await request.formData();
const vorgang = data.get('vorgang');
const name = data.get('name');
@@ -20,28 +23,29 @@ export const actions = {
const code = data.get('zugangscode');
const fileName = data.get('fileName');
let objectName = `${vorgang}/${name}`;
// store case in database
let db = new Database('./src/lib/data/tatort.db');
let token = uuidv4();
let insert_stmt = `INSERT INTO cases (token, name, pw) VALUES (?, ?, ?)`;
const stmt = db.prepare(insert_stmt);
stmt.run(token, vorgang, code);
let objectName = `${token}/${name}`;
switch (type) {
case 'image/png':
if (!objectName.endsWith('.png')) objectName += '.png';
break;
case '':
if (fileName?.toString().endsWith('.glb') && !objectName.endsWith('.glb')) objectName += '.glb';
if (fileName?.toString().endsWith('.glb') && !objectName.endsWith('.glb'))
objectName += '.glb';
}
const url = await client.presignedPutObject('tatort', objectName);
// store code in S3
// tatort/<vorgang>/__perm__
const code_filename = '__perm__';
const buf = Buffer.from(code, 'utf-8');
const code_stream = Readable.from(buf);
const code_path = `${vorgang}/${code_filename}`;
await client.putObject('tatort', code_path, code_stream);
return { url };
},
validate: async ({ request }: {request: Request}) => {
validate: async ({ request }: { request: Request }) => {
const requestData = await request.formData();
const data = Object.fromEntries(requestData);
const vorgang = data.vorgang;
@@ -73,7 +77,7 @@ export const actions = {
return fail(400, err);
},
upload: async ({ request }: {request: Request}) => {
upload: async ({ request }: { request: Request }) => {
const requestData = await request.formData();
const data = Object.fromEntries(requestData);
const vorgang = data.vorgang;
@@ -83,7 +87,7 @@ export const actions = {
return { url };
},
upload3: async ({ request }: {request: Request}) => {
upload3: async ({ request }: { request: Request }) => {
const requestData = await request.formData();
const data = Object.fromEntries(requestData);
const name = data.name;

View File

@@ -1,4 +1,9 @@
import { checkIfVorgangExists, hasValidToken } from '$lib/server/vorgangService';
import {
checkIfVorgangExists,
hasValidToken,
tokenValid,
vorgangExists
} from '$lib/server/vorgangService';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './list/[vorgang]/$types';
@@ -12,8 +17,9 @@ export const load: PageServerLoad = async ({ params, url, locals }) => {
const caseId = params.vorgang;
const caseToken = url.searchParams.get('token');
const isVorgangValid = await checkIfVorgangExists(caseId);
const isTokenValid = await hasValidToken(caseId, caseToken);
const isVorgangValid = vorgangExists(caseId);
const isTokenValid = tokenValid(caseId, caseToken);
console.log(`--- is valid: ${isTokenValid}`);
if (!isVorgangValid || !isTokenValid) throw redirect(303, `/anmeldung`);
};

View File

@@ -1,4 +1,4 @@
import { getVorgangByCaseId } from '$lib/server/vorgangService';
import { getVorgang, getVorgangByCaseId } from '$lib/server/vorgangService';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ params, url }) => {
@@ -6,9 +6,11 @@ export const load: PageServerLoad = async ({ params, url }) => {
const caseToken = url.searchParams.get('token');
const crimesList = await getVorgangByCaseId(caseId);
const vorg = getVorgang(caseId);
return {
crimesList,
caseToken
caseToken,
vorg
};
};

View File

@@ -26,6 +26,7 @@
// add other properties as needed
}
const vorg = data.vorg;
const crimesList: ListItem[] = data.crimesList;
const token: string = data.caseToken;
@@ -132,7 +133,7 @@
<div class="-z-10 bg-white">
<div class="flex flex-col items-center justify-center w-full">
<h1 class="text-xl">Vorgang {$page.params.vorgang}</h1>
<h1 class="text-xl">Vorgang {vorg.name}</h1>
</div>
<div class="mx-auto flex justify-center max-w-7xl h-full">
<ul class="divide-y divide-gray-100">