diff --git a/server/auth/actions.ts b/server/auth/actions.ts index 5ae98f965..89ccd7e37 100644 --- a/server/auth/actions.ts +++ b/server/auth/actions.ts @@ -154,10 +154,7 @@ export enum ActionsEnum { createHealthCheck = "createHealthCheck", updateHealthCheck = "updateHealthCheck", deleteHealthCheck = "deleteHealthCheck", - listHealthChecks = "listHealthChecks", - triggerSiteAlert = "triggerSiteAlert", - triggerResourceAlert = "triggerResourceAlert", - triggerHealthCheckAlert = "triggerHealthCheckAlert" + listHealthChecks = "listHealthChecks" } export async function checkUserActionPermission( diff --git a/server/private/lib/acmeCertSync.ts b/server/private/lib/acmeCertSync.ts index f5dfdeb12..a9e818986 100644 --- a/server/private/lib/acmeCertSync.ts +++ b/server/private/lib/acmeCertSync.ts @@ -50,7 +50,7 @@ interface AcmeJson { }; } -async function pushCertUpdateToAffectedNewts( +export async function pushCertUpdateToAffectedNewts( domain: string, domainId: string | null, oldCertPem: string | null, diff --git a/server/private/routers/certificates/index.ts b/server/private/routers/certificates/index.ts index 1ced04c31..18b942d5c 100644 --- a/server/private/routers/certificates/index.ts +++ b/server/private/routers/certificates/index.ts @@ -13,3 +13,4 @@ export * from "./getCertificate"; export * from "./restartCertificate"; +export * from "./syncCertToNewts"; diff --git a/server/private/routers/certificates/syncCertToNewts.ts b/server/private/routers/certificates/syncCertToNewts.ts new file mode 100644 index 000000000..ac6089acb --- /dev/null +++ b/server/private/routers/certificates/syncCertToNewts.ts @@ -0,0 +1,68 @@ +/* + * This file is part of a proprietary work. + * + * Copyright (c) 2025-2026 Fossorial, Inc. + * All rights reserved. + * + * This file is licensed under the Fossorial Commercial License. + * You may not use this file except in compliance with the License. + * Unauthorized use, copying, modification, or distribution is strictly prohibited. + * + * This file is not licensed under the AGPLv3. + */ + +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import { pushCertUpdateToAffectedNewts } from "#private/lib/acmeCertSync"; +import logger from "@server/logger"; +import HttpCode from "@server/types/HttpCode"; +import createHttpError from "http-errors"; +import { fromError } from "zod-validation-error"; + +const bodySchema = z.object({ + domain: z.string().min(1), + domainId: z.string().nullable().optional().default(null) +}); + +export async function syncCertToNewts( + req: Request, + res: Response, + next: NextFunction +): Promise { + const parsed = bodySchema.safeParse(req.body); + if (!parsed.success) { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + fromError(parsed.error).toString() + ) + ); + } + + const { domain, domainId } = parsed.data; + + logger.debug( + `syncCertToNewts: received request to push cert update for domain "${domain}" (domainId: ${domainId ?? "none"})` + ); + + try { + await pushCertUpdateToAffectedNewts(domain, domainId, null, null); + + res.status(HttpCode.OK).json({ + data: null, + success: true, + error: false, + message: `Certificate update pushed to affected newts for domain "${domain}"` + }); + } catch (err) { + logger.error( + `syncCertToNewts: error pushing cert update for domain "${domain}": ${err}` + ); + return next( + createHttpError( + HttpCode.INTERNAL_SERVER_ERROR, + "Failed to push certificate update to affected newts" + ) + ); + } +} \ No newline at end of file diff --git a/server/private/routers/integration.ts b/server/private/routers/integration.ts index ed97b3751..d5dac01e1 100644 --- a/server/private/routers/integration.ts +++ b/server/private/routers/integration.ts @@ -15,6 +15,7 @@ import * as orgIdp from "#private/routers/orgIdp"; import * as org from "#private/routers/org"; import * as logs from "#private/routers/auditLogs"; import * as alertEvents from "#private/routers/alertEvents"; +import * as certificates from "#private/routers/certificates"; import { verifyApiKeyHasAction, @@ -37,30 +38,36 @@ import { } from "@server/routers/integration"; import { logActionAudit } from "#private/middlewares"; import { tierMatrix } from "@server/lib/billing/tierMatrix"; +import { build } from "@server/build"; export const unauthenticated = ua; export const authenticated = a; -authenticated.post( - "/org/:orgId/site/:siteId/trigger-alert", - verifyApiKeyIsRoot, - verifyApiKeyHasAction(ActionsEnum.triggerSiteAlert), - alertEvents.triggerSiteAlert -); +if (build == "saas") { + authenticated.post( + "/org/:orgId/site/:siteId/trigger-alert", + verifyApiKeyIsRoot, + alertEvents.triggerSiteAlert + ); -authenticated.post( - "/org/:orgId/resource/:resourceId/trigger-alert", - verifyApiKeyIsRoot, - verifyApiKeyHasAction(ActionsEnum.triggerResourceAlert), - alertEvents.triggerResourceAlert -); + authenticated.post( + "/org/:orgId/resource/:resourceId/trigger-alert", + verifyApiKeyIsRoot, + alertEvents.triggerResourceAlert + ); -authenticated.post( - "/org/:orgId/health-check/:healthCheckId/trigger-alert", - verifyApiKeyIsRoot, - verifyApiKeyHasAction(ActionsEnum.triggerHealthCheckAlert), - alertEvents.triggerHealthCheckAlert -); + authenticated.post( + "/org/:orgId/health-check/:healthCheckId/trigger-alert", + verifyApiKeyIsRoot, + alertEvents.triggerHealthCheckAlert + ); + + authenticated.post( + "/cert/sync-to-newts", + verifyApiKeyIsRoot, + certificates.syncCertToNewts + ); +} authenticated.post( `/org/:orgId/send-usage-notification`,