Skip to content

Commit aa72091

Browse files
authored
fix: allow members with git providers permission to create and delete their own (#4713)
The canAccessToGitProviders legacy override only granted read access, so members with the Git Providers toggle enabled could not add providers — the create/delete endpoints require gitProviders.create / gitProviders.delete. This mirrors how the SSH Keys toggle already grants read/create/delete. The git-provider remove endpoint now restricts non owner/admin roles to deleting only their own providers (matching the ownership model used for visibility and sharing), while owner/admin can still delete any provider in the organization. Closes #4695
1 parent c2a9587 commit aa72091

4 files changed

Lines changed: 59 additions & 0 deletions

File tree

‎apps/dokploy/__test__/permissions/check-permission.test.ts‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,29 @@ describe("legacy boolean overrides for member", () => {
183183
memberToReturn = mockMemberData("member");
184184
await expect(checkPermission(ctx, { docker: ["read"] })).rejects.toThrow();
185185
});
186+
187+
it("member passes gitProviders.create with canAccessToGitProviders=true", async () => {
188+
memberToReturn = mockMemberData("member", {
189+
canAccessToGitProviders: true,
190+
});
191+
await expect(
192+
checkPermission(ctx, { gitProviders: ["create"] }),
193+
).resolves.toBeUndefined();
194+
});
195+
196+
it("member passes gitProviders.delete with canAccessToGitProviders=true", async () => {
197+
memberToReturn = mockMemberData("member", {
198+
canAccessToGitProviders: true,
199+
});
200+
await expect(
201+
checkPermission(ctx, { gitProviders: ["delete"] }),
202+
).resolves.toBeUndefined();
203+
});
204+
205+
it("member fails gitProviders.create with canAccessToGitProviders=false", async () => {
206+
memberToReturn = mockMemberData("member");
207+
await expect(
208+
checkPermission(ctx, { gitProviders: ["create"] }),
209+
).rejects.toThrow();
210+
});
186211
});

‎apps/dokploy/__test__/permissions/resolve-permissions.test.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,24 @@ describe("free-tier resources for member", () => {
143143
const perms = await resolvePermissions(ctx);
144144
expect(perms.docker.read).toBe(true);
145145
});
146+
147+
it("member gets gitProviders create/delete=false without legacy override", async () => {
148+
memberToReturn = mockMemberData("member");
149+
const perms = await resolvePermissions(ctx);
150+
expect(perms.gitProviders.read).toBe(false);
151+
expect(perms.gitProviders.create).toBe(false);
152+
expect(perms.gitProviders.delete).toBe(false);
153+
});
154+
155+
it("member gets gitProviders read/create/delete=true with canAccessToGitProviders", async () => {
156+
memberToReturn = mockMemberData("member", {
157+
canAccessToGitProviders: true,
158+
});
159+
const perms = await resolvePermissions(ctx);
160+
expect(perms.gitProviders.read).toBe(true);
161+
expect(perms.gitProviders.create).toBe(true);
162+
expect(perms.gitProviders.delete).toBe(true);
163+
});
146164
});
147165

148166
describe("free-tier resources for owner", () => {

‎apps/dokploy/server/api/routers/git-provider.ts‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
updateGitProvider,
66
} from "@dokploy/server";
77
import { db } from "@dokploy/server/db";
8+
import { findMemberByUserId } from "@dokploy/server/services/permission";
89
import { hasValidLicense } from "@dokploy/server/services/proprietary/license-key";
910
import { TRPCError } from "@trpc/server";
1011
import { desc, eq, inArray } from "drizzle-orm";
@@ -144,6 +145,19 @@ export const gitProviderRouter = createTRPCRouter({
144145
message: "You are not allowed to delete this Git provider",
145146
});
146147
}
148+
149+
const memberRecord = await findMemberByUserId(
150+
ctx.user.id,
151+
ctx.session.activeOrganizationId,
152+
);
153+
const isPrivileged =
154+
memberRecord.role === "owner" || memberRecord.role === "admin";
155+
if (!isPrivileged && gitProvider.userId !== ctx.session.userId) {
156+
throw new TRPCError({
157+
code: "UNAUTHORIZED",
158+
message: "You can only delete your own Git providers",
159+
});
160+
}
147161
await audit(ctx, {
148162
action: "delete",
149163
resourceType: "gitProvider",

‎packages/server/src/services/permission.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ const getLegacyOverrides = (
170170
},
171171
gitProviders: {
172172
read: !!memberRecord.canAccessToGitProviders,
173+
create: !!memberRecord.canAccessToGitProviders,
174+
delete: !!memberRecord.canAccessToGitProviders,
173175
},
174176
};
175177
};

0 commit comments

Comments
 (0)