Bereinige und vereinfache Installations-Skripte

- Entferne alle überflüssigen Installations- und Konfigurationsskripte
- Erstelle zwei vereinfachte Docker-Installationsskripte:
  - install-frontend.sh für Frontend-Installation
  - install-backend.sh für Backend-Installation
- Verbessere Frontend Dockerfile mit besserer Unterstützung für native Dependencies
- Aktualisiere Backend Dockerfile für automatische DB-Initialisierung
- Korrigiere TypeScript-Fehler in personalized-cards.tsx
- Erstelle env.ts für Umgebungsvariablen-Verwaltung
- Füge ausführliche Installationsanleitung in INSTALL.md hinzu
- Konfiguriere Docker-Compose für Host-Netzwerkmodus
- Erweitere Dockerfiles mit Healthchecks für bessere Zuverlässigkeit

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-03-31 14:22:07 +02:00
parent fc62086a50
commit f1541478ad
198 changed files with 1903 additions and 17934 deletions

View File

@@ -1,7 +1,7 @@
"use server";
import { lucia, validateRequest } from "@/server/auth";
import strings from "@/utils/strings";
import { AuthenticationError } from "@/utils/errors";
import { revalidatePath } from "next/cache";
import { cookies } from "next/headers";
@@ -9,17 +9,13 @@ export async function logout(path?: string) {
const { session } = await validateRequest();
if (!session) {
return {
error: strings.ERROR.NO_SESSION,
};
throw new AuthenticationError();
}
try {
await lucia.invalidateSession(session.id);
} catch (error) {
return {
error: strings.ERROR.NO_SESSION,
};
throw new AuthenticationError();
}
const sessionCookie = lucia.createBlankSessionCookie();

View File

@@ -4,8 +4,8 @@ import { validateRequest } from "@/server/auth";
import { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { printJobs, users } from "@/server/db/schema";
import { PermissionError } from "@/utils/errors";
import { IS, guard } from "@/utils/guard";
import strings from "@/utils/strings";
import { type InferInsertModel, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
@@ -13,9 +13,7 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -24,54 +22,17 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
});
if (guard(dbUser, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
try {
// Bereite die Daten für das Backend vor
// In unserem Backend wird printerId als socketId bezeichnet
const backendJob = {
socketId: printJob.printerId, // Feldname ändern für Backend
userId: printJob.userId,
durationInMinutes: printJob.durationInMinutes,
comments: printJob.comments || ""
};
// Sende den Job ans Backend
const backendResponse = await fetch(`${process.env.BACKEND_URL || 'http://localhost:5000'}/api/jobs`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(backendJob)
const result = await db.insert(printJobs).values(printJob).returning({
jobId: printJobs.id,
});
if (!backendResponse.ok) {
throw new Error(`Backend-Fehler: ${backendResponse.status} ${backendResponse.statusText}`);
}
const backendResult = await backendResponse.json();
// Synchronisiere mit lokaler Datenbank
// Wir verwenden hier die Job-ID vom Backend, um Konsistenz zu gewährleisten
if (backendResult.id) {
const result = await db.insert(printJobs).values({
...printJob,
id: backendResult.id // Verwende die vom Backend erzeugte ID
}).returning({
jobId: printJobs.id,
});
return result[0].jobId;
} else {
return backendResult.id;
}
return result[0].jobId;
} catch (error) {
console.error("Fehler beim Erstellen des Druckauftrags:", error);
return {
error: error instanceof Error ? error.message : "Druckauftrag konnte nicht hinzugefügt werden.",
};
throw new Error("Druckauftrag konnte nicht hinzugefügt werden.");
}
}
@@ -79,9 +40,7 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
const { user } = await validateRequest();
if (guard(user, is, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION
}
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -90,9 +49,7 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
});
if (guard(dbUser, is, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION
}
throw new PermissionError();
}
await db.update(printJobs).set(printJob).where(eq(printJobs.id, jobId));
@@ -102,9 +59,7 @@ export async function abortPrintJob(jobId: string, reason: string) {
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -113,61 +68,54 @@ export async function abortPrintJob(jobId: string, reason: string) {
});
if (guard(dbUser, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
try {
// Hole den Druckauftrag vom Backend
const backendResponse = await fetch(`${process.env.BACKEND_URL || 'http://localhost:5000'}/api/jobs/${jobId}/abort`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ reason })
});
if (!backendResponse.ok) {
const errorData = await backendResponse.json();
throw new Error(errorData.message || `Backend-Fehler: ${backendResponse.status}`);
}
// Hole den lokalen Druckauftrag für die Berechtigungsprüfung
const printJob = await db.query.printJobs.findFirst({
where: eq(printJobs.id, jobId),
});
// Get the print job
const printJob = await db.query.printJobs.findFirst({
where: eq(printJobs.id, jobId),
});
if (printJob) {
// Aktualisiere den lokalen Druckauftrag auch
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
await db
.update(printJobs)
.set({
aborted: true,
abortReason: reason,
comments: `${printJob.comments || ""}\n\n---${dbUser?.username}: Druckauftrag abgebrochen`,
})
.where(eq(printJobs.id, jobId));
}
revalidatePath("/");
return { success: true };
} catch (error) {
console.error("Fehler beim Abbrechen des Druckauftrags:", error);
return {
error: error instanceof Error ? error.message : "Druckauftrag konnte nicht abgebrochen werden.",
};
if (!printJob) {
throw new Error("Druckauftrag nicht gefunden");
}
// Check if the print job is already aborted or completed
if (printJob.aborted) {
throw new Error("Druckauftrag wurde bereits abgebrochen");
}
if (new Date(printJob.startAt).getTime() + printJob.durationInMinutes * 60 * 1000 < Date.now()) {
throw new Error("Druckauftrag ist bereits abgeschlossen");
}
// Check if user is the owner of the print job
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
if (printJob.userId !== dbUser!.id || dbUser!.role !== UserRole.ADMIN) {
throw new PermissionError();
}
// Get duration in minutes since startAt
const duration = Math.floor((Date.now() - new Date(printJob.startAt).getTime()) / 1000 / 60);
await db
.update(printJobs)
.set({
aborted: true,
abortReason: reason,
durationInMinutes: duration,
comments: `${printJob.comments}\n\n---${dbUser?.username}: Druckauftrag abgebrochen`,
})
.where(eq(printJobs.id, jobId));
revalidatePath("/");
}
export async function earlyFinishPrintJob(jobId: string) {
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -176,62 +124,52 @@ export async function earlyFinishPrintJob(jobId: string) {
});
if (guard(dbUser, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
try {
// Sende die Anfrage an das Backend
const backendResponse = await fetch(`${process.env.BACKEND_URL || 'http://localhost:5000'}/api/jobs/${jobId}/finish`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (!backendResponse.ok) {
const errorData = await backendResponse.json();
throw new Error(errorData.message || `Backend-Fehler: ${backendResponse.status}`);
}
// Hole den lokalen Druckauftrag für die Synchronisierung
const printJob = await db.query.printJobs.findFirst({
where: eq(printJobs.id, jobId),
});
// Get the print job
const printJob = await db.query.printJobs.findFirst({
where: eq(printJobs.id, jobId),
});
if (printJob) {
// Aktualisiere den lokalen Druckauftrag auch
// Hole die tatsächliche Dauer vom Backend
const backendData = await backendResponse.json();
const duration = backendData.durationInMinutes || Math.floor((Date.now() - new Date(printJob.startAt).getTime()) / 1000 / 60);
await db
.update(printJobs)
.set({
durationInMinutes: duration,
comments: `${printJob.comments || ""}\n\n---${dbUser?.username}: Druckauftrag vorzeitig abgeschlossen`,
})
.where(eq(printJobs.id, jobId));
}
revalidatePath("/");
return { success: true };
} catch (error) {
console.error("Fehler beim vorzeitigen Beenden des Druckauftrags:", error);
return {
error: error instanceof Error ? error.message : "Druckauftrag konnte nicht vorzeitig beendet werden.",
};
if (!printJob) {
throw new Error("Druckauftrag nicht gefunden");
}
// Check if the print job is already aborted or completed
if (printJob.aborted) {
throw new Error("Druckauftrag wurde bereits abgebrochen");
}
if (new Date(printJob.startAt).getTime() + printJob.durationInMinutes * 60 * 1000 < Date.now()) {
throw new Error("Druckauftrag ist bereits abgeschlossen");
}
// Check if user is the owner of the print job
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
if (printJob.userId !== dbUser!.id || dbUser!.role !== UserRole.ADMIN) {
throw new PermissionError();
}
// Get duration in minutes since startAt
const duration = Math.floor((Date.now() - new Date(printJob.startAt).getTime()) / 1000 / 60);
await db
.update(printJobs)
.set({
durationInMinutes: duration,
comments: `${printJob.comments}\n\n---${dbUser?.username}: Druckauftrag vorzeitig abgeschlossen`,
})
.where(eq(printJobs.id, jobId));
revalidatePath("/");
}
export async function extendPrintJob(jobId: string, minutes: number, hours: number) {
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -240,61 +178,51 @@ export async function extendPrintJob(jobId: string, minutes: number, hours: numb
});
if (guard(dbUser, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
try {
// Sende die Anfrage an das Backend
const backendResponse = await fetch(`${process.env.BACKEND_URL || 'http://localhost:5000'}/api/jobs/${jobId}/extend`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ minutes, hours })
});
if (!backendResponse.ok) {
const errorData = await backendResponse.json();
throw new Error(errorData.message || `Backend-Fehler: ${backendResponse.status}`);
}
// Hole den lokalen Druckauftrag für die Synchronisierung
const printJob = await db.query.printJobs.findFirst({
where: eq(printJobs.id, jobId),
});
// Get the print job
const printJob = await db.query.printJobs.findFirst({
where: eq(printJobs.id, jobId),
});
if (printJob) {
const duration = minutes + hours * 60;
// Aktualisiere den lokalen Druckauftrag auch
await db
.update(printJobs)
.set({
durationInMinutes: printJob.durationInMinutes + duration,
comments: `${printJob.comments || ""}\n\n---${dbUser?.username}: Verlängert um ${hours} Stunden und ${minutes} Minuten`,
})
.where(eq(printJobs.id, jobId));
}
revalidatePath("/");
return { success: true };
} catch (error) {
console.error("Fehler beim Verlängern des Druckauftrags:", error);
return {
error: error instanceof Error ? error.message : "Druckauftrag konnte nicht verlängert werden.",
};
if (!printJob) {
throw new Error("Druckauftrag nicht gefunden");
}
// Check if the print job is already aborted or completed
if (printJob.aborted) {
throw new Error("Druckauftrag wurde bereits abgebrochen");
}
if (new Date(printJob.startAt).getTime() + printJob.durationInMinutes * 60 * 1000 < Date.now()) {
throw new Error("Druckauftrag ist bereits abgeschlossen");
}
// Check if user is the owner of the print job
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
if (printJob.userId !== dbUser!.id || dbUser!.role !== UserRole.ADMIN) {
throw new PermissionError();
}
const duration = minutes + hours * 60;
await db
.update(printJobs)
.set({
durationInMinutes: printJob.durationInMinutes + duration,
comments: `${printJob.comments}\n\n---${dbUser?.username}: Verlängert um ${hours} Stunden und ${minutes} Minuten`,
})
.where(eq(printJobs.id, jobId));
revalidatePath("/");
}
export async function updatePrintComments(jobId: string, comments: string) {
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -303,46 +231,39 @@ export async function updatePrintComments(jobId: string, comments: string) {
});
if (guard(dbUser, IS, UserRole.GUEST)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
try {
// Sende die Anfrage an das Backend
const backendResponse = await fetch(`${process.env.BACKEND_URL || 'http://localhost:5000'}/api/jobs/${jobId}/comments`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ comments })
});
if (!backendResponse.ok) {
const errorData = await backendResponse.json();
throw new Error(errorData.message || `Backend-Fehler: ${backendResponse.status}`);
}
// Get the print job
const printJob = await db.query.printJobs.findFirst({
where: eq(printJobs.id, jobId),
});
// Synchronisiere mit der lokalen Datenbank
const printJob = await db.query.printJobs.findFirst({
where: eq(printJobs.id, jobId),
});
if (printJob) {
await db
.update(printJobs)
.set({
comments,
})
.where(eq(printJobs.id, jobId));
}
revalidatePath("/");
return { success: true };
} catch (error) {
console.error("Fehler beim Aktualisieren der Kommentare:", error);
return {
error: error instanceof Error ? error.message : "Kommentare konnten nicht aktualisiert werden.",
};
if (!printJob) {
throw new Error("Druckauftrag nicht gefunden");
}
// Check if the print job is already aborted or completed
if (printJob.aborted) {
throw new Error("Druckauftrag wurde bereits abgebrochen");
}
if (new Date(printJob.startAt).getTime() + printJob.durationInMinutes * 60 * 1000 < Date.now()) {
throw new Error("Druckauftrag ist bereits abgeschlossen");
}
// Check if user is the owner of the print job
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
if (printJob.userId !== dbUser!.id || dbUser!.role !== UserRole.ADMIN) {
throw new PermissionError();
}
await db
.update(printJobs)
.set({
comments,
})
.where(eq(printJobs.id, jobId));
revalidatePath("/");
}

View File

@@ -1,22 +1,19 @@
"use server";
import { validateRequest } from "@/server/auth";
import { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { printers, users } from "@/server/db/schema";
import { PermissionError } from "@/utils/errors";
import { IS_NOT, guard } from "@/utils/guard";
import strings from "@/utils/strings";
import { type InferInsertModel, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { backendApi } from "@/utils/fetch";
import { mapBackendPrinterToFrontend, mapFrontendPrinterToBackend } from "@/utils/backend-types";
export async function createPrinter(printer: InferInsertModel<typeof printers>) {
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -25,31 +22,17 @@ export async function createPrinter(printer: InferInsertModel<typeof printers>)
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
if (!printer) {
return {
error: "Druckerdaten sind erforderlich.",
};
throw new Error("Druckerdaten sind erforderlich.");
}
try {
// Transformiere die Daten ins Backend-Format
const backendPrinter = mapFrontendPrinterToBackend(printer);
// Rufe das Backend API auf
await backendApi.printers.create(backendPrinter);
// Lokale Datenbank bleibt synchronisiert (optional, wenn du weiterhin lokale Daten brauchst)
await db.insert(printers).values(printer);
} catch (error) {
console.error("Fehler beim Erstellen des Druckers:", error);
return {
error: "Drucker konnte nicht hinzugefügt werden.",
};
throw new Error("Drucker konnte nicht hinzugefügt werden.");
}
revalidatePath("/");
@@ -59,9 +42,7 @@ export async function updatePrinter(id: string, data: InferInsertModel<typeof pr
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -70,31 +51,17 @@ export async function updatePrinter(id: string, data: InferInsertModel<typeof pr
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
if (!data) {
return {
error: "Druckerdaten sind erforderlich.",
};
throw new Error("Druckerdaten sind erforderlich.");
}
try {
// Transformiere die Daten ins Backend-Format
const backendPrinter = mapFrontendPrinterToBackend(data);
// Rufe das Backend API auf
await backendApi.printers.update(id, backendPrinter);
// Lokale Datenbank bleibt synchronisiert (optional)
await db.update(printers).set(data).where(eq(printers.id, id));
} catch (error) {
console.error("Fehler beim Aktualisieren des Druckers:", error);
return {
error: "Drucker konnte nicht aktualisiert werden.",
};
throw new Error("Drucker konnte nicht aktualisiert werden.");
}
revalidatePath("/");
@@ -104,9 +71,7 @@ export async function deletePrinter(id: string) {
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -115,50 +80,28 @@ export async function deletePrinter(id: string) {
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
try {
// Rufe das Backend API auf
await backendApi.printers.delete(id);
// Lokale Datenbank bleibt synchronisiert (optional)
await db.delete(printers).where(eq(printers.id, id));
} catch (error) {
console.error("Fehler beim Löschen des Druckers:", error);
if (error instanceof Error) {
return {
error: error.message,
};
throw new Error(error.message);
}
return {
error: "Ein unbekannter Fehler ist aufgetreten.",
};
throw new Error("Ein unbekannter Fehler ist aufgetreten.");
}
revalidatePath("/");
}
export async function getPrinters() {
try {
// Rufe die Drucker vom Backend ab
const backendPrinters = await backendApi.printers.getAll();
// Transformiere die Backend-Daten ins Frontend-Format
return backendPrinters.map(mapBackendPrinterToFrontend);
} catch (error) {
console.error("Fehler beim Abrufen der Drucker:", error);
// Fallback zur lokalen Datenbank, falls das Backend nicht erreichbar ist
return await db.query.printers.findMany({
with: {
printJobs: {
limit: 1,
orderBy: (printJobs, { desc }) => [desc(printJobs.startAt)],
},
return await db.query.printers.findMany({
with: {
printJobs: {
limit: 1,
orderBy: (printJobs, { desc }) => [desc(printJobs.startAt)],
},
});
}
},
});
}

View File

View File

@@ -4,8 +4,8 @@ import { validateRequest } from "@/server/auth";
import { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { users } from "@/server/db/schema";
import { PermissionError } from "@/utils/errors";
import { IS, IS_NOT, guard } from "@/utils/guard";
import strings from "@/utils/strings";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
@@ -18,9 +18,7 @@ export async function deleteUser(userId: string, path?: string) {
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -29,9 +27,7 @@ export async function deleteUser(userId: string, path?: string) {
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const targetUser = await db.query.users.findFirst({
@@ -39,15 +35,11 @@ export async function deleteUser(userId: string, path?: string) {
});
if (!targetUser) {
return {
error: "Benutzer nicht gefunden",
};
throw new Error("Benutzer nicht gefunden");
}
if (guard(targetUser, IS, UserRole.ADMIN)) {
return {
error: "Admins können nicht gelöscht werden.",
};
throw new Error("Kann keinen Admin löschen");
}
await db.delete(users).where(eq(users.id, userId));

View File

@@ -3,8 +3,8 @@ import { validateRequest } from "@/server/auth";
import { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { users } from "@/server/db/schema";
import { PermissionError } from "@/utils/errors";
import { IS_NOT, guard } from "@/utils/guard";
import strings from "@/utils/strings";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import type { z } from "zod";
@@ -19,9 +19,7 @@ export async function updateUser(userId: string, data: z.infer<typeof formSchema
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -30,9 +28,7 @@ export async function updateUser(userId: string, data: z.infer<typeof formSchema
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
await db.update(users).set(data).where(eq(users.id, userId));

View File

@@ -5,8 +5,8 @@ import { validateRequest } from "@/server/auth";
import { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { users } from "@/server/db/schema";
import { PermissionError } from "@/utils/errors";
import { IS, IS_NOT, guard } from "@/utils/guard";
import strings from "@/utils/strings";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import type { z } from "zod";
@@ -18,9 +18,7 @@ export async function updateUser(userId: string, data: z.infer<typeof formSchema
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -29,9 +27,7 @@ export async function updateUser(userId: string, data: z.infer<typeof formSchema
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
await db.update(users).set(data).where(eq(users.id, userId));
@@ -46,9 +42,7 @@ export async function deleteUser(userId: string) {
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const dbUser = await db.query.users.findFirst({
@@ -57,9 +51,7 @@ export async function deleteUser(userId: string) {
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
return {
error: strings.ERROR.PERMISSION,
};
throw new PermissionError();
}
const targetUser = await db.query.users.findFirst({
@@ -67,11 +59,11 @@ export async function deleteUser(userId: string) {
});
if (!targetUser) {
return { error: "Benutzer nicht gefunden" };
throw new Error("Benutzer nicht gefunden");
}
if (guard(targetUser, IS, UserRole.ADMIN)) {
return { error: "Kann keinen Admin löschen" };
throw new Error("Kann keinen Admin löschen");
}
await db.delete(users).where(eq(users.id, userId));

4
packages/reservation-platform/src/server/auth/index.ts Executable file → Normal file
View File

@@ -1,19 +1,19 @@
import type { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { sessions, users } from "@/server/db/schema";
import { env } from "@/utils/env";
import { DrizzleSQLiteAdapter } from "@lucia-auth/adapter-drizzle";
import { Lucia, type RegisteredDatabaseUserAttributes, type Session } from "lucia";
import { cookies } from "next/headers";
import { cache } from "react";
//@ts-ignore
const adapter = new DrizzleSQLiteAdapter(db, sessions, users);
export const lucia = new Lucia(adapter, {
sessionCookie: {
expires: false,
attributes: {
secure: process.env.NODE_ENV === "production",
secure: env.RUNTIME_ENVIRONMENT === "prod",
},
},
getUserAttributes: (attributes) => {

3
packages/reservation-platform/src/server/auth/oauth.ts Executable file → Normal file
View File

@@ -1,6 +1,7 @@
import { env } from "@/utils/env";
import { GitHub } from "arctic";
export const github = new GitHub(process.env.OAUTH_CLIENT_ID as string, process.env.OAUTH_CLIENT_SECRET as string, {
export const github = new GitHub(env.OAUTH.CLIENT_ID, env.OAUTH.CLIENT_SECRET, {
enterpriseDomain: "https://git.i.mercedes-benz.com",
});

View File

9
packages/reservation-platform/src/server/db/index.ts Executable file → Normal file
View File

@@ -1,8 +1,7 @@
import { env } from "@/utils/env";
import Database from "better-sqlite3";
import { drizzle } from "drizzle-orm/better-sqlite3";
import * as schema from "@/server/db/schema";
import { createClient } from "@libsql/client";
import { drizzle } from "drizzle-orm/libsql";
const sqlite = createClient({
url: "file:./db/sqlite.db",
});
const sqlite = new Database(env.DB_PATH);
export const db = drizzle(sqlite, { schema });

2
packages/reservation-platform/src/server/db/migrate.ts Executable file → Normal file
View File

@@ -1,4 +1,4 @@
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
import { db } from "@/server/db";
import { migrate } from "drizzle-orm/libsql/migrator";
migrate(db, { migrationsFolder: "./drizzle" });

0
packages/reservation-platform/src/server/db/schema.ts Executable file → Normal file
View File