fix: remove wrong conditions to fetch users on /bookings (#19580)
This commit is contained in:
@@ -2,7 +2,7 @@ import { expect } from "@playwright/test";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { BookingStatus } from "@calcom/prisma/client";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
import { MembershipRole, SchedulingType } from "@calcom/prisma/enums";
|
||||
|
||||
import { createTeamEventType } from "./fixtures/users";
|
||||
import type { Fixtures } from "./lib/fixtures";
|
||||
@@ -378,6 +378,80 @@ test.describe("Bookings", () => {
|
||||
thirdUpcomingBooking.locator(`text=${thirdUserAttendeeTeamEvent!.title}`)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("Does not show booking from another user from collective event type when a member is filtered", async ({
|
||||
page,
|
||||
users,
|
||||
bookings,
|
||||
}) => {
|
||||
const teamMatesObj = [
|
||||
{ name: "teammate-1" },
|
||||
{ name: "teammate-2" },
|
||||
{ name: "teammate-3" },
|
||||
{ name: "teammate-4" },
|
||||
];
|
||||
const owner = await users.create(
|
||||
{ username: "pro-user", name: "pro-user" },
|
||||
{
|
||||
hasTeam: true,
|
||||
teammates: teamMatesObj,
|
||||
schedulingType: SchedulingType.COLLECTIVE,
|
||||
}
|
||||
);
|
||||
|
||||
const { team } = await owner.getFirstTeamMembership();
|
||||
const eventType = await owner.getFirstTeamEvent(team.id);
|
||||
const { id: eventTypeId, title: teamEventTitle, slug: teamEventSlug } = eventType;
|
||||
|
||||
// remove myself from host of this event type
|
||||
await prisma.host.delete({
|
||||
where: {
|
||||
userId_eventTypeId: {
|
||||
userId: owner.id,
|
||||
eventTypeId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// teammate-1
|
||||
const host = await prisma.membership.findFirstOrThrow({
|
||||
where: {
|
||||
teamId: team.id,
|
||||
userId: {
|
||||
not: owner.id,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
|
||||
await createBooking({
|
||||
bookingsFixture: bookings,
|
||||
organizer: host.user,
|
||||
organizerEventType: eventType,
|
||||
attendees: [{ name: "test user", email: "test@example.com", timeZone: "Europe/Paris" }],
|
||||
relativeDate: 0,
|
||||
title: "Booking from test user",
|
||||
});
|
||||
|
||||
// teammate-2
|
||||
const anotherUser = teamMatesObj.find((m) => m.name !== host.user.name)?.name;
|
||||
|
||||
await owner.apiLogin();
|
||||
await page.goto("/bookings/upcoming");
|
||||
await page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url()));
|
||||
|
||||
await page.locator('[data-testid="add-filter-button"]').click();
|
||||
await page.locator('[data-testid="add-filter-item-userId"]').click();
|
||||
await page.locator('[data-testid="filter-popover-trigger-userId"]').click();
|
||||
await page
|
||||
.locator(`[data-testid="multi-select-options-userId"] [role="option"]:has-text("${anotherUser}")`)
|
||||
.click();
|
||||
await page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url()));
|
||||
|
||||
await expect(page.locator('[data-testid="booking-item"]')).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
|
||||
async function createBooking({
|
||||
|
||||
@@ -170,13 +170,13 @@ export async function getBookings({
|
||||
|
||||
const [
|
||||
eventTypeIdsFromTeamIdsFilter,
|
||||
{ attendeeEmailsFromUserIdsFilter, eventTypeIdsFromUserIdsFilter },
|
||||
attendeeEmailsFromUserIdsFilter,
|
||||
eventTypeIdsFromEventTypeIdsFilter,
|
||||
eventTypeIdsWhereUserIsAdminOrOwener,
|
||||
userIdsWhereUserIsOrgAdminOrOwener,
|
||||
] = await Promise.all([
|
||||
getEventTypeIdsFromTeamIdsFilter(prisma, filters?.teamIds),
|
||||
getIdsFromUserIdsFilter(prisma, user.email, filters?.userIds),
|
||||
getAttendeeEmailsFromUserIdsFilter(prisma, user.email, filters?.userIds),
|
||||
getEventTypeIdsFromEventTypeIdsFilter(prisma, filters?.eventTypeIds),
|
||||
getEventTypeIdsWhereUserIsAdminOrOwner(prisma, membershipConditionWhereUserIsAdminOwner),
|
||||
getUserIdsWhereUserIsOrgAdminOrOwner(prisma, membershipConditionWhereUserIsAdminOwner),
|
||||
@@ -226,7 +226,7 @@ export async function getBookings({
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(filters?.userIds && filters.userIds.length > 0 && eventTypeIdsFromUserIdsFilter
|
||||
...(filters?.userIds && filters.userIds.length > 0
|
||||
? [
|
||||
{
|
||||
OR: [
|
||||
@@ -235,15 +235,6 @@ export async function getBookings({
|
||||
in: filters.userIds,
|
||||
},
|
||||
},
|
||||
...(eventTypeIdsFromUserIdsFilter?.length
|
||||
? [
|
||||
{
|
||||
eventTypeId: {
|
||||
in: eventTypeIdsFromUserIdsFilter,
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(attendeeEmailsFromUserIdsFilter?.length
|
||||
? [
|
||||
{
|
||||
@@ -491,71 +482,30 @@ async function getEventTypeIdsFromTeamIdsFilter(prisma: PrismaClient, teamIds?:
|
||||
return Array.from(new Set([...directTeamEventTypeIds, ...parentTeamEventTypeIds]));
|
||||
}
|
||||
|
||||
async function getIdsFromUserIdsFilter(prisma: PrismaClient, userEmail: string, userIds?: number[]) {
|
||||
async function getAttendeeEmailsFromUserIdsFilter(
|
||||
prisma: PrismaClient,
|
||||
userEmail: string,
|
||||
userIds?: number[]
|
||||
) {
|
||||
if (!userIds || userIds.length === 0) {
|
||||
return {
|
||||
eventTypeIdsFromUserIdsFilter: undefined,
|
||||
attendeeEmailsFromUserIdsFilter: undefined,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
const [attendeeEmailsFromUserIdsFilter, eventTypeIdsFromHostsFilter, eventTypeIdsFromUsersFilter] =
|
||||
await Promise.all([
|
||||
prisma.user
|
||||
.findMany({
|
||||
where: {
|
||||
id: {
|
||||
in: userIds,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
email: true,
|
||||
},
|
||||
})
|
||||
// Include booking if current user is an attendee, regardless of user ID filter
|
||||
.then((users) => users.map((user) => user.email).concat([userEmail])),
|
||||
const attendeeEmailsFromUserIdsFilter = await prisma.user
|
||||
.findMany({
|
||||
where: {
|
||||
id: {
|
||||
in: userIds,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
email: true,
|
||||
},
|
||||
})
|
||||
// Include booking if current user is an attendee, regardless of user ID filter
|
||||
.then((users) => users.map((user) => user.email).concat([userEmail]));
|
||||
|
||||
prisma.eventType
|
||||
.findMany({
|
||||
where: {
|
||||
hosts: {
|
||||
some: {
|
||||
userId: {
|
||||
in: userIds,
|
||||
},
|
||||
isFixed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
.then((eventTypes) => eventTypes.map((eventType) => eventType.id)),
|
||||
|
||||
prisma.eventType
|
||||
.findMany({
|
||||
where: {
|
||||
users: {
|
||||
some: {
|
||||
id: {
|
||||
in: userIds,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
.then((eventTypes) => eventTypes.map((eventType) => eventType.id)),
|
||||
]);
|
||||
|
||||
const eventTypeIdsFromUserIdsFilter = Array.from(
|
||||
new Set([...eventTypeIdsFromHostsFilter, ...eventTypeIdsFromUsersFilter])
|
||||
);
|
||||
|
||||
return { attendeeEmailsFromUserIdsFilter, eventTypeIdsFromUserIdsFilter };
|
||||
return attendeeEmailsFromUserIdsFilter;
|
||||
}
|
||||
|
||||
async function getEventTypeIdsFromEventTypeIdsFilter(prisma: PrismaClient, eventTypeIds?: number[]) {
|
||||
|
||||
Reference in New Issue
Block a user