refactor: remove unused auth service and clean up server-side code

This commit is contained in:
Mauricio Siu
2025-02-22 18:03:12 -06:00
parent 81a881b07e
commit 1a415b96c9
201 changed files with 434 additions and 1035 deletions

View File

@@ -1,4 +1,4 @@
import { relations, sql } from "drizzle-orm";
import { relations } from "drizzle-orm";
import {
boolean,
integer,

View File

@@ -12,7 +12,6 @@ import {
Tailwind,
Text,
} from "@react-email/components";
import * as React from "react";
export type TemplateProps = {
projectName: string;

View File

@@ -12,7 +12,6 @@ import {
Tailwind,
Text,
} from "@react-email/components";
import * as React from "react";
export type TemplateProps = {
projectName: string;

View File

@@ -10,7 +10,6 @@ import {
Tailwind,
Text,
} from "@react-email/components";
import * as React from "react";
export type TemplateProps = {
projectName: string;

View File

@@ -1,6 +1,5 @@
import {
Body,
Button,
Container,
Head,
Heading,
@@ -11,7 +10,6 @@ import {
Tailwind,
Text,
} from "@react-email/components";
import * as React from "react";
export type TemplateProps = {
message: string;

View File

@@ -10,7 +10,6 @@ import {
Tailwind,
Text,
} from "@react-email/components";
import * as React from "react";
export type TemplateProps = {
date: string;

View File

@@ -9,7 +9,6 @@ import {
Preview,
Text,
} from "@react-email/components";
import * as React from "react";
interface NotionMagicLinkEmailProps {
loginCode?: string;

View File

@@ -9,7 +9,6 @@ import {
Section,
Text,
} from "@react-email/components";
import * as React from "react";
interface PlaidVerifyIdentityEmailProps {
validationCode?: string;

View File

@@ -11,7 +11,6 @@ import {
Section,
Text,
} from "@react-email/components";
import * as React from "react";
const baseUrl = process.env.VERCEL_URL!;

View File

@@ -15,7 +15,6 @@ import {
Tailwind,
Text,
} from "@react-email/components";
import * as React from "react";
interface VercelInviteUserEmailProps {
username?: string;

View File

@@ -1,5 +1,4 @@
export * from "./auth/random-password";
// export * from "./db";
export * from "./services/admin";
export * from "./services/user";
export * from "./services/project";
@@ -28,7 +27,6 @@ export * from "./services/ssh-key";
export * from "./services/git-provider";
export * from "./services/bitbucket";
export * from "./services/github";
export * from "./services/auth";
export * from "./services/gitlab";
export * from "./services/server";
export * from "./services/application";

View File

@@ -10,7 +10,6 @@ import {
import { and, desc, eq } from "drizzle-orm";
import { db } from "../db";
import * as schema from "../db/schema";
import { ac } from "./permissions";
export const auth = betterAuth({
database: drizzleAdapter(db, {

View File

@@ -1,7 +1,5 @@
import { randomBytes } from "node:crypto";
import { db } from "@dokploy/server/db";
import {
account,
type apiCreateUserInvitation,
invitation,
member,
@@ -9,7 +7,6 @@ import {
users_temp,
} from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";
import * as bcrypt from "bcrypt";
import { eq } from "drizzle-orm";
import { IS_CLOUD } from "../constants";

View File

@@ -4,7 +4,6 @@ import {
type apiCreateApplication,
applications,
buildAppName,
cleanAppName,
} from "@dokploy/server/db/schema";
import { getAdvancedStats } from "@dokploy/server/monitoring/utils";
import {
@@ -28,7 +27,6 @@ import {
getCustomGitCloneCommand,
} from "@dokploy/server/utils/providers/git";
import {
authGithub,
cloneGithubRepository,
getGithubCloneCommand,
} from "@dokploy/server/utils/providers/github";
@@ -40,7 +38,7 @@ import { createTraefikConfig } from "@dokploy/server/utils/traefik/application";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import { encodeBase64 } from "../utils/docker/utils";
import { findAdminById, findUserById, getDokployUrl } from "./admin";
import { getDokployUrl } from "./admin";
import {
createDeployment,
createDeploymentPreview,
@@ -58,7 +56,6 @@ import {
updatePreviewDeployment,
} from "./preview-deployment";
import { validUniqueServerAppName } from "./project";
import { cleanupFullDocker } from "./settings";
export type Application = typeof applications.$inferSelect;
export const createApplication = async (

View File

@@ -1,212 +0,0 @@
import { randomBytes } from "node:crypto";
import { createOTP } from "@better-auth/utils/otp";
import { db } from "@dokploy/server/db";
import { users_temp } from "@dokploy/server/db/schema";
import { getPublicIpWithFallback } from "@dokploy/server/wss/utils";
import { TRPCError } from "@trpc/server";
import * as bcrypt from "bcrypt";
import { eq } from "drizzle-orm";
import encode from "hi-base32";
import { TOTP } from "otpauth";
import QRCode from "qrcode";
import { IS_CLOUD } from "../constants";
import { findUserById } from "./admin";
import type { User } from "./user";
export const findAuthById = async (authId: string) => {
const result = await db.query.users_temp.findFirst({
where: eq(users_temp.id, authId),
columns: {
createdAt: false,
updatedAt: false,
},
});
if (!result) {
throw new TRPCError({
code: "NOT_FOUND",
message: "Auth not found",
});
}
return result;
};
const generateBase32Secret = () => {
// Generamos 32 bytes (256 bits) para asegurar que tengamos suficiente longitud
const buffer = randomBytes(32);
// Convertimos directamente a hex para Better Auth
const hex = buffer.toString("hex");
// También necesitamos la versión base32 para el QR code
const base32 = encode.encode(buffer).replace(/=/g, "").substring(0, 32);
return {
hex,
base32,
};
};
export const generate2FASecret = () => {
const secret = "46JMUCG4NJ3CIU6LQAIVFWUW";
const totp = new TOTP({
issuer: "Dokploy",
label: "siumauricio@hotmail.com",
algorithm: "SHA1",
digits: 6,
secret: secret,
});
// Convertir los bytes del secreto a hex
const secretBytes = totp.secret.bytes;
const hexSecret = Buffer.from(secretBytes).toString("hex");
console.log("Secret bytes:", secretBytes);
console.log("Hex secret:", hexSecret);
return {
secret,
hexSecret,
totp,
};
};
export const verify2FA = async (auth: User, secret: string, pin: string) => {
const totp = new TOTP({
issuer: "Dokploy",
label: `${auth?.email}`,
algorithm: "SHA1",
digits: 6,
secret: secret,
period: 30,
});
const delta = totp.validate({ token: pin });
if (delta === null) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Invalid 2FA code",
});
}
return auth;
};
const convertBase32ToHex = (base32Secret: string) => {
try {
// Asegurarnos de que la longitud sea múltiplo de 8 agregando padding
let paddedSecret = base32Secret;
while (paddedSecret.length % 8 !== 0) {
paddedSecret += "=";
}
const bytes = encode.decode.asBytes(paddedSecret.toUpperCase());
let hex = Buffer.from(bytes).toString("hex");
// Asegurarnos de que el hex tenga al menos 32 caracteres (16 bytes)
while (hex.length < 32) {
hex += "0";
}
return hex;
} catch (error) {
console.error("Error converting base32 to hex:", error);
return base32Secret;
}
};
// Para probar
// const testSecret = "46JMUCG4NJ3CIU6LQAIVFWUW";
// console.log("Original:", testSecret);
// console.log("Converted:", convertBase32ToHex(testSecret));
// console.log(
// "Length in bytes:",
// Buffer.from(convertBase32ToHex(testSecret), "hex").length,
// );
// console.log(generate2FASecret().secret.secret);
// // Para probar
// const testResult = generate2FASecret();
// console.log("\nResultados:");
// console.log("Original base32:", testResult.secret);
// console.log("Hex convertido:", testResult.hexSecret);
// console.log(
// "Longitud en bytes:",
// Buffer.from(testResult.hexSecret, "hex").length,
// );
export const symmetricDecrypt = async ({ key, data }) => {
const keyAsBytes = await createHash("SHA-256").digest(key);
const dataAsBytes = hexToBytes(data);
const chacha = managedNonce(xchacha20poly1305)(new Uint8Array(keyAsBytes));
return new TextDecoder().decode(chacha.decrypt(dataAsBytes));
};
// export const migrateExistingSecret = async (
// existingBase32Secret: string,
// encryptionKey: string,
// ) => {
// try {
// // 1. Primero asegurarnos que el secreto base32 tenga el padding correcto
// let paddedSecret = existingBase32Secret;
// while (paddedSecret.length % 8 !== 0) {
// paddedSecret += "=";
// }
// // 2. Decodificar el base32 a bytes usando hi-base32
// const bytes = encode.decode.asBytes(paddedSecret.toUpperCase());
// // 3. Convertir los bytes a hex
// const hexSecret = Buffer.from(bytes).toString("hex");
// // 4. Encriptar el secreto hex usando Better Auth
// const encryptedSecret = await symmetricEncrypt({
// key: encryptionKey,
// data: hexSecret,
// });
// // 5. Crear TOTP con el secreto original para validación
// const originalTotp = new TOTP({
// issuer: "Dokploy",
// label: "migration-test",
// algorithm: "SHA1",
// digits: 6,
// secret: existingBase32Secret,
// });
// // 6. Generar un código de prueba con el secreto original
// const testCode = originalTotp.generate();
// // 7. Validar que el código funcione con el secreto original
// const isValid = originalTotp.validate({ token: testCode }) !== null;
// return {
// originalSecret: existingBase32Secret,
// hexSecret,
// encryptedSecret, // Este es el valor que debes guardar en la base de datos
// isValid,
// testCode,
// secretLength: hexSecret.length,
// };
// } catch (error: unknown) {
// const errorMessage =
// error instanceof Error ? error.message : "Unknown error";
// console.error("Error durante la migración:", errorMessage);
// throw new Error(`Error al migrar el secreto: ${errorMessage}`);
// }
// };
// // // Ejemplo de uso con el secreto de prueba
// // const testMigration = await migrateExistingSecret(
// // "46JMUCG4NJ3CIU6LQAIVFWUW",
// // process.env.BETTER_AUTH_SECRET || "your-encryption-key",
// // );
// // console.log("\nPrueba de migración:");
// // console.log("Secreto original (base32):", testMigration.originalSecret);
// // console.log("Secreto convertido (hex):", testMigration.hexSecret);
// // console.log("Secreto encriptado:", testMigration.encryptedSecret);
// // console.log("Longitud del secreto hex:", testMigration.secretLength);
// // console.log("¿Conversión válida?:", testMigration.isValid);
// // console.log("Código de prueba:", testMigration.testCode);
// const secret = "46JMUCG4NJ3CIU6LQAIVFWUW";
// const isValid = createOTP(secret, {
// digits: 6,
// period: 30,
// }).verify("123456");
// console.log(isValid.then((isValid) => console.log(isValid)));

View File

@@ -2,8 +2,6 @@ import { db } from "@dokploy/server/db";
import { type apiCreateBackup, backups } from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import { IS_CLOUD } from "../constants";
import { removeScheduleBackup, scheduleBackup } from "../utils/backups/utils";
export type Backup = typeof backups.$inferSelect;

View File

@@ -44,10 +44,9 @@ import {
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import { encodeBase64 } from "../utils/docker/utils";
import { findAdminById, findUserById, getDokployUrl } from "./admin";
import { getDokployUrl } from "./admin";
import { createDeploymentCompose, updateDeploymentStatus } from "./deployment";
import { validUniqueServerAppName } from "./project";
import { cleanupFullDocker } from "./settings";
export type Compose = typeof compose.$inferSelect;

View File

@@ -12,7 +12,7 @@ import {
import { removeDirectoryIfExistsContent } from "@dokploy/server/utils/filesystem/directory";
import { TRPCError } from "@trpc/server";
import { format } from "date-fns";
import { and, desc, eq, isNull } from "drizzle-orm";
import { desc, eq } from "drizzle-orm";
import {
type Application,
findApplicationById,
@@ -278,9 +278,11 @@ export const removeDeployment = async (deploymentId: string) => {
.returning();
return deployment[0];
} catch (error) {
const message =
error instanceof Error ? error.message : "Error creating the deployment";
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error deleting this deployment",
message,
});
}
};
@@ -535,9 +537,11 @@ export const createServerDeployment = async (
}
return deploymentCreate[0];
} catch (error) {
const message =
error instanceof Error ? error.message : "Error creating the deployment";
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error creating the deployment",
message,
});
}
};

View File

@@ -4,7 +4,7 @@ import { manageDomain } from "@dokploy/server/utils/traefik/domain";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import { type apiCreateDomain, domains } from "../db/schema";
import { findAdmin, findAdminById, findUserById } from "./admin";
import { findUserById } from "./admin";
import { findApplicationById } from "./application";
import { findServerById } from "./server";

View File

@@ -1,9 +1,7 @@
import { db } from "@dokploy/server/db";
import {
type apiCreateGitlab,
type bitbucket,
gitProvider,
type github,
gitlab,
} from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";

View File

@@ -4,7 +4,7 @@ import {
backups,
mariadb,
} from "@dokploy/server/db/schema";
import { buildAppName, cleanAppName } from "@dokploy/server/db/schema";
import { buildAppName } from "@dokploy/server/db/schema";
import { generatePassword } from "@dokploy/server/templates/utils";
import { buildMariadb } from "@dokploy/server/utils/databases/mariadb";
import { pullImage } from "@dokploy/server/utils/docker/utils";

View File

@@ -1,6 +1,6 @@
import { db } from "@dokploy/server/db";
import { type apiCreateMongo, backups, mongo } from "@dokploy/server/db/schema";
import { buildAppName, cleanAppName } from "@dokploy/server/db/schema";
import { buildAppName } from "@dokploy/server/db/schema";
import { generatePassword } from "@dokploy/server/templates/utils";
import { buildMongo } from "@dokploy/server/utils/databases/mongo";
import { pullImage } from "@dokploy/server/utils/docker/utils";

View File

@@ -123,8 +123,8 @@ export const updateMount = async (
mountId: string,
mountData: Partial<Mount>,
) => {
return await db.transaction(async (transaction) => {
const mount = await db
return await db.transaction(async (tx) => {
const mount = await tx
.update(mounts)
.set({
...mountData,

View File

@@ -4,7 +4,7 @@ import {
backups,
postgres,
} from "@dokploy/server/db/schema";
import { buildAppName, cleanAppName } from "@dokploy/server/db/schema";
import { buildAppName } from "@dokploy/server/db/schema";
import { generatePassword } from "@dokploy/server/templates/utils";
import { buildPostgres } from "@dokploy/server/utils/databases/postgres";
import { pullImage } from "@dokploy/server/utils/docker/utils";

View File

@@ -7,19 +7,15 @@ import {
} from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";
import { and, desc, eq } from "drizzle-orm";
import { slugify } from "../setup/server-setup";
import { generatePassword, generateRandomDomain } from "../templates/utils";
import { generatePassword } from "../templates/utils";
import { removeService } from "../utils/docker/utils";
import { removeDirectoryCode } from "../utils/filesystem/directory";
import { authGithub } from "../utils/providers/github";
import { removeTraefikConfig } from "../utils/traefik/application";
import { manageDomain } from "../utils/traefik/domain";
import { findAdminById, findUserById } from "./admin";
import { findUserById } from "./admin";
import { findApplicationById } from "./application";
import {
removeDeployments,
removeDeploymentsByPreviewDeploymentId,
} from "./deployment";
import { removeDeploymentsByPreviewDeploymentId } from "./deployment";
import { createDomain } from "./domain";
import { type Github, getIssueComment } from "./github";
@@ -111,9 +107,13 @@ export const removePreviewDeployment = async (previewDeploymentId: string) => {
}
return deployment[0];
} catch (error) {
const message =
error instanceof Error
? error.message
: "Error deleting this preview deployment";
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error deleting this preview deployment",
message,
});
}
};

View File

@@ -6,7 +6,7 @@ import {
updateRedirectMiddleware,
} from "@dokploy/server/utils/traefik/redirect";
import { TRPCError } from "@trpc/server";
import { desc, eq } from "drizzle-orm";
import { eq } from "drizzle-orm";
import type { z } from "zod";
import { findApplicationById } from "./application";
export type Redirect = typeof redirects.$inferSelect;
@@ -114,9 +114,11 @@ export const updateRedirectById = async (
return redirect;
} catch (error) {
const message =
error instanceof Error ? error.message : "Error updating this redirect";
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error updating this redirect",
message,
});
}
};

View File

@@ -1,6 +1,6 @@
import { db } from "@dokploy/server/db";
import { type apiCreateRedis, redis } from "@dokploy/server/db/schema";
import { buildAppName, cleanAppName } from "@dokploy/server/db/schema";
import { buildAppName } from "@dokploy/server/db/schema";
import { generatePassword } from "@dokploy/server/templates/utils";
import { buildRedis } from "@dokploy/server/utils/databases/redis";
import { pullImage } from "@dokploy/server/utils/docker/utils";

View File

@@ -112,9 +112,11 @@ export const updateRegistry = async (
return response;
} catch (error) {
const message =
error instanceof Error ? error.message : "Error updating this registry";
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error updating this registry",
message,
});
}
};

View File

@@ -76,9 +76,11 @@ export const deleteSecurityById = async (securityId: string) => {
await removeSecurityMiddleware(application, result);
return result;
} catch (error) {
const message =
error instanceof Error ? error.message : "Error removing this security";
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error removing this security",
message,
});
}
};
@@ -98,9 +100,11 @@ export const updateSecurityById = async (
return response[0];
} catch (error) {
const message =
error instanceof Error ? error.message : "Error updating this security";
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error updating this security",
message,
});
}
};

View File

@@ -5,7 +5,7 @@ import {
server,
} from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";
import { desc, eq } from "drizzle-orm";
import { eq } from "drizzle-orm";
export type Server = typeof server.$inferSelect;

View File

@@ -169,7 +169,6 @@ echo "$json_output"
const result = JSON.parse(stdout);
return result;
}
const items = readdirSync(dirPath, { withFileTypes: true });
const stack = [dirPath];
const result: TreeDataItem[] = [];

View File

@@ -1,38 +1,10 @@
import { db } from "@dokploy/server/db";
import { type users_temp, member } from "@dokploy/server/db/schema";
import { member, type users_temp } from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";
import { and, eq } from "drizzle-orm";
import { findUserById } from "./admin";
export type User = typeof users_temp.$inferSelect;
// export const findUserById = async (userId: string) => {
// // const userR = await db.query.user.findFirst({
// // where: eq(user.userId, userId),
// // });
// // if (!userR) {
// // throw new TRPCError({
// // code: "NOT_FOUND",
// // message: "User not found",
// // });
// // }
// // return user;
// };
export const findUserByAuthId = async (authId: string) => {
// const userR = await db.query.user.findFirst({
// where: eq(user.id, authId),
// with: {},
// });
// if (!userR) {
// throw new TRPCError({
// code: "NOT_FOUND",
// message: "User not found",
// });
// }
// return userR;
};
export const addNewProject = async (
userId: string,
projectId: string,

View File

@@ -1,7 +1,7 @@
import { findServerById } from "@dokploy/server/services/server";
import type { ContainerCreateOptions } from "dockerode";
import { IS_CLOUD } from "../constants";
import { findAdminById, findUserById } from "../services/admin";
import { findUserById } from "../services/admin";
import { getDokployImageTag } from "../services/settings";
import { pullImage, pullRemoteImage } from "../utils/docker/utils";
import { execAsync, execAsyncRemote } from "../utils/process/execAsync";

View File

@@ -1,6 +1,5 @@
import { IS_CLOUD, paths } from "@dokploy/server/constants";
import { type RotatingFileStream, createStream } from "rotating-file-stream";
import { db } from "../../db";
import { execAsync } from "../process/execAsync";
class LogRotationManager {

View File

@@ -1,4 +1,3 @@
import { unlink } from "node:fs/promises";
import path from "node:path";
import type { BackupSchedule } from "@dokploy/server/services/backup";
import type { MySql } from "@dokploy/server/services/mysql";

View File

@@ -2,7 +2,6 @@ import {
createWriteStream,
existsSync,
mkdirSync,
readFileSync,
writeFileSync,
} from "node:fs";
import { dirname, join } from "node:path";

View File

@@ -1,4 +1,3 @@
import { error } from "node:console";
import { db } from "@dokploy/server/db";
import { notifications } from "@dokploy/server/db/schema";
import DatabaseBackupEmail from "@dokploy/server/emails/emails/database-backup";

View File

@@ -95,7 +95,7 @@ export const loadRemoteMiddlewares = async (serverId: string) => {
}
const config = load(stdout) as FileConfig;
return config;
} catch (error) {
} catch (_) {
throw new Error(`File not found: ${configPath}`);
}
};