Таблица audit_log, recordAudit на CRUD, GET /api/v1/audit и dual-write source_app=cfdm. Co-authored-by: Cursor <cursoragent@cursor.com>
106 lines
3.4 KiB
TypeScript
106 lines
3.4 KiB
TypeScript
import type { FastifyInstance } from "fastify";
|
|
import { bulkUpdateDomainsSchema, updateDomainSchema } from "@cfdm/shared";
|
|
import { z } from "zod";
|
|
import * as domainService from "../services/domain-service.js";
|
|
import { recordAudit } from "../lib/audit.js";
|
|
|
|
export async function domainRoutes(app: FastifyInstance) {
|
|
const createSchema = z.object({
|
|
zone_name: z.string(),
|
|
group_id: z.number().nullable().optional(),
|
|
});
|
|
|
|
app.get("/domains", async (request) => {
|
|
const query = request.query as { group_id?: string };
|
|
const groupId = query.group_id ? Number(query.group_id) : undefined;
|
|
return domainService.listDomains(request.server.db, groupId);
|
|
});
|
|
|
|
app.post("/domains", async (request) => {
|
|
const body = createSchema.parse(request.body);
|
|
const domain = await domainService.createDomain(
|
|
request.server.db,
|
|
request.server.cf,
|
|
body.group_id ?? null,
|
|
body.zone_name,
|
|
);
|
|
recordAudit(request.server, request, {
|
|
action: "domain.create",
|
|
targetType: "app_resource",
|
|
targetId: String(domain.id),
|
|
summary: `Добавлен домен ${domain.zone_name}`,
|
|
details: { zone_name: domain.zone_name, group_id: domain.group_id },
|
|
});
|
|
return domain;
|
|
});
|
|
|
|
app.post("/domains/bulk", async (request) => {
|
|
const body = bulkUpdateDomainsSchema.parse(request.body);
|
|
const updated = domainService.bulkUpdateDomains(
|
|
request.server.db,
|
|
body.ids,
|
|
{
|
|
group_id: body.group_id,
|
|
environment: body.environment,
|
|
tags_add: body.tags_add,
|
|
},
|
|
);
|
|
return { updated };
|
|
});
|
|
|
|
app.get("/domains/:id", async (request) => {
|
|
const { id } = request.params as { id: string };
|
|
return domainService.getDomain(request.server.db, Number(id));
|
|
});
|
|
|
|
app.patch("/domains/:id", async (request) => {
|
|
const { id } = request.params as { id: string };
|
|
const body = updateDomainSchema.parse(request.body);
|
|
const domain = domainService.updateDomain(request.server.db, Number(id), body);
|
|
recordAudit(request.server, request, {
|
|
action: "domain.update",
|
|
targetType: "app_resource",
|
|
targetId: String(domain.id),
|
|
summary: `Обновлён домен ${domain.zone_name}`,
|
|
details: body,
|
|
});
|
|
return domain;
|
|
});
|
|
|
|
app.delete("/domains/:id", async (request) => {
|
|
const { id } = request.params as { id: string };
|
|
const domain = domainService.getDomain(request.server.db, Number(id));
|
|
domainService.deleteDomain(request.server.db, Number(id));
|
|
recordAudit(request.server, request, {
|
|
action: "domain.delete",
|
|
severity: "warning",
|
|
targetType: "app_resource",
|
|
targetId: String(id),
|
|
summary: `Удалён домен ${domain.zone_name}`,
|
|
details: { zone_name: domain.zone_name },
|
|
});
|
|
return { deleted: true };
|
|
});
|
|
|
|
app.post("/domains/:id/import", async (request) => {
|
|
const { id } = request.params as { id: string };
|
|
const imported = await domainService.importZoneRecords(
|
|
request.server.db,
|
|
request.server.cf,
|
|
Number(id),
|
|
);
|
|
return { imported };
|
|
});
|
|
|
|
app.put("/domains/:id/services", async (request) => {
|
|
const { id } = request.params as { id: string };
|
|
const body = z.object({ service_ids: z.array(z.number()) }).parse(request.body);
|
|
const serviceIds = await domainService.setDomainServices(
|
|
request.server.db,
|
|
Number(id),
|
|
body.service_ids,
|
|
);
|
|
return { service_ids: serviceIds };
|
|
});
|
|
}
|