From 0722182650fee325d670cecf36729263226694f5 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Mon, 17 Mar 2025 23:59:39 -0600 Subject: [PATCH] feat(auth): implement user creation validation and IP update logic - Added validation for user creation to check for existing admin presence and validate x-dokploy-token. - Integrated public IP retrieval for user updates when not in cloud environment. - Enhanced error handling with APIError for better feedback during user creation process. --- packages/server/src/lib/auth.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/server/src/lib/auth.ts b/packages/server/src/lib/auth.ts index 9043f203..6695756c 100644 --- a/packages/server/src/lib/auth.ts +++ b/packages/server/src/lib/auth.ts @@ -8,6 +8,10 @@ import { db } from "../db"; import * as schema from "../db/schema"; import { sendEmail } from "../verification/send-verification-email"; import { IS_CLOUD } from "../constants"; +import { getPublicIpWithFallback } from "../wss/utils"; +import { updateUser } from "../services/user"; +import { getUserByToken } from "../services/admin"; +import { APIError } from "better-auth/api"; const { handler, api } = betterAuth({ database: drizzleAdapter(db, { @@ -88,11 +92,40 @@ const { handler, api } = betterAuth({ databaseHooks: { user: { create: { + before: async (_user, context) => { + if (!IS_CLOUD) { + const xDokployToken = + context?.request?.headers?.get("x-dokploy-token"); + if (xDokployToken) { + const user = await getUserByToken(xDokployToken); + if (!user) { + throw new APIError("BAD_REQUEST", { + message: "User not found", + }); + } + } else { + const isAdminPresent = await db.query.member.findFirst({ + where: eq(schema.member.role, "owner"), + }); + if (isAdminPresent) { + throw new APIError("BAD_REQUEST", { + message: "Admin is already created", + }); + } + } + } + }, after: async (user) => { const isAdminPresent = await db.query.member.findFirst({ where: eq(schema.member.role, "owner"), }); + if (!IS_CLOUD) { + await updateUser(user.id, { + serverIp: await getPublicIpWithFallback(), + }); + } + if (IS_CLOUD || !isAdminPresent) { await db.transaction(async (tx) => { const organization = await tx