Patchpass V1
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
import { fileRouter } from "../..";
|
||||
import { requireSession } from "../../lib/RouteAuth";
|
||||
import {
|
||||
createAgent,
|
||||
deleteAgent,
|
||||
listAgents,
|
||||
regenerateApiKey,
|
||||
setAgentDisabled,
|
||||
updateAgent,
|
||||
} from "../../lib/AgentService";
|
||||
import { recordAudit } from "../../lib/Audit";
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
function reply(ctr: any, result: { ok: boolean; status?: number; message?: string; data?: unknown }) {
|
||||
if (!result.ok) {
|
||||
return ctr.status(result.status ?? 400).print({ status: "FAILED", message: result.message });
|
||||
}
|
||||
return ctr.print({ status: "OK", data: (result as any).data });
|
||||
}
|
||||
|
||||
export = new fileRouter.Path("/")
|
||||
// List agents
|
||||
.http("GET", "/api/agents", (http) =>
|
||||
http.onRequest(async (ctr) => {
|
||||
const session = requireSession(ctr);
|
||||
if (!session) return;
|
||||
const agents = await listAgents(session.user);
|
||||
return ctr.print({ status: "OK", data: agents });
|
||||
}),
|
||||
)
|
||||
// Create agent
|
||||
.http("POST", "/api/agents", (http) =>
|
||||
http
|
||||
.ratelimit((limit) => limit.hits(10).window(60000).penalty(2000))
|
||||
.onRequest(async (ctr) => {
|
||||
const session = requireSession(ctr);
|
||||
if (!session) return;
|
||||
const [data, error] = await ctr.bindBody((z) =>
|
||||
z.object({
|
||||
name: z.string().min(1).max(128),
|
||||
description: z.string().max(500).nullable().optional(),
|
||||
website: z.string().max(300).nullable().optional(),
|
||||
icon_url: z.string().max(1000).nullable().optional(),
|
||||
max_pending_requests: z.number().int().min(1).max(10).optional(),
|
||||
}),
|
||||
);
|
||||
if (!data) return ctr.status(ctr.$status.BAD_REQUEST).print(error.toString());
|
||||
const result = await createAgent(session.user, data);
|
||||
if (result.ok) {
|
||||
await recordAudit({
|
||||
actorId: session.user.id,
|
||||
action: "agent_created",
|
||||
targetType: "agent",
|
||||
targetId: String((result.data as any).id),
|
||||
});
|
||||
}
|
||||
return reply(ctr, result);
|
||||
}),
|
||||
)
|
||||
// Update agent
|
||||
.http("PATCH", "/api/agents/{id}", (http) =>
|
||||
http.onRequest(async (ctr) => {
|
||||
const session = requireSession(ctr);
|
||||
if (!session) return;
|
||||
const id = Number(ctr.params.get("id"));
|
||||
if (Number.isNaN(id)) {
|
||||
return ctr.status(ctr.$status.BAD_REQUEST).print({ status: "FAILED", message: "Invalid agent id" });
|
||||
}
|
||||
const [data, error] = await ctr.bindBody((z) =>
|
||||
z.object({
|
||||
name: z.string().min(1).max(128).optional(),
|
||||
description: z.string().max(500).nullable().optional(),
|
||||
website: z.string().max(300).nullable().optional(),
|
||||
icon_url: z.string().max(1000).nullable().optional(),
|
||||
max_pending_requests: z.number().int().min(1).max(10).optional(),
|
||||
}),
|
||||
);
|
||||
if (!data) return ctr.status(ctr.$status.BAD_REQUEST).print(error.toString());
|
||||
return reply(ctr, await updateAgent(session.user, id, data));
|
||||
}),
|
||||
)
|
||||
// Regenerate API key
|
||||
.http("POST", "/api/agents/{id}/regenerate-key", (http) =>
|
||||
http
|
||||
.ratelimit((limit) => limit.hits(10).window(60000).penalty(2000))
|
||||
.onRequest(async (ctr) => {
|
||||
const session = requireSession(ctr);
|
||||
if (!session) return;
|
||||
const id = Number(ctr.params.get("id"));
|
||||
if (Number.isNaN(id)) {
|
||||
return ctr.status(ctr.$status.BAD_REQUEST).print({ status: "FAILED", message: "Invalid agent id" });
|
||||
}
|
||||
const result = await regenerateApiKey(session.user, id);
|
||||
if (result.ok) {
|
||||
await recordAudit({
|
||||
actorId: session.user.id,
|
||||
action: "agent_key_regenerated",
|
||||
targetType: "agent",
|
||||
targetId: String(id),
|
||||
});
|
||||
}
|
||||
return reply(ctr, result);
|
||||
}),
|
||||
)
|
||||
// Enable / disable agent
|
||||
.http("POST", "/api/agents/{id}/disabled", (http) =>
|
||||
http.onRequest(async (ctr) => {
|
||||
const session = requireSession(ctr);
|
||||
if (!session) return;
|
||||
const id = Number(ctr.params.get("id"));
|
||||
if (Number.isNaN(id)) {
|
||||
return ctr.status(ctr.$status.BAD_REQUEST).print({ status: "FAILED", message: "Invalid agent id" });
|
||||
}
|
||||
const [data, error] = await ctr.bindBody((z) => z.object({ disabled: z.boolean() }));
|
||||
if (!data) return ctr.status(ctr.$status.BAD_REQUEST).print(error.toString());
|
||||
return reply(ctr, await setAgentDisabled(session.user, id, data.disabled));
|
||||
}),
|
||||
)
|
||||
// Delete agent
|
||||
.http("DELETE", "/api/agents/{id}", (http) =>
|
||||
http.onRequest(async (ctr) => {
|
||||
const session = requireSession(ctr);
|
||||
if (!session) return;
|
||||
const id = Number(ctr.params.get("id"));
|
||||
if (Number.isNaN(id)) {
|
||||
return ctr.status(ctr.$status.BAD_REQUEST).print({ status: "FAILED", message: "Invalid agent id" });
|
||||
}
|
||||
const result = await deleteAgent(session.user, id);
|
||||
if (result.ok) {
|
||||
await recordAudit({
|
||||
actorId: session.user.id,
|
||||
action: "agent_deleted",
|
||||
targetType: "agent",
|
||||
targetId: String(id),
|
||||
});
|
||||
}
|
||||
return reply(ctr, result);
|
||||
}),
|
||||
);
|
||||
Reference in New Issue
Block a user