generated from Dicken/dickendock
Reset-Button, Service-Reorder, Port/HTTPS-Spalten, Healthcheck in Sidebar, Kategorien-Sync
This commit is contained in:
34
apps/backend/src/routes/reset.ts
Normal file
34
apps/backend/src/routes/reset.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import * as deviceRepo from "../db/repositories/devices.js";
|
||||
import * as logRepo from "../db/repositories/logs.js";
|
||||
|
||||
/**
|
||||
* Löscht ALLE Geräte und (per FK-Cascade) alle zugehörigen Dienste.
|
||||
* Kategorien und Logs bleiben unangetastet.
|
||||
*
|
||||
* Erfordert { confirm: true } im Body – zusätzlich zur Bestätigung im
|
||||
* Frontend eine zweite Sicherung gegen versehentliche Aufrufe (z. B. per
|
||||
* Skript oder Browser-Erweiterung).
|
||||
*/
|
||||
export async function resetRoutes(app: FastifyInstance): Promise<void> {
|
||||
app.post("/api/reset", async (request, reply) => {
|
||||
const body = request.body as { confirm?: boolean } | undefined;
|
||||
|
||||
if (body?.confirm !== true) {
|
||||
return reply.code(400).send({
|
||||
error: "Bestätigung erforderlich. Bitte { \"confirm\": true } im Body senden.",
|
||||
});
|
||||
}
|
||||
|
||||
const deviceCount = deviceRepo.listDevices().length;
|
||||
const deletedCount = deviceRepo.deleteAllDevices();
|
||||
|
||||
logRepo.logScan({
|
||||
type: "device",
|
||||
level: "info",
|
||||
message: `Reset: ${deletedCount} Gerät(e) und alle zugehörigen Dienste gelöscht`,
|
||||
});
|
||||
|
||||
return { deletedDevices: deletedCount, previousDeviceCount: deviceCount };
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import * as deviceRepo from "../db/repositories/devices.js";
|
||||
import * as serviceRepo from "../db/repositories/services.js";
|
||||
import * as categoryRepo from "../db/repositories/categories.js";
|
||||
import * as logRepo from "../db/repositories/logs.js";
|
||||
import { scanDeviceServices } from "../scanner/networkScanner.js";
|
||||
import { fetchFritzBoxHosts } from "../scanner/fritzbox.js";
|
||||
@@ -22,6 +23,13 @@ export async function scanRoutes(app: FastifyInstance): Promise<void> {
|
||||
try {
|
||||
const discovered = await scanDeviceServices(device);
|
||||
|
||||
// Jede erkannte Kategorie auch in der categories-Tabelle anlegen, damit
|
||||
// sie unter Admin -> Kategorien auftaucht und dort umbenannt/sortiert
|
||||
// werden kann (services.category ist reiner Freitext, kein Fremdschlüssel).
|
||||
for (const category of new Set(discovered.map((d) => d.category).filter((c): c is string => !!c))) {
|
||||
categoryRepo.ensureCategory(category);
|
||||
}
|
||||
|
||||
const results = discovered.map((found) =>
|
||||
serviceRepo.upsertServiceFromScan({
|
||||
deviceId: device.id,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import { ServiceCreateSchema, ServiceUpdateSchema } from "@launchpad/shared";
|
||||
import { ServiceCreateSchema, ServiceReorderSchema, ServiceUpdateSchema } from "@launchpad/shared";
|
||||
import * as deviceRepo from "../db/repositories/devices.js";
|
||||
import * as serviceRepo from "../db/repositories/services.js";
|
||||
|
||||
@@ -43,6 +43,15 @@ export async function serviceRoutes(app: FastifyInstance): Promise<void> {
|
||||
return reply.code(201).send(service);
|
||||
});
|
||||
|
||||
// Muss vor der /:id-Route stehen, damit "reorder" nicht als ID interpretiert wird.
|
||||
app.patch("/api/services/reorder", async (request, reply) => {
|
||||
const parsed = ServiceReorderSchema.safeParse(request.body);
|
||||
if (!parsed.success) {
|
||||
return reply.code(400).send({ error: "Ungültige Eingabe", issues: parsed.error.issues });
|
||||
}
|
||||
return serviceRepo.reorderServices(parsed.data);
|
||||
});
|
||||
|
||||
app.patch("/api/services/:id", async (request, reply) => {
|
||||
const { id } = request.params as { id: string };
|
||||
const parsed = ServiceUpdateSchema.safeParse(request.body);
|
||||
|
||||
Reference in New Issue
Block a user