refactor(cloud): validate all the routes to prevent get access from private resource

This commit is contained in:
Mauricio Siu 2024-10-03 19:34:38 -06:00
parent cc90d9ec9b
commit 8abeae5e63
17 changed files with 796 additions and 163 deletions

View File

@ -10,16 +10,18 @@ import {
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import {
findAdmin,
createInvitation,
getUserByToken,
removeUserByAuthId,
findAdminById,
findUserByAuthId,
findUserById,
} from "@dokploy/builders";
import { adminProcedure, createTRPCRouter, publicProcedure } from "../trpc";
export const adminRouter = createTRPCRouter({
one: adminProcedure.query(async ({ ctx }) => {
const { sshPrivateKey, ...rest } = await findAdmin();
const { sshPrivateKey, ...rest } = await findAdminById(ctx.user.adminId);
return {
haveSSH: !!sshPrivateKey,
...rest,
@ -27,9 +29,9 @@ export const adminRouter = createTRPCRouter({
}),
createUserInvitation: adminProcedure
.input(apiCreateUserInvitation)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
await createInvitation(input);
await createInvitation(input, ctx.user.adminId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@ -41,8 +43,16 @@ export const adminRouter = createTRPCRouter({
}),
removeUser: adminProcedure
.input(apiRemoveUser)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
const user = await findUserByAuthId(input.authId);
if (user.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to delete this user",
});
}
return await removeUserByAuthId(input.authId);
} catch (error) {
throw new TRPCError({
@ -59,8 +69,16 @@ export const adminRouter = createTRPCRouter({
}),
assignPermissions: adminProcedure
.input(apiAssignPermissions)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
const user = await findUserById(input.userId);
if (user.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to assign permissions",
});
}
await db
.update(users)
.set({
@ -68,10 +86,7 @@ export const adminRouter = createTRPCRouter({
})
.where(eq(users.userId, input.userId));
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error to assign permissions",
});
throw error;
}
}),
});

View File

@ -47,6 +47,7 @@ import {
removeDeployments,
addNewService,
checkServiceAccess,
IS_CLOUD,
// uploadFileSchema
} from "@dokploy/builders";
import { uploadFileSchema } from "@/utils/schema";
@ -89,13 +90,26 @@ export const applicationRouter = createTRPCRouter({
"access",
);
}
return await findApplicationById(input.applicationId);
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",
});
}
return application;
}),
reload: protectedProcedure
.input(apiReloadApplication)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this application",
});
}
if (application.serverId) {
await stopServiceRemote(application.serverId, input.appName);
} else {
@ -124,6 +138,13 @@ export const applicationRouter = createTRPCRouter({
}
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this application",
});
}
const result = await db
.delete(applications)
.where(eq(applications.applicationId, input.applicationId))
@ -156,8 +177,14 @@ export const applicationRouter = createTRPCRouter({
stop: protectedProcedure
.input(apiFindOneApplication)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const service = await findApplicationById(input.applicationId);
if (service.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this application",
});
}
if (service.serverId) {
await stopServiceRemote(service.serverId, service.appName);
} else {
@ -170,8 +197,15 @@ export const applicationRouter = createTRPCRouter({
start: protectedProcedure
.input(apiFindOneApplication)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const service = await findApplicationById(input.applicationId);
if (service.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this application",
});
}
if (service.serverId) {
await startServiceRemote(service.serverId, service.appName);
} else {
@ -184,8 +218,14 @@ export const applicationRouter = createTRPCRouter({
redeploy: protectedProcedure
.input(apiFindOneApplication)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to redeploy this application",
});
}
const jobData: DeploymentJob = {
applicationId: input.applicationId,
titleLog: "Rebuild deployment",
@ -205,7 +245,14 @@ export const applicationRouter = createTRPCRouter({
}),
saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariables)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
});
}
await updateApplication(input.applicationId, {
env: input.env,
buildArgs: input.buildArgs,
@ -214,7 +261,14 @@ export const applicationRouter = createTRPCRouter({
}),
saveBuildType: protectedProcedure
.input(apiSaveBuildType)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this build type",
});
}
await updateApplication(input.applicationId, {
buildType: input.buildType,
dockerfile: input.dockerfile,
@ -227,7 +281,14 @@ export const applicationRouter = createTRPCRouter({
}),
saveGithubProvider: protectedProcedure
.input(apiSaveGithubProvider)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this github provider",
});
}
await updateApplication(input.applicationId, {
repository: input.repository,
branch: input.branch,
@ -242,7 +303,14 @@ export const applicationRouter = createTRPCRouter({
}),
saveGitlabProvider: protectedProcedure
.input(apiSaveGitlabProvider)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this gitlab provider",
});
}
await updateApplication(input.applicationId, {
gitlabRepository: input.gitlabRepository,
gitlabOwner: input.gitlabOwner,
@ -259,7 +327,14 @@ export const applicationRouter = createTRPCRouter({
}),
saveBitbucketProvider: protectedProcedure
.input(apiSaveBitbucketProvider)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this bitbucket provider",
});
}
await updateApplication(input.applicationId, {
bitbucketRepository: input.bitbucketRepository,
bitbucketOwner: input.bitbucketOwner,
@ -274,7 +349,14 @@ export const applicationRouter = createTRPCRouter({
}),
saveDockerProvider: protectedProcedure
.input(apiSaveDockerProvider)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this docker provider",
});
}
await updateApplication(input.applicationId, {
dockerImage: input.dockerImage,
username: input.username,
@ -287,7 +369,14 @@ export const applicationRouter = createTRPCRouter({
}),
saveGitProdiver: protectedProcedure
.input(apiSaveGitProvider)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this git provider",
});
}
await updateApplication(input.applicationId, {
customGitBranch: input.customGitBranch,
customGitBuildPath: input.customGitBuildPath,
@ -301,18 +390,32 @@ export const applicationRouter = createTRPCRouter({
}),
markRunning: protectedProcedure
.input(apiFindOneApplication)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to mark this application as running",
});
}
await updateApplicationStatus(input.applicationId, "running");
}),
update: protectedProcedure
.input(apiUpdateApplication)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this application",
});
}
const { applicationId, ...rest } = input;
const application = await updateApplication(applicationId, {
const updateApp = await updateApplication(applicationId, {
...rest,
});
if (!application) {
if (!updateApp) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Update: Error to update application",
@ -323,7 +426,14 @@ export const applicationRouter = createTRPCRouter({
}),
refreshToken: protectedProcedure
.input(apiFindOneApplication)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to refresh this application",
});
}
await updateApplication(input.applicationId, {
refreshToken: nanoid(),
});
@ -333,6 +443,12 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this application",
});
}
const jobData: DeploymentJob = {
applicationId: input.applicationId,
titleLog: "Manual deployment",
@ -353,14 +469,28 @@ export const applicationRouter = createTRPCRouter({
cleanQueues: protectedProcedure
.input(apiFindOneApplication)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to clean this application",
});
}
await cleanQueuesByApplication(input.applicationId);
}),
readTraefikConfig: protectedProcedure
.input(apiFindOneApplication)
.query(async ({ input }) => {
.query(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to read this application",
});
}
let traefikConfig = null;
if (application.serverId) {
traefikConfig = await readRemoteConfig(
@ -384,15 +514,23 @@ export const applicationRouter = createTRPCRouter({
})
.use(uploadProcedure)
.input(uploadFileSchema)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const zipFile = input.zip;
const app = await findApplicationById(input.applicationId as string);
if (app.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this application",
});
}
updateApplication(input.applicationId as string, {
sourceType: "drop",
dropBuildPath: input.dropBuildPath,
});
const app = await findApplicationById(input.applicationId as string);
await unzipDrop(zipFile, app);
const jobData: DeploymentJob = {
@ -415,9 +553,16 @@ export const applicationRouter = createTRPCRouter({
}),
updateTraefikConfig: protectedProcedure
.input(z.object({ applicationId: z.string(), traefikConfig: z.string() }))
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this application",
});
}
if (application.serverId) {
await writeConfigRemote(
application.serverId,
@ -431,14 +576,15 @@ export const applicationRouter = createTRPCRouter({
}),
readAppMonitoring: protectedProcedure
.input(apiFindMonitoringStats)
.query(async ({ input }) => {
.query(async ({ input, ctx }) => {
if (IS_CLOUD) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "Functionality not available in cloud version",
});
}
const stats = await getApplicationStats(input.appName);
return stats;
}),
});
// Paketo Buildpacks: paketobuildpacks/builder-jammy-full Ubuntu 22.04 Jammy Jellyfish full image with buildpacks for Apache HTTPD, Go, Java, Java Native Image, .NET, NGINX, Node.js, PHP, Procfile, Python, and Ruby
// Heroku: heroku/builder:22 Heroku-22 (Ubuntu 22.04) base image with buildpacks for Go, Java, Node.js, PHP, Python, Ruby & Scala.
// pack build imageName --path ./ --builder paketobuildpacks/builder-jammy-full
// pack build prueba-pack --path ./ --builder heroku/builder:22

View File

@ -83,12 +83,26 @@ export const composeRouter = createTRPCRouter({
await checkServiceAccess(ctx.user.authId, input.composeId, "access");
}
return await findComposeById(input.composeId);
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",
});
}
return compose;
}),
update: protectedProcedure
.input(apiUpdateCompose)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this compose",
});
}
return updateCompose(input.composeId, input);
}),
delete: protectedProcedure
@ -99,6 +113,14 @@ export const composeRouter = createTRPCRouter({
}
const composeResult = await findComposeById(input.composeId);
if (composeResult.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this compose",
});
}
4;
const result = await db
.delete(compose)
.where(eq(compose.composeId, input.composeId))
@ -120,20 +142,41 @@ export const composeRouter = createTRPCRouter({
}),
cleanQueues: protectedProcedure
.input(apiFindCompose)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to clean this compose",
});
}
await cleanQueuesByCompose(input.composeId);
}),
loadServices: protectedProcedure
.input(apiFetchServices)
.query(async ({ input }) => {
.query(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to load this compose",
});
}
return await loadServices(input.composeId, input.type);
}),
fetchSourceType: protectedProcedure
.input(apiFindCompose)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to fetch this compose",
});
}
if (compose.serverId) {
await cloneComposeRemote(compose);
} else {
@ -151,13 +194,26 @@ export const composeRouter = createTRPCRouter({
randomizeCompose: protectedProcedure
.input(apiRandomizeCompose)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to randomize this compose",
});
}
return await randomizeComposeFile(input.composeId, input.suffix);
}),
getConvertedCompose: protectedProcedure
.input(apiFindCompose)
.query(async ({ input }) => {
.query(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to get this compose",
});
}
const domains = await findDomainsByComposeId(input.composeId);
const composeFile = await addDomainToCompose(compose, domains);
return dump(composeFile, {
@ -167,8 +223,15 @@ export const composeRouter = createTRPCRouter({
deploy: protectedProcedure
.input(apiFindCompose)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this compose",
});
}
const jobData: DeploymentJob = {
composeId: input.composeId,
titleLog: "Manual deployment",
@ -188,8 +251,14 @@ export const composeRouter = createTRPCRouter({
}),
redeploy: protectedProcedure
.input(apiFindCompose)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to redeploy this compose",
});
}
const jobData: DeploymentJob = {
composeId: input.composeId,
titleLog: "Rebuild deployment",
@ -207,21 +276,44 @@ export const composeRouter = createTRPCRouter({
},
);
}),
stop: protectedProcedure.input(apiFindCompose).mutation(async ({ input }) => {
await stopCompose(input.composeId);
stop: protectedProcedure
.input(apiFindCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this compose",
});
}
await stopCompose(input.composeId);
return true;
}),
return true;
}),
getDefaultCommand: protectedProcedure
.input(apiFindCompose)
.query(async ({ input }) => {
.query(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to get this compose",
});
}
const command = createCommand(compose);
return `docker ${command}`;
}),
refreshToken: protectedProcedure
.input(apiFindCompose)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to refresh this compose",
});
}
await updateCompose(input.composeId, {
refreshToken: nanoid(),
});
@ -233,6 +325,7 @@ export const composeRouter = createTRPCRouter({
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
}
const composeFile = await readTemplateComposeFile(input.id);
const generate = await loadTemplateModule(input.id as TemplatesKeys);

View File

@ -9,6 +9,7 @@ import {
apiFindOneDestination,
apiRemoveDestination,
apiUpdateDestination,
destinations,
} from "@/server/db/schema";
import { TRPCError } from "@trpc/server";
import {
@ -19,14 +20,14 @@ import {
removeDestinationById,
updateDestinationById,
} from "@dokploy/builders";
import { eq } from "drizzle-orm";
export const destinationRouter = createTRPCRouter({
create: adminProcedure
.input(apiCreateDestination)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
await createDestintation(input);
return await findAdmin();
return await createDestintation(input, ctx.user.adminId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@ -54,7 +55,6 @@ export const destinationRouter = createTRPCRouter({
const rcloneCommand = `rclone ls ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
await execAsync(rcloneCommand);
} catch (error) {
console.log(error);
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error to connect to bucket",
@ -64,36 +64,58 @@ export const destinationRouter = createTRPCRouter({
}),
one: protectedProcedure
.input(apiFindOneDestination)
.query(async ({ input }) => {
.query(async ({ input, ctx }) => {
const destination = await findDestinationById(input.destinationId);
if (destination.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to access this destination",
});
}
return destination;
}),
all: protectedProcedure.query(async () => {
return await db.query.destinations.findMany({});
all: protectedProcedure.query(async ({ ctx }) => {
return await db.query.destinations.findMany({
where: eq(destinations.adminId, ctx.user.adminId),
});
}),
remove: adminProcedure
.input(apiRemoveDestination)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
return await removeDestinationById(input.destinationId);
const destination = await findDestinationById(input.destinationId);
if (destination.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to delete this destination",
});
}
return await removeDestinationById(
input.destinationId,
ctx.user.adminId,
);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error to delete this destination",
});
throw error;
}
}),
update: adminProcedure
.input(apiUpdateDestination)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
return await updateDestinationById(input.destinationId, input);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error to update this destination",
cause: error,
const destination = await findDestinationById(input.destinationId);
if (destination.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to update this destination",
});
}
return await updateDestinationById(input.destinationId, {
...input,
adminId: ctx.user.adminId,
});
} catch (error) {
throw error;
}
}),
});

View File

@ -66,13 +66,26 @@ export const mariadbRouter = createTRPCRouter({
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mariadbId, "access");
}
return await findMariadbById(input.mariadbId);
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this mariadb",
});
}
return mariadb;
}),
start: protectedProcedure
.input(apiFindOneMariaDB)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const service = await findMariadbById(input.mariadbId);
if (service.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this mariadb",
});
}
if (service.serverId) {
await startServiceRemote(service.serverId, service.appName);
} else {
@ -102,8 +115,14 @@ export const mariadbRouter = createTRPCRouter({
}),
saveExternalPort: protectedProcedure
.input(apiSaveExternalPortMariaDB)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMariadbById(input.mariadbId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
});
}
await updateMariadbById(input.mariadbId, {
externalPort: input.externalPort,
});
@ -112,13 +131,26 @@ export const mariadbRouter = createTRPCRouter({
}),
deploy: protectedProcedure
.input(apiDeployMariaDB)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this mariadb",
});
}
return deployMariadb(input.mariadbId);
}),
changeStatus: protectedProcedure
.input(apiChangeMariaDBStatus)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMariadbById(input.mariadbId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this mariadb status",
});
}
await updateMariadbById(input.mariadbId, {
applicationStatus: input.applicationStatus,
});
@ -132,6 +164,12 @@ export const mariadbRouter = createTRPCRouter({
}
const mongo = await findMariadbById(input.mariadbId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this mariadb",
});
}
const cleanupOperations = [
async () => await removeService(mongo?.appName, mongo.serverId),
@ -148,7 +186,14 @@ export const mariadbRouter = createTRPCRouter({
}),
saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariablesMariaDB)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
});
}
const service = await updateMariadbById(input.mariadbId, {
env: input.env,
});
@ -164,8 +209,14 @@ export const mariadbRouter = createTRPCRouter({
}),
reload: protectedProcedure
.input(apiResetMariadb)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this mariadb",
});
}
if (mariadb.serverId) {
await stopServiceRemote(mariadb.serverId, mariadb.appName);
} else {
@ -187,8 +238,15 @@ export const mariadbRouter = createTRPCRouter({
}),
update: protectedProcedure
.input(apiUpdateMariaDB)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const { mariadbId, ...rest } = input;
const mariadb = await findMariadbById(mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this mariadb",
});
}
const service = await updateMariadbById(mariadbId, {
...rest,
});

View File

@ -67,14 +67,28 @@ export const mongoRouter = createTRPCRouter({
await checkServiceAccess(ctx.user.authId, input.mongoId, "access");
}
return await findMongoById(input.mongoId);
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this mongo",
});
}
return mongo;
}),
start: protectedProcedure
.input(apiFindOneMongo)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const service = await findMongoById(input.mongoId);
if (service.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this mongo",
});
}
if (service.serverId) {
await startServiceRemote(service.serverId, service.appName);
} else {
@ -88,9 +102,16 @@ export const mongoRouter = createTRPCRouter({
}),
stop: protectedProcedure
.input(apiFindOneMongo)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this mongo",
});
}
if (mongo.serverId) {
await stopServiceRemote(mongo.serverId, mongo.appName);
} else {
@ -104,8 +125,14 @@ export const mongoRouter = createTRPCRouter({
}),
saveExternalPort: protectedProcedure
.input(apiSaveExternalPortMongo)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
});
}
await updateMongoById(input.mongoId, {
externalPort: input.externalPort,
});
@ -114,13 +141,26 @@ export const mongoRouter = createTRPCRouter({
}),
deploy: protectedProcedure
.input(apiDeployMongo)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this mongo",
});
}
return deployMongo(input.mongoId);
}),
changeStatus: protectedProcedure
.input(apiChangeMongoStatus)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this mongo status",
});
}
await updateMongoById(input.mongoId, {
applicationStatus: input.applicationStatus,
});
@ -128,8 +168,14 @@ export const mongoRouter = createTRPCRouter({
}),
reload: protectedProcedure
.input(apiResetMongo)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this mongo",
});
}
if (mongo.serverId) {
await stopServiceRemote(mongo.serverId, mongo.appName);
} else {
@ -158,6 +204,13 @@ export const mongoRouter = createTRPCRouter({
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this mongo",
});
}
const cleanupOperations = [
async () => await removeService(mongo?.appName, mongo.serverId),
async () => await removeMongoById(input.mongoId),
@ -173,7 +226,14 @@ export const mongoRouter = createTRPCRouter({
}),
saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariablesMongo)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
});
}
const service = await updateMongoById(input.mongoId, {
env: input.env,
});
@ -189,8 +249,15 @@ export const mongoRouter = createTRPCRouter({
}),
update: protectedProcedure
.input(apiUpdateMongo)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const { mongoId, ...rest } = input;
const mongo = await findMongoById(mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this mongo",
});
}
const service = await updateMongoById(mongoId, {
...rest,
});

View File

@ -68,13 +68,26 @@ export const mysqlRouter = createTRPCRouter({
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mysqlId, "access");
}
return await findMySqlById(input.mysqlId);
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this mysql",
});
}
return mysql;
}),
start: protectedProcedure
.input(apiFindOneMySql)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const service = await findMySqlById(input.mysqlId);
if (service.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this mysql",
});
}
if (service.serverId) {
await startServiceRemote(service.serverId, service.appName);
@ -89,8 +102,14 @@ export const mysqlRouter = createTRPCRouter({
}),
stop: protectedProcedure
.input(apiFindOneMySql)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this mysql",
});
}
if (mongo.serverId) {
await stopServiceRemote(mongo.serverId, mongo.appName);
} else {
@ -104,8 +123,14 @@ export const mysqlRouter = createTRPCRouter({
}),
saveExternalPort: protectedProcedure
.input(apiSaveExternalPortMySql)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
});
}
await updateMySqlById(input.mysqlId, {
externalPort: input.externalPort,
});
@ -114,13 +139,26 @@ export const mysqlRouter = createTRPCRouter({
}),
deploy: protectedProcedure
.input(apiDeployMySql)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this mysql",
});
}
return deployMySql(input.mysqlId);
}),
changeStatus: protectedProcedure
.input(apiChangeMySqlStatus)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this mysql status",
});
}
await updateMySqlById(input.mysqlId, {
applicationStatus: input.applicationStatus,
});
@ -128,8 +166,14 @@ export const mysqlRouter = createTRPCRouter({
}),
reload: protectedProcedure
.input(apiResetMysql)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this mysql",
});
}
if (mysql.serverId) {
await stopServiceRemote(mysql.serverId, mysql.appName);
} else {
@ -155,6 +199,12 @@ export const mysqlRouter = createTRPCRouter({
await checkServiceAccess(ctx.user.authId, input.mysqlId, "delete");
}
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this mysql",
});
}
const cleanupOperations = [
async () => await removeService(mongo?.appName, mongo.serverId),
@ -171,7 +221,14 @@ export const mysqlRouter = createTRPCRouter({
}),
saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariablesMySql)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
});
}
const service = await updateMySqlById(input.mysqlId, {
env: input.env,
});
@ -187,8 +244,15 @@ export const mysqlRouter = createTRPCRouter({
}),
update: protectedProcedure
.input(apiUpdateMySql)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const { mysqlId, ...rest } = input;
const mysql = await findMySqlById(mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this mysql",
});
}
const service = await updateMySqlById(mysqlId, {
...rest,
});

View File

@ -67,14 +67,28 @@ export const postgresRouter = createTRPCRouter({
await checkServiceAccess(ctx.user.authId, input.postgresId, "access");
}
return await findPostgresById(input.postgresId);
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this postgres",
});
}
return postgres;
}),
start: protectedProcedure
.input(apiFindOnePostgres)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const service = await findPostgresById(input.postgresId);
if (service.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this postgres",
});
}
if (service.serverId) {
await startServiceRemote(service.serverId, service.appName);
} else {
@ -88,8 +102,14 @@ export const postgresRouter = createTRPCRouter({
}),
stop: protectedProcedure
.input(apiFindOnePostgres)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this postgres",
});
}
if (postgres.serverId) {
await stopServiceRemote(postgres.serverId, postgres.appName);
} else {
@ -103,8 +123,15 @@ export const postgresRouter = createTRPCRouter({
}),
saveExternalPort: protectedProcedure
.input(apiSaveExternalPortPostgres)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
});
}
await updatePostgresById(input.postgresId, {
externalPort: input.externalPort,
});
@ -113,13 +140,26 @@ export const postgresRouter = createTRPCRouter({
}),
deploy: protectedProcedure
.input(apiDeployPostgres)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this postgres",
});
}
return deployPostgres(input.postgresId);
}),
changeStatus: protectedProcedure
.input(apiChangePostgresStatus)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this postgres status",
});
}
await updatePostgresById(input.postgresId, {
applicationStatus: input.applicationStatus,
});
@ -133,6 +173,13 @@ export const postgresRouter = createTRPCRouter({
}
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this postgres",
});
}
const cleanupOperations = [
removeService(postgres.appName, postgres.serverId),
removePostgresById(input.postgresId),
@ -144,7 +191,14 @@ export const postgresRouter = createTRPCRouter({
}),
saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariablesPostgres)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
});
}
const service = await updatePostgresById(input.postgresId, {
env: input.env,
});
@ -160,8 +214,14 @@ export const postgresRouter = createTRPCRouter({
}),
reload: protectedProcedure
.input(apiResetPostgres)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this postgres",
});
}
if (postgres.serverId) {
await stopServiceRemote(postgres.serverId, postgres.appName);
} else {
@ -183,8 +243,15 @@ export const postgresRouter = createTRPCRouter({
}),
update: protectedProcedure
.input(apiUpdatePostgres)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const { postgresId, ...rest } = input;
const postgres = await findPostgresById(postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this postgres",
});
}
const service = await updatePostgresById(postgresId, {
...rest,
});

View File

@ -16,7 +16,7 @@ import {
} from "@/server/db/schema";
import { TRPCError } from "@trpc/server";
import { desc, eq, sql } from "drizzle-orm";
import { and, desc, eq, sql } from "drizzle-orm";
import type { AnyPgColumn } from "drizzle-orm/pg-core";
import {
@ -45,7 +45,6 @@ export const projectRouter = createTRPCRouter({
return project;
} catch (error) {
console.log(error);
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error to create the project",
@ -62,8 +61,11 @@ export const projectRouter = createTRPCRouter({
await checkProjectAccess(ctx.user.authId, "access", input.projectId);
const service = await db.query.projects.findFirst({
where: eq(projects.projectId, input.projectId),
const project = await db.query.projects.findFirst({
where: and(
eq(projects.projectId, input.projectId),
eq(projects.adminId, ctx.user.adminId),
),
with: {
compose: {
where: buildServiceFilter(compose.composeId, accesedServices),
@ -92,15 +94,22 @@ export const projectRouter = createTRPCRouter({
},
});
if (!service) {
if (!project) {
throw new TRPCError({
code: "NOT_FOUND",
message: "Project not found",
});
}
return service;
return project;
}
const project = await findProjectById(input.projectId);
if (project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
return project;
}),
all: protectedProcedure.query(async ({ ctx }) => {
@ -170,32 +179,38 @@ export const projectRouter = createTRPCRouter({
if (ctx.user.rol === "user") {
await checkProjectAccess(ctx.user.authId, "delete");
}
const project = await deleteProject(input.projectId);
const currentProject = await findProjectById(input.projectId);
if (currentProject.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this project",
});
}
const deletedProject = await deleteProject(input.projectId);
return project;
return deletedProject;
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error to delete this project",
cause: error,
});
throw error;
}
}),
update: protectedProcedure
.input(apiUpdateProject)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
const project = updateProjectById(input.projectId, {
const currentProject = await findProjectById(input.projectId);
if (currentProject.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this project",
});
}
const project = await updateProjectById(input.projectId, {
...input,
});
return project;
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Error to update this project",
cause: error,
});
throw error;
}
}),
});

View File

@ -26,6 +26,7 @@ import {
findRedisById,
removeRedisById,
updateRedisById,
IS_CLOUD,
} from "@dokploy/builders";
export const redisRouter = createTRPCRouter({
@ -65,13 +66,27 @@ export const redisRouter = createTRPCRouter({
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.redisId, "access");
}
return await findRedisById(input.redisId);
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this redis",
});
}
return redis;
}),
start: protectedProcedure
.input(apiFindOneRedis)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this redis",
});
}
if (redis.serverId) {
await startServiceRemote(redis.serverId, redis.appName);
@ -86,8 +101,14 @@ export const redisRouter = createTRPCRouter({
}),
reload: protectedProcedure
.input(apiResetRedis)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this redis",
});
}
if (redis.serverId) {
await stopServiceRemote(redis.serverId, redis.appName);
} else {
@ -110,8 +131,14 @@ export const redisRouter = createTRPCRouter({
stop: protectedProcedure
.input(apiFindOneRedis)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this redis",
});
}
if (redis.serverId) {
await stopServiceRemote(redis.serverId, redis.appName);
} else {
@ -125,8 +152,14 @@ export const redisRouter = createTRPCRouter({
}),
saveExternalPort: protectedProcedure
.input(apiSaveExternalPortRedis)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findRedisById(input.redisId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
});
}
await updateRedisById(input.redisId, {
externalPort: input.externalPort,
});
@ -135,13 +168,26 @@ export const redisRouter = createTRPCRouter({
}),
deploy: protectedProcedure
.input(apiDeployRedis)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this redis",
});
}
return deployRedis(input.redisId);
}),
changeStatus: protectedProcedure
.input(apiChangeRedisStatus)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
const mongo = await findRedisById(input.redisId);
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this redis status",
});
}
await updateRedisById(input.redisId, {
applicationStatus: input.applicationStatus,
});
@ -156,6 +202,13 @@ export const redisRouter = createTRPCRouter({
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this redis",
});
}
const cleanupOperations = [
async () => await removeService(redis?.appName, redis.serverId),
async () => await removeRedisById(input.redisId),
@ -171,12 +224,19 @@ export const redisRouter = createTRPCRouter({
}),
saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariablesRedis)
.mutation(async ({ input }) => {
const redis = await updateRedisById(input.redisId, {
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
});
}
const updatedRedis = await updateRedisById(input.redisId, {
env: input.env,
});
if (!redis) {
if (!updatedRedis) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Update: Error to add environment variables",

View File

@ -1,6 +1,7 @@
import { apiFindOneUser, apiFindOneUserByAuth } from "@/server/db/schema";
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
import { findUserByAuthId, findUserById, findUsers } from "@dokploy/builders";
import { TRPCError } from "@trpc/server";
export const userRouter = createTRPCRouter({
all: adminProcedure.query(async ({ ctx }) => {
@ -8,12 +9,26 @@ export const userRouter = createTRPCRouter({
}),
byAuthId: protectedProcedure
.input(apiFindOneUserByAuth)
.query(async ({ input }) => {
return await findUserByAuthId(input.authId);
.query(async ({ input, ctx }) => {
const user = await findUserByAuthId(input.authId);
if (user.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to access this user",
});
}
return user;
}),
byUserId: protectedProcedure
.input(apiFindOneUser)
.query(async ({ input }) => {
return await findUserById(input.userId);
.query(async ({ input, ctx }) => {
const user = await findUserById(input.userId);
if (user.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to access this user",
});
}
return user;
}),
});

View File

@ -61,4 +61,5 @@ export const apiUpdateBitbucket = createSchema.extend({
name: z.string().min(1),
bitbucketUsername: z.string().optional(),
bitbucketWorkspaceName: z.string().optional(),
adminId: z.string().optional(),
});

View File

@ -13,10 +13,9 @@ import { eq } from "drizzle-orm";
export type Admin = typeof admins.$inferSelect;
export const createInvitation = async (
input: typeof apiCreateUserInvitation._type,
adminId: string,
) => {
await db.transaction(async (tx) => {
const admin = await findAdmin();
const result = await tx
.insert(auth)
.values({
@ -39,7 +38,7 @@ export const createInvitation = async (
await tx
.insert(users)
.values({
adminId: admin.adminId,
adminId: adminId,
authId: result.id,
token,
expirationDate: expiresIn24Hours.toISOString(),

View File

@ -14,6 +14,7 @@ import { eq } from "drizzle-orm";
import encode from "hi-base32";
import { TOTP } from "otpauth";
import QRCode from "qrcode";
import { IS_CLOUD } from "../constants";
export type Auth = typeof auth.$inferSelect;
@ -37,13 +38,15 @@ export const createAdmin = async (input: typeof apiCreateAdmin._type) => {
});
}
await tx
.insert(admins)
.values({
authId: newAuth.id,
serverIp: await getPublicIpWithFallback(),
})
.returning();
if (!IS_CLOUD) {
await tx
.insert(admins)
.values({
authId: newAuth.id,
serverIp: await getPublicIpWithFallback(),
})
.returning();
}
return newAuth;
});

View File

@ -4,13 +4,16 @@ import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
export type Github = typeof github.$inferSelect;
export const createGithub = async (input: typeof apiCreateGithub._type) => {
export const createGithub = async (
input: typeof apiCreateGithub._type,
adminId: string,
) => {
return await db.transaction(async (tx) => {
const newGitProvider = await tx
.insert(gitProvider)
.values({
providerType: "github",
authId: input.authId,
adminId: adminId,
name: input.name,
})
.returning()

View File

@ -11,13 +11,16 @@ import { eq } from "drizzle-orm";
export type Gitlab = typeof gitlab.$inferSelect;
export const createGitlab = async (input: typeof apiCreateGitlab._type) => {
export const createGitlab = async (
input: typeof apiCreateGitlab._type,
adminId: string,
) => {
return await db.transaction(async (tx) => {
const newGitProvider = await tx
.insert(gitProvider)
.values({
providerType: "gitlab",
authId: input.authId,
adminId: adminId,
name: input.name,
})
.returning()

View File

@ -9,19 +9,19 @@ import {
} from "@/server/utils/traefik/registry";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import { findAdmin } from "./admin";
export type Registry = typeof registry.$inferSelect;
export const createRegistry = async (input: typeof apiCreateRegistry._type) => {
const admin = await findAdmin();
export const createRegistry = async (
input: typeof apiCreateRegistry._type,
adminId: string,
) => {
return await db.transaction(async (tx) => {
const newRegistry = await tx
.insert(registry)
.values({
...input,
adminId: admin.adminId,
adminId: adminId,
})
.returning()
.then((value) => value[0]);
@ -126,7 +126,9 @@ export const findRegistryById = async (registryId: string) => {
return registryResponse;
};
export const findAllRegistry = async () => {
const registryResponse = await db.query.registry.findMany();
export const findAllRegistryByAdminId = async (adminId: string) => {
const registryResponse = await db.query.registry.findMany({
where: eq(registry.adminId, adminId),
});
return registryResponse;
};