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

View File

@ -47,6 +47,7 @@ import {
removeDeployments, removeDeployments,
addNewService, addNewService,
checkServiceAccess, checkServiceAccess,
IS_CLOUD,
// uploadFileSchema // uploadFileSchema
} from "@dokploy/builders"; } from "@dokploy/builders";
import { uploadFileSchema } from "@/utils/schema"; import { uploadFileSchema } from "@/utils/schema";
@ -89,13 +90,26 @@ export const applicationRouter = createTRPCRouter({
"access", "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 reload: protectedProcedure
.input(apiReloadApplication) .input(apiReloadApplication)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const application = 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 reload this application",
});
}
if (application.serverId) { if (application.serverId) {
await stopServiceRemote(application.serverId, input.appName); await stopServiceRemote(application.serverId, input.appName);
} else { } else {
@ -124,6 +138,13 @@ export const applicationRouter = createTRPCRouter({
} }
const application = 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 delete this application",
});
}
const result = await db const result = await db
.delete(applications) .delete(applications)
.where(eq(applications.applicationId, input.applicationId)) .where(eq(applications.applicationId, input.applicationId))
@ -156,8 +177,14 @@ export const applicationRouter = createTRPCRouter({
stop: protectedProcedure stop: protectedProcedure
.input(apiFindOneApplication) .input(apiFindOneApplication)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const service = await findApplicationById(input.applicationId); 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) { if (service.serverId) {
await stopServiceRemote(service.serverId, service.appName); await stopServiceRemote(service.serverId, service.appName);
} else { } else {
@ -170,8 +197,15 @@ export const applicationRouter = createTRPCRouter({
start: protectedProcedure start: protectedProcedure
.input(apiFindOneApplication) .input(apiFindOneApplication)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const service = await findApplicationById(input.applicationId); 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) { if (service.serverId) {
await startServiceRemote(service.serverId, service.appName); await startServiceRemote(service.serverId, service.appName);
} else { } else {
@ -184,8 +218,14 @@ export const applicationRouter = createTRPCRouter({
redeploy: protectedProcedure redeploy: protectedProcedure
.input(apiFindOneApplication) .input(apiFindOneApplication)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const application = 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 redeploy this application",
});
}
const jobData: DeploymentJob = { const jobData: DeploymentJob = {
applicationId: input.applicationId, applicationId: input.applicationId,
titleLog: "Rebuild deployment", titleLog: "Rebuild deployment",
@ -205,7 +245,14 @@ export const applicationRouter = createTRPCRouter({
}), }),
saveEnvironment: protectedProcedure saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariables) .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, { await updateApplication(input.applicationId, {
env: input.env, env: input.env,
buildArgs: input.buildArgs, buildArgs: input.buildArgs,
@ -214,7 +261,14 @@ export const applicationRouter = createTRPCRouter({
}), }),
saveBuildType: protectedProcedure saveBuildType: protectedProcedure
.input(apiSaveBuildType) .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, { await updateApplication(input.applicationId, {
buildType: input.buildType, buildType: input.buildType,
dockerfile: input.dockerfile, dockerfile: input.dockerfile,
@ -227,7 +281,14 @@ export const applicationRouter = createTRPCRouter({
}), }),
saveGithubProvider: protectedProcedure saveGithubProvider: protectedProcedure
.input(apiSaveGithubProvider) .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, { await updateApplication(input.applicationId, {
repository: input.repository, repository: input.repository,
branch: input.branch, branch: input.branch,
@ -242,7 +303,14 @@ export const applicationRouter = createTRPCRouter({
}), }),
saveGitlabProvider: protectedProcedure saveGitlabProvider: protectedProcedure
.input(apiSaveGitlabProvider) .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, { await updateApplication(input.applicationId, {
gitlabRepository: input.gitlabRepository, gitlabRepository: input.gitlabRepository,
gitlabOwner: input.gitlabOwner, gitlabOwner: input.gitlabOwner,
@ -259,7 +327,14 @@ export const applicationRouter = createTRPCRouter({
}), }),
saveBitbucketProvider: protectedProcedure saveBitbucketProvider: protectedProcedure
.input(apiSaveBitbucketProvider) .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, { await updateApplication(input.applicationId, {
bitbucketRepository: input.bitbucketRepository, bitbucketRepository: input.bitbucketRepository,
bitbucketOwner: input.bitbucketOwner, bitbucketOwner: input.bitbucketOwner,
@ -274,7 +349,14 @@ export const applicationRouter = createTRPCRouter({
}), }),
saveDockerProvider: protectedProcedure saveDockerProvider: protectedProcedure
.input(apiSaveDockerProvider) .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, { await updateApplication(input.applicationId, {
dockerImage: input.dockerImage, dockerImage: input.dockerImage,
username: input.username, username: input.username,
@ -287,7 +369,14 @@ export const applicationRouter = createTRPCRouter({
}), }),
saveGitProdiver: protectedProcedure saveGitProdiver: protectedProcedure
.input(apiSaveGitProvider) .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, { await updateApplication(input.applicationId, {
customGitBranch: input.customGitBranch, customGitBranch: input.customGitBranch,
customGitBuildPath: input.customGitBuildPath, customGitBuildPath: input.customGitBuildPath,
@ -301,18 +390,32 @@ export const applicationRouter = createTRPCRouter({
}), }),
markRunning: protectedProcedure markRunning: protectedProcedure
.input(apiFindOneApplication) .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"); await updateApplicationStatus(input.applicationId, "running");
}), }),
update: protectedProcedure update: protectedProcedure
.input(apiUpdateApplication) .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 { applicationId, ...rest } = input;
const application = await updateApplication(applicationId, { const updateApp = await updateApplication(applicationId, {
...rest, ...rest,
}); });
if (!application) { if (!updateApp) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "BAD_REQUEST",
message: "Update: Error to update application", message: "Update: Error to update application",
@ -323,7 +426,14 @@ export const applicationRouter = createTRPCRouter({
}), }),
refreshToken: protectedProcedure refreshToken: protectedProcedure
.input(apiFindOneApplication) .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, { await updateApplication(input.applicationId, {
refreshToken: nanoid(), refreshToken: nanoid(),
}); });
@ -333,6 +443,12 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication) .input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
const application = 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 deploy this application",
});
}
const jobData: DeploymentJob = { const jobData: DeploymentJob = {
applicationId: input.applicationId, applicationId: input.applicationId,
titleLog: "Manual deployment", titleLog: "Manual deployment",
@ -353,14 +469,28 @@ export const applicationRouter = createTRPCRouter({
cleanQueues: protectedProcedure cleanQueues: protectedProcedure
.input(apiFindOneApplication) .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); await cleanQueuesByApplication(input.applicationId);
}), }),
readTraefikConfig: protectedProcedure readTraefikConfig: protectedProcedure
.input(apiFindOneApplication) .input(apiFindOneApplication)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const application = 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 read this application",
});
}
let traefikConfig = null; let traefikConfig = null;
if (application.serverId) { if (application.serverId) {
traefikConfig = await readRemoteConfig( traefikConfig = await readRemoteConfig(
@ -384,15 +514,23 @@ export const applicationRouter = createTRPCRouter({
}) })
.use(uploadProcedure) .use(uploadProcedure)
.input(uploadFileSchema) .input(uploadFileSchema)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const zipFile = input.zip; 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, { updateApplication(input.applicationId as string, {
sourceType: "drop", sourceType: "drop",
dropBuildPath: input.dropBuildPath, dropBuildPath: input.dropBuildPath,
}); });
const app = await findApplicationById(input.applicationId as string);
await unzipDrop(zipFile, app); await unzipDrop(zipFile, app);
const jobData: DeploymentJob = { const jobData: DeploymentJob = {
@ -415,9 +553,16 @@ export const applicationRouter = createTRPCRouter({
}), }),
updateTraefikConfig: protectedProcedure updateTraefikConfig: protectedProcedure
.input(z.object({ applicationId: z.string(), traefikConfig: z.string() })) .input(z.object({ applicationId: z.string(), traefikConfig: z.string() }))
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const application = 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 update this application",
});
}
if (application.serverId) { if (application.serverId) {
await writeConfigRemote( await writeConfigRemote(
application.serverId, application.serverId,
@ -431,14 +576,15 @@ export const applicationRouter = createTRPCRouter({
}), }),
readAppMonitoring: protectedProcedure readAppMonitoring: protectedProcedure
.input(apiFindMonitoringStats) .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); const stats = await getApplicationStats(input.appName);
return stats; 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"); 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 update: protectedProcedure
.input(apiUpdateCompose) .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); return updateCompose(input.composeId, input);
}), }),
delete: protectedProcedure delete: protectedProcedure
@ -99,6 +113,14 @@ export const composeRouter = createTRPCRouter({
} }
const composeResult = await findComposeById(input.composeId); 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 const result = await db
.delete(compose) .delete(compose)
.where(eq(compose.composeId, input.composeId)) .where(eq(compose.composeId, input.composeId))
@ -120,20 +142,41 @@ export const composeRouter = createTRPCRouter({
}), }),
cleanQueues: protectedProcedure cleanQueues: protectedProcedure
.input(apiFindCompose) .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); await cleanQueuesByCompose(input.composeId);
}), }),
loadServices: protectedProcedure loadServices: protectedProcedure
.input(apiFetchServices) .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); return await loadServices(input.composeId, input.type);
}), }),
fetchSourceType: protectedProcedure fetchSourceType: protectedProcedure
.input(apiFindCompose) .input(apiFindCompose)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
try { try {
const compose = 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 fetch this compose",
});
}
if (compose.serverId) { if (compose.serverId) {
await cloneComposeRemote(compose); await cloneComposeRemote(compose);
} else { } else {
@ -151,13 +194,26 @@ export const composeRouter = createTRPCRouter({
randomizeCompose: protectedProcedure randomizeCompose: protectedProcedure
.input(apiRandomizeCompose) .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); return await randomizeComposeFile(input.composeId, input.suffix);
}), }),
getConvertedCompose: protectedProcedure getConvertedCompose: protectedProcedure
.input(apiFindCompose) .input(apiFindCompose)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const compose = 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 get this compose",
});
}
const domains = await findDomainsByComposeId(input.composeId); const domains = await findDomainsByComposeId(input.composeId);
const composeFile = await addDomainToCompose(compose, domains); const composeFile = await addDomainToCompose(compose, domains);
return dump(composeFile, { return dump(composeFile, {
@ -167,8 +223,15 @@ export const composeRouter = createTRPCRouter({
deploy: protectedProcedure deploy: protectedProcedure
.input(apiFindCompose) .input(apiFindCompose)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const compose = 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 deploy this compose",
});
}
const jobData: DeploymentJob = { const jobData: DeploymentJob = {
composeId: input.composeId, composeId: input.composeId,
titleLog: "Manual deployment", titleLog: "Manual deployment",
@ -188,8 +251,14 @@ export const composeRouter = createTRPCRouter({
}), }),
redeploy: protectedProcedure redeploy: protectedProcedure
.input(apiFindCompose) .input(apiFindCompose)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const compose = 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 redeploy this compose",
});
}
const jobData: DeploymentJob = { const jobData: DeploymentJob = {
composeId: input.composeId, composeId: input.composeId,
titleLog: "Rebuild deployment", titleLog: "Rebuild deployment",
@ -207,21 +276,44 @@ export const composeRouter = createTRPCRouter({
}, },
); );
}), }),
stop: protectedProcedure.input(apiFindCompose).mutation(async ({ input }) => { 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); await stopCompose(input.composeId);
return true; return true;
}), }),
getDefaultCommand: protectedProcedure getDefaultCommand: protectedProcedure
.input(apiFindCompose) .input(apiFindCompose)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const compose = 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 get this compose",
});
}
const command = createCommand(compose); const command = createCommand(compose);
return `docker ${command}`; return `docker ${command}`;
}), }),
refreshToken: protectedProcedure refreshToken: protectedProcedure
.input(apiFindCompose) .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, { await updateCompose(input.composeId, {
refreshToken: nanoid(), refreshToken: nanoid(),
}); });
@ -233,6 +325,7 @@ export const composeRouter = createTRPCRouter({
if (ctx.user.rol === "user") { if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create"); await checkServiceAccess(ctx.user.authId, input.projectId, "create");
} }
const composeFile = await readTemplateComposeFile(input.id); const composeFile = await readTemplateComposeFile(input.id);
const generate = await loadTemplateModule(input.id as TemplatesKeys); const generate = await loadTemplateModule(input.id as TemplatesKeys);

View File

@ -9,6 +9,7 @@ import {
apiFindOneDestination, apiFindOneDestination,
apiRemoveDestination, apiRemoveDestination,
apiUpdateDestination, apiUpdateDestination,
destinations,
} from "@/server/db/schema"; } from "@/server/db/schema";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { import {
@ -19,14 +20,14 @@ import {
removeDestinationById, removeDestinationById,
updateDestinationById, updateDestinationById,
} from "@dokploy/builders"; } from "@dokploy/builders";
import { eq } from "drizzle-orm";
export const destinationRouter = createTRPCRouter({ export const destinationRouter = createTRPCRouter({
create: adminProcedure create: adminProcedure
.input(apiCreateDestination) .input(apiCreateDestination)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
try { try {
await createDestintation(input); return await createDestintation(input, ctx.user.adminId);
return await findAdmin();
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "BAD_REQUEST",
@ -54,7 +55,6 @@ export const destinationRouter = createTRPCRouter({
const rcloneCommand = `rclone ls ${rcloneFlags.join(" ")} "${rcloneDestination}"`; const rcloneCommand = `rclone ls ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
await execAsync(rcloneCommand); await execAsync(rcloneCommand);
} catch (error) { } catch (error) {
console.log(error);
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "BAD_REQUEST",
message: "Error to connect to bucket", message: "Error to connect to bucket",
@ -64,36 +64,58 @@ export const destinationRouter = createTRPCRouter({
}), }),
one: protectedProcedure one: protectedProcedure
.input(apiFindOneDestination) .input(apiFindOneDestination)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
const destination = await findDestinationById(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 access this destination",
});
}
return destination; return destination;
}), }),
all: protectedProcedure.query(async () => { all: protectedProcedure.query(async ({ ctx }) => {
return await db.query.destinations.findMany({}); return await db.query.destinations.findMany({
where: eq(destinations.adminId, ctx.user.adminId),
});
}), }),
remove: adminProcedure remove: adminProcedure
.input(apiRemoveDestination) .input(apiRemoveDestination)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
try { try {
return await removeDestinationById(input.destinationId); const destination = await findDestinationById(input.destinationId);
} catch (error) {
if (destination.adminId !== ctx.user.adminId) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "UNAUTHORIZED",
message: "Error to delete this destination", message: "You are not allowed to delete this destination",
}); });
} }
return await removeDestinationById(
input.destinationId,
ctx.user.adminId,
);
} catch (error) {
throw error;
}
}), }),
update: adminProcedure update: adminProcedure
.input(apiUpdateDestination) .input(apiUpdateDestination)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
try { try {
return await updateDestinationById(input.destinationId, input); const destination = await findDestinationById(input.destinationId);
} catch (error) { if (destination.adminId !== ctx.user.adminId) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "UNAUTHORIZED",
message: "Error to update this destination", message: "You are not allowed to update this destination",
cause: error,
}); });
} }
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") { if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mariadbId, "access"); 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 start: protectedProcedure
.input(apiFindOneMariaDB) .input(apiFindOneMariaDB)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const service = await findMariadbById(input.mariadbId); 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) { if (service.serverId) {
await startServiceRemote(service.serverId, service.appName); await startServiceRemote(service.serverId, service.appName);
} else { } else {
@ -102,8 +115,14 @@ export const mariadbRouter = createTRPCRouter({
}), }),
saveExternalPort: protectedProcedure saveExternalPort: protectedProcedure
.input(apiSaveExternalPortMariaDB) .input(apiSaveExternalPortMariaDB)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const mongo = await findMariadbById(input.mariadbId); 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, { await updateMariadbById(input.mariadbId, {
externalPort: input.externalPort, externalPort: input.externalPort,
}); });
@ -112,13 +131,26 @@ export const mariadbRouter = createTRPCRouter({
}), }),
deploy: protectedProcedure deploy: protectedProcedure
.input(apiDeployMariaDB) .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); return deployMariadb(input.mariadbId);
}), }),
changeStatus: protectedProcedure changeStatus: protectedProcedure
.input(apiChangeMariaDBStatus) .input(apiChangeMariaDBStatus)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const mongo = await findMariadbById(input.mariadbId); 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, { await updateMariadbById(input.mariadbId, {
applicationStatus: input.applicationStatus, applicationStatus: input.applicationStatus,
}); });
@ -132,6 +164,12 @@ export const mariadbRouter = createTRPCRouter({
} }
const mongo = await findMariadbById(input.mariadbId); 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 = [ const cleanupOperations = [
async () => await removeService(mongo?.appName, mongo.serverId), async () => await removeService(mongo?.appName, mongo.serverId),
@ -148,7 +186,14 @@ export const mariadbRouter = createTRPCRouter({
}), }),
saveEnvironment: protectedProcedure saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariablesMariaDB) .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, { const service = await updateMariadbById(input.mariadbId, {
env: input.env, env: input.env,
}); });
@ -164,8 +209,14 @@ export const mariadbRouter = createTRPCRouter({
}), }),
reload: protectedProcedure reload: protectedProcedure
.input(apiResetMariadb) .input(apiResetMariadb)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const mariadb = 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 reload this mariadb",
});
}
if (mariadb.serverId) { if (mariadb.serverId) {
await stopServiceRemote(mariadb.serverId, mariadb.appName); await stopServiceRemote(mariadb.serverId, mariadb.appName);
} else { } else {
@ -187,8 +238,15 @@ export const mariadbRouter = createTRPCRouter({
}), }),
update: protectedProcedure update: protectedProcedure
.input(apiUpdateMariaDB) .input(apiUpdateMariaDB)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const { mariadbId, ...rest } = input; 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, { const service = await updateMariadbById(mariadbId, {
...rest, ...rest,
}); });

View File

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

View File

@ -68,13 +68,26 @@ export const mysqlRouter = createTRPCRouter({
if (ctx.user.rol === "user") { if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mysqlId, "access"); 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 start: protectedProcedure
.input(apiFindOneMySql) .input(apiFindOneMySql)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const service = await findMySqlById(input.mysqlId); 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) { if (service.serverId) {
await startServiceRemote(service.serverId, service.appName); await startServiceRemote(service.serverId, service.appName);
@ -89,8 +102,14 @@ export const mysqlRouter = createTRPCRouter({
}), }),
stop: protectedProcedure stop: protectedProcedure
.input(apiFindOneMySql) .input(apiFindOneMySql)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId); 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) { if (mongo.serverId) {
await stopServiceRemote(mongo.serverId, mongo.appName); await stopServiceRemote(mongo.serverId, mongo.appName);
} else { } else {
@ -104,8 +123,14 @@ export const mysqlRouter = createTRPCRouter({
}), }),
saveExternalPort: protectedProcedure saveExternalPort: protectedProcedure
.input(apiSaveExternalPortMySql) .input(apiSaveExternalPortMySql)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId); 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, { await updateMySqlById(input.mysqlId, {
externalPort: input.externalPort, externalPort: input.externalPort,
}); });
@ -114,13 +139,26 @@ export const mysqlRouter = createTRPCRouter({
}), }),
deploy: protectedProcedure deploy: protectedProcedure
.input(apiDeployMySql) .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); return deployMySql(input.mysqlId);
}), }),
changeStatus: protectedProcedure changeStatus: protectedProcedure
.input(apiChangeMySqlStatus) .input(apiChangeMySqlStatus)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId); 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, { await updateMySqlById(input.mysqlId, {
applicationStatus: input.applicationStatus, applicationStatus: input.applicationStatus,
}); });
@ -128,8 +166,14 @@ export const mysqlRouter = createTRPCRouter({
}), }),
reload: protectedProcedure reload: protectedProcedure
.input(apiResetMysql) .input(apiResetMysql)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const mysql = 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 reload this mysql",
});
}
if (mysql.serverId) { if (mysql.serverId) {
await stopServiceRemote(mysql.serverId, mysql.appName); await stopServiceRemote(mysql.serverId, mysql.appName);
} else { } else {
@ -155,6 +199,12 @@ export const mysqlRouter = createTRPCRouter({
await checkServiceAccess(ctx.user.authId, input.mysqlId, "delete"); await checkServiceAccess(ctx.user.authId, input.mysqlId, "delete");
} }
const mongo = await findMySqlById(input.mysqlId); 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 = [ const cleanupOperations = [
async () => await removeService(mongo?.appName, mongo.serverId), async () => await removeService(mongo?.appName, mongo.serverId),
@ -171,7 +221,14 @@ export const mysqlRouter = createTRPCRouter({
}), }),
saveEnvironment: protectedProcedure saveEnvironment: protectedProcedure
.input(apiSaveEnvironmentVariablesMySql) .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, { const service = await updateMySqlById(input.mysqlId, {
env: input.env, env: input.env,
}); });
@ -187,8 +244,15 @@ export const mysqlRouter = createTRPCRouter({
}), }),
update: protectedProcedure update: protectedProcedure
.input(apiUpdateMySql) .input(apiUpdateMySql)
.mutation(async ({ input }) => { .mutation(async ({ input, ctx }) => {
const { mysqlId, ...rest } = input; 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, { const service = await updateMySqlById(mysqlId, {
...rest, ...rest,
}); });

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
import { apiFindOneUser, apiFindOneUserByAuth } from "@/server/db/schema"; import { apiFindOneUser, apiFindOneUserByAuth } from "@/server/db/schema";
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc"; import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
import { findUserByAuthId, findUserById, findUsers } from "@dokploy/builders"; import { findUserByAuthId, findUserById, findUsers } from "@dokploy/builders";
import { TRPCError } from "@trpc/server";
export const userRouter = createTRPCRouter({ export const userRouter = createTRPCRouter({
all: adminProcedure.query(async ({ ctx }) => { all: adminProcedure.query(async ({ ctx }) => {
@ -8,12 +9,26 @@ export const userRouter = createTRPCRouter({
}), }),
byAuthId: protectedProcedure byAuthId: protectedProcedure
.input(apiFindOneUserByAuth) .input(apiFindOneUserByAuth)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
return await findUserByAuthId(input.authId); 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 byUserId: protectedProcedure
.input(apiFindOneUser) .input(apiFindOneUser)
.query(async ({ input }) => { .query(async ({ input, ctx }) => {
return await findUserById(input.userId); 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), name: z.string().min(1),
bitbucketUsername: z.string().optional(), bitbucketUsername: z.string().optional(),
bitbucketWorkspaceName: 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 type Admin = typeof admins.$inferSelect;
export const createInvitation = async ( export const createInvitation = async (
input: typeof apiCreateUserInvitation._type, input: typeof apiCreateUserInvitation._type,
adminId: string,
) => { ) => {
await db.transaction(async (tx) => { await db.transaction(async (tx) => {
const admin = await findAdmin();
const result = await tx const result = await tx
.insert(auth) .insert(auth)
.values({ .values({
@ -39,7 +38,7 @@ export const createInvitation = async (
await tx await tx
.insert(users) .insert(users)
.values({ .values({
adminId: admin.adminId, adminId: adminId,
authId: result.id, authId: result.id,
token, token,
expirationDate: expiresIn24Hours.toISOString(), expirationDate: expiresIn24Hours.toISOString(),

View File

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

View File

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

View File

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

View File

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