KI-AGENT: Push Test im Admin Dashboard ergänzen
This commit is contained in:
@@ -6,6 +6,7 @@ import { db } from "../db/client.js";
|
||||
import { requireAdmin } from "../lib/auth.js";
|
||||
import { encryptSecret } from "../lib/crypto.js";
|
||||
import { createClientSecret, createPublicId, previewSecret } from "../lib/ids.js";
|
||||
import { deliverJob } from "../services/delivery.js";
|
||||
|
||||
const createInstanceSchema = z.object({
|
||||
name: z.string().min(2),
|
||||
@@ -21,6 +22,13 @@ const updateInstanceSchema = createInstanceSchema.partial().extend({
|
||||
status: z.enum(["active", "blocked", "disabled"]).optional(),
|
||||
});
|
||||
|
||||
const testPushSchema = z.object({
|
||||
deviceIds: z.array(z.string().min(1)).max(100).optional(),
|
||||
title: z.string().min(1).max(120).default("FEDEO Push-Test"),
|
||||
body: z.string().min(1).max(240).default("Diese Testnachricht wurde über das Push-Admin-Dashboard gesendet."),
|
||||
priority: z.enum(["normal", "high"]).default("high"),
|
||||
});
|
||||
|
||||
export async function adminRoutes(app: FastifyInstance): Promise<void> {
|
||||
app.addHook("preHandler", requireAdmin);
|
||||
|
||||
@@ -122,6 +130,72 @@ export async function adminRoutes(app: FastifyInstance): Promise<void> {
|
||||
return await db.select().from(deliveryJobs).where(eq(deliveryJobs.instanceId, params.id)).orderBy(desc(deliveryJobs.createdAt)).limit(100);
|
||||
});
|
||||
|
||||
app.post("/admin/instances/:id/test-push", async (request, reply) => {
|
||||
const params = z.object({ id: z.string().uuid() }).parse(request.params);
|
||||
const body = testPushSchema.parse(request.body || {});
|
||||
const [instance] = await db.select().from(pushInstances).where(eq(pushInstances.id, params.id)).limit(1);
|
||||
if (!instance) return reply.code(404).send({ error: "instance_not_found" });
|
||||
|
||||
const devices = await db
|
||||
.select()
|
||||
.from(pushDevices)
|
||||
.where(and(eq(pushDevices.instanceId, instance.id), eq(pushDevices.status, "active")));
|
||||
const requested = body.deviceIds?.length ? new Set(body.deviceIds) : null;
|
||||
const acceptedDevices = devices
|
||||
.map((device) => device.centralDeviceId)
|
||||
.filter((centralDeviceId) => !requested || requested.has(centralDeviceId));
|
||||
|
||||
if (!acceptedDevices.length) {
|
||||
return reply.code(400).send({ error: "no_active_devices", message: "Für diese Auswahl wurden keine aktiven Geräte gefunden." });
|
||||
}
|
||||
|
||||
const rejected = requested ? body.deviceIds!.length - acceptedDevices.length : 0;
|
||||
const [job] = await db.insert(deliveryJobs).values({
|
||||
deliveryJobId: createPublicId("job"),
|
||||
instanceId: instance.id,
|
||||
idempotencyKey: `admin-test:${instance.id}:${Date.now()}`,
|
||||
priority: body.priority,
|
||||
ttlSeconds: 600,
|
||||
collapseKey: "admin-test",
|
||||
acceptedCount: acceptedDevices.length,
|
||||
rejectedCount: rejected,
|
||||
status: "processing",
|
||||
}).returning();
|
||||
|
||||
await deliverJob(job, acceptedDevices, {
|
||||
priority: body.priority,
|
||||
ttlSeconds: 600,
|
||||
collapseKey: "admin-test",
|
||||
notification: {
|
||||
title: body.title,
|
||||
body: body.body,
|
||||
},
|
||||
data: {
|
||||
type: "admin.test_push",
|
||||
deliveryJobId: job.deliveryJobId,
|
||||
instanceId: instance.instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
await audit("admin", "instance.test_push.sent", instance.id, {
|
||||
deliveryJobId: job.deliveryJobId,
|
||||
accepted: acceptedDevices.length,
|
||||
rejected,
|
||||
});
|
||||
|
||||
const [updatedJob] = await db.select().from(deliveryJobs).where(eq(deliveryJobs.id, job.id)).limit(1);
|
||||
return reply.code(202).send({
|
||||
deliveryJobId: job.deliveryJobId,
|
||||
accepted: acceptedDevices.length,
|
||||
rejected,
|
||||
status: updatedJob?.status || "processing",
|
||||
sent: updatedJob?.sentCount || 0,
|
||||
failed: updatedJob?.failedCount || 0,
|
||||
lastErrorCode: updatedJob?.lastErrorCode,
|
||||
lastErrorMessage: updatedJob?.lastErrorMessage,
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/admin/jobs", async () => {
|
||||
return await db.select({
|
||||
id: deliveryJobs.id,
|
||||
|
||||
Reference in New Issue
Block a user