33 lines
2.1 KiB
TypeScript
33 lines
2.1 KiB
TypeScript
import { randomUUID } from "node:crypto"
|
|
import type { CertificateIssueRequest } from "@mmapp/contracts/certificates"
|
|
import { parseJsonArray } from "../db/json.js"
|
|
|
|
export type IssueRecordInput = { id: string; serverId: string; certName: string; domainNames: string[]; keyType: string; trustStore: string; source: "manual" }
|
|
type ExistingIssue = { serverId: number | string; certName: string; domainNames: unknown; keyType: string; trustStore: string; source: string }
|
|
export class IssueRequestError extends Error {
|
|
constructor(message: string, readonly status: number) { super(message) }
|
|
}
|
|
|
|
export async function acceptCertificateIssueRequest(input: CertificateIssueRequest, deps: {
|
|
getServer: (id: string) => Promise<unknown | null>
|
|
getJob: (id: string) => Promise<ExistingIssue | null>
|
|
createJob: (row: IssueRecordInput) => Promise<boolean>
|
|
queue: (id: string) => void
|
|
}) {
|
|
const id = input.requestId ?? randomUUID()
|
|
const row: IssueRecordInput = { id, serverId: String(input.serverId), certName: input.certName, domainNames: input.domainNames, keyType: input.keyType ?? "rsa2048", trustStore: (input.trustStore ?? ["www", "api"]).join(","), source: "manual" }
|
|
const matches = (existing: ExistingIssue) => String(existing.serverId) === row.serverId && existing.certName === row.certName && JSON.stringify(parseJsonArray(existing.domainNames)) === JSON.stringify(row.domainNames) && existing.keyType === row.keyType && existing.trustStore === row.trustStore && existing.source === "manual"
|
|
const previous = await deps.getJob(id)
|
|
if (previous) {
|
|
if (!matches(previous)) throw new IssueRequestError("requestId уже относится к другому выпуску", 409)
|
|
return { jobId: id }
|
|
}
|
|
if (!await deps.getServer(row.serverId)) throw new IssueRequestError("Сервер не найден", 404)
|
|
const created = await deps.createJob(row)
|
|
if (!created) {
|
|
const existing = await deps.getJob(id)
|
|
if (!existing || !matches(existing)) throw new IssueRequestError("requestId уже относится к другому выпуску", 409)
|
|
} else deps.queue(id)
|
|
return { jobId: id }
|
|
}
|