fix: org admins can manage team even-types (#23953)
* fix: org admins can manage team even-types * fix: org admins can manage team even-types
This commit is contained in:
+1231
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -35,7 +35,7 @@ import type {
|
||||
import type { User, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Organizations Event Types Endpoints", () => {
|
||||
describe("User Authentication - User is Org Admin", () => {
|
||||
describe("User Authentication - User is Org member and team admin", () => {
|
||||
let app: INestApplication;
|
||||
|
||||
let userRepositoryFixture: UserRepositoryFixture;
|
||||
@@ -172,7 +172,7 @@ describe("Organizations Event Types Endpoints", () => {
|
||||
});
|
||||
|
||||
await membershipsRepositoryFixture.create({
|
||||
role: "ADMIN",
|
||||
role: "MEMBER",
|
||||
user: { connect: { id: userAdmin.id } },
|
||||
team: { connect: { id: org.id } },
|
||||
accepted: true,
|
||||
@@ -247,7 +247,7 @@ describe("Organizations Event Types Endpoints", () => {
|
||||
return request(app.getHttpServer())
|
||||
.post(`/v2/organizations/${org.id}/teams/${falseTestTeam.id}/event-types`)
|
||||
.send(body)
|
||||
.expect(404);
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it("should not be able to create event-type for user outside org", async () => {
|
||||
@@ -511,7 +511,7 @@ describe("Organizations Event Types Endpoints", () => {
|
||||
it("should not get an event-type of team outside org", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get(`/v2/organizations/${org.id}/teams/${falseTestTeam.id}/event-types/${collectiveEventType.id}`)
|
||||
.expect(404);
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it("should not get a non existing event-type", async () => {
|
||||
@@ -576,7 +576,7 @@ describe("Organizations Event Types Endpoints", () => {
|
||||
return request(app.getHttpServer())
|
||||
.patch(`/v2/organizations/${org.id}/teams/${falseTestTeam.id}/event-types/${collectiveEventType.id}`)
|
||||
.send(body)
|
||||
.expect(404);
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it("should not be able to update non existing event-type", async () => {
|
||||
@@ -950,7 +950,7 @@ describe("Organizations Event Types Endpoints", () => {
|
||||
it("should not delete event-type of team outside org", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.delete(`/v2/organizations/${org.id}/teams/${falseTestTeam.id}/event-types/${collectiveEventType.id}`)
|
||||
.expect(404);
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it("should delete event-type not part of the team", async () => {
|
||||
@@ -116,41 +116,42 @@ export const createHandler = async ({ ctx, input }: CreateOptions) => {
|
||||
},
|
||||
});
|
||||
|
||||
if (!hasMembership) {
|
||||
console.warn(`User ${userId} is not a member of team ${teamId}`);
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
|
||||
const isSystemAdmin = ctx.user.role === "ADMIN";
|
||||
|
||||
// Check PBAC permissions for eventType.create with fallback to role-based check
|
||||
// Initialize team-level permission to false.
|
||||
// We will only try to set this to true if the user is a member.
|
||||
let hasCreatePermission = false;
|
||||
|
||||
try {
|
||||
const permissions = await getResourcePermissions({
|
||||
userId,
|
||||
teamId,
|
||||
resource: Resource.EventType,
|
||||
userRole: hasMembership.role,
|
||||
fallbackRoles: {
|
||||
create: {
|
||||
roles: [MembershipRole.ADMIN, MembershipRole.OWNER],
|
||||
// Only check for team-level permissions if the user is actually a member of the team.
|
||||
if (hasMembership) {
|
||||
try {
|
||||
const permissions = await getResourcePermissions({
|
||||
userId,
|
||||
teamId,
|
||||
resource: Resource.EventType,
|
||||
userRole: hasMembership.role,
|
||||
fallbackRoles: {
|
||||
create: {
|
||||
roles: [MembershipRole.ADMIN, MembershipRole.OWNER],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
hasCreatePermission = permissions.canCreate;
|
||||
} catch (error) {
|
||||
// If PBAC check fails, fall back to role-based check
|
||||
console.warn(
|
||||
`PBAC check failed for user ${userId} on team ${teamId}, falling back to role check:`,
|
||||
error
|
||||
);
|
||||
hasCreatePermission = ["ADMIN", "OWNER"].includes(hasMembership.role);
|
||||
});
|
||||
hasCreatePermission = permissions.canCreate;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
`PBAC check failed for user ${userId} on team ${teamId}, falling back to role check:`,
|
||||
error
|
||||
);
|
||||
hasCreatePermission = ["ADMIN", "OWNER"].includes(hasMembership.role);
|
||||
}
|
||||
}
|
||||
|
||||
// System admins and users with org-level eventType.create permission can always create event types
|
||||
if (!isSystemAdmin && !hasOrgEventTypeCreatePermission && !hasCreatePermission) {
|
||||
console.warn(`User ${userId} does not have eventType.create permission for team ${teamId}`);
|
||||
// If none of the above conditions are met, the user is unauthorized.
|
||||
// which means the user is not admin of the team nor the org.
|
||||
console.warn(
|
||||
`User ${userId} does not have eventType.create permission for team ${teamId}. Membership found: ${!!hasMembership}`
|
||||
);
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user