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

This commit is contained in:
Mauricio Siu
2024-10-03 19:50:17 -06:00
parent ec1d6c7430
commit 767d3e1944
3 changed files with 66 additions and 39 deletions

View File

@@ -17,7 +17,6 @@ import { useEffect, useState } from "react";
export const AddGithubProvider = () => { export const AddGithubProvider = () => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const url = useUrl();
const { data } = api.auth.get.useQuery(); const { data } = api.auth.get.useQuery();
const [manifest, setManifest] = useState(""); const [manifest, setManifest] = useState("");
const [isOrganization, setIsOrganization] = useState(false); const [isOrganization, setIsOrganization] = useState(false);

View File

@@ -2,11 +2,11 @@ import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
import { db } from "@/server/db"; 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 } from "drizzle-orm"; import { desc, eq } from "drizzle-orm";
import { removeGitProvider } from "@dokploy/builders"; import { findGitProviderById, removeGitProvider } from "@dokploy/builders";
export const gitProviderRouter = createTRPCRouter({ export const gitProviderRouter = createTRPCRouter({
getAll: protectedProcedure.query(async () => { getAll: protectedProcedure.query(async ({ ctx }) => {
return await db.query.gitProvider.findMany({ return await db.query.gitProvider.findMany({
with: { with: {
gitlab: true, gitlab: true,
@@ -14,12 +14,21 @@ 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
}); });
}), }),
remove: protectedProcedure remove: protectedProcedure
.input(apiRemoveGitProvider) .input(apiRemoveGitProvider)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
try { try {
const gitProvider = await findGitProviderById(input.gitProviderId);
// if (gitProvider.adminId !== ctx.user.adminId) {
// throw new TRPCError({
// 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

@@ -13,10 +13,11 @@ import {
execAsync, execAsync,
manageRegistry, manageRegistry,
createRegistry, createRegistry,
findAllRegistry, findAllRegistryByAdminId,
findRegistryById, findRegistryById,
removeRegistry, removeRegistry,
updateRegistry, updateRegistry,
IS_CLOUD,
} from "@dokploy/builders"; } from "@dokploy/builders";
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc"; import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
@@ -24,17 +25,31 @@ export const registryRouter = createTRPCRouter({
create: adminProcedure create: adminProcedure
.input(apiCreateRegistry) .input(apiCreateRegistry)
.mutation(async ({ ctx, input }) => { .mutation(async ({ ctx, input }) => {
return await createRegistry(input); return await createRegistry(input, ctx.user.adminId);
}), }),
remove: adminProcedure remove: adminProcedure
.input(apiRemoveRegistry) .input(apiRemoveRegistry)
.mutation(async ({ ctx, input }) => { .mutation(async ({ ctx, input }) => {
const registry = await findRegistryById(input.registryId);
if (registry.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to delete this registry",
});
}
return await removeRegistry(input.registryId); return await removeRegistry(input.registryId);
}), }),
update: protectedProcedure update: protectedProcedure
.input(apiUpdateRegistry) .input(apiUpdateRegistry)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const { registryId, ...rest } = input; const { registryId, ...rest } = input;
const registry = await findRegistryById(registryId);
if (registry.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to update this registry",
});
}
const application = await updateRegistry(registryId, { const application = await updateRegistry(registryId, {
...rest, ...rest,
}); });
@@ -48,12 +63,21 @@ export const registryRouter = createTRPCRouter({
return true; return true;
}), }),
all: protectedProcedure.query(async () => { all: protectedProcedure.query(async ({ ctx }) => {
return await findAllRegistry(); return await findAllRegistryByAdminId(ctx.user.adminId);
}),
one: adminProcedure.input(apiFindOneRegistry).query(async ({ input }) => {
return await findRegistryById(input.registryId);
}), }),
one: adminProcedure
.input(apiFindOneRegistry)
.query(async ({ input, ctx }) => {
const registry = await findRegistryById(input.registryId);
if (registry.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to access this registry",
});
}
return registry;
}),
testRegistry: protectedProcedure testRegistry: protectedProcedure
.input(apiTestRegistry) .input(apiTestRegistry)
.mutation(async ({ input }) => { .mutation(async ({ input }) => {
@@ -75,18 +99,27 @@ export const registryRouter = createTRPCRouter({
enableSelfHostedRegistry: adminProcedure enableSelfHostedRegistry: adminProcedure
.input(apiEnableSelfHostedRegistry) .input(apiEnableSelfHostedRegistry)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const selfHostedRegistry = await createRegistry({ if (IS_CLOUD) {
...input, throw new TRPCError({
registryName: "Self Hosted Registry", code: "UNAUTHORIZED",
registryType: "selfHosted", message: "Self Hosted Registry is not available in the cloud version",
registryUrl: });
process.env.NODE_ENV === "production" }
? input.registryUrl const selfHostedRegistry = await createRegistry(
: "dokploy-registry.docker.localhost", {
imagePrefix: null, ...input,
serverId: undefined, registryName: "Self Hosted Registry",
}); registryType: "selfHosted",
registryUrl:
process.env.NODE_ENV === "production"
? input.registryUrl
: "dokploy-registry.docker.localhost",
imagePrefix: null,
serverId: undefined,
},
ctx.user.adminId,
);
await manageRegistry(selfHostedRegistry); await manageRegistry(selfHostedRegistry);
await initializeRegistry(input.username, input.password); await initializeRegistry(input.username, input.password);
@@ -94,17 +127,3 @@ export const registryRouter = createTRPCRouter({
return selfHostedRegistry; return selfHostedRegistry;
}), }),
}); });
const shellEscape = (str: string) => {
const ret = [];
let s = str;
if (/[^A-Za-z0-9_\/:=-]/.test(s)) {
s = `'${s.replace(/'/g, "'\\''")}'`;
s = s
.replace(/^(?:'')+/g, "") // unduplicate single-quote at the beginning
.replace(/\\'''/g, "\\'"); // remove non-escaped single-quote if there are enclosed between 2 escaped
}
ret.push(s);
return ret.join(" ");
};