fix: getBookings for team admins within orgs (#21833)

* fix: getBookings for team admins within orgs

* fixup! fix: getBookings for team admins within orgs

* chore: update getUserIdsAndEmailsWhereUserIsAdminOrOwner and remove unused orgId

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
This commit is contained in:
Morgan
2025-06-16 09:34:02 -03:00
committed by GitHub
co-authored by Anik Dhabal Babu
parent 0a60864310
commit 3dd3372c35
10 changed files with 51 additions and 32 deletions
+1 -1
View File
@@ -37,7 +37,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.222",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.223",
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
@@ -6,7 +6,7 @@ import {
getRecordingsOfCalVideoByRoomName,
getAllTranscriptsAccessLinkFromRoomName,
getDownloadLinkOfCalVideoByRecordingId,
} from "@calcom/platform-libraries";
} from "@calcom/platform-libraries/conferencing";
@Injectable()
export class CalVideoService {
+11 -2
View File
@@ -10695,6 +10695,16 @@
"type": "string"
}
},
{
"name": "bookingUidToReschedule",
"required": false,
"in": "query",
"description": "The unique identifier of the booking being rescheduled. When provided will ensure that the original booking time appears within the returned available slots when rescheduling.",
"example": "abc123def456",
"schema": {
"type": "string"
}
},
{
"name": "routingFormId",
"required": true,
@@ -25447,8 +25457,7 @@
"startTs",
"status",
"duration",
"shareToken",
"downloadLink"
"shareToken"
]
},
"GetBookingRecordingsOutput": {
+2 -1
View File
@@ -24,7 +24,8 @@
"@calcom/platform-libraries/emails": ["../../../packages/platform/libraries/emails.ts"],
"@calcom/platform-libraries/schedules": ["../../../packages/platform/libraries/schedules.ts"],
"@calcom/platform-libraries/app-store": ["../../../packages/platform/libraries/app-store.ts"],
"@calcom/platform-libraries/workflows": ["../../../packages/platform/libraries/workflows.ts"]
"@calcom/platform-libraries/workflows": ["../../../packages/platform/libraries/workflows.ts"],
"@calcom/platform-libraries/conferencing": ["../../../packages/platform/libraries/conferencing.ts"]
},
"incremental": true,
"skipLibCheck": true,
+11 -1
View File
@@ -10205,6 +10205,16 @@
"type": "string"
}
},
{
"name": "bookingUidToReschedule",
"required": false,
"in": "query",
"description": "The unique identifier of the booking being rescheduled. When provided will ensure that the original booking time appears within the returned available slots when rescheduling.",
"example": "abc123def456",
"schema": {
"type": "string"
}
},
{
"name": "routingFormId",
"required": true,
@@ -23342,7 +23352,7 @@
"example": "Error message"
}
},
"required": ["id", "roomName", "startTs", "status", "duration", "shareToken", "downloadLink"]
"required": ["id", "roomName", "startTs", "status", "duration", "shareToken"]
},
"GetBookingRecordingsOutput": {
"type": "object",
@@ -0,0 +1,5 @@
export {
getRecordingsOfCalVideoByRoomName,
getDownloadLinkOfCalVideoByRecordingId,
getAllTranscriptsAccessLinkFromRoomName,
} from "@calcom/lib/videoClient";
-6
View File
@@ -74,12 +74,6 @@ export { getTranslation };
export { roundRobinReassignment } from "@calcom/features/ee/round-robin/roundRobinReassignment";
export { roundRobinManualReassignment } from "@calcom/features/ee/round-robin/roundRobinManualReassignment";
export {
getRecordingsOfCalVideoByRoomName,
getDownloadLinkOfCalVideoByRecordingId,
getAllTranscriptsAccessLinkFromRoomName,
} from "@calcom/lib/videoClient";
export { ErrorCode } from "@calcom/lib/errorCodes";
export { validateCustomEventName } from "@calcom/lib/event";
+8
View File
@@ -63,6 +63,11 @@
"import": "./dist/slots.js",
"require": "./dist/slots.cjs",
"types": "./dist/slots.d.ts"
},
"./conferencing": {
"import": "./dist/conferencing.js",
"require": "./dist/conferencing.cjs",
"types": "./dist/conferencing.d.ts"
}
},
"typesVersions": {
@@ -84,6 +89,9 @@
],
"workflows": [
"dist/workflows.d.ts"
],
"conferencing": [
"dist/conferencing.d.ts"
]
}
}
@@ -24,6 +24,7 @@ export default defineConfig({
"app-store": resolve(__dirname, "./app-store.ts"),
workflows: resolve(__dirname, "./workflows.ts"),
slots: resolve(__dirname, "./slots.ts"),
conferencing: resolve(__dirname, "./conferencing.ts"),
},
name: "calcom-lib",
fileName: "calcom-lib",
@@ -123,7 +123,7 @@ export async function getBookings({
getAttendeeEmailsFromUserIdsFilter(prisma, user.email, filters?.userIds),
getEventTypeIdsFromEventTypeIdsFilter(prisma, filters?.eventTypeIds),
getEventTypeIdsWhereUserIsAdminOrOwner(prisma, membershipConditionWhereUserIsAdminOwner),
getUserIdsAndEmailsWhereUserIsAdminOrOwner(prisma, membershipConditionWhereUserIsAdminOwner, user.orgId),
getUserIdsAndEmailsWhereUserIsAdminOrOwner(prisma, membershipConditionWhereUserIsAdminOwner),
]);
const bookingQueries: { query: BookingsUnionQuery; tables: (keyof DB)[] }[] = [];
@@ -829,34 +829,22 @@ async function getEventTypeIdsWhereUserIsAdminOrOwner(
}
/**
* Gets [IDs, Emails] of members where the auth user is admin/owner.
* Scope depends on `orgId`:
* - If set (number): Fetches members of that specific organization (`isOrganization: true`).
* - If unset (null/undefined): Fetches members of all teams (`isOrganization: false`)
* where the auth user meets the `membershipCondition`.
*
* Gets [IDs, Emails] of members where the auth user is team/org admin/owner.
* @param prisma The Prisma client.
* @param membershipCondition Filter defining the auth user's required role (e.g., OWNER/ADMIN)
* to identify the target orgs/teams.
* @param orgId Optional ID to target a specific org; absence targets teams.
* @param membershipCondition Filter containing the team/org ids where user is ADMIN/OWNER
* @returns {Promise<[number[], string[]]>} [UserIDs, UserEmails] for members in the determined scope.
*/
async function getUserIdsAndEmailsWhereUserIsAdminOrOwner(
prisma: PrismaClient,
membershipCondition: PrismaClientType.MembershipListRelationFilter,
orgId?: number | null
membershipCondition: PrismaClientType.MembershipListRelationFilter
): Promise<[number[], string[]]> {
const users = await prisma.user.findMany({
where: {
teams: {
some: {
team: orgId
? {
isOrganization: true,
members: membershipCondition,
id: orgId,
}
: { isOrganization: false, members: membershipCondition, parentId: null },
team: {
members: membershipCondition,
},
},
},
},
@@ -865,7 +853,10 @@ async function getUserIdsAndEmailsWhereUserIsAdminOrOwner(
email: true,
},
});
return [users.map((user) => user.id), users.map((user) => user.email)];
const userIds = Array.from(new Set(users.map((user) => user.id)));
const userEmails = Array.from(new Set(users.map((user) => user.email)));
return [userIds, userEmails];
}
function addStatusesQueryFilters(query: BookingsUnionQuery, statuses: InputByStatus[]) {