Files
calendar/packages/prisma/extensions/booking-idempotency-key.ts
T
Alex van AndelandGitHub d85e0b51e4 fix: Prevent duplicate bookings with idempotency key (#13865)
* fix: Prevent duplicate bookings with idempotency key

* Add idempotencyKey to builder.ts type fix

* Add tests for new idempotency key (booking create)

* Add endTime to idempotency key, it should be possible to book different durations

* Move reschedule before the create so the idempotency key is unset
2024-02-26 18:33:22 +00:00

39 lines
1.4 KiB
TypeScript

import { Prisma } from "@prisma/client";
import { v5 as uuidv5 } from "uuid";
import { BookingStatus } from "@calcom/prisma/enums";
export function bookingIdempotencyKeyExtension() {
return Prisma.defineExtension({
query: {
booking: {
async create({ args, query }) {
const uniqueEmailJoinInput: string[] = [];
if (args.data.attendees?.create && !Array.isArray(args.data.attendees?.create)) {
uniqueEmailJoinInput.push(args.data.attendees?.create.email);
}
if (args.data.attendees?.createMany && Array.isArray(args.data.attendees?.createMany.data)) {
uniqueEmailJoinInput.push(...args.data.attendees?.createMany.data.map((record) => record.email));
}
const idempotencyKey = uuidv5(
`${
args.data.eventType?.connect?.id
}.${args.data.startTime.valueOf()}.${args.data.endTime.valueOf()}.${uniqueEmailJoinInput.join(
","
)}`,
uuidv5.URL
);
args.data.idempotencyKey = idempotencyKey;
return query(args);
},
async update({ args, query }) {
if (args.data.status === BookingStatus.CANCELLED || args.data.status === BookingStatus.REJECTED) {
args.data.idempotencyKey = null;
}
return query(args);
},
},
},
});
}