From 82c06a487a292e71f8601af343479b7ce88991c2 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Thu, 29 Jan 2026 22:42:59 -0600 Subject: [PATCH] Remove refresh-license-validity API endpoint and integrate enterprise backup cron job initialization: Deleted the cron endpoint for refreshing license validity and added the initialization of enterprise backup cron jobs in the server setup. Updated the enterprise cron job logic to filter users based on license key and enterprise feature status. --- .../api/cron/refresh-license-validity.ts | 47 ------------------- apps/dokploy/server/server.ts | 7 ++- packages/server/src/utils/crons/enterprise.ts | 28 ++++++----- 3 files changed, 23 insertions(+), 59 deletions(-) delete mode 100644 apps/dokploy/pages/api/cron/refresh-license-validity.ts diff --git a/apps/dokploy/pages/api/cron/refresh-license-validity.ts b/apps/dokploy/pages/api/cron/refresh-license-validity.ts deleted file mode 100644 index bd932ce71..000000000 --- a/apps/dokploy/pages/api/cron/refresh-license-validity.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; -import { refreshAllLicenseValidity } from "@/server/utils/enterprise"; - -/** - * Cron endpoint to refresh isValidEnterpriseLicense for all users with a license key. - * Call every 2 weeks (e.g. 0 0 1,15 * * for 1st and 15th, or via your hosting cron). - * - * Requires CRON_SECRET in Authorization header or query: ?secret=CRON_SECRET - */ -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - if (req.method !== "GET" && req.method !== "POST") { - return res.status(405).json({ error: "Method not allowed" }); - } - - const secret = - process.env.CRON_SECRET ?? process.env.LICENSE_CRON_SECRET; - if (!secret) { - return res.status(500).json({ - error: "CRON_SECRET or LICENSE_CRON_SECRET not configured", - }); - } - - const authHeader = req.headers.authorization; - const bearer = authHeader?.startsWith("Bearer ") - ? authHeader.slice(7) - : undefined; - const querySecret = typeof req.query.secret === "string" ? req.query.secret : undefined; - - if (bearer !== secret && querySecret !== secret) { - return res.status(401).json({ error: "Unauthorized" }); - } - - try { - const result = await refreshAllLicenseValidity(); - return res.status(200).json(result); - } catch (err) { - console.error("refresh-license-validity:", err); - return res - .status(500) - .json({ - error: err instanceof Error ? err.message : "Refresh failed", - }); - } -} diff --git a/apps/dokploy/server/server.ts b/apps/dokploy/server/server.ts index e594538c6..dbd7c2638 100644 --- a/apps/dokploy/server/server.ts +++ b/apps/dokploy/server/server.ts @@ -6,6 +6,7 @@ import { IS_CLOUD, initCancelDeployments, initCronJobs, + initEnterpriseBackupCronJobs, initializeNetwork, initSchedules, initVolumeBackupsCronJobs, @@ -15,6 +16,7 @@ import { import { config } from "dotenv"; import next from "next"; import { migration } from "@/server/db/migration"; +import packageInfo from "../package.json"; import { setupDockerContainerLogsWebSocketServer } from "./wss/docker-container-logs"; import { setupDockerContainerTerminalWebSocketServer } from "./wss/docker-container-terminal"; import { setupDockerStatsMonitoringSocketServer } from "./wss/docker-stats"; @@ -33,13 +35,14 @@ if (process.env.NODE_ENV === "production" && !IS_CLOUD) { setupDirectories(); createDefaultTraefikConfig(); createDefaultServerTraefikConfig(); - console.log("✅ Critical initialization complete"); + console.log("✅ initialization complete"); } const app = next({ dev, turbopack: process.env.TURBOPACK === "1" }); const handle = app.getRequestHandler(); void app.prepare().then(async () => { try { + console.log("Running DokployVersion: ", packageInfo.version); const server = http.createServer((req, res) => { handle(req, res); }); @@ -71,6 +74,8 @@ void app.prepare().then(async () => { server.listen(PORT, HOST); console.log(`Server Started on: http://${HOST}:${PORT}`); + await initEnterpriseBackupCronJobs(); + if (!IS_CLOUD) { console.log("Starting Deployment Worker"); const { deploymentWorker } = await import("./queues/deployments-queue"); diff --git a/packages/server/src/utils/crons/enterprise.ts b/packages/server/src/utils/crons/enterprise.ts index a7693eccd..8e915b35f 100644 --- a/packages/server/src/utils/crons/enterprise.ts +++ b/packages/server/src/utils/crons/enterprise.ts @@ -1,22 +1,28 @@ -import { member } from "@dokploy/server/db/schema"; import { getPublicIpWithFallback } from "@dokploy/server/wss/utils"; -import { eq } from "drizzle-orm"; +import { and, eq, isNotNull } from "drizzle-orm"; import { scheduleJob } from "node-schedule"; import { db } from "../../db/index"; import { user as userSchema } from "../../db/schema/user"; export const initEnterpriseBackupCronJobs = async () => { - console.log("Setting up enterprise backup cron jobs...."); - - const admins = await db.query.member.findMany({ - where: eq(member.role, "owner"), - with: { - user: true, - }, + const users = await db.query.user.findMany({ + where: and( + isNotNull(userSchema.licenseKey), + isNotNull(userSchema.enableEnterpriseFeatures), + eq(userSchema.isValidEnterpriseLicense, true), + ), }); - for (const admin of admins) { - const { user } = admin; + if (users.length === 0) { + return; + } + + console.log( + "Setting up enterprise backup cron jobs for users....", + users.length, + ); + + for (const user of users) { if (user.isValidEnterpriseLicense) { scheduleJob(`enterprise-backup-${user.id}`, "0 0 */14 * *", async () => { try {