From 6ec60b6bab2a7f0bc0c31ea230fcc0bd9c299db0 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 15 Feb 2025 13:14:48 -0600 Subject: [PATCH] refactor: update validation --- packages/server/src/lib/auth.ts | 132 ++++++------ packages/server/src/services/admin.ts | 292 +++++++++++++------------- 2 files changed, 213 insertions(+), 211 deletions(-) diff --git a/packages/server/src/lib/auth.ts b/packages/server/src/lib/auth.ts index 48e11f215..226ab0a8c 100644 --- a/packages/server/src/lib/auth.ts +++ b/packages/server/src/lib/auth.ts @@ -8,78 +8,80 @@ import { db } from "../db"; import * as schema from "../db/schema"; export const auth = betterAuth({ - database: drizzleAdapter(db, { - provider: "pg", - schema: schema, - }), + database: drizzleAdapter(db, { + provider: "pg", + schema: schema, + }), - emailAndPassword: { - enabled: true, + emailAndPassword: { + enabled: true, - password: { - async hash(password) { - return bcrypt.hashSync(password, 10); - }, - async verify({ hash, password }) { - return bcrypt.compareSync(password, hash); - }, - }, - }, - hooks: { - after: createAuthMiddleware(async (ctx) => { - if (ctx.path.startsWith("/sign-up")) { - const newSession = ctx.context.newSession; - await db - .update(schema.users_temp) - .set({ - role: "admin", - }) - .where(eq(schema.users_temp.id, newSession?.user?.id || "")); - } - }), - }, - user: { - modelName: "users_temp", - additionalFields: { - role: { - type: "string", - }, - ownerId: { - type: "string", - }, - }, - }, - plugins: [organization()], + password: { + async hash(password) { + return bcrypt.hashSync(password, 10); + }, + async verify({ hash, password }) { + return bcrypt.compareSync(password, hash); + }, + }, + }, + hooks: { + after: createAuthMiddleware(async (ctx) => { + if (ctx.path.startsWith("/sign-up")) { + const newSession = ctx.context.newSession; + await db + .update(schema.users_temp) + .set({ + role: "admin", + }) + .where(eq(schema.users_temp.id, newSession?.user?.id || "")); + } + }), + }, + user: { + modelName: "users_temp", + additionalFields: { + role: { + type: "string", + }, + ownerId: { + type: "string", + }, + }, + }, + plugins: [organization()], }); export const validateRequest = async (request: IncomingMessage) => { - const session = await auth.api.getSession({ - headers: new Headers({ - cookie: request.headers.cookie || "", - }), - }); + const session = await auth.api.getSession({ + headers: new Headers({ + cookie: request.headers.cookie || "", + }), + }); - if (session?.user.role === "user") { - const owner = await db.query.member.findFirst({ - where: eq(schema.member.userId, session.user.id), - with: { - organization: true, - }, - }); + if (!session?.session || !session.user) { + return { + session: null, + user: null, + }; + } - if (owner) { - session.user.ownerId = owner.organization.ownerId; - } - } else { - session.user.ownerId = session?.user.id; - } + if (session?.user) { + if (session?.user.role === "user") { + const owner = await db.query.member.findFirst({ + where: eq(schema.member.userId, session.user.id), + with: { + organization: true, + }, + }); - if (!session?.session || !session.user) { - return { - session: null, - user: null, - }; - } + if (owner) { + session.user.ownerId = owner.organization.ownerId; + } + } else { + session.user.ownerId = session?.user?.id || ""; + } + } - return session; + return session; }; diff --git a/packages/server/src/services/admin.ts b/packages/server/src/services/admin.ts index ea87e4560..e8a60498f 100644 --- a/packages/server/src/services/admin.ts +++ b/packages/server/src/services/admin.ts @@ -1,10 +1,10 @@ import { randomBytes } from "node:crypto"; import { db } from "@dokploy/server/db"; import { - admins, - type apiCreateUserInvitation, - auth, - users_temp, + admins, + type apiCreateUserInvitation, + auth, + users_temp, } from "@dokploy/server/db/schema"; import { TRPCError } from "@trpc/server"; import * as bcrypt from "bcrypt"; @@ -13,188 +13,188 @@ import { IS_CLOUD } from "../constants"; export type Admin = typeof users_temp.$inferSelect; export const createInvitation = async ( - input: typeof apiCreateUserInvitation._type, - adminId: string, + input: typeof apiCreateUserInvitation._type, + adminId: string ) => { - await db.transaction(async (tx) => { - const result = await tx - .insert(auth) - .values({ - email: input.email.toLowerCase(), - rol: "user", - password: bcrypt.hashSync("01231203012312", 10), - }) - .returning() - .then((res) => res[0]); + await db.transaction(async (tx) => { + const result = await tx + .insert(auth) + .values({ + email: input.email.toLowerCase(), + rol: "user", + password: bcrypt.hashSync("01231203012312", 10), + }) + .returning() + .then((res) => res[0]); - if (!result) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error creating the user", - }); - } - const expiresIn24Hours = new Date(); - expiresIn24Hours.setDate(expiresIn24Hours.getDate() + 1); - const token = randomBytes(32).toString("hex"); - await tx - .insert(users) - .values({ - adminId: adminId, - authId: result.id, - token, - expirationDate: expiresIn24Hours.toISOString(), - }) - .returning(); - }); + if (!result) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error creating the user", + }); + } + const expiresIn24Hours = new Date(); + expiresIn24Hours.setDate(expiresIn24Hours.getDate() + 1); + const token = randomBytes(32).toString("hex"); + await tx + .insert(users) + .values({ + adminId: adminId, + authId: result.id, + token, + expirationDate: expiresIn24Hours.toISOString(), + }) + .returning(); + }); }; export const findUserById = async (userId: string) => { - const user = await db.query.users_temp.findFirst({ - where: eq(users_temp.id, userId), - // with: { - // account: true, - // }, - }); - if (!user) { - throw new TRPCError({ - code: "NOT_FOUND", - message: "User not found", - }); - } - return user; + const user = await db.query.users_temp.findFirst({ + where: eq(users_temp.id, userId), + // with: { + // account: true, + // }, + }); + if (!user) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "User not found", + }); + } + return user; }; export const updateUser = async (userId: string, userData: Partial) => { - const user = await db - .update(users_temp) - .set({ - ...userData, - }) - .where(eq(users_temp.id, userId)) - .returning() - .then((res) => res[0]); + const user = await db + .update(users_temp) + .set({ + ...userData, + }) + .where(eq(users_temp.id, userId)) + .returning() + .then((res) => res[0]); - return user; + return user; }; export const updateAdminById = async ( - adminId: string, - adminData: Partial, + adminId: string, + adminData: Partial ) => { - const admin = await db - .update(admins) - .set({ - ...adminData, - }) - .where(eq(admins.adminId, adminId)) - .returning() - .then((res) => res[0]); + const admin = await db + .update(admins) + .set({ + ...adminData, + }) + .where(eq(admins.adminId, adminId)) + .returning() + .then((res) => res[0]); - return admin; + return admin; }; export const findAdminById = async (userId: string) => { - const admin = await db.query.admins.findFirst({ - where: eq(admins.userId, userId), - }); - return admin; + const admin = await db.query.admins.findFirst({ + where: eq(admins.userId, userId), + }); + return admin; }; export const isAdminPresent = async () => { - const admin = await db.query.user.findFirst({ - where: eq(user.role, "admin"), - }); - if (!admin) { - return false; - } - return true; + const admin = await db.query.users_temp.findFirst({ + where: eq(users_temp.role, "admin"), + }); + if (!admin) { + return false; + } + return true; }; export const findAdminByAuthId = async (authId: string) => { - const admin = await db.query.admins.findFirst({ - where: eq(admins.authId, authId), - with: { - users: true, - }, - }); - if (!admin) { - throw new TRPCError({ - code: "NOT_FOUND", - message: "Admin not found", - }); - } - return admin; + const admin = await db.query.admins.findFirst({ + where: eq(admins.authId, authId), + with: { + users: true, + }, + }); + if (!admin) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "Admin not found", + }); + } + return admin; }; export const findAdmin = async () => { - const admin = await db.query.admins.findFirst({}); - if (!admin) { - throw new TRPCError({ - code: "NOT_FOUND", - message: "Admin not found", - }); - } - return admin; + const admin = await db.query.admins.findFirst({}); + if (!admin) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "Admin not found", + }); + } + return admin; }; export const getUserByToken = async (token: string) => { - const user = await db.query.users.findFirst({ - where: eq(users.token, token), - with: { - auth: { - columns: { - password: false, - }, - }, - }, - }); + const user = await db.query.users.findFirst({ + where: eq(users.token, token), + with: { + auth: { + columns: { + password: false, + }, + }, + }, + }); - if (!user) { - throw new TRPCError({ - code: "NOT_FOUND", - message: "Invitation not found", - }); - } - return { - ...user, - isExpired: user.isRegistered, - }; + if (!user) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "Invitation not found", + }); + } + return { + ...user, + isExpired: user.isRegistered, + }; }; export const removeUserById = async (userId: string) => { - await db - .delete(users_temp) - .where(eq(users_temp.id, userId)) - .returning() - .then((res) => res[0]); + await db + .delete(users_temp) + .where(eq(users_temp.id, userId)) + .returning() + .then((res) => res[0]); }; export const removeAdminByAuthId = async (authId: string) => { - const admin = await findAdminByAuthId(authId); - if (!admin) return null; + const admin = await findAdminByAuthId(authId); + if (!admin) return null; - // First delete all associated users - const users = admin.users; + // First delete all associated users + const users = admin.users; - for (const user of users) { - await removeUserById(user.id); - } - // Then delete the auth record which will cascade delete the admin - return await db - .delete(auth) - .where(eq(auth.id, authId)) - .returning() - .then((res) => res[0]); + for (const user of users) { + await removeUserById(user.id); + } + // Then delete the auth record which will cascade delete the admin + return await db + .delete(auth) + .where(eq(auth.id, authId)) + .returning() + .then((res) => res[0]); }; export const getDokployUrl = async () => { - if (IS_CLOUD) { - return "https://app.dokploy.com"; - } - const admin = await findAdmin(); + if (IS_CLOUD) { + return "https://app.dokploy.com"; + } + const admin = await findAdmin(); - if (admin.host) { - return `https://${admin.host}`; - } - return `http://${admin.serverIp}:${process.env.PORT}`; + if (admin.host) { + return `https://${admin.host}`; + } + return `http://${admin.serverIp}:${process.env.PORT}`; };