1+ import logger from "@calcom/lib/logger" ;
12import db from "@calcom/prisma" ;
23import type { PrismaClient as PrismaClientWithExtensions } from "@calcom/prisma" ;
34import type { MembershipRole } from "@calcom/prisma/enums" ;
@@ -15,6 +16,7 @@ import {
1516export class PermissionRepository implements IPermissionRepository {
1617 private readonly PBAC_FEATURE_FLAG = "pbac" as const ;
1718 private client : PrismaClientWithExtensions ;
19+ private readonly logger = logger . getSubLogger ( { prefix : [ "PermissionRepository" ] } ) ;
1820
1921 constructor ( client : PrismaClientWithExtensions = db ) {
2022 this . client = client ;
@@ -237,7 +239,16 @@ export class PermissionRepository implements IPermissionRepository {
237239 return { resource, action } ;
238240 } ) ;
239241
242+ const permissionPairsJson = JSON . stringify ( permissionPairs ) ;
243+
244+ // Teams with PBAC permissions (direct memberships + child teams via org membership)
240245 const teamsWithPermissionPromise = this . client . $queryRaw < { teamId : number } [ ] > `
246+ WITH required_permissions AS (
247+ SELECT
248+ required_perm->>'resource' as resource,
249+ required_perm->>'action' as action
250+ FROM jsonb_array_elements(${ permissionPairsJson } ::jsonb) AS required_perm
251+ )
241252 SELECT DISTINCT m."teamId"
242253 FROM "Membership" m
243254 INNER JOIN "Role" r ON m."customRoleId" = r.id
@@ -246,26 +257,61 @@ export class PermissionRepository implements IPermissionRepository {
246257 AND m."customRoleId" IS NOT NULL
247258 AND (
248259 SELECT COUNT(*)
249- FROM jsonb_array_elements(${ JSON . stringify ( permissionPairs ) } ::jsonb) AS required_perm(perm)
260+ FROM required_permissions rp_req
261+ WHERE EXISTS (
262+ SELECT 1
263+ FROM "RolePermission" rp
264+ WHERE rp."roleId" = r.id
265+ AND (
266+ (rp."resource" = '*' AND rp."action" = '*') OR
267+ (rp."resource" = '*' AND rp."action" = rp_req.action) OR
268+ (rp."resource" = rp_req.resource AND rp."action" = '*') OR
269+ (rp."resource" = rp_req.resource AND rp."action" = rp_req.action)
270+ )
271+ )
272+ ) = ${ permissions . length }
273+ UNION
274+ SELECT DISTINCT child."id"
275+ FROM "Membership" m
276+ INNER JOIN "Role" r ON m."customRoleId" = r.id
277+ INNER JOIN "Team" org ON m."teamId" = org.id
278+ INNER JOIN "Team" child ON child."parentId" = org.id
279+ WHERE m."userId" = ${ userId }
280+ AND m."accepted" = true
281+ AND m."customRoleId" IS NOT NULL
282+ AND (
283+ SELECT COUNT(*)
284+ FROM required_permissions rp_req
250285 WHERE EXISTS (
251286 SELECT 1
252287 FROM "RolePermission" rp
253288 WHERE rp."roleId" = r.id
254289 AND (
255290 (rp."resource" = '*' AND rp."action" = '*') OR
256- (rp."resource" = '*' AND rp."action" = required_perm.perm->>' action' ) OR
257- (rp."resource" = required_perm.perm->>' resource' AND rp."action" = '*') OR
258- (rp."resource" = required_perm.perm->>' resource' AND rp."action" = required_perm.perm->>' action' )
291+ (rp."resource" = '*' AND rp."action" = rp_req. action) OR
292+ (rp."resource" = rp_req. resource AND rp."action" = '*') OR
293+ (rp."resource" = rp_req. resource AND rp."action" = rp_req. action)
259294 )
260295 )
261296 ) = ${ permissions . length }
262297 ` ;
263298
299+ // Teams with fallback roles (direct memberships + child teams via org membership, PBAC disabled)
264300 const teamsWithFallbackRolesPromise = this . client . $queryRaw < { teamId : number } [ ] > `
265301 SELECT DISTINCT m."teamId"
266302 FROM "Membership" m
267303 INNER JOIN "Team" t ON m."teamId" = t.id
268- LEFT JOIN "TeamFeatures" f ON t.id = f."teamId" AND f."featureId" = ${ this . PBAC_FEATURE_FLAG }
304+ LEFT JOIN "TeamFeatures" f ON f."teamId" = t.id AND f."featureId" = ${ this . PBAC_FEATURE_FLAG }
305+ WHERE m."userId" = ${ userId }
306+ AND m."accepted" = true
307+ AND m."role"::text = ANY(${ fallbackRoles } )
308+ AND f."teamId" IS NULL
309+ UNION
310+ SELECT DISTINCT child."id"
311+ FROM "Membership" m
312+ INNER JOIN "Team" org ON m."teamId" = org.id
313+ INNER JOIN "Team" child ON child."parentId" = org.id
314+ LEFT JOIN "TeamFeatures" f ON f."teamId" = org.id AND f."featureId" = ${ this . PBAC_FEATURE_FLAG }
269315 WHERE m."userId" = ${ userId }
270316 AND m."accepted" = true
271317 AND m."role"::text = ANY(${ fallbackRoles } )
0 commit comments