fix: get v2/calendars existing record conflict (#22286)

* refactor: upsert destination calendar

* test: v2 connected calendars

* chore: bump libraries

* refactor: have only createIfNotExistsForUser

* refactor: exclude eventTypeId from user calendar search

* chore: bump libraries
This commit is contained in:
Lauris Skraucis
2025-07-14 08:01:43 +00:00
committed by GitHub
parent 2838053ba8
commit 35022a0478
5 changed files with 77 additions and 21 deletions
+1 -1
View File
@@ -38,7 +38,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.257",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.258",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
"@calcom/prisma": "*",
@@ -1,6 +1,7 @@
import { bootstrap } from "@/app";
import { AppModule } from "@/app.module";
import { CreateIcsFeedOutput, CreateIcsFeedOutputResponseDto } from "@/ee/calendars/input/create-ics.output";
import { ConnectedCalendarsData } from "@/ee/calendars/outputs/connected-calendars.output";
import { DeletedCalendarCredentialsOutputResponseDto } from "@/ee/calendars/outputs/delete-calendar-credentials.output";
import { CalendarsService } from "@/ee/calendars/services/calendars.service";
import { HttpExceptionFilter } from "@/filters/http-exception.filter";
@@ -30,7 +31,7 @@ import {
GOOGLE_CALENDAR_ID,
} from "@calcom/platform-constants";
import { OFFICE_365_CALENDAR_ID, OFFICE_365_CALENDAR_TYPE } from "@calcom/platform-constants";
import { ICS_CALENDAR } from "@calcom/platform-constants/apps";
import { ICS_CALENDAR, ICS_CALENDAR_TYPE } from "@calcom/platform-constants/apps";
import { IcsFeedCalendarService } from "@calcom/platform-libraries/app-store";
const CLIENT_REDIRECT_URI = "http://localhost:5555";
@@ -247,6 +248,35 @@ describe("Platform Calendars Endpoints", () => {
.expect(200);
});
it(`/GET/v2/calendars with access token`, async () => {
const response = await request(app.getHttpServer())
.get(`/v2/calendars`)
.set("Authorization", `Bearer ${accessTokenSecret}`)
.set("Origin", CLIENT_REDIRECT_URI)
.expect(200);
const data: ConnectedCalendarsData = response.body.data;
expect(data.connectedCalendars).toBeDefined();
expect(data.connectedCalendars).toHaveLength(3);
const googleConnectedCalendar = data.connectedCalendars.find(
(calendar) => calendar.integration.type === GOOGLE_CALENDAR_TYPE
);
const office365ConnectedCalendar = data.connectedCalendars.find(
(calendar) => calendar.integration.type === OFFICE_365_CALENDAR_TYPE
);
const icsConnectedCalendar = data.connectedCalendars.find(
(calendar) => calendar.integration.type === ICS_CALENDAR_TYPE
);
expect(googleConnectedCalendar).toBeDefined();
expect(office365ConnectedCalendar).toBeDefined();
expect(icsConnectedCalendar).toBeDefined();
expect(data.destinationCalendar).toBeDefined();
expect(data.destinationCalendar.integration).toEqual(GOOGLE_CALENDAR_TYPE);
});
it.skip(`/POST/v2/calendars/${OFFICE_365_CALENDAR}/disconnect: it should respond with a 201 returning back the user deleted calendar credentials`, async () => {
const body = {
id: 10,
@@ -8,6 +8,7 @@ import type { DestinationCalendar, SelectedCalendar, User } from "@calcom/prisma
import { AppCategories } from "@calcom/prisma/enums";
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
import { DestinationCalendarRepository } from "./server/repository/destinationCalendar";
import { EventTypeRepository } from "./server/repository/eventType";
import { SelectedCalendarRepository } from "./server/repository/selectedCalendar";
@@ -134,20 +135,18 @@ async function handleNoDestinationCalendar({
}
}
user.destinationCalendar = await prisma.destinationCalendar.create({
data: {
userId: user.id,
integration,
externalId,
primaryEmail,
...(!isDelegationCredential({ credentialId })
? {
credentialId,
}
: {
delegationCredentialId,
}),
},
user.destinationCalendar = await DestinationCalendarRepository.createIfNotExistsForUser({
userId: user.id,
integration,
externalId,
primaryEmail,
...(!isDelegationCredential({ credentialId })
? {
credentialId,
}
: {
delegationCredentialId,
}),
});
return {
@@ -14,6 +14,18 @@ export class DestinationCalendarRepository {
});
}
static async createIfNotExistsForUser(
data: { userId: number } & Prisma.DestinationCalendarUncheckedCreateInput
) {
const conflictingCalendar = await DestinationCalendarRepository.findConflictingForUser(data);
if (conflictingCalendar) {
return conflictingCalendar;
}
return await prisma.destinationCalendar.create({
data,
});
}
static async getByUserId(userId: number) {
return await prisma.destinationCalendar.findFirst({
where: {
@@ -36,6 +48,21 @@ export class DestinationCalendarRepository {
});
}
private static async findConflictingForUser(data: {
userId: number;
integration: string;
externalId: string;
}) {
return await DestinationCalendarRepository.find({
where: {
userId: data.userId,
integration: data.integration,
externalId: data.externalId,
eventTypeId: null,
},
});
}
static async upsert({
where,
update,
+5 -5
View File
@@ -2519,7 +2519,7 @@ __metadata:
"@axiomhq/winston": ^1.2.0
"@calcom/platform-constants": "*"
"@calcom/platform-enums": "*"
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.257"
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.258"
"@calcom/platform-types": "*"
"@calcom/platform-utils": "*"
"@calcom/prisma": "*"
@@ -3565,13 +3565,13 @@ __metadata:
languageName: unknown
linkType: soft
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.257":
version: 0.0.257
resolution: "@calcom/platform-libraries@npm:0.0.257"
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.258":
version: 0.0.258
resolution: "@calcom/platform-libraries@npm:0.0.258"
dependencies:
"@calcom/features": "*"
"@calcom/lib": "*"
checksum: d45647591a26b6a73b6ae7602d8b8e59d87339de0e49468737437ffdd716fbd953898cd59a1eff8938326eba9ca895c28990bc91355aa55006980a2e716ddfd0
checksum: ca522eee904921d4a2f285ba6ed195118a6d68c76fb454d826574d1f5487e8d3d7e41915c968ad0eff6bb01730578ee414069684c7a395b0c19b910f136bffb7
languageName: node
linkType: hard