mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-09-12 19:51:00 +05:00
fix: require ownership to change an existing GitLab source
Assigned provider access can connect new deploys, but it must not let a member reassign someone else's source or register its webhook.
This commit is contained in:
parent
d1f684cbe8
commit
50b977eb77
@ -1,6 +1,8 @@
|
||||
import {
|
||||
assertCanEditExistingDeployGitSource,
|
||||
canEditDeployGitSource,
|
||||
getAccessibleGitProviderIds,
|
||||
getConnectedGitProviderId,
|
||||
} from "@dokploy/server/services/git-provider";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
@ -367,3 +369,61 @@ describe("canEditDeployGitSource", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("getConnectedGitProviderId", () => {
|
||||
it("returns the gitlab gitProviderId for a gitlab source", () => {
|
||||
expect(
|
||||
getConnectedGitProviderId({
|
||||
sourceType: "gitlab",
|
||||
gitlab: { gitProviderId: "gp-gitlab" },
|
||||
}),
|
||||
).toBe("gp-gitlab");
|
||||
});
|
||||
|
||||
it("returns null when there is no connected git provider", () => {
|
||||
expect(getConnectedGitProviderId({ sourceType: "docker" })).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("assertCanEditExistingDeployGitSource", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockHasValidLicense.mockResolvedValue(true);
|
||||
});
|
||||
|
||||
it("allows first-time connects when no git source is attached", async () => {
|
||||
await expect(
|
||||
assertCanEditExistingDeployGitSource(null, session(USER_MEMBER)),
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("rejects existing-source edits that only have accessedGitProviders", async () => {
|
||||
mockDb.query.member.findFirst.mockResolvedValue({ role: "member" });
|
||||
mockDb.query.gitProvider.findFirst.mockResolvedValue({
|
||||
userId: USER_OWNER,
|
||||
sharedWithOrganization: false,
|
||||
});
|
||||
|
||||
await expect(
|
||||
assertCanEditExistingDeployGitSource(
|
||||
providerPrivate.gitProviderId,
|
||||
session(USER_MEMBER),
|
||||
),
|
||||
).rejects.toMatchObject({ code: "FORBIDDEN" });
|
||||
});
|
||||
|
||||
it("allows existing-source edits when the member owns the provider", async () => {
|
||||
mockDb.query.member.findFirst.mockResolvedValue({ role: "member" });
|
||||
mockDb.query.gitProvider.findFirst.mockResolvedValue({
|
||||
userId: USER_MEMBER,
|
||||
sharedWithOrganization: false,
|
||||
});
|
||||
|
||||
await expect(
|
||||
assertCanEditExistingDeployGitSource(
|
||||
providerOwned.gitProviderId,
|
||||
session(USER_MEMBER),
|
||||
),
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -35,7 +35,11 @@ import {
|
||||
writeConfigRemote,
|
||||
} from "@dokploy/server";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { canEditDeployGitSource } from "@dokploy/server/services/git-provider";
|
||||
import {
|
||||
assertCanEditExistingDeployGitSource,
|
||||
canEditDeployGitSource,
|
||||
getConnectedGitProviderId,
|
||||
} from "@dokploy/server/services/git-provider";
|
||||
import {
|
||||
addNewService,
|
||||
checkServiceAccess,
|
||||
@ -461,6 +465,11 @@ export const applicationRouter = createTRPCRouter({
|
||||
message: "GitLab provider is required",
|
||||
});
|
||||
}
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
await assertCanEditExistingDeployGitSource(
|
||||
getConnectedGitProviderId(application),
|
||||
ctx.session,
|
||||
);
|
||||
await assertGitlabProviderAccess(input.gitlabId, ctx.session);
|
||||
await updateApplication(input.applicationId, {
|
||||
gitlabRepository: input.gitlabRepository,
|
||||
@ -475,7 +484,6 @@ export const applicationRouter = createTRPCRouter({
|
||||
watchPaths: input.watchPaths,
|
||||
enableSubmodules: input.enableSubmodules,
|
||||
});
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.autoDeploy) {
|
||||
const dokployUrl = await getDokployUrl();
|
||||
await registerGitlabDeployWebhook({
|
||||
|
||||
@ -36,7 +36,11 @@ import {
|
||||
updateDeploymentStatus,
|
||||
} from "@dokploy/server";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { canEditDeployGitSource } from "@dokploy/server/services/git-provider";
|
||||
import {
|
||||
assertCanEditExistingDeployGitSource,
|
||||
canEditDeployGitSource,
|
||||
getConnectedGitProviderId,
|
||||
} from "@dokploy/server/services/git-provider";
|
||||
import {
|
||||
addNewService,
|
||||
checkServiceAccess,
|
||||
@ -199,6 +203,11 @@ export const composeRouter = createTRPCRouter({
|
||||
service: ["create"],
|
||||
});
|
||||
if (input.gitlabId) {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
await assertCanEditExistingDeployGitSource(
|
||||
getConnectedGitProviderId(compose),
|
||||
ctx.session,
|
||||
);
|
||||
await assertGitlabProviderAccess(input.gitlabId, ctx.session);
|
||||
}
|
||||
const updated = await updateCompose(input.composeId, input);
|
||||
|
||||
@ -75,6 +75,43 @@ export const canEditDeployGitSource = async (
|
||||
return provider.userId === userId || provider.sharedWithOrganization;
|
||||
};
|
||||
|
||||
export const getConnectedGitProviderId = (service: {
|
||||
sourceType: string;
|
||||
github?: { gitProviderId: string } | null;
|
||||
gitlab?: { gitProviderId: string } | null;
|
||||
bitbucket?: { gitProviderId: string } | null;
|
||||
gitea?: { gitProviderId: string } | null;
|
||||
}): string | null => {
|
||||
switch (service.sourceType) {
|
||||
case "github":
|
||||
return service.github?.gitProviderId ?? null;
|
||||
case "gitlab":
|
||||
return service.gitlab?.gitProviderId ?? null;
|
||||
case "bitbucket":
|
||||
return service.bitbucket?.gitProviderId ?? null;
|
||||
case "gitea":
|
||||
return service.gitea?.gitProviderId ?? null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const assertCanEditExistingDeployGitSource = async (
|
||||
gitProviderId: string | null | undefined,
|
||||
session: { userId: string; activeOrganizationId: string },
|
||||
) => {
|
||||
if (!gitProviderId) return;
|
||||
|
||||
const canEdit = await canEditDeployGitSource(gitProviderId, session);
|
||||
if (!canEdit) {
|
||||
throw new TRPCError({
|
||||
code: "FORBIDDEN",
|
||||
message:
|
||||
"You are not authorized to change the git source of this service",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const getAccessibleGitProviderIds = async (session: {
|
||||
userId: string;
|
||||
activeOrganizationId: string;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user