mirror of
https://github.com/LukeHagar/dokploy.git
synced 2025-12-10 04:19:48 +00:00
refactor(cloud): add api key for autentication between servers
This commit is contained in:
@@ -7,7 +7,6 @@ import { createClient } from "redis";
|
|||||||
import { logger } from "./logger";
|
import { logger } from "./logger";
|
||||||
import { type DeployJob, deployJobSchema } from "./schema";
|
import { type DeployJob, deployJobSchema } from "./schema";
|
||||||
import { deploy } from "./utils";
|
import { deploy } from "./utils";
|
||||||
import { validateBearerTokenAPI } from "@dokploy/server";
|
|
||||||
|
|
||||||
const app = new Hono();
|
const app = new Hono();
|
||||||
const redisClient = createClient({
|
const redisClient = createClient({
|
||||||
@@ -15,17 +14,12 @@ const redisClient = createClient({
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.use(async (c, next) => {
|
app.use(async (c, next) => {
|
||||||
const authHeader = c.req.header("authorization");
|
const authHeader = c.req.header("X-API-Key");
|
||||||
|
|
||||||
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
if (process.env.API_KEY !== authHeader) {
|
||||||
return c.json({ message: "Authorization header missing" }, 401);
|
return c.json({ message: "Invalid API Key" }, 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await validateBearerTokenAPI(authHeader);
|
|
||||||
|
|
||||||
if (!result.user || !result.session) {
|
|
||||||
return c.json({ message: "Invalid session" }, 403);
|
|
||||||
}
|
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
|
|
||||||
if (IS_CLOUD && application.serverId) {
|
if (IS_CLOUD && application.serverId) {
|
||||||
jobData.serverId = application.serverId;
|
jobData.serverId = application.serverId;
|
||||||
await deploy(jobData, ctx.session.id);
|
await deploy(jobData);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
await myQueue.add(
|
await myQueue.add(
|
||||||
@@ -482,7 +482,7 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
};
|
};
|
||||||
if (IS_CLOUD && application.serverId) {
|
if (IS_CLOUD && application.serverId) {
|
||||||
jobData.serverId = application.serverId;
|
jobData.serverId = application.serverId;
|
||||||
await deploy(jobData, ctx.session.id);
|
await deploy(jobData);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -571,7 +571,7 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
};
|
};
|
||||||
if (IS_CLOUD && app.serverId) {
|
if (IS_CLOUD && app.serverId) {
|
||||||
jobData.serverId = app.serverId;
|
jobData.serverId = app.serverId;
|
||||||
await deploy(jobData, ctx.session.id);
|
await deploy(jobData);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ import {
|
|||||||
createBackup,
|
createBackup,
|
||||||
findBackupById,
|
findBackupById,
|
||||||
findMariadbByBackupId,
|
findMariadbByBackupId,
|
||||||
|
findMariadbById,
|
||||||
findMongoByBackupId,
|
findMongoByBackupId,
|
||||||
|
findMongoById,
|
||||||
findMySqlByBackupId,
|
findMySqlByBackupId,
|
||||||
|
findMySqlById,
|
||||||
findPostgresByBackupId,
|
findPostgresByBackupId,
|
||||||
|
findPostgresById,
|
||||||
removeBackupById,
|
removeBackupById,
|
||||||
removeScheduleBackup,
|
removeScheduleBackup,
|
||||||
runMariadbBackup,
|
runMariadbBackup,
|
||||||
@@ -36,14 +40,11 @@ export const backupRouter = createTRPCRouter({
|
|||||||
const backup = await findBackupById(newBackup.backupId);
|
const backup = await findBackupById(newBackup.backupId);
|
||||||
|
|
||||||
if (IS_CLOUD && backup.enabled) {
|
if (IS_CLOUD && backup.enabled) {
|
||||||
await schedule(
|
await schedule({
|
||||||
{
|
|
||||||
cronSchedule: backup.schedule,
|
cronSchedule: backup.schedule,
|
||||||
backupId: backup.backupId,
|
backupId: backup.backupId,
|
||||||
type: "backup",
|
type: "backup",
|
||||||
},
|
});
|
||||||
ctx.session.id,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
if (backup.enabled) {
|
if (backup.enabled) {
|
||||||
scheduleBackup(backup);
|
scheduleBackup(backup);
|
||||||
@@ -57,8 +58,11 @@ export const backupRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
one: protectedProcedure.input(apiFindOneBackup).query(async ({ input }) => {
|
one: protectedProcedure
|
||||||
|
.input(apiFindOneBackup)
|
||||||
|
.query(async ({ input, ctx }) => {
|
||||||
const backup = await findBackupById(input.backupId);
|
const backup = await findBackupById(input.backupId);
|
||||||
|
|
||||||
return backup;
|
return backup;
|
||||||
}),
|
}),
|
||||||
update: protectedProcedure
|
update: protectedProcedure
|
||||||
@@ -70,23 +74,17 @@ export const backupRouter = createTRPCRouter({
|
|||||||
|
|
||||||
if (IS_CLOUD) {
|
if (IS_CLOUD) {
|
||||||
if (backup.enabled) {
|
if (backup.enabled) {
|
||||||
await updateJob(
|
await updateJob({
|
||||||
{
|
|
||||||
cronSchedule: backup.schedule,
|
cronSchedule: backup.schedule,
|
||||||
backupId: backup.backupId,
|
backupId: backup.backupId,
|
||||||
type: "backup",
|
type: "backup",
|
||||||
},
|
});
|
||||||
ctx.session.id,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
await removeJob(
|
await removeJob({
|
||||||
{
|
|
||||||
cronSchedule: backup.schedule,
|
cronSchedule: backup.schedule,
|
||||||
backupId: backup.backupId,
|
backupId: backup.backupId,
|
||||||
type: "backup",
|
type: "backup",
|
||||||
},
|
});
|
||||||
ctx.session.id,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (backup.enabled) {
|
if (backup.enabled) {
|
||||||
@@ -109,14 +107,11 @@ export const backupRouter = createTRPCRouter({
|
|||||||
try {
|
try {
|
||||||
const value = await removeBackupById(input.backupId);
|
const value = await removeBackupById(input.backupId);
|
||||||
if (IS_CLOUD && value) {
|
if (IS_CLOUD && value) {
|
||||||
removeJob(
|
removeJob({
|
||||||
{
|
|
||||||
backupId: input.backupId,
|
backupId: input.backupId,
|
||||||
cronSchedule: value.schedule,
|
cronSchedule: value.schedule,
|
||||||
type: "backup",
|
type: "backup",
|
||||||
},
|
});
|
||||||
ctx.session.id,
|
|
||||||
);
|
|
||||||
} else if (!IS_CLOUD) {
|
} else if (!IS_CLOUD) {
|
||||||
removeScheduleBackup(input.backupId);
|
removeScheduleBackup(input.backupId);
|
||||||
}
|
}
|
||||||
@@ -196,3 +191,26 @@ export const backupRouter = createTRPCRouter({
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// export const getAdminId = async (backupId: string) => {
|
||||||
|
// const backup = await findBackupById(backupId);
|
||||||
|
|
||||||
|
// if (backup.databaseType === "postgres" && backup.postgresId) {
|
||||||
|
// const postgres = await findPostgresById(backup.postgresId);
|
||||||
|
// return postgres.project.adminId;
|
||||||
|
// }
|
||||||
|
// if (backup.databaseType === "mariadb" && backup.mariadbId) {
|
||||||
|
// const mariadb = await findMariadbById(backup.mariadbId);
|
||||||
|
// return mariadb.project.adminId;
|
||||||
|
// }
|
||||||
|
// if (backup.databaseType === "mysql" && backup.mysqlId) {
|
||||||
|
// const mysql = await findMySqlById(backup.mysqlId);
|
||||||
|
// return mysql.project.adminId;
|
||||||
|
// }
|
||||||
|
// if (backup.databaseType === "mongo" && backup.mongoId) {
|
||||||
|
// const mongo = await findMongoById(backup.mongoId);
|
||||||
|
// return mongo.project.adminId;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return null;
|
||||||
|
// };
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ export const composeRouter = createTRPCRouter({
|
|||||||
|
|
||||||
if (IS_CLOUD && compose.serverId) {
|
if (IS_CLOUD && compose.serverId) {
|
||||||
jobData.serverId = compose.serverId;
|
jobData.serverId = compose.serverId;
|
||||||
await deploy(jobData, ctx.session.id);
|
await deploy(jobData);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
await myQueue.add(
|
await myQueue.add(
|
||||||
@@ -288,7 +288,7 @@ export const composeRouter = createTRPCRouter({
|
|||||||
};
|
};
|
||||||
if (IS_CLOUD && compose.serverId) {
|
if (IS_CLOUD && compose.serverId) {
|
||||||
jobData.serverId = compose.serverId;
|
jobData.serverId = compose.serverId;
|
||||||
await deploy(jobData, ctx.session.id);
|
await deploy(jobData);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
await myQueue.add(
|
await myQueue.add(
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ type QueueJob =
|
|||||||
cronSchedule: string;
|
cronSchedule: string;
|
||||||
serverId: string;
|
serverId: string;
|
||||||
};
|
};
|
||||||
export const schedule = async (job: QueueJob, authSession: string) => {
|
export const schedule = async (job: QueueJob) => {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`${process.env.JOBS_URL}/create-backup`, {
|
const result = await fetch(`${process.env.JOBS_URL}/create-backup`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${authSession}`,
|
"X-API-Key": process.env.API_KEY || "NO-DEFINED",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(job),
|
body: JSON.stringify(job),
|
||||||
});
|
});
|
||||||
@@ -28,13 +28,13 @@ export const schedule = async (job: QueueJob, authSession: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeJob = async (job: QueueJob, authSession: string) => {
|
export const removeJob = async (job: QueueJob) => {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`${process.env.JOBS_URL}/remove-job`, {
|
const result = await fetch(`${process.env.JOBS_URL}/remove-job`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${authSession}`,
|
"X-API-Key": process.env.API_KEY || "NO-DEFINED",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(job),
|
body: JSON.stringify(job),
|
||||||
});
|
});
|
||||||
@@ -47,13 +47,13 @@ export const removeJob = async (job: QueueJob, authSession: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateJob = async (job: QueueJob, authSession: string) => {
|
export const updateJob = async (job: QueueJob) => {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`${process.env.JOBS_URL}/update-backup`, {
|
const result = await fetch(`${process.env.JOBS_URL}/update-backup`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${authSession}`,
|
"X-API-Key": process.env.API_KEY || "NO-DEFINED",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(job),
|
body: JSON.stringify(job),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import type { DeploymentJob } from "../queues/deployments-queue";
|
import type { DeploymentJob } from "../queues/deployments-queue";
|
||||||
|
|
||||||
export const deploy = async (jobData: DeploymentJob, sessionId: string) => {
|
export const deploy = async (jobData: DeploymentJob) => {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`${process.env.SERVER_URL}/deploy`, {
|
const result = await fetch(`${process.env.SERVER_URL}/deploy`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${sessionId}`,
|
"X-API-Key": process.env.API_KEY || "NO-DEFINED",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(jobData),
|
body: JSON.stringify(jobData),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,24 +6,18 @@ import { logger } from "./logger";
|
|||||||
import { cleanQueue, getJobRepeatable, removeJob, scheduleJob } from "./queue";
|
import { cleanQueue, getJobRepeatable, removeJob, scheduleJob } from "./queue";
|
||||||
import { jobQueueSchema } from "./schema";
|
import { jobQueueSchema } from "./schema";
|
||||||
import { firstWorker, secondWorker } from "./workers";
|
import { firstWorker, secondWorker } from "./workers";
|
||||||
import { validateBearerTokenAPI } from "@dokploy/server";
|
|
||||||
|
|
||||||
const app = new Hono();
|
const app = new Hono();
|
||||||
|
|
||||||
cleanQueue();
|
cleanQueue();
|
||||||
|
|
||||||
app.use(async (c, next) => {
|
app.use(async (c, next) => {
|
||||||
const authHeader = c.req.header("authorization");
|
const authHeader = c.req.header("X-API-Key");
|
||||||
|
|
||||||
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
if (process.env.API_KEY !== authHeader) {
|
||||||
return c.json({ message: "Authorization header missing" }, 401);
|
return c.json({ message: "Invalid API Key" }, 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await validateBearerTokenAPI(authHeader);
|
|
||||||
|
|
||||||
if (!result.user || !result.session) {
|
|
||||||
return c.json({ message: "Invalid session" }, 403);
|
|
||||||
}
|
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -55,6 +49,7 @@ app.post("/update-backup", zValidator("json", jobQueueSchema), async (c) => {
|
|||||||
logger.info("Job removed", result);
|
logger.info("Job removed", result);
|
||||||
}
|
}
|
||||||
scheduleJob(data);
|
scheduleJob(data);
|
||||||
|
logger.info("Backup updated successfully");
|
||||||
|
|
||||||
return c.json({ message: "Backup updated successfully" });
|
return c.json({ message: "Backup updated successfully" });
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user