refactor(cloud): add validation to prevent access to shared resources

This commit is contained in:
Mauricio Siu
2024-10-04 20:44:57 -06:00
parent 5cebf5540a
commit 7c4987d84d
14 changed files with 353 additions and 146 deletions

View File

@@ -11,7 +11,6 @@ import {
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch"; import { Switch } from "@/components/ui/switch";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { useUrl } from "@/utils/hooks/use-url";
import { format } from "date-fns"; import { format } from "date-fns";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";

View File

@@ -11,6 +11,7 @@ interface TabInfo {
tabLabel?: string; tabLabel?: string;
description: string; description: string;
index: string; index: string;
type: TabState;
isShow?: ({ rol, user }: { rol?: Auth["rol"]; user?: User }) => boolean; isShow?: ({ rol, user }: { rol?: Auth["rol"]; user?: User }) => boolean;
} }
@@ -23,19 +24,24 @@ export type TabState =
| "docker"; | "docker";
const getTabMaps = (isCloud: boolean) => { const getTabMaps = (isCloud: boolean) => {
const tabMap: Record<TabState | undefined, TabInfo> = { const elements: TabInfo[] = [
projects: { {
label: "Projects", label: "Projects",
description: "Manage your projects", description: "Manage your projects",
index: "/dashboard/projects", index: "/dashboard/projects",
type: "projects",
}, },
...(!isCloud && { ];
monitoring: {
if (!isCloud) {
elements.push(
{
label: "Monitoring", label: "Monitoring",
description: "Monitor your projects", description: "Monitor your projects",
index: "/dashboard/monitoring", index: "/dashboard/monitoring",
type: "monitoring",
}, },
traefik: { {
label: "Traefik", label: "Traefik",
tabLabel: "Traefik File System", tabLabel: "Traefik File System",
description: "Manage your traefik", description: "Manage your traefik",
@@ -43,35 +49,39 @@ const getTabMaps = (isCloud: boolean) => {
isShow: ({ rol, user }) => { isShow: ({ rol, user }) => {
return Boolean(rol === "admin" || user?.canAccessToTraefikFiles); return Boolean(rol === "admin" || user?.canAccessToTraefikFiles);
}, },
type: "traefik",
}, },
docker: { {
label: "Docker", label: "Docker",
description: "Manage your docker", description: "Manage your docker",
index: "/dashboard/docker", index: "/dashboard/docker",
isShow: ({ rol, user }) => { isShow: ({ rol, user }) => {
return Boolean(rol === "admin" || user?.canAccessToDocker); return Boolean(rol === "admin" || user?.canAccessToDocker);
}, },
type: "docker",
}, },
requests: { {
label: "Requests", label: "Requests",
description: "Manage your requests", description: "Manage your requests",
index: "/dashboard/requests", index: "/dashboard/requests",
isShow: ({ rol, user }) => { isShow: ({ rol, user }) => {
return Boolean(rol === "admin" || user?.canAccessToDocker); return Boolean(rol === "admin" || user?.canAccessToDocker);
}, },
type: "requests",
}, },
}), );
}
settings: { elements.push({
label: "Settings", label: "Settings",
description: "Manage your settings", description: "Manage your settings",
index: isCloud type: "settings",
? "/dashboard/settings/profile" index: isCloud
: "/dashboard/settings/server", ? "/dashboard/settings/profile"
}, : "/dashboard/settings/server",
}; });
return tabMap; return elements;
}; };
interface Props { interface Props {
@@ -99,7 +109,7 @@ export const NavigationTabs = ({ tab, children }: Props) => {
}, [tab]); }, [tab]);
const activeTabInfo = useMemo(() => { const activeTabInfo = useMemo(() => {
return tabMap[activeTab]; return tabMap.find((tab) => tab.type === activeTab);
}, [activeTab]); }, [activeTab]);
return ( return (
@@ -107,10 +117,10 @@ export const NavigationTabs = ({ tab, children }: Props) => {
<header className="mb-6 flex w-full items-center gap-2 justify-between flex-wrap"> <header className="mb-6 flex w-full items-center gap-2 justify-between flex-wrap">
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<h1 className="text-xl font-bold lg:text-3xl"> <h1 className="text-xl font-bold lg:text-3xl">
{activeTabInfo.label} {activeTabInfo?.label}
</h1> </h1>
<p className="lg:text-medium text-muted-foreground"> <p className="lg:text-medium text-muted-foreground">
{activeTabInfo.description} {activeTabInfo?.description}
</p> </p>
</div> </div>
{tab === "projects" && {tab === "projects" &&
@@ -122,27 +132,26 @@ export const NavigationTabs = ({ tab, children }: Props) => {
className="w-full" className="w-full"
onValueChange={async (e) => { onValueChange={async (e) => {
setActiveTab(e as TabState); setActiveTab(e as TabState);
router.push(tabMap[e as TabState].index); const tab = tabMap.find((tab) => tab.type === e);
router.push(tab?.index || "");
}} }}
> >
{/* className="grid w-fit grid-cols-4 bg-transparent" */}
<div className="flex flex-row items-center justify-between w-full gap-4 max-sm:overflow-x-auto border-b border-b-divider pb-1"> <div className="flex flex-row items-center justify-between w-full gap-4 max-sm:overflow-x-auto border-b border-b-divider pb-1">
<TabsList className="bg-transparent relative px-0"> <TabsList className="bg-transparent relative px-0">
{Object.keys(tabMap).map((key) => { {tabMap.map((tab, index) => {
const tab = tabMap[key as TabState]; if (tab?.isShow && !tab?.isShow?.({ rol: data?.rol, user })) {
if (tab.isShow && !tab.isShow?.({ rol: data?.rol, user })) {
return null; return null;
} }
return ( return (
<TabsTrigger <TabsTrigger
key={key} key={tab.type}
value={key} value={tab.type}
className="relative py-2.5 md:px-5 data-[state=active]:shadow-none data-[state=active]:bg-transparent rounded-md hover:bg-zinc-100 hover:dark:bg-zinc-800 data-[state=active]:hover:bg-zinc-100 data-[state=active]:hover:dark:bg-zinc-800" className="relative py-2.5 md:px-5 data-[state=active]:shadow-none data-[state=active]:bg-transparent rounded-md hover:bg-zinc-100 hover:dark:bg-zinc-800 data-[state=active]:hover:bg-zinc-100 data-[state=active]:hover:dark:bg-zinc-800"
> >
<span className="relative z-[1] w-full"> <span className="relative z-[1] w-full">
{tab.tabLabel || tab.label} {tab?.tabLabel || tab?.label}
</span> </span>
{key === activeTab && ( {tab.type === activeTab && (
<div className="absolute -bottom-[5.5px] w-full"> <div className="absolute -bottom-[5.5px] w-full">
<div className="h-0.5 bg-foreground rounded-t-md" /> <div className="h-0.5 bg-foreground rounded-t-md" />
</div> </div>

View File

@@ -48,12 +48,16 @@ export const SettingsLayout = ({ children }: Props) => {
icon: Database, icon: Database,
href: "/dashboard/settings/destinations", href: "/dashboard/settings/destinations",
}, },
{ ...(!isCloud
title: "Certificates", ? [
label: "", {
icon: ShieldCheck, title: "Certificates",
href: "/dashboard/settings/certificates", label: "",
}, icon: ShieldCheck,
href: "/dashboard/settings/certificates",
},
]
: []),
{ {
title: "SSH Keys", title: "SSH Keys",
label: "", label: "",

View File

@@ -23,7 +23,7 @@ export default async function handler(
const signature = req.headers["x-hub-signature-256"]; const signature = req.headers["x-hub-signature-256"];
const githubBody = req.body; const githubBody = req.body;
if (!githubBody?.installation.id) { if (!githubBody?.installation?.id) {
res.status(400).json({ message: "Github Installation not found" }); res.status(400).json({ message: "Github Installation not found" });
return; return;
} }

View File

@@ -1,4 +1,9 @@
import { createGithub } from "@dokploy/builders"; import {
createGithub,
findAdminByAuthId,
findAuthById,
findUserByAuthId,
} from "@dokploy/builders";
import { db } from "@/server/db"; import { db } from "@/server/db";
import { github } from "@/server/db/schema"; import { github } from "@/server/db/schema";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
@@ -34,16 +39,29 @@ export default async function handler(
}, },
); );
await createGithub({ const auth = await findAuthById(value as string);
name: data.name,
githubAppName: data.html_url, let adminId = "";
githubAppId: data.id, if (auth.rol === "admin") {
githubClientId: data.client_id, const admin = await findAdminByAuthId(auth.id);
githubClientSecret: data.client_secret, adminId = admin.adminId;
githubWebhookSecret: data.webhook_secret, } else {
githubPrivateKey: data.pem, const user = await findUserByAuthId(auth.id);
authId: value as string, adminId = user.adminId;
}); }
await createGithub(
{
name: data.name,
githubAppName: data.html_url,
githubAppId: data.id,
githubClientId: data.client_id,
githubClientSecret: data.client_secret,
githubWebhookSecret: data.webhook_secret,
githubPrivateKey: data.pem,
},
adminId,
);
} else if (action === "gh_setup") { } else if (action === "gh_setup") {
await db await db
.update(github) .update(github)

View File

@@ -220,7 +220,7 @@ export const authRouter = createTRPCRouter({
lucia.createSessionCookie(session.id).serialize(), lucia.createSessionCookie(session.id).serialize(),
); );
return auth; return true;
}), }),
disable2FA: protectedProcedure.mutation(async ({ ctx }) => { disable2FA: protectedProcedure.mutation(async ({ ctx }) => {
const auth = await findAuthById(ctx.user.authId); const auth = await findAuthById(ctx.user.authId);

View File

@@ -14,6 +14,7 @@ import {
createBitbucket, createBitbucket,
findBitbucketById, findBitbucketById,
updateBitbucket, updateBitbucket,
IS_CLOUD,
} from "@dokploy/builders"; } from "@dokploy/builders";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
@@ -33,11 +34,22 @@ export const bitbucketRouter = createTRPCRouter({
}), }),
one: protectedProcedure one: protectedProcedure
.input(apiFindOneBitbucket) .input(apiFindOneBitbucket)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
return await findBitbucketById(input.bitbucketId); const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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",
});
}
return bitbucketProvider;
}), }),
bitbucketProviders: protectedProcedure.query(async () => { bitbucketProviders: protectedProcedure.query(async ({ ctx }) => {
const result = await db.query.bitbucket.findMany({ let result = await db.query.bitbucket.findMany({
with: { with: {
gitProvider: true, gitProvider: true,
}, },
@@ -45,23 +57,65 @@ export const bitbucketRouter = createTRPCRouter({
bitbucketId: true, bitbucketId: true,
}, },
}); });
if (IS_CLOUD) {
// TODO: mAyBe a rEfaCtoR 🤫
result = result.filter(
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
);
}
return result; return result;
}), }),
getBitbucketRepositories: protectedProcedure getBitbucketRepositories: protectedProcedure
.input(apiFindOneBitbucket) .input(apiFindOneBitbucket)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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",
});
}
return await getBitbucketRepositories(input.bitbucketId); return await getBitbucketRepositories(input.bitbucketId);
}), }),
getBitbucketBranches: protectedProcedure getBitbucketBranches: protectedProcedure
.input(apiFindBitbucketBranches) .input(apiFindBitbucketBranches)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const bitbucketProvider = await findBitbucketById(
input.bitbucketId || "",
);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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",
});
}
return await getBitbucketBranches(input); return await getBitbucketBranches(input);
}), }),
testConnection: protectedProcedure testConnection: protectedProcedure
.input(apiBitbucketTestConnection) .input(apiBitbucketTestConnection)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
try { try {
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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",
});
}
const result = await testBitbucketConnection(input); const result = await testBitbucketConnection(input);
return `Found ${result} repositories`; return `Found ${result} repositories`;
@@ -75,6 +129,17 @@ export const bitbucketRouter = createTRPCRouter({
update: protectedProcedure update: protectedProcedure
.input(apiUpdateBitbucket) .input(apiUpdateBitbucket)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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",
});
}
return await updateBitbucket(input.bitbucketId, { return await updateBitbucket(input.bitbucketId, {
...input, ...input,
adminId: ctx.user.adminId, adminId: ctx.user.adminId,

View File

@@ -3,7 +3,11 @@ import { db } from "@/server/db";
import { apiRemoveGitProvider, gitProvider } from "@/server/db/schema"; import { apiRemoveGitProvider, gitProvider } from "@/server/db/schema";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { desc, eq } from "drizzle-orm"; import { desc, eq } from "drizzle-orm";
import { findGitProviderById, removeGitProvider } from "@dokploy/builders"; import {
findGitProviderById,
IS_CLOUD,
removeGitProvider,
} from "@dokploy/builders";
export const gitProviderRouter = createTRPCRouter({ export const gitProviderRouter = createTRPCRouter({
getAll: protectedProcedure.query(async ({ ctx }) => { getAll: protectedProcedure.query(async ({ ctx }) => {
@@ -14,7 +18,8 @@ export const gitProviderRouter = createTRPCRouter({
github: true, github: true,
}, },
orderBy: desc(gitProvider.createdAt), orderBy: desc(gitProvider.createdAt),
// where: eq(gitProvider.adminId, ctx.user.adminId), //TODO: Remove this line when the cloud version is ready ...(IS_CLOUD && { where: eq(gitProvider.adminId, ctx.user.adminId) }),
//TODO: Remove this line when the cloud version is ready
}); });
}), }),
remove: protectedProcedure remove: protectedProcedure
@@ -23,12 +28,13 @@ export const gitProviderRouter = createTRPCRouter({
try { try {
const gitProvider = await findGitProviderById(input.gitProviderId); const gitProvider = await findGitProviderById(input.gitProviderId);
// if (gitProvider.adminId !== ctx.user.adminId) { if (IS_CLOUD && gitProvider.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not allowed to delete this git provider", code: "UNAUTHORIZED",
// }); message: "You are not allowed to delete this git provider",
// } });
}
return await removeGitProvider(input.gitProviderId); return await removeGitProvider(input.gitProviderId);
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({

View File

@@ -12,6 +12,7 @@ import {
findGithubById, findGithubById,
haveGithubRequirements, haveGithubRequirements,
updateGitProvider, updateGitProvider,
IS_CLOUD,
} from "@dokploy/builders"; } from "@dokploy/builders";
export const githubRouter = createTRPCRouter({ export const githubRouter = createTRPCRouter({
@@ -19,31 +20,55 @@ export const githubRouter = createTRPCRouter({
.input(apiFindOneGithub) .input(apiFindOneGithub)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
const githubProvider = await findGithubById(input.githubId); const githubProvider = await findGithubById(input.githubId);
// if (githubProvider.gitProvider.adminId !== ctx.user.adminId) { //TODO: Remove this line when the cloud version is ready if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
// throw new TRPCError({ //TODO: Remove this line when the cloud version is ready
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not allowed to access this github provider", code: "UNAUTHORIZED",
// }); message: "You are not allowed to access this github provider",
// } });
}
return githubProvider; return githubProvider;
}), }),
getGithubRepositories: protectedProcedure getGithubRepositories: protectedProcedure
.input(apiFindOneGithub) .input(apiFindOneGithub)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const githubProvider = await findGithubById(input.githubId);
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
//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",
});
}
return await getGithubRepositories(input.githubId); return await getGithubRepositories(input.githubId);
}), }),
getGithubBranches: protectedProcedure getGithubBranches: protectedProcedure
.input(apiFindGithubBranches) .input(apiFindGithubBranches)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const githubProvider = await findGithubById(input.githubId || "");
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
//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",
});
}
return await getGithubBranches(input); return await getGithubBranches(input);
}), }),
githubProviders: protectedProcedure.query(async () => { githubProviders: protectedProcedure.query(async ({ ctx }) => {
const result = await db.query.github.findMany({ let result = await db.query.github.findMany({
with: { with: {
gitProvider: true, gitProvider: true,
}, },
}); });
if (IS_CLOUD) {
// TODO: mAyBe a rEfaCtoR 🤫
result = result.filter(
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
);
}
const filtered = result const filtered = result
.filter((provider) => haveGithubRequirements(provider)) .filter((provider) => haveGithubRequirements(provider))
.map((provider) => { .map((provider) => {
@@ -60,8 +85,19 @@ export const githubRouter = createTRPCRouter({
testConnection: protectedProcedure testConnection: protectedProcedure
.input(apiFindOneGithub) .input(apiFindOneGithub)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
try { try {
const githubProvider = await findGithubById(input.githubId);
if (
IS_CLOUD &&
githubProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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",
});
}
const result = await getGithubRepositories(input.githubId); const result = await getGithubRepositories(input.githubId);
return `Found ${result.length} repositories`; return `Found ${result.length} repositories`;
} catch (err) { } catch (err) {
@@ -75,12 +111,13 @@ export const githubRouter = createTRPCRouter({
.input(apiUpdateGithub) .input(apiUpdateGithub)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
const githubProvider = await findGithubById(input.githubId); const githubProvider = await findGithubById(input.githubId);
// if (githubProvider.gitProvider.adminId !== ctx.user.adminId) { //TODO: Remove this line when the cloud version is ready if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
// throw new TRPCError({ //TODO: Remove this line when the cloud version is ready
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not allowed to access this github provider", code: "UNAUTHORIZED",
// }); message: "You are not allowed to access this github provider",
// } });
}
await updateGitProvider(input.gitProviderId, { await updateGitProvider(input.gitProviderId, {
name: input.name, name: input.name,
adminId: ctx.user.adminId, adminId: ctx.user.adminId,

View File

@@ -18,6 +18,7 @@ import {
findGitlabById, findGitlabById,
updateGitlab, updateGitlab,
updateGitProvider, updateGitProvider,
IS_CLOUD,
} from "@dokploy/builders"; } from "@dokploy/builders";
export const gitlabRouter = createTRPCRouter({ export const gitlabRouter = createTRPCRouter({
@@ -34,15 +35,32 @@ export const gitlabRouter = createTRPCRouter({
}); });
} }
}), }),
one: protectedProcedure.input(apiFindOneGitlab).query(async ({ input }) => { one: protectedProcedure
return await findGitlabById(input.gitlabId); .input(apiFindOneGitlab)
}), .query(async ({ input, ctx }) => {
gitlabProviders: protectedProcedure.query(async () => { const gitlabProvider = await findGitlabById(input.gitlabId);
const result = await db.query.gitlab.findMany({ if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
//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",
});
}
return gitlabProvider;
}),
gitlabProviders: protectedProcedure.query(async ({ ctx }) => {
let result = await db.query.gitlab.findMany({
with: { with: {
gitProvider: true, gitProvider: true,
}, },
}); });
if (IS_CLOUD) {
// TODO: mAyBe a rEfaCtoR 🤫
result = result.filter(
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
);
}
const filtered = result const filtered = result
.filter((provider) => haveGitlabRequirements(provider)) .filter((provider) => haveGitlabRequirements(provider))
.map((provider) => { .map((provider) => {
@@ -58,19 +76,46 @@ export const gitlabRouter = createTRPCRouter({
}), }),
getGitlabRepositories: protectedProcedure getGitlabRepositories: protectedProcedure
.input(apiFindOneGitlab) .input(apiFindOneGitlab)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const gitlabProvider = await findGitlabById(input.gitlabId);
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
//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",
});
}
return await getGitlabRepositories(input.gitlabId); return await getGitlabRepositories(input.gitlabId);
}), }),
getGitlabBranches: protectedProcedure getGitlabBranches: protectedProcedure
.input(apiFindGitlabBranches) .input(apiFindGitlabBranches)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const gitlabProvider = await findGitlabById(input.gitlabId || "");
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
//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",
});
}
return await getGitlabBranches(input); return await getGitlabBranches(input);
}), }),
testConnection: protectedProcedure testConnection: protectedProcedure
.input(apiGitlabTestConnection) .input(apiGitlabTestConnection)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
try { try {
const gitlabProvider = await findGitlabById(input.gitlabId || "");
if (
IS_CLOUD &&
gitlabProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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",
});
}
const result = await testGitlabConnection(input); const result = await testGitlabConnection(input);
return `Found ${result} repositories`; return `Found ${result} repositories`;
@@ -84,6 +129,14 @@ export const gitlabRouter = createTRPCRouter({
update: protectedProcedure update: protectedProcedure
.input(apiUpdateGitlab) .input(apiUpdateGitlab)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
const gitlabProvider = await findGitlabById(input.gitlabId);
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
//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",
});
}
if (input.name) { if (input.name) {
await updateGitProvider(input.gitProviderId, { await updateGitProvider(input.gitProviderId, {
name: input.name, name: input.name,

View File

@@ -37,6 +37,7 @@ import {
sendEmailNotification, sendEmailNotification,
sendSlackNotification, sendSlackNotification,
sendTelegramNotification, sendTelegramNotification,
IS_CLOUD,
} from "@dokploy/builders"; } from "@dokploy/builders";
// TODO: Uncomment the validations when is cloud ready // TODO: Uncomment the validations when is cloud ready
@@ -59,12 +60,13 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
const notification = await findNotificationById(input.notificationId); const notification = await findNotificationById(input.notificationId);
// if (notification.adminId !== ctx.user.adminId) { if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not authorized to update this notification", code: "UNAUTHORIZED",
// }); message: "You are not authorized to update this notification",
// } });
}
return await updateSlackNotification({ return await updateSlackNotification({
...input, ...input,
adminId: ctx.user.adminId, adminId: ctx.user.adminId,
@@ -109,12 +111,13 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
const notification = await findNotificationById(input.notificationId); const notification = await findNotificationById(input.notificationId);
// if (notification.adminId !== ctx.user.adminId) { if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not authorized to update this notification", code: "UNAUTHORIZED",
// }); message: "You are not authorized to update this notification",
// } });
}
return await updateTelegramNotification({ return await updateTelegramNotification({
...input, ...input,
adminId: ctx.user.adminId, adminId: ctx.user.adminId,
@@ -166,12 +169,13 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
const notification = await findNotificationById(input.notificationId); const notification = await findNotificationById(input.notificationId);
// if (notification.adminId !== ctx.user.adminId) { if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not authorized to update this notification", code: "UNAUTHORIZED",
// }); message: "You are not authorized to update this notification",
// } });
}
return await updateDiscordNotification({ return await updateDiscordNotification({
...input, ...input,
adminId: ctx.user.adminId, adminId: ctx.user.adminId,
@@ -220,12 +224,13 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
const notification = await findNotificationById(input.notificationId); const notification = await findNotificationById(input.notificationId);
// if (notification.adminId !== ctx.user.adminId) { if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not authorized to update this notification", code: "UNAUTHORIZED",
// }); message: "You are not authorized to update this notification",
// } });
}
return await updateEmailNotification({ return await updateEmailNotification({
...input, ...input,
adminId: ctx.user.adminId, adminId: ctx.user.adminId,
@@ -261,12 +266,13 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
const notification = await findNotificationById(input.notificationId); const notification = await findNotificationById(input.notificationId);
// if (notification.adminId !== ctx.user.adminId) { if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not authorized to delete this notification", code: "UNAUTHORIZED",
// }); message: "You are not authorized to delete this notification",
// } });
}
return await removeNotificationById(input.notificationId); return await removeNotificationById(input.notificationId);
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({
@@ -279,12 +285,13 @@ export const notificationRouter = createTRPCRouter({
.input(apiFindOneNotification) .input(apiFindOneNotification)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
const notification = await findNotificationById(input.notificationId); const notification = await findNotificationById(input.notificationId);
// if (notification.adminId !== ctx.user.adminId) { if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not authorized to access this notification", code: "UNAUTHORIZED",
// }); message: "You are not authorized to access this notification",
// } });
}
return notification; return notification;
}), }),
all: adminProcedure.query(async ({ ctx }) => { all: adminProcedure.query(async ({ ctx }) => {
@@ -296,7 +303,8 @@ export const notificationRouter = createTRPCRouter({
email: true, email: true,
}, },
orderBy: desc(notifications.createdAt), orderBy: desc(notifications.createdAt),
// where: eq(notifications.adminId, ctx.user.adminId), ...(IS_CLOUD && { where: eq(notifications.adminId, ctx.user.adminId) }),
// TODO: Remove this line when the cloud version is ready
}); });
}), }),
}); });

View File

@@ -484,7 +484,10 @@ export const settingsRouter = createTRPCRouter({
.input(apiReadStatsLogs) .input(apiReadStatsLogs)
.query(({ input }) => { .query(({ input }) => {
if (IS_CLOUD) { if (IS_CLOUD) {
return true; return {
data: [],
totalCount: 0,
};
} }
const rawConfig = readMonitoringConfig(); const rawConfig = readMonitoringConfig();
const parsedConfig = parseRawConfig( const parsedConfig = parseRawConfig(
@@ -499,7 +502,7 @@ export const settingsRouter = createTRPCRouter({
}), }),
readStats: adminProcedure.query(() => { readStats: adminProcedure.query(() => {
if (IS_CLOUD) { if (IS_CLOUD) {
return true; return [];
} }
const rawConfig = readMonitoringConfig(); const rawConfig = readMonitoringConfig();
const processedLogs = processLogs(rawConfig as string); const processedLogs = processLogs(rawConfig as string);

View File

@@ -15,7 +15,9 @@ import {
findSSHKeyById, findSSHKeyById,
removeSSHKeyById, removeSSHKeyById,
updateSSHKeyById, updateSSHKeyById,
IS_CLOUD,
} from "@dokploy/builders"; } from "@dokploy/builders";
import { eq } from "drizzle-orm";
export const sshRouter = createTRPCRouter({ export const sshRouter = createTRPCRouter({
create: protectedProcedure create: protectedProcedure
@@ -39,12 +41,14 @@ export const sshRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
const sshKey = await findSSHKeyById(input.sshKeyId); const sshKey = await findSSHKeyById(input.sshKeyId);
// if (sshKey.adminId !== ctx.user.adminId) { if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not allowed to delete this ssh key", code: "UNAUTHORIZED",
// }); message: "You are not allowed to delete this ssh key",
// } });
}
return await removeSSHKeyById(input.sshKeyId); return await removeSSHKeyById(input.sshKeyId);
} catch (error) { } catch (error) {
throw error; throw error;
@@ -55,7 +59,8 @@ export const sshRouter = createTRPCRouter({
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
const sshKey = await findSSHKeyById(input.sshKeyId); const sshKey = await findSSHKeyById(input.sshKeyId);
if (sshKey.adminId !== ctx.user.adminId) { if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
message: "You are not allowed to access this ssh key", message: "You are not allowed to access this ssh key",
@@ -64,10 +69,10 @@ export const sshRouter = createTRPCRouter({
return sshKey; return sshKey;
}), }),
all: protectedProcedure.query(async ({ ctx }) => { all: protectedProcedure.query(async ({ ctx }) => {
return await db.query.sshKeys.findMany({}); return await db.query.sshKeys.findMany({
// return await db.query.sshKeys.findMany({ ...(IS_CLOUD && { where: eq(sshKeys.adminId, ctx.user.adminId) }),
// where: eq(sshKeys.adminId, ctx.user.adminId), });
// }); // TODO: Remove this line when the cloud version is ready // TODO: Remove this line when the cloud version is ready
}), }),
generate: protectedProcedure generate: protectedProcedure
.input(apiGenerateSSHKey) .input(apiGenerateSSHKey)
@@ -79,12 +84,13 @@ export const sshRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
const sshKey = await findSSHKeyById(input.sshKeyId); const sshKey = await findSSHKeyById(input.sshKeyId);
// if (sshKey.adminId !== ctx.user.adminId) { if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
// throw new TRPCError({ // TODO: Remove isCloud in the next versions of dokploy
// code: "UNAUTHORIZED", throw new TRPCError({
// message: "You are not allowed to update this ssh key", code: "UNAUTHORIZED",
// }); message: "You are not allowed to update this ssh key",
// } });
}
return await updateSSHKeyById(input); return await updateSSHKeyById(input);
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({

View File

@@ -40,7 +40,6 @@ export const apiCreateGithub = createSchema.extend({
githubWebhookSecret: z.string().nullable(), githubWebhookSecret: z.string().nullable(),
gitProviderId: z.string().optional(), gitProviderId: z.string().optional(),
name: z.string().min(1), name: z.string().min(1),
authId: z.string().min(1),
}); });
export const apiFindGithubBranches = z.object({ export const apiFindGithubBranches = z.object({