From e7db0ccb70fb3acb985998cff340c910527ea9c6 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 16 Feb 2025 02:57:49 -0600 Subject: [PATCH] refactor: update invitation --- .../components/dashboard/search-command.tsx | 2 +- .../git/github/add-github-provider.tsx | 8 +- .../dashboard/settings/users/add-user.tsx | 28 ++-- apps/dokploy/lib/auth.ts | 2 +- .../accept-invitation/[accept-invitation].tsx | 30 ++++ .../pages/api/providers/github/setup.ts | 17 +- apps/dokploy/server/api/routers/bitbucket.ts | 36 ++--- apps/dokploy/server/api/routers/github.ts | 24 +-- apps/dokploy/server/api/routers/gitlab.ts | 19 +-- apps/dokploy/server/api/routers/project.ts | 2 +- apps/dokploy/server/api/routers/user.ts | 2 +- apps/dokploy/server/server.ts | 16 +- .../server/wss/docker-container-logs.ts | 4 +- .../server/wss/docker-container-terminal.ts | 4 +- apps/dokploy/server/wss/docker-stats.ts | 4 +- apps/dokploy/server/wss/drawer-logs.ts | 7 + apps/dokploy/server/wss/listen-deployment.ts | 4 +- apps/dokploy/server/wss/terminal.ts | 8 +- packages/server/src/auth/auth.ts | 78 ---------- packages/server/src/auth/token.ts | 146 +++++++++--------- packages/server/src/lib/auth.ts | 17 +- packages/server/src/services/application.ts | 56 +++---- packages/server/src/services/compose.ts | 40 ++--- .../server/src/services/preview-deployment.ts | 6 +- packages/server/src/services/settings.ts | 2 - packages/server/src/services/user.ts | 22 +-- .../src/utils/notifications/build-error.ts | 6 +- .../src/utils/notifications/build-success.ts | 6 +- .../src/utils/notifications/docker-cleanup.ts | 4 +- 29 files changed, 270 insertions(+), 330 deletions(-) create mode 100644 apps/dokploy/pages/accept-invitation/[accept-invitation].tsx diff --git a/apps/dokploy/components/dashboard/search-command.tsx b/apps/dokploy/components/dashboard/search-command.tsx index 952bbe5c8..8158a9ca8 100644 --- a/apps/dokploy/components/dashboard/search-command.tsx +++ b/apps/dokploy/components/dashboard/search-command.tsx @@ -36,7 +36,7 @@ export const SearchCommand = () => { const router = useRouter(); const [open, setOpen] = React.useState(false); const [search, setSearch] = React.useState(""); - const { data: session } = authClient.getSession(); + const { data: session } = authClient.useSession(); const { data } = api.project.all.useQuery(undefined, { enabled: !!session, }); diff --git a/apps/dokploy/components/dashboard/settings/git/github/add-github-provider.tsx b/apps/dokploy/components/dashboard/settings/git/github/add-github-provider.tsx index 0e3e56336..5f2cb934d 100644 --- a/apps/dokploy/components/dashboard/settings/git/github/add-github-provider.tsx +++ b/apps/dokploy/components/dashboard/settings/git/github/add-github-provider.tsx @@ -10,12 +10,14 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Switch } from "@/components/ui/switch"; +import { authClient } from "@/lib/auth"; import { api } from "@/utils/api"; import { format } from "date-fns"; import { useEffect, useState } from "react"; export const AddGithubProvider = () => { const [isOpen, setIsOpen] = useState(false); + const { data: activeOrganization } = authClient.useActiveOrganization(); const { data } = api.auth.get.useQuery(); const [manifest, setManifest] = useState(""); const [isOrganization, setIsOrganization] = useState(false); @@ -25,7 +27,7 @@ export const AddGithubProvider = () => { const url = document.location.origin; const manifest = JSON.stringify( { - redirect_url: `${origin}/api/providers/github/setup?authId=${data?.id}`, + redirect_url: `${origin}/api/providers/github/setup?organizationId=${activeOrganization?.id}`, name: `Dokploy-${format(new Date(), "yyyy-MM-dd")}`, url: origin, hook_attributes: { @@ -93,8 +95,8 @@ export const AddGithubProvider = () => {
diff --git a/apps/dokploy/components/dashboard/settings/users/add-user.tsx b/apps/dokploy/components/dashboard/settings/users/add-user.tsx index 8fb6de27c..175f723f5 100644 --- a/apps/dokploy/components/dashboard/settings/users/add-user.tsx +++ b/apps/dokploy/components/dashboard/settings/users/add-user.tsx @@ -19,6 +19,7 @@ import { FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; +import { authClient } from "@/lib/auth"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; import { PlusIcon } from "lucide-react"; @@ -40,6 +41,7 @@ export const AddUser = () => { const [open, setOpen] = useState(false); const utils = api.useUtils(); + const { data: activeOrganization } = authClient.useActiveOrganization(); const { mutateAsync, isError, error, isLoading } = api.admin.createUserInvitation.useMutation(); @@ -54,17 +56,23 @@ export const AddUser = () => { }, [form, form.formState.isSubmitSuccessful, form.reset]); const onSubmit = async (data: AddUser) => { - await mutateAsync({ + const result = await authClient.organization.inviteMember({ email: data.email.toLowerCase(), - }) - .then(async () => { - toast.success("Invitation created"); - await utils.user.all.invalidate(); - setOpen(false); - }) - .catch(() => { - toast.error("Error creating the invitation"); - }); + role: "user", + organizationId: activeOrganization?.id, + }); + console.log(result); + // await mutateAsync({ + // email: data.email.toLowerCase(), + // }) + // .then(async () => { + // toast.success("Invitation created"); + // await utils.user.all.invalidate(); + // setOpen(false); + // }) + // .catch(() => { + // toast.error("Error creating the invitation"); + // }); }; return ( diff --git a/apps/dokploy/lib/auth.ts b/apps/dokploy/lib/auth.ts index a5b193700..12c3cc3e7 100644 --- a/apps/dokploy/lib/auth.ts +++ b/apps/dokploy/lib/auth.ts @@ -2,6 +2,6 @@ import { organizationClient } from "better-auth/client/plugins"; import { createAuthClient } from "better-auth/react"; export const authClient = createAuthClient({ - baseURL: "http://localhost:3000", // the base url of your auth server + // baseURL: "http://localhost:3000", // the base url of your auth server plugins: [organizationClient()], }); diff --git a/apps/dokploy/pages/accept-invitation/[accept-invitation].tsx b/apps/dokploy/pages/accept-invitation/[accept-invitation].tsx new file mode 100644 index 000000000..6936a802d --- /dev/null +++ b/apps/dokploy/pages/accept-invitation/[accept-invitation].tsx @@ -0,0 +1,30 @@ +import { Button } from "@/components/ui/button"; +import { authClient } from "@/lib/auth"; +import { useRouter } from "next/router"; + +export const AcceptInvitation = () => { + const { query } = useRouter(); + + const invitationId = query["accept-invitation"]; + + // const { data: organization } = api.organization.getById.useQuery({ + // id: id as string + // }) + + return ( +
+ +
+ ); +}; + +export default AcceptInvitation; diff --git a/apps/dokploy/pages/api/providers/github/setup.ts b/apps/dokploy/pages/api/providers/github/setup.ts index bd123c687..9a03ed3d7 100644 --- a/apps/dokploy/pages/api/providers/github/setup.ts +++ b/apps/dokploy/pages/api/providers/github/setup.ts @@ -1,10 +1,12 @@ import { db } from "@/server/db"; import { github } from "@/server/db/schema"; import { + auth, createGithub, findAdminByAuthId, findAuthById, findUserByAuthId, + findUserById, } from "@dokploy/server"; import { eq } from "drizzle-orm"; import type { NextApiRequest, NextApiResponse } from "next"; @@ -28,7 +30,7 @@ export default async function handler( return res.status(400).json({ error: "Missing code parameter" }); } const [action, value] = state?.split(":"); - // Value could be the authId or the githubProviderId + // Value could be the organizationId or the githubProviderId if (action === "gh_init") { const octokit = new Octokit({}); @@ -39,17 +41,6 @@ export default async function handler( }, ); - const auth = await findAuthById(value as string); - - let adminId = ""; - if (auth.role === "owner") { - const admin = await findAdminByAuthId(auth.id); - adminId = admin.adminId; - } else { - const user = await findUserByAuthId(auth.id); - adminId = user.adminId; - } - await createGithub( { name: data.name, @@ -60,7 +51,7 @@ export default async function handler( githubWebhookSecret: data.webhook_secret, githubPrivateKey: data.pem, }, - adminId, + value as string, ); } else if (action === "gh_setup") { await db diff --git a/apps/dokploy/server/api/routers/bitbucket.ts b/apps/dokploy/server/api/routers/bitbucket.ts index 987555e5f..7a8462641 100644 --- a/apps/dokploy/server/api/routers/bitbucket.ts +++ b/apps/dokploy/server/api/routers/bitbucket.ts @@ -8,7 +8,6 @@ import { apiUpdateBitbucket, } from "@/server/db/schema"; import { - IS_CLOUD, createBitbucket, findBitbucketById, getBitbucketBranches, @@ -37,11 +36,9 @@ export const bitbucketRouter = createTRPCRouter({ .query(async ({ input, ctx }) => { const bitbucketProvider = await findBitbucketById(input.bitbucketId); if ( - IS_CLOUD && bitbucketProvider.gitProvider.organizationId !== - ctx.session.activeOrganizationId + ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this bitbucket provider", @@ -59,14 +56,11 @@ export const bitbucketRouter = createTRPCRouter({ }, }); - if (IS_CLOUD) { - // TODO: mAyBe a rEfaCtoR 🤫 - result = result.filter( - (provider) => - provider.gitProvider.organizationId === - ctx.session.activeOrganizationId, - ); - } + result = result.filter( + (provider) => + provider.gitProvider.organizationId === + ctx.session.activeOrganizationId, + ); return result; }), @@ -75,11 +69,9 @@ export const bitbucketRouter = createTRPCRouter({ .query(async ({ input, ctx }) => { const bitbucketProvider = await findBitbucketById(input.bitbucketId); if ( - IS_CLOUD && bitbucketProvider.gitProvider.organizationId !== - ctx.session.activeOrganizationId + ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this bitbucket provider", @@ -94,11 +86,9 @@ export const bitbucketRouter = createTRPCRouter({ input.bitbucketId || "", ); if ( - IS_CLOUD && bitbucketProvider.gitProvider.organizationId !== - ctx.session.activeOrganizationId + ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this bitbucket provider", @@ -112,11 +102,9 @@ export const bitbucketRouter = createTRPCRouter({ try { const bitbucketProvider = await findBitbucketById(input.bitbucketId); if ( - IS_CLOUD && bitbucketProvider.gitProvider.organizationId !== - ctx.session.activeOrganizationId + ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this bitbucket provider", @@ -137,11 +125,9 @@ export const bitbucketRouter = createTRPCRouter({ .mutation(async ({ input, ctx }) => { const bitbucketProvider = await findBitbucketById(input.bitbucketId); if ( - IS_CLOUD && bitbucketProvider.gitProvider.organizationId !== - ctx.session.activeOrganizationId + ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this bitbucket provider", @@ -149,7 +135,7 @@ export const bitbucketRouter = createTRPCRouter({ } return await updateBitbucket(input.bitbucketId, { ...input, - userId: ctx.user.ownerId, + organizationId: ctx.session.activeOrganizationId, }); }), }); diff --git a/apps/dokploy/server/api/routers/github.ts b/apps/dokploy/server/api/routers/github.ts index 2b3f15029..691030e27 100644 --- a/apps/dokploy/server/api/routers/github.ts +++ b/apps/dokploy/server/api/routers/github.ts @@ -6,7 +6,6 @@ import { apiUpdateGithub, } from "@/server/db/schema"; import { - IS_CLOUD, findGithubById, getGithubBranches, getGithubRepositories, @@ -24,7 +23,6 @@ export const githubRouter = createTRPCRouter({ githubProvider.gitProvider.organizationId !== ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this github provider", @@ -40,7 +38,6 @@ export const githubRouter = createTRPCRouter({ githubProvider.gitProvider.organizationId !== ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this github provider", @@ -71,14 +68,11 @@ export const githubRouter = createTRPCRouter({ }, }); - if (IS_CLOUD) { - // TODO: mAyBe a rEfaCtoR 🤫 - result = result.filter( - (provider) => - provider.gitProvider.organizationId === - ctx.session.activeOrganizationId, - ); - } + result = result.filter( + (provider) => + provider.gitProvider.organizationId === + ctx.session.activeOrganizationId, + ); const filtered = result .filter((provider) => haveGithubRequirements(provider)) @@ -100,11 +94,9 @@ export const githubRouter = createTRPCRouter({ try { const githubProvider = await findGithubById(input.githubId); if ( - IS_CLOUD && githubProvider.gitProvider.organizationId !== - ctx.session.activeOrganizationId + ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this github provider", @@ -124,11 +116,9 @@ export const githubRouter = createTRPCRouter({ .mutation(async ({ input, ctx }) => { const githubProvider = await findGithubById(input.githubId); if ( - IS_CLOUD && githubProvider.gitProvider.organizationId !== - ctx.session.activeOrganizationId + ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this github provider", diff --git a/apps/dokploy/server/api/routers/gitlab.ts b/apps/dokploy/server/api/routers/gitlab.ts index 338b8c64d..b702bc2a4 100644 --- a/apps/dokploy/server/api/routers/gitlab.ts +++ b/apps/dokploy/server/api/routers/gitlab.ts @@ -9,7 +9,6 @@ import { import { db } from "@/server/db"; import { - IS_CLOUD, createGitlab, findGitlabById, getGitlabBranches, @@ -43,7 +42,6 @@ export const gitlabRouter = createTRPCRouter({ gitlabProvider.gitProvider.organizationId !== ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this Gitlab provider", @@ -58,14 +56,11 @@ export const gitlabRouter = createTRPCRouter({ }, }); - if (IS_CLOUD) { - // TODO: mAyBe a rEfaCtoR 🤫 - result = result.filter( - (provider) => - provider.gitProvider.organizationId === - ctx.session.activeOrganizationId, - ); - } + result = result.filter( + (provider) => + provider.gitProvider.organizationId === + ctx.session.activeOrganizationId, + ); const filtered = result .filter((provider) => haveGitlabRequirements(provider)) .map((provider) => { @@ -87,7 +82,6 @@ export const gitlabRouter = createTRPCRouter({ gitlabProvider.gitProvider.organizationId !== ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this Gitlab provider", @@ -104,7 +98,6 @@ export const gitlabRouter = createTRPCRouter({ gitlabProvider.gitProvider.organizationId !== ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this Gitlab provider", @@ -121,7 +114,6 @@ export const gitlabRouter = createTRPCRouter({ gitlabProvider.gitProvider.organizationId !== ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this Gitlab provider", @@ -145,7 +137,6 @@ export const gitlabRouter = createTRPCRouter({ gitlabProvider.gitProvider.organizationId !== ctx.session.activeOrganizationId ) { - //TODO: Remove this line when the cloud version is ready throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this Gitlab provider", diff --git a/apps/dokploy/server/api/routers/project.ts b/apps/dokploy/server/api/routers/project.ts index b5beadf4d..5fc79f437 100644 --- a/apps/dokploy/server/api/routers/project.ts +++ b/apps/dokploy/server/api/routers/project.ts @@ -71,7 +71,7 @@ export const projectRouter = createTRPCRouter({ .input(apiFindOneProject) .query(async ({ input, ctx }) => { if (ctx.user.rol === "member") { - const { accessedServices } = await findUserByAuthId(ctx.user.id); + const { accessedServices } = await findUserById(ctx.user.id); await checkProjectAccess(ctx.user.id, "access", input.projectId); diff --git a/apps/dokploy/server/api/routers/user.ts b/apps/dokploy/server/api/routers/user.ts index 269da8f5a..00c2bb82e 100644 --- a/apps/dokploy/server/api/routers/user.ts +++ b/apps/dokploy/server/api/routers/user.ts @@ -4,8 +4,8 @@ import { db } from "@dokploy/server/db"; import { member } from "@dokploy/server/db/schema"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; -import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc"; import { z } from "zod"; +import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc"; export const userRouter = createTRPCRouter({ all: adminProcedure.query(async ({ ctx }) => { return await db.query.member.findMany({ diff --git a/apps/dokploy/server/server.ts b/apps/dokploy/server/server.ts index a277dc0ac..c8f53f6f9 100644 --- a/apps/dokploy/server/server.ts +++ b/apps/dokploy/server/server.ts @@ -34,14 +34,14 @@ void app.prepare().then(async () => { }); // WEBSOCKET - // setupDrawerLogsWebSocketServer(server); - // setupDeploymentLogsWebSocketServer(server); - // setupDockerContainerLogsWebSocketServer(server); - // setupDockerContainerTerminalWebSocketServer(server); - // setupTerminalWebSocketServer(server); - // if (!IS_CLOUD) { - // setupDockerStatsMonitoringSocketServer(server); - // } + setupDrawerLogsWebSocketServer(server); + setupDeploymentLogsWebSocketServer(server); + setupDockerContainerLogsWebSocketServer(server); + setupDockerContainerTerminalWebSocketServer(server); + setupTerminalWebSocketServer(server); + if (!IS_CLOUD) { + setupDockerStatsMonitoringSocketServer(server); + } if (process.env.NODE_ENV === "production" && !IS_CLOUD) { setupDirectories(); diff --git a/apps/dokploy/server/wss/docker-container-logs.ts b/apps/dokploy/server/wss/docker-container-logs.ts index 092f39735..8d08ebd46 100644 --- a/apps/dokploy/server/wss/docker-container-logs.ts +++ b/apps/dokploy/server/wss/docker-container-logs.ts @@ -1,5 +1,5 @@ import type http from "node:http"; -import { findServerById, validateWebSocketRequest } from "@dokploy/server"; +import { findServerById, validateRequest } from "@dokploy/server"; import { spawn } from "node-pty"; import { Client } from "ssh2"; import { WebSocketServer } from "ws"; @@ -35,7 +35,7 @@ export const setupDockerContainerLogsWebSocketServer = ( const since = url.searchParams.get("since"); const serverId = url.searchParams.get("serverId"); const runType = url.searchParams.get("runType"); - const { user, session } = await validateWebSocketRequest(req); + const { user, session } = await validateRequest(req); if (!containerId) { ws.close(4000, "containerId no provided"); diff --git a/apps/dokploy/server/wss/docker-container-terminal.ts b/apps/dokploy/server/wss/docker-container-terminal.ts index 8981ccbc2..04ef5c96c 100644 --- a/apps/dokploy/server/wss/docker-container-terminal.ts +++ b/apps/dokploy/server/wss/docker-container-terminal.ts @@ -1,5 +1,5 @@ import type http from "node:http"; -import { findServerById, validateWebSocketRequest } from "@dokploy/server"; +import { findServerById, validateRequest } from "@dokploy/server"; import { spawn } from "node-pty"; import { Client } from "ssh2"; import { WebSocketServer } from "ws"; @@ -32,7 +32,7 @@ export const setupDockerContainerTerminalWebSocketServer = ( const containerId = url.searchParams.get("containerId"); const activeWay = url.searchParams.get("activeWay"); const serverId = url.searchParams.get("serverId"); - const { user, session } = await validateWebSocketRequest(req); + const { user, session } = await validateRequest(req); if (!containerId) { ws.close(4000, "containerId no provided"); diff --git a/apps/dokploy/server/wss/docker-stats.ts b/apps/dokploy/server/wss/docker-stats.ts index b1e4585c1..99e993dce 100644 --- a/apps/dokploy/server/wss/docker-stats.ts +++ b/apps/dokploy/server/wss/docker-stats.ts @@ -4,7 +4,7 @@ import { execAsync, getLastAdvancedStatsFile, recordAdvancedStats, - validateWebSocketRequest, + validateRequest, } from "@dokploy/server"; import { WebSocketServer } from "ws"; @@ -36,7 +36,7 @@ export const setupDockerStatsMonitoringSocketServer = ( | "application" | "stack" | "docker-compose"; - const { user, session } = await validateWebSocketRequest(req); + const { user, session } = await validateRequest(req); if (!appName) { ws.close(4000, "appName no provided"); diff --git a/apps/dokploy/server/wss/drawer-logs.ts b/apps/dokploy/server/wss/drawer-logs.ts index c1dec315b..da2c529ac 100644 --- a/apps/dokploy/server/wss/drawer-logs.ts +++ b/apps/dokploy/server/wss/drawer-logs.ts @@ -3,6 +3,7 @@ import { applyWSSHandler } from "@trpc/server/adapters/ws"; import { WebSocketServer } from "ws"; import { appRouter } from "../api/root"; import { createTRPCContext } from "../api/trpc"; +import { validateRequest } from "@dokploy/server/index"; export const setupDrawerLogsWebSocketServer = ( server: http.Server, @@ -32,5 +33,11 @@ export const setupDrawerLogsWebSocketServer = ( wssTerm.on("connection", async (ws, req) => { const url = new URL(req.url || "", `http://${req.headers.host}`); + const { user, session } = await validateRequest(req); + + if (!user || !session) { + ws.close(); + return; + } }); }; diff --git a/apps/dokploy/server/wss/listen-deployment.ts b/apps/dokploy/server/wss/listen-deployment.ts index df77ceb41..ee470fcbf 100644 --- a/apps/dokploy/server/wss/listen-deployment.ts +++ b/apps/dokploy/server/wss/listen-deployment.ts @@ -1,6 +1,6 @@ import { spawn } from "node:child_process"; import type http from "node:http"; -import { findServerById, validateWebSocketRequest } from "@dokploy/server"; +import { findServerById, validateRequest } from "@dokploy/server"; import { Client } from "ssh2"; import { WebSocketServer } from "ws"; @@ -29,7 +29,7 @@ export const setupDeploymentLogsWebSocketServer = ( const url = new URL(req.url || "", `http://${req.headers.host}`); const logPath = url.searchParams.get("logPath"); const serverId = url.searchParams.get("serverId"); - const { user, session } = await validateWebSocketRequest(req); + const { user, session } = await validateRequest(req); if (!logPath) { console.log("logPath no provided"); diff --git a/apps/dokploy/server/wss/terminal.ts b/apps/dokploy/server/wss/terminal.ts index 5fa1accc2..6e9c3614f 100644 --- a/apps/dokploy/server/wss/terminal.ts +++ b/apps/dokploy/server/wss/terminal.ts @@ -1,9 +1,5 @@ import type http from "node:http"; -import { - IS_CLOUD, - findServerById, - validateWebSocketRequest, -} from "@dokploy/server"; +import { IS_CLOUD, findServerById, validateRequest } from "@dokploy/server"; import { publicIpv4, publicIpv6 } from "public-ip"; import { Client, type ConnectConfig } from "ssh2"; import { WebSocketServer } from "ws"; @@ -71,7 +67,7 @@ export const setupTerminalWebSocketServer = ( wssTerm.on("connection", async (ws, req) => { const url = new URL(req.url || "", `http://${req.headers.host}`); const serverId = url.searchParams.get("serverId"); - const { user, session } = await validateWebSocketRequest(req); + const { user, session } = await validateRequest(req); if (!user || !session || !serverId) { ws.close(); return; diff --git a/packages/server/src/auth/auth.ts b/packages/server/src/auth/auth.ts index ab18955f2..28052f5f6 100644 --- a/packages/server/src/auth/auth.ts +++ b/packages/server/src/auth/auth.ts @@ -1,6 +1,3 @@ -import type { IncomingMessage, ServerResponse } from "node:http"; -import { findAdminByAuthId } from "@dokploy/server/services/admin"; -import { findUserByAuthId } from "@dokploy/server/services/user"; import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle"; import { TimeSpan } from "lucia"; import { Lucia } from "lucia/dist/core.js"; @@ -42,78 +39,3 @@ export type ReturnValidateToken = Promise<{ user: (User & { authId: string; adminId: string }) | null; session: Session | null; }>; - -export async function validateRequest( - req: IncomingMessage, - res: ServerResponse, -): ReturnValidateToken { - console.log(session); - const sessionId = lucia.readSessionCookie(req.headers.cookie ?? ""); - - if (!sessionId) { - return { - user: null, - session: null, - }; - } - const result = await lucia.validateSession(sessionId); - if (result?.session?.fresh) { - res.appendHeader( - "Set-Cookie", - lucia.createSessionCookie(result.session.id).serialize(), - ); - } - if (!result.session) { - res.appendHeader( - "Set-Cookie", - lucia.createBlankSessionCookie().serialize(), - ); - } - if (result.user) { - try { - if (result.user?.rol === "owner") { - const admin = await findAdminByAuthId(result.user.id); - result.user.adminId = admin.adminId; - } else if (result.user?.rol === "member") { - const userResult = await findUserByAuthId(result.user.id); - result.user.adminId = userResult.adminId; - } - } catch (error) { - return { - user: null, - session: null, - }; - } - } - - return { - session: result.session, - ...((result.user && { - user: { - authId: result.user.id, - email: result.user.email, - rol: result.user.rol, - id: result.user.id, - secret: result.user.secret, - adminId: result.user.adminId, - }, - }) || { - user: null, - }), - }; -} - -export async function validateWebSocketRequest( - req: IncomingMessage, -): Promise<{ user: User; session: Session } | { user: null; session: null }> { - const sessionId = lucia.readSessionCookie(req.headers.cookie ?? ""); - - if (!sessionId) { - return { - user: null, - session: null, - }; - } - const result = await lucia.validateSession(sessionId); - return result; -} diff --git a/packages/server/src/auth/token.ts b/packages/server/src/auth/token.ts index 9dcf99736..e3f404b05 100644 --- a/packages/server/src/auth/token.ts +++ b/packages/server/src/auth/token.ts @@ -21,79 +21,79 @@ export const luciaToken = new Lucia(adapter, { }, }); -export const validateBearerToken = async ( - req: IncomingMessage, -): ReturnValidateToken => { - const authorizationHeader = req.headers.authorization; - const sessionId = luciaToken.readBearerToken(authorizationHeader ?? ""); - if (!sessionId) { - return { - user: null, - session: null, - }; - } - const result = await luciaToken.validateSession(sessionId); +// export const validateBearerToken = async ( +// req: IncomingMessage, +// ): ReturnValidateToken => { +// const authorizationHeader = req.headers.authorization; +// const sessionId = luciaToken.readBearerToken(authorizationHeader ?? ""); +// if (!sessionId) { +// return { +// user: null, +// session: null, +// }; +// } +// const result = await luciaToken.validateSession(sessionId); - if (result.user) { - if (result.user?.rol === "owner") { - const admin = await findAdminByAuthId(result.user.id); - result.user.adminId = admin.adminId; - } else if (result.user?.rol === "member") { - const userResult = await findUserByAuthId(result.user.id); - result.user.adminId = userResult.adminId; - } - } - return { - session: result.session, - ...((result.user && { - user: { - adminId: result.user.adminId, - authId: result.user.id, - email: result.user.email, - rol: result.user.rol, - id: result.user.id, - secret: result.user.secret, - }, - }) || { - user: null, - }), - }; -}; +// if (result.user) { +// if (result.user?.rol === "owner") { +// const admin = await findAdminByAuthId(result.user.id); +// result.user.adminId = admin.adminId; +// } else if (result.user?.rol === "member") { +// const userResult = await findUserByAuthId(result.user.id); +// result.user.adminId = userResult.adminId; +// } +// } +// return { +// session: result.session, +// ...((result.user && { +// user: { +// adminId: result.user.adminId, +// authId: result.user.id, +// email: result.user.email, +// rol: result.user.rol, +// id: result.user.id, +// secret: result.user.secret, +// }, +// }) || { +// user: null, +// }), +// }; +// }; -export const validateBearerTokenAPI = async ( - authorizationHeader: string, -): ReturnValidateToken => { - const sessionId = luciaToken.readBearerToken(authorizationHeader ?? ""); - if (!sessionId) { - return { - user: null, - session: null, - }; - } - const result = await luciaToken.validateSession(sessionId); +// export const validateBearerTokenAPI = async ( +// authorizationHeader: string, +// ): ReturnValidateToken => { +// const sessionId = luciaToken.readBearerToken(authorizationHeader ?? ""); +// if (!sessionId) { +// return { +// user: null, +// session: null, +// }; +// } +// const result = await luciaToken.validateSession(sessionId); - if (result.user) { - if (result.user?.rol === "owner") { - const admin = await findAdminByAuthId(result.user.id); - result.user.adminId = admin.adminId; - } else if (result.user?.rol === "member") { - const userResult = await findUserByAuthId(result.user.id); - result.user.adminId = userResult.adminId; - } - } - return { - session: result.session, - ...((result.user && { - user: { - adminId: result.user.adminId, - authId: result.user.id, - email: result.user.email, - rol: result.user.rol, - id: result.user.id, - secret: result.user.secret, - }, - }) || { - user: null, - }), - }; -}; +// if (result.user) { +// if (result.user?.rol === "owner") { +// const admin = await findAdminByAuthId(result.user.id); +// result.user.adminId = admin.adminId; +// } else if (result.user?.rol === "member") { +// const userResult = await findUserByAuthId(result.user.id); +// result.user.adminId = userResult.adminId; +// } +// } +// return { +// session: result.session, +// ...((result.user && { +// user: { +// adminId: result.user.adminId, +// authId: result.user.id, +// email: result.user.email, +// rol: result.user.rol, +// id: result.user.id, +// secret: result.user.secret, +// }, +// }) || { +// user: null, +// }), +// }; +// }; diff --git a/packages/server/src/lib/auth.ts b/packages/server/src/lib/auth.ts index 3b29e0240..a7fbde9a5 100644 --- a/packages/server/src/lib/auth.ts +++ b/packages/server/src/lib/auth.ts @@ -84,7 +84,22 @@ export const auth = betterAuth({ }, }, - plugins: [organization()], + plugins: [ + organization({ + async sendInvitationEmail(data, request) { + const inviteLink = `https://example.com/accept-invitation/${data.id}`; + // https://example.com/accept-invitation/8jlBi9Tb9isDb8mc8Sb85u1BaJYklKB2 + // sendOrganizationInvitation({ + // email: data.email, + // invitedByUsername: data.inviter.user.name, + // invitedByEmail: data.inviter.user.email, + // teamName: data.organization.name, + // inviteLink + // }) + console.log("Invitation link", inviteLink); + }, + }), + ], }); export const validateRequest = async (request: IncomingMessage) => { diff --git a/packages/server/src/services/application.ts b/packages/server/src/services/application.ts index b60665304..ddc3a4504 100644 --- a/packages/server/src/services/application.ts +++ b/packages/server/src/services/application.ts @@ -185,11 +185,11 @@ export const deployApplication = async ({ }); try { - const admin = await findUserById(application.project.userId); + // const admin = await findUserById(application.project.userId); - if (admin.cleanupCacheApplications) { - await cleanupFullDocker(application?.serverId); - } + // if (admin.cleanupCacheApplications) { + // await cleanupFullDocker(application?.serverId); + // } if (application.sourceType === "github") { await cloneGithubRepository({ @@ -220,7 +220,7 @@ export const deployApplication = async ({ applicationName: application.name, applicationType: "application", buildLink, - userId: application.project.userId, + organizationId: application.project.organizationId, domains: application.domains, }); } catch (error) { @@ -233,7 +233,7 @@ export const deployApplication = async ({ // @ts-ignore errorMessage: error?.message || "Error building", buildLink, - userId: application.project.userId, + organizationId: application.project.organizationId, }); throw error; @@ -260,11 +260,11 @@ export const rebuildApplication = async ({ }); try { - const admin = await findUserById(application.project.userId); + // const admin = await findUserById(application.project.userId); - if (admin.cleanupCacheApplications) { - await cleanupFullDocker(application?.serverId); - } + // if (admin.cleanupCacheApplications) { + // await cleanupFullDocker(application?.serverId); + // } if (application.sourceType === "github") { await buildApplication(application, deployment.logPath); } else if (application.sourceType === "gitlab") { @@ -309,11 +309,11 @@ export const deployRemoteApplication = async ({ try { if (application.serverId) { - const admin = await findUserById(application.project.userId); + // const admin = await findUserById(application.project.userId); - if (admin.cleanupCacheApplications) { - await cleanupFullDocker(application?.serverId); - } + // if (admin.cleanupCacheApplications) { + // await cleanupFullDocker(application?.serverId); + // } let command = "set -e;"; if (application.sourceType === "github") { command += await getGithubCloneCommand({ @@ -352,7 +352,7 @@ export const deployRemoteApplication = async ({ applicationName: application.name, applicationType: "application", buildLink, - userId: application.project.userId, + organizationId: application.project.organizationId, domains: application.domains, }); } catch (error) { @@ -376,7 +376,7 @@ export const deployRemoteApplication = async ({ // @ts-ignore errorMessage: error?.message || "Error building", buildLink, - userId: application.project.userId, + organizationId: application.project.organizationId, }); throw error; @@ -454,11 +454,11 @@ export const deployPreviewApplication = async ({ application.env = `${application.previewEnv}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain}`; application.buildArgs = application.previewBuildArgs; - const admin = await findUserById(application.project.userId); + // const admin = await findUserById(application.project.userId); - if (admin.cleanupCacheOnPreviews) { - await cleanupFullDocker(application?.serverId); - } + // if (admin.cleanupCacheOnPreviews) { + // await cleanupFullDocker(application?.serverId); + // } if (application.sourceType === "github") { await cloneGithubRepository({ @@ -568,11 +568,11 @@ export const deployRemotePreviewApplication = async ({ application.buildArgs = application.previewBuildArgs; if (application.serverId) { - const admin = await findUserById(application.project.userId); + // const admin = await findUserById(application.project.userId); - if (admin.cleanupCacheOnPreviews) { - await cleanupFullDocker(application?.serverId); - } + // if (admin.cleanupCacheOnPreviews) { + // await cleanupFullDocker(application?.serverId); + // } let command = "set -e;"; if (application.sourceType === "github") { command += await getGithubCloneCommand({ @@ -637,11 +637,11 @@ export const rebuildRemoteApplication = async ({ try { if (application.serverId) { - const admin = await findUserById(application.project.userId); + // const admin = await findUserById(application.project.userId); - if (admin.cleanupCacheApplications) { - await cleanupFullDocker(application?.serverId); - } + // if (admin.cleanupCacheApplications) { + // await cleanupFullDocker(application?.serverId); + // } if (application.sourceType !== "docker") { let command = "set -e;"; command += getBuildCommand(application, deployment.logPath); diff --git a/packages/server/src/services/compose.ts b/packages/server/src/services/compose.ts index a4126a0d0..70bc411c1 100644 --- a/packages/server/src/services/compose.ts +++ b/packages/server/src/services/compose.ts @@ -217,10 +217,10 @@ export const deployCompose = async ({ }); try { - const admin = await findUserById(compose.project.userId); - if (admin.cleanupCacheOnCompose) { - await cleanupFullDocker(compose?.serverId); - } + // const admin = await findUserById(compose.project.userId); + // if (admin.cleanupCacheOnCompose) { + // await cleanupFullDocker(compose?.serverId); + // } if (compose.sourceType === "github") { await cloneGithubRepository({ ...compose, @@ -247,7 +247,7 @@ export const deployCompose = async ({ applicationName: compose.name, applicationType: "compose", buildLink, - userId: compose.project.userId, + organizationId: compose.project.organizationId, domains: compose.domains, }); } catch (error) { @@ -262,7 +262,7 @@ export const deployCompose = async ({ // @ts-ignore errorMessage: error?.message || "Error building", buildLink, - userId: compose.project.userId, + organizationId: compose.project.organizationId, }); throw error; } @@ -286,10 +286,10 @@ export const rebuildCompose = async ({ }); try { - const admin = await findUserById(compose.project.userId); - if (admin.cleanupCacheOnCompose) { - await cleanupFullDocker(compose?.serverId); - } + // const admin = await findUserById(compose.project.userId); + // if (admin.cleanupCacheOnCompose) { + // await cleanupFullDocker(compose?.serverId); + // } if (compose.serverId) { await getBuildComposeCommand(compose, deployment.logPath); } else { @@ -332,10 +332,10 @@ export const deployRemoteCompose = async ({ }); try { if (compose.serverId) { - const admin = await findUserById(compose.project.userId); - if (admin.cleanupCacheOnCompose) { - await cleanupFullDocker(compose?.serverId); - } + // const admin = await findUserById(compose.project.userId); + // if (admin.cleanupCacheOnCompose) { + // await cleanupFullDocker(compose?.serverId); + // } let command = "set -e;"; if (compose.sourceType === "github") { @@ -381,7 +381,7 @@ export const deployRemoteCompose = async ({ applicationName: compose.name, applicationType: "compose", buildLink, - userId: compose.project.userId, + organizationId: compose.project.organizationId, domains: compose.domains, }); } catch (error) { @@ -406,7 +406,7 @@ export const deployRemoteCompose = async ({ // @ts-ignore errorMessage: error?.message || "Error building", buildLink, - userId: compose.project.userId, + organizationId: compose.project.organizationId, }); throw error; } @@ -430,10 +430,10 @@ export const rebuildRemoteCompose = async ({ }); try { - const admin = await findUserById(compose.project.userId); - if (admin.cleanupCacheOnCompose) { - await cleanupFullDocker(compose?.serverId); - } + // const admin = await findUserById(compose.project.userId); + // if (admin.cleanupCacheOnCompose) { + // await cleanupFullDocker(compose?.serverId); + // } if (compose.serverId) { await getBuildComposeCommand(compose, deployment.logPath); } diff --git a/packages/server/src/services/preview-deployment.ts b/packages/server/src/services/preview-deployment.ts index 69279b027..d5a2149a7 100644 --- a/packages/server/src/services/preview-deployment.ts +++ b/packages/server/src/services/preview-deployment.ts @@ -2,6 +2,7 @@ import { db } from "@dokploy/server/db"; import { type apiCreatePreviewDeployment, deployments, + organization, previewDeployments, } from "@dokploy/server/db/schema"; import { TRPCError } from "@trpc/server"; @@ -154,11 +155,14 @@ export const createPreviewDeployment = async ( const application = await findApplicationById(schema.applicationId); const appName = `preview-${application.appName}-${generatePassword(6)}`; + const org = await db.query.organization.findFirst({ + where: eq(organization.id, application.project.organizationId), + }); const generateDomain = await generateWildcardDomain( application.previewWildcard || "*.traefik.me", appName, application.server?.ipAddress || "", - application.project.userId, + org?.ownerId || "", ); const octokit = authGithub(application?.github as Github); diff --git a/packages/server/src/services/settings.ts b/packages/server/src/services/settings.ts index dd5b4e183..01ac43a14 100644 --- a/packages/server/src/services/settings.ts +++ b/packages/server/src/services/settings.ts @@ -5,8 +5,6 @@ import { execAsync, execAsyncRemote, } from "@dokploy/server/utils/process/execAsync"; -import { findAdminById } from "./admin"; -// import packageInfo from "../../../package.json"; export interface IUpdateData { latestVersion: string | null; diff --git a/packages/server/src/services/user.ts b/packages/server/src/services/user.ts index c32ceef2c..fbd81cf1b 100644 --- a/packages/server/src/services/user.ts +++ b/packages/server/src/services/user.ts @@ -20,17 +20,17 @@ export type User = typeof users_temp.$inferSelect; // }; 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; + // 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 findUsers = async (adminId: string) => { diff --git a/packages/server/src/utils/notifications/build-error.ts b/packages/server/src/utils/notifications/build-error.ts index 4ed227e1e..c873c9ab5 100644 --- a/packages/server/src/utils/notifications/build-error.ts +++ b/packages/server/src/utils/notifications/build-error.ts @@ -18,7 +18,7 @@ interface Props { applicationType: string; errorMessage: string; buildLink: string; - userId: string; + organizationId: string; } export const sendBuildErrorNotifications = async ({ @@ -27,14 +27,14 @@ export const sendBuildErrorNotifications = async ({ applicationType, errorMessage, buildLink, - userId, + organizationId, }: Props) => { const date = new Date(); const unixDate = ~~(Number(date) / 1000); const notificationList = await db.query.notifications.findMany({ where: and( eq(notifications.appBuildError, true), - eq(notifications.userId, userId), + eq(notifications.organizationId, organizationId), ), with: { email: true, diff --git a/packages/server/src/utils/notifications/build-success.ts b/packages/server/src/utils/notifications/build-success.ts index dfa4824f6..ac470c49f 100644 --- a/packages/server/src/utils/notifications/build-success.ts +++ b/packages/server/src/utils/notifications/build-success.ts @@ -18,7 +18,7 @@ interface Props { applicationName: string; applicationType: string; buildLink: string; - userId: string; + organizationId: string; domains: Domain[]; } @@ -27,7 +27,7 @@ export const sendBuildSuccessNotifications = async ({ applicationName, applicationType, buildLink, - userId, + organizationId, domains, }: Props) => { const date = new Date(); @@ -35,7 +35,7 @@ export const sendBuildSuccessNotifications = async ({ const notificationList = await db.query.notifications.findMany({ where: and( eq(notifications.appDeploy, true), - eq(notifications.userId, userId), + eq(notifications.organizationId, organizationId), ), with: { email: true, diff --git a/packages/server/src/utils/notifications/docker-cleanup.ts b/packages/server/src/utils/notifications/docker-cleanup.ts index 0acf1b6c4..b3959cccd 100644 --- a/packages/server/src/utils/notifications/docker-cleanup.ts +++ b/packages/server/src/utils/notifications/docker-cleanup.ts @@ -13,7 +13,7 @@ import { } from "./utils"; export const sendDockerCleanupNotifications = async ( - userId: string, + organizationId: string, message = "Docker cleanup for dokploy", ) => { const date = new Date(); @@ -21,7 +21,7 @@ export const sendDockerCleanupNotifications = async ( const notificationList = await db.query.notifications.findMany({ where: and( eq(notifications.dockerCleanup, true), - eq(notifications.userId, userId), + eq(notifications.organizationId, organizationId), ), with: { email: true,