Skip to content

Commit bd4964f

Browse files
committed
feat(user): implement organization membership checks for API key creation and user organization queries
- Added verification to ensure users are members of the specified organization when creating API keys. - Implemented checks to restrict organization queries to users who are either checking their own organizations or are admins/owners of the active organization. - Enhanced error handling to return FORBIDDEN responses for unauthorized access attempts.
1 parent 07bf520 commit bd4964f

File tree

1 file changed

+46
-1
lines changed
  • apps/dokploy/server/api/routers

1 file changed

+46
-1
lines changed

apps/dokploy/server/api/routers/user.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,23 @@ export const userRouter = createTRPCRouter({
430430
createApiKey: protectedProcedure
431431
.input(apiCreateApiKey)
432432
.mutation(async ({ input, ctx }) => {
433+
// Verify user is a member of the organization specified in metadata
434+
if (input.metadata?.organizationId) {
435+
const userMember = await db.query.member.findFirst({
436+
where: and(
437+
eq(member.organizationId, input.metadata.organizationId),
438+
eq(member.userId, ctx.user.id),
439+
),
440+
});
441+
442+
if (!userMember) {
443+
throw new TRPCError({
444+
code: "FORBIDDEN",
445+
message: "You are not a member of this organization",
446+
});
447+
}
448+
}
449+
433450
const apiKey = await createApiKey(ctx.user.id, input);
434451
return apiKey;
435452
}),
@@ -440,7 +457,35 @@ export const userRouter = createTRPCRouter({
440457
userId: z.string(),
441458
}),
442459
)
443-
.query(async ({ input }) => {
460+
.query(async ({ input, ctx }) => {
461+
// Users can check their own organizations
462+
// Admins and owners can check organizations of members in their active organization
463+
if (input.userId !== ctx.user.id) {
464+
// Verify the target user is a member of the active organization
465+
const targetMember = await db.query.member.findFirst({
466+
where: and(
467+
eq(member.userId, input.userId),
468+
eq(member.organizationId, ctx.session?.activeOrganizationId || ""),
469+
),
470+
});
471+
472+
if (!targetMember) {
473+
throw new TRPCError({
474+
code: "FORBIDDEN",
475+
message: "User is not a member of your active organization",
476+
});
477+
}
478+
479+
// Only admins and owners can check other users' organizations
480+
if (ctx.user.role !== "owner" && ctx.user.role !== "admin") {
481+
throw new TRPCError({
482+
code: "FORBIDDEN",
483+
message:
484+
"Only admins and owners can check other users' organizations",
485+
});
486+
}
487+
}
488+
444489
const organizations = await db.query.member.findMany({
445490
where: eq(member.userId, input.userId),
446491
});

0 commit comments

Comments
 (0)