Compare commits
71
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18ba54522c | ||
|
|
5483597a5b | ||
|
|
4ed0901957 | ||
|
|
dbbf3ae2a2 | ||
|
|
c3985e3efb | ||
|
|
c28eb90928 | ||
|
|
a55d56f260 | ||
|
|
1d25265c56 | ||
|
|
65f6689025 | ||
|
|
92005b93c3 | ||
|
|
0a7e573117 | ||
|
|
943c1a3c03 | ||
|
|
9156848503 | ||
|
|
2e6ad8be9a | ||
|
|
1aca18324d | ||
|
|
a8a3e48465 | ||
|
|
2e96600529 | ||
|
|
b9074aeb81 | ||
|
|
13add03479 | ||
|
|
bb2dcc51c6 | ||
|
|
8f82e78597 | ||
|
|
34d2a13080 | ||
|
|
6066ed206b | ||
|
|
d30d2792cd | ||
|
|
ba50268634 | ||
|
|
4ca78f46df | ||
|
|
3a7ca0246c | ||
|
|
2cc8b1c2af | ||
|
|
a2d0cbfe5b | ||
|
|
d65c0753ef | ||
|
|
76bd90b228 | ||
|
|
d908403a99 | ||
|
|
0fe775962f | ||
|
|
412a6992c7 | ||
|
|
cfd1992733 | ||
|
|
e86d6169ba | ||
|
|
a379bd2b52 | ||
|
|
1137047606 | ||
|
|
ad4cf0cc3a | ||
|
|
e7d2e0dc2f | ||
|
|
aa51218428 | ||
|
|
38bc5fb71e | ||
|
|
411516ddb9 | ||
|
|
c6c17ac388 | ||
|
|
6838133865 | ||
|
|
4b2bb2271a | ||
|
|
20b7ac8c0d | ||
|
|
ca7c432728 | ||
|
|
3b966191e3 | ||
|
|
a7889984a0 | ||
|
|
3c72d7aaa0 | ||
|
|
ece0030978 | ||
|
|
a26a769119 | ||
|
|
3313de1eec | ||
|
|
7a6e16631b | ||
|
|
ce4d71ba2e | ||
|
|
300cd31efb | ||
|
|
f5bb734441 | ||
|
|
e33560ef82 | ||
|
|
84f34b2244 | ||
|
|
086bae03d3 | ||
|
|
4a0a429774 | ||
|
|
c4142ab4e7 | ||
|
|
95f8046db9 | ||
|
|
d8a87e9f04 | ||
|
|
86dcd6f0ff | ||
|
|
411a14dd3d | ||
|
|
03bc8db64a | ||
|
|
fe7fd8bc79 | ||
|
|
92eb41c117 | ||
|
|
a1fca56aac |
@@ -318,3 +318,12 @@ dates.map((date) => dayjs.utc(date).add(1, "day").format());
|
||||
// ✅ Best - Use native Date when possible
|
||||
dates.map((date) => new Date(date.valueOf() + 24 * 60 * 60 * 1000));
|
||||
```
|
||||
|
||||
## Avoid using Dayjs if you don’t need to be strictly tz aware.
|
||||
|
||||
When doing logic like Dayjs.startOf(".."), you can instead use date-fns' `startOfMonth(dateObj)` / `endOfDay(dateObj)`;
|
||||
When doing logic that depends on Browser locale, use i18n.language (prefer to deconstruct) like: `const { i18n: { language } } = useLocale();`, in combination with built-in Intl.
|
||||
|
||||
Note that with Date, you’re dealing with System time, so it’s not suited to everywhere (such as in the Booker, where instead we’ll likely migrate to Temporal) - but in most cases the above are suitable.
|
||||
|
||||
The main reason for doing so is that Dayjs uses a useful, but highly risky plugin system, which has led us to create `@calcom/dayjs` - this is heavy however, because it pre-loads ALL plugins, including locale handling. It’s a non-ideal solution to a problem that unfortunately exists due to Dayjs.
|
||||
|
||||
+3
-8
@@ -103,19 +103,14 @@ NEXT_PUBLIC_INTERCOM_APP_ID=
|
||||
# Secret to enable Intercom Identity Verification
|
||||
INTERCOM_SECRET=
|
||||
|
||||
# Intercom api token for free users
|
||||
INTERCOM_API_TOKEN=
|
||||
|
||||
# Posthog Config
|
||||
NEXT_PUBLIC_POSTHOG_KEY=
|
||||
|
||||
NEXT_PUBLIC_POSTHOG_HOST=
|
||||
|
||||
# plain.com config
|
||||
|
||||
PLAIN_API_KEY=
|
||||
PLAIN_API_URL=https://api.plain.com/v1
|
||||
PLAIN_HMAC_SECRET_KEY=
|
||||
NEXT_PUBLIC_PLAIN_CHAT_ID=
|
||||
PLAIN_CHAT_HMAC_SECRET_KEY=
|
||||
NEXT_PUBLIC_PLAIN_CHAT_EXCLUDED_PATHS=
|
||||
|
||||
|
||||
# Dub Config
|
||||
|
||||
@@ -19,5 +19,17 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["packages/app-store/**/*.{ts,tsx,js,jsx}"],
|
||||
rules: {
|
||||
"no-restricted-imports": [
|
||||
"warn",
|
||||
{
|
||||
paths: ["@calcom/trpc"],
|
||||
patterns: ["@calcom/trpc/*"],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+2
-1
@@ -66,7 +66,8 @@ tsconfig.tsbuildinfo
|
||||
.turbo
|
||||
|
||||
# Prisma generated files
|
||||
packages/prisma/zod/*.ts
|
||||
packages/prisma/client/*
|
||||
packages/prisma/zod/**/*.ts
|
||||
packages/prisma/enums
|
||||
|
||||
# Builds
|
||||
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
Vendored
Vendored
Vendored
Vendored
@@ -1,6 +1,6 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { _ApiKeyModel as ApiKey } from "@calcom/prisma/zod";
|
||||
import { ApiKeySchema as ApiKey } from "@calcom/prisma/zod/modelSchema/ApiKeySchema";
|
||||
|
||||
export const apiKeyCreateBodySchema = ApiKey.pick({
|
||||
note: true,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { emailSchema } from "@calcom/lib/emailSchema";
|
||||
import { _AttendeeModel as Attendee } from "@calcom/prisma/zod";
|
||||
import { AttendeeSchema } from "@calcom/prisma/zod/modelSchema/AttendeeSchema";
|
||||
|
||||
import { timeZone } from "~/lib/validations/shared/timeZone";
|
||||
|
||||
export const schemaAttendeeBaseBodyParams = Attendee.pick({
|
||||
export const schemaAttendeeBaseBodyParams = AttendeeSchema.pick({
|
||||
bookingId: true,
|
||||
email: true,
|
||||
name: true,
|
||||
@@ -31,7 +31,7 @@ const schemaAttendeeEditParams = z
|
||||
export const schemaAttendeeEditBodyParams = schemaAttendeeBaseBodyParams.merge(schemaAttendeeEditParams);
|
||||
export const schemaAttendeeCreateBodyParams = schemaAttendeeBaseBodyParams.merge(schemaAttendeeCreateParams);
|
||||
|
||||
export const schemaAttendeeReadPublic = Attendee.pick({
|
||||
export const schemaAttendeeReadPublic = AttendeeSchema.pick({
|
||||
id: true,
|
||||
bookingId: true,
|
||||
name: true,
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { _AvailabilityModel as Availability, _ScheduleModel as Schedule } from "@calcom/prisma/zod";
|
||||
import { denullishShape } from "@calcom/prisma/zod-utils";
|
||||
import { AvailabilitySchema } from "@calcom/prisma/zod/modelSchema/AvailabilitySchema";
|
||||
import { ScheduleSchema } from "@calcom/prisma/zod/modelSchema/ScheduleSchema";
|
||||
|
||||
export const schemaAvailabilityBaseBodyParams = /** We make all these properties required */ denullishShape(
|
||||
Availability.pick({
|
||||
AvailabilitySchema.pick({
|
||||
/** We need to pass the schedule where this availability belongs to */
|
||||
scheduleId: true,
|
||||
})
|
||||
);
|
||||
|
||||
export const schemaAvailabilityReadPublic = Availability.pick({
|
||||
export const schemaAvailabilityReadPublic = AvailabilitySchema.pick({
|
||||
id: true,
|
||||
startTime: true,
|
||||
endTime: true,
|
||||
@@ -19,7 +20,7 @@ export const schemaAvailabilityReadPublic = Availability.pick({
|
||||
days: true,
|
||||
// eventTypeId: true /** @deprecated */,
|
||||
// userId: true /** @deprecated */,
|
||||
}).merge(z.object({ success: z.boolean().optional(), Schedule: Schedule.partial() }).partial());
|
||||
}).merge(z.object({ success: z.boolean().optional(), Schedule: ScheduleSchema.partial() }).partial());
|
||||
|
||||
const schemaAvailabilityCreateParams = z
|
||||
.object({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { _BookingReferenceModel as BookingReference } from "@calcom/prisma/zod";
|
||||
import { denullishShape } from "@calcom/prisma/zod-utils";
|
||||
import { BookingReferenceSchema } from "@calcom/prisma/zod/modelSchema/BookingReferenceSchema";
|
||||
|
||||
export const schemaBookingReferenceBaseBodyParams = BookingReference.pick({
|
||||
export const schemaBookingReferenceBaseBodyParams = BookingReferenceSchema.pick({
|
||||
type: true,
|
||||
bookingId: true,
|
||||
uid: true,
|
||||
@@ -11,7 +11,7 @@ export const schemaBookingReferenceBaseBodyParams = BookingReference.pick({
|
||||
deleted: true,
|
||||
}).partial();
|
||||
|
||||
export const schemaBookingReferenceReadPublic = BookingReference.pick({
|
||||
export const schemaBookingReferenceReadPublic = BookingReferenceSchema.pick({
|
||||
id: true,
|
||||
type: true,
|
||||
bookingId: true,
|
||||
@@ -22,7 +22,7 @@ export const schemaBookingReferenceReadPublic = BookingReference.pick({
|
||||
deleted: true,
|
||||
});
|
||||
|
||||
export const schemaBookingCreateBodyParams = BookingReference.omit({ id: true, bookingId: true })
|
||||
.merge(denullishShape(BookingReference.pick({ bookingId: true })))
|
||||
export const schemaBookingCreateBodyParams = BookingReferenceSchema.omit({ id: true, bookingId: true })
|
||||
.merge(denullishShape(BookingReferenceSchema.pick({ bookingId: true })))
|
||||
.strict();
|
||||
export const schemaBookingEditBodyParams = schemaBookingCreateBodyParams.partial();
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
_AttendeeModel,
|
||||
_BookingModel as Booking,
|
||||
_EventTypeModel,
|
||||
_PaymentModel,
|
||||
_TeamModel,
|
||||
_UserModel,
|
||||
} from "@calcom/prisma/zod";
|
||||
import { extendedBookingCreateBody } from "@calcom/features/bookings/lib/bookingCreateBodySchema";
|
||||
import { iso8601 } from "@calcom/prisma/zod-utils";
|
||||
import { extendedBookingCreateBody } from "@calcom/prisma/zod/custom/booking";
|
||||
import { AttendeeSchema } from "@calcom/prisma/zod/modelSchema/AttendeeSchema";
|
||||
import { BookingSchema as Booking } from "@calcom/prisma/zod/modelSchema/BookingSchema";
|
||||
import { EventTypeSchema } from "@calcom/prisma/zod/modelSchema/EventTypeSchema";
|
||||
import { PaymentSchema } from "@calcom/prisma/zod/modelSchema/PaymentSchema";
|
||||
import { TeamSchema } from "@calcom/prisma/zod/modelSchema/TeamSchema";
|
||||
import { UserSchema } from "@calcom/prisma/zod/modelSchema/UserSchema";
|
||||
|
||||
import { schemaQueryUserId } from "./shared/queryUserId";
|
||||
|
||||
@@ -72,17 +70,16 @@ export const schemaBookingEditBodyParams = schemaBookingBaseBodyParams
|
||||
.merge(schemaBookingEditParams)
|
||||
.omit({ uid: true });
|
||||
|
||||
const teamSchema = _TeamModel.pick({
|
||||
const teamSchema = TeamSchema.pick({
|
||||
name: true,
|
||||
slug: true,
|
||||
});
|
||||
|
||||
export const schemaBookingReadPublic = Booking.extend({
|
||||
eventType: _EventTypeModel
|
||||
.pick({
|
||||
title: true,
|
||||
slug: true,
|
||||
})
|
||||
eventType: EventTypeSchema.pick({
|
||||
title: true,
|
||||
slug: true,
|
||||
})
|
||||
.merge(
|
||||
z.object({
|
||||
team: teamSchema.nullish(),
|
||||
@@ -91,7 +88,7 @@ export const schemaBookingReadPublic = Booking.extend({
|
||||
.nullish(),
|
||||
attendees: z
|
||||
.array(
|
||||
_AttendeeModel.pick({
|
||||
AttendeeSchema.pick({
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
@@ -100,17 +97,15 @@ export const schemaBookingReadPublic = Booking.extend({
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
user: _UserModel
|
||||
.pick({
|
||||
email: true,
|
||||
name: true,
|
||||
timeZone: true,
|
||||
locale: true,
|
||||
})
|
||||
.nullish(),
|
||||
user: UserSchema.pick({
|
||||
email: true,
|
||||
name: true,
|
||||
timeZone: true,
|
||||
locale: true,
|
||||
}).nullish(),
|
||||
payment: z
|
||||
.array(
|
||||
_PaymentModel.pick({
|
||||
PaymentSchema.pick({
|
||||
id: true,
|
||||
success: true,
|
||||
paymentOption: true,
|
||||
@@ -140,3 +135,8 @@ export const schemaBookingReadPublic = Booking.extend({
|
||||
rescheduledBy: true,
|
||||
createdAt: true,
|
||||
});
|
||||
|
||||
export {
|
||||
bookingCreateSchemaLegacyPropsForApi,
|
||||
bookingCreateBodySchemaForApi,
|
||||
} from "@calcom/features/bookings/lib/bookingCreateBodySchema";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { _DestinationCalendarModel as DestinationCalendar } from "@calcom/prisma/zod";
|
||||
import { DestinationCalendarSchema } from "@calcom/prisma/zod/modelSchema/DestinationCalendarSchema";
|
||||
|
||||
export const schemaDestinationCalendarBaseBodyParams = DestinationCalendar.pick({
|
||||
export const schemaDestinationCalendarBaseBodyParams = DestinationCalendarSchema.pick({
|
||||
integration: true,
|
||||
externalId: true,
|
||||
eventTypeId: true,
|
||||
@@ -38,7 +38,7 @@ export const schemaDestinationCalendarEditBodyParams = schemaDestinationCalendar
|
||||
schemaDestinationCalendarEditParams
|
||||
);
|
||||
|
||||
export const schemaDestinationCalendarReadPublic = DestinationCalendar.pick({
|
||||
export const schemaDestinationCalendarReadPublic = DestinationCalendarSchema.pick({
|
||||
id: true,
|
||||
integration: true,
|
||||
externalId: true,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { _EventTypeCustomInputModel as EventTypeCustomInput } from "@calcom/prisma/zod";
|
||||
import { EventTypeCustomInputSchema } from "@calcom/prisma/zod/modelSchema/EventTypeCustomInputSchema";
|
||||
|
||||
export const schemaEventTypeCustomInputBaseBodyParams = EventTypeCustomInput.omit({
|
||||
export const schemaEventTypeCustomInputBaseBodyParams = EventTypeCustomInputSchema.omit({
|
||||
id: true,
|
||||
});
|
||||
|
||||
export const schemaEventTypeCustomInputPublic = EventTypeCustomInput.omit({});
|
||||
export const schemaEventTypeCustomInputPublic = EventTypeCustomInputSchema.omit({});
|
||||
|
||||
export const schemaEventTypeCustomInputBodyParams = schemaEventTypeCustomInputBaseBodyParams.strict();
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@ import {
|
||||
MIN_EVENT_DURATION_MINUTES,
|
||||
} from "@calcom/lib/constants";
|
||||
import slugify from "@calcom/lib/slugify";
|
||||
import { _EventTypeModel as EventType, _HostModel } from "@calcom/prisma/zod";
|
||||
import { customInputSchema, eventTypeBookingFields } from "@calcom/prisma/zod-utils";
|
||||
import { EventTypeSchema } from "@calcom/prisma/zod/modelSchema/EventTypeSchema";
|
||||
import { HostSchema } from "@calcom/prisma/zod/modelSchema/HostSchema";
|
||||
|
||||
import { Frequency } from "~/lib/types";
|
||||
|
||||
@@ -24,7 +25,7 @@ const recurringEventInputSchema = z.object({
|
||||
tzid: timeZone.optional(),
|
||||
});
|
||||
|
||||
const hostSchema = _HostModel.pick({
|
||||
const hostSchema = HostSchema.pick({
|
||||
isFixed: true,
|
||||
userId: true,
|
||||
scheduleId: true,
|
||||
@@ -35,7 +36,7 @@ export const childrenSchema = z.object({
|
||||
userId: z.number().int(),
|
||||
});
|
||||
|
||||
export const schemaEventTypeBaseBodyParams = EventType.pick({
|
||||
export const schemaEventTypeBaseBodyParams = EventTypeSchema.pick({
|
||||
title: true,
|
||||
description: true,
|
||||
slug: true,
|
||||
@@ -117,7 +118,7 @@ const schemaEventTypeEditParams = z
|
||||
.strict();
|
||||
|
||||
export const schemaEventTypeEditBodyParams = schemaEventTypeBaseBodyParams.merge(schemaEventTypeEditParams);
|
||||
export const schemaEventTypeReadPublic = EventType.pick({
|
||||
export const schemaEventTypeReadPublic = EventTypeSchema.pick({
|
||||
id: true,
|
||||
title: true,
|
||||
slug: true,
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
import { _MembershipModel as Membership, _TeamModel } from "@calcom/prisma/zod";
|
||||
import { stringOrNumber } from "@calcom/prisma/zod-utils";
|
||||
import { MembershipSchema } from "@calcom/prisma/zod/modelSchema/MembershipSchema";
|
||||
import { TeamSchema } from "@calcom/prisma/zod/modelSchema/TeamSchema";
|
||||
|
||||
import { schemaQueryIdAsString } from "~/lib/validations/shared/queryIdString";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export const schemaMembershipBaseBodyParams = Membership.omit({});
|
||||
export const schemaMembershipBaseBodyParams = MembershipSchema.omit({});
|
||||
|
||||
const schemaMembershipRequiredParams = z.object({
|
||||
teamId: z.number(),
|
||||
});
|
||||
|
||||
export const membershipCreateBodySchema = Membership.omit({ id: true })
|
||||
export const membershipCreateBodySchema = MembershipSchema.omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
})
|
||||
.partial({
|
||||
accepted: true,
|
||||
role: true,
|
||||
@@ -26,11 +31,13 @@ export const membershipCreateBodySchema = Membership.omit({ id: true })
|
||||
...v,
|
||||
}));
|
||||
|
||||
export const membershipEditBodySchema = Membership.omit({
|
||||
export const membershipEditBodySchema = MembershipSchema.omit({
|
||||
/** To avoid complication, let's avoid updating these, instead you can delete and create a new invite */
|
||||
teamId: true,
|
||||
userId: true,
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
})
|
||||
.partial({
|
||||
accepted: true,
|
||||
@@ -43,7 +50,7 @@ export const schemaMembershipBodyParams = schemaMembershipBaseBodyParams.merge(
|
||||
schemaMembershipRequiredParams
|
||||
);
|
||||
|
||||
export const schemaMembershipPublic = Membership.merge(z.object({ team: _TeamModel }).partial());
|
||||
export const schemaMembershipPublic = MembershipSchema.merge(z.object({ team: TeamSchema }).partial());
|
||||
|
||||
/** We extract userId and teamId from compound ID string */
|
||||
export const membershipIdSchema = schemaQueryIdAsString
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { _PaymentModel as Payment } from "@calcom/prisma/zod";
|
||||
import { PaymentSchema } from "@calcom/prisma/zod/modelSchema/PaymentSchema";
|
||||
|
||||
export const schemaPaymentPublic = Payment.pick({
|
||||
export const schemaPaymentPublic = PaymentSchema.pick({
|
||||
id: true,
|
||||
amount: true,
|
||||
success: true,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { _ReminderMailModel as ReminderMail } from "@calcom/prisma/zod";
|
||||
import { ReminderMailSchema } from "@calcom/prisma/zod/modelSchema/ReminderMailSchema";
|
||||
|
||||
export const schemaReminderMailBaseBodyParams = ReminderMail.omit({ id: true }).partial();
|
||||
export const schemaReminderMailBaseBodyParams = ReminderMailSchema.omit({ id: true }).partial();
|
||||
|
||||
export const schemaReminderMailPublic = ReminderMail.omit({});
|
||||
export const schemaReminderMailPublic = ReminderMailSchema.omit({});
|
||||
|
||||
const schemaReminderMailRequiredParams = z.object({
|
||||
referenceId: z.number().int(),
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { _ScheduleModel as Schedule, _AvailabilityModel as Availability } from "@calcom/prisma/zod";
|
||||
import { AvailabilitySchema } from "@calcom/prisma/zod/modelSchema/AvailabilitySchema";
|
||||
import { ScheduleSchema } from "@calcom/prisma/zod/modelSchema/ScheduleSchema";
|
||||
|
||||
import { timeZone } from "./shared/timeZone";
|
||||
|
||||
const schemaScheduleBaseBodyParams = Schedule.omit({ id: true, timeZone: true }).partial();
|
||||
const schemaScheduleBaseBodyParams = ScheduleSchema.omit({ id: true, timeZone: true }).partial();
|
||||
|
||||
export const schemaSingleScheduleBodyParams = schemaScheduleBaseBodyParams.merge(
|
||||
z.object({ userId: z.number().optional(), timeZone: timeZone.optional() })
|
||||
@@ -17,12 +18,12 @@ export const schemaCreateScheduleBodyParams = schemaScheduleBaseBodyParams.merge
|
||||
|
||||
export const schemaSchedulePublic = z
|
||||
.object({ id: z.number() })
|
||||
.merge(Schedule)
|
||||
.merge(ScheduleSchema)
|
||||
.merge(
|
||||
z.object({
|
||||
availability: z
|
||||
.array(
|
||||
Availability.pick({
|
||||
AvailabilitySchema.pick({
|
||||
id: true,
|
||||
eventTypeId: true,
|
||||
date: true,
|
||||
|
||||
@@ -1,28 +1,22 @@
|
||||
import z from "zod";
|
||||
|
||||
import { _SelectedCalendarModel as SelectedCalendar } from "@calcom/prisma/zod";
|
||||
import { SelectedCalendarSchema } from "@calcom/prisma/zod/modelSchema/SelectedCalendarSchema";
|
||||
|
||||
import { schemaQueryIdAsString } from "./shared/queryIdString";
|
||||
import { schemaQueryIdParseInt } from "./shared/queryIdTransformParseInt";
|
||||
|
||||
export const schemaSelectedCalendarBaseBodyParams = SelectedCalendar;
|
||||
export const schemaSelectedCalendarBaseBodyParams = SelectedCalendarSchema;
|
||||
|
||||
export const schemaSelectedCalendarPublic = SelectedCalendar.omit({});
|
||||
export const schemaSelectedCalendarPublic = SelectedCalendarSchema.omit({});
|
||||
|
||||
export const schemaSelectedCalendarBodyParams = schemaSelectedCalendarBaseBodyParams
|
||||
.partial({
|
||||
.pick({
|
||||
integration: true,
|
||||
externalId: true,
|
||||
userId: true,
|
||||
})
|
||||
.omit({
|
||||
// id will be set by the database
|
||||
id: true,
|
||||
// No eventTypeId support in API v1
|
||||
eventTypeId: true,
|
||||
|
||||
/** No watch related fields support in API v1 */
|
||||
watchAttempts: true,
|
||||
unwatchAttempts: true,
|
||||
maxAttempts: true,
|
||||
.partial({
|
||||
userId: true,
|
||||
});
|
||||
|
||||
export const schemaSelectedCalendarUpdateBodyParams = schemaSelectedCalendarBaseBodyParams
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { _TeamModel as Team } from "@calcom/prisma/zod";
|
||||
import { TeamSchema } from "@calcom/prisma/zod/modelSchema/TeamSchema";
|
||||
|
||||
export const schemaTeamBaseBodyParams = Team.omit({ id: true, createdAt: true }).partial({
|
||||
export const schemaTeamBaseBodyParams = TeamSchema.omit({ id: true, createdAt: true }).partial({
|
||||
hideBranding: true,
|
||||
metadata: true,
|
||||
pendingPayment: true,
|
||||
@@ -28,6 +28,6 @@ const schemaOwnerId = z.object({
|
||||
|
||||
export const schemaTeamCreateBodyParams = schemaTeamBodyParams.merge(schemaOwnerId).strict();
|
||||
|
||||
export const schemaTeamReadPublic = Team.omit({});
|
||||
export const schemaTeamReadPublic = TeamSchema.omit({});
|
||||
|
||||
export const schemaTeamsReadPublic = z.array(schemaTeamReadPublic);
|
||||
|
||||
@@ -2,8 +2,8 @@ import { z } from "zod";
|
||||
|
||||
import { emailSchema } from "@calcom/lib/emailSchema";
|
||||
import { checkUsername } from "@calcom/lib/server/checkUsername";
|
||||
import { _UserModel as User } from "@calcom/prisma/zod";
|
||||
import { iso8601 } from "@calcom/prisma/zod-utils";
|
||||
import { UserSchema } from "@calcom/prisma/zod/modelSchema/UserSchema";
|
||||
|
||||
import { isValidBase64Image } from "~/lib/utils/isValidBase64Image";
|
||||
import { timeZone } from "~/lib/validations/shared/timeZone";
|
||||
@@ -68,7 +68,7 @@ const usernameSchema = z
|
||||
});
|
||||
|
||||
// @note: These are the values that are editable via PATCH method on the user Model
|
||||
export const schemaUserBaseBodyParams = User.pick({
|
||||
export const schemaUserBaseBodyParams = UserSchema.pick({
|
||||
name: true,
|
||||
email: true,
|
||||
username: true,
|
||||
@@ -151,7 +151,7 @@ export const schemaUserCreateBodyParams = schemaUserBaseBodyParams
|
||||
.strict();
|
||||
|
||||
// @note: These are the values that are always returned when reading a user
|
||||
export const schemaUserReadPublic = User.pick({
|
||||
export const schemaUserReadPublic = UserSchema.pick({
|
||||
id: true,
|
||||
username: true,
|
||||
name: true,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { WEBHOOK_TRIGGER_EVENTS } from "@calcom/features/webhooks/lib/constants";
|
||||
import { _WebhookModel as Webhook } from "@calcom/prisma/zod";
|
||||
import { WebhookSchema } from "@calcom/prisma/zod/modelSchema/WebhookSchema";
|
||||
|
||||
const schemaWebhookBaseBodyParams = Webhook.pick({
|
||||
const schemaWebhookBaseBodyParams = WebhookSchema.pick({
|
||||
userId: true,
|
||||
eventTypeId: true,
|
||||
eventTriggers: true,
|
||||
@@ -38,7 +38,7 @@ export const schemaWebhookEditBodyParams = schemaWebhookBaseBodyParams
|
||||
.partial()
|
||||
.strict();
|
||||
|
||||
export const schemaWebhookReadPublic = Webhook.pick({
|
||||
export const schemaWebhookReadPublic = WebhookSchema.pick({
|
||||
id: true,
|
||||
userId: true,
|
||||
eventTypeId: true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const { withAxiom } = require("next-axiom");
|
||||
const { withSentryConfig } = require("@sentry/nextjs");
|
||||
const { PrismaPlugin } = require("@prisma/nextjs-monorepo-workaround-plugin");
|
||||
|
||||
const plugins = [withAxiom];
|
||||
|
||||
@@ -14,6 +15,12 @@ const nextConfig = {
|
||||
"@calcom/prisma",
|
||||
"@calcom/trpc",
|
||||
],
|
||||
webpack: (config, { isServer }) => {
|
||||
if (isServer) {
|
||||
config.plugins = [...config.plugins, new PrismaPlugin()];
|
||||
}
|
||||
return config;
|
||||
},
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"@calcom/lib": "*",
|
||||
"@calcom/prisma": "*",
|
||||
"@calcom/trpc": "*",
|
||||
"@prisma/nextjs-monorepo-workaround-plugin": "^6.16.1",
|
||||
"@sentry/nextjs": "^9.15.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"memory-cache": "^0.2.0",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
import type { Ensure } from "@calcom/types/utils";
|
||||
|
||||
import { apiKeyPublicSchema } from "~/lib/validations/api-key";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
@@ -6,6 +5,7 @@ import { generateUniqueAPIKey } from "@calcom/features/ee/api-keys/lib/apiKeys";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { apiKeyCreateBodySchema, apiKeyPublicSchema } from "~/lib/validations/api-key";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaAttendeeReadPublic } from "~/lib/validations/attendee";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import {
|
||||
schemaBookingEditBodyParams,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaBookingReferenceReadPublic } from "~/lib/validations/booking-reference";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import {
|
||||
schemaBookingCreateBodyParams,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
|
||||
import { getAccessibleUsers } from "~/lib/utils/retrieveScopedAccessibleUsers";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -34,7 +34,14 @@ async function authMiddleware(req: NextApiRequest) {
|
||||
where: { id: userId },
|
||||
select: {
|
||||
email: true,
|
||||
bookings: true,
|
||||
bookings: {
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma, Booking } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma, Booking } from "@calcom/prisma/client";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
import { buildWhereClause } from "~/lib/utils/bookings/get/buildWhereClause";
|
||||
|
||||
@@ -3,7 +3,8 @@ import type { NextApiRequest } from "next";
|
||||
import { OAuth2UniversalSchema } from "@calcom/app-store/_utils/oauth/universalSchema";
|
||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaCredentialPatchParams, schemaCredentialPatchBody } from "~/lib/validations/credential-sync";
|
||||
|
||||
@@ -71,7 +72,7 @@ async function handler(req: NextApiRequest) {
|
||||
userId,
|
||||
},
|
||||
data: {
|
||||
key,
|
||||
key: key as unknown as Prisma.InputJsonValue,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
|
||||
@@ -6,7 +6,8 @@ import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData";
|
||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
|
||||
import { schemaCredentialPostBody, schemaCredentialPostParams } from "~/lib/validations/credential-sync";
|
||||
@@ -92,7 +93,7 @@ async function handler(req: NextApiRequest) {
|
||||
data: {
|
||||
userId,
|
||||
appId: appSlug,
|
||||
key,
|
||||
key: key as unknown as Prisma.InputJsonValue,
|
||||
type: appMetadata.type,
|
||||
},
|
||||
select: credentialForCalendarServiceSelect,
|
||||
|
||||
@@ -80,7 +80,13 @@ export async function patchHandler(req: NextApiRequest) {
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = schemaEventTypeCustomInputEditBodyParams.parse(req.body);
|
||||
const result = await prisma.eventTypeCustomInput.update({ where: { id }, data });
|
||||
const result = await prisma.eventTypeCustomInput.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...data,
|
||||
options: data.options === null ? [] : data.options,
|
||||
},
|
||||
});
|
||||
return { event_type_custom_input: schemaEventTypeCustomInputPublic.parse(result) };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaEventTypeCustomInputPublic } from "~/lib/validations/event-type-custom-input";
|
||||
|
||||
|
||||
@@ -92,7 +92,11 @@ async function postHandler(req: NextApiRequest) {
|
||||
}
|
||||
|
||||
const data = await prisma.eventTypeCustomInput.create({
|
||||
data: { ...body, eventType: { connect: { id: eventTypeId } } },
|
||||
data: {
|
||||
...body,
|
||||
options: body.options === null ? [] : body.options,
|
||||
eventType: { connect: { id: eventTypeId } },
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
import type { z } from "zod";
|
||||
|
||||
@@ -7,6 +6,7 @@ import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
|
||||
import {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { Prisma } from "@calcom/prisma/client";
|
||||
import { SchedulingType } from "@calcom/prisma/enums";
|
||||
|
||||
import type { schemaEventTypeBaseBodyParams } from "~/lib/validations/event-type";
|
||||
@@ -210,6 +210,7 @@ export async function patchHandler(req: NextApiRequest) {
|
||||
hosts = [],
|
||||
bookingLimits,
|
||||
durationLimits,
|
||||
locations,
|
||||
/** FIXME: Updating event-type children from API not supported for now */
|
||||
children: _,
|
||||
...parsedBody
|
||||
@@ -217,8 +218,10 @@ export async function patchHandler(req: NextApiRequest) {
|
||||
|
||||
const data: Prisma.EventTypeUpdateArgs["data"] = {
|
||||
...parsedBody,
|
||||
teamId: parsedBody.teamId === null ? undefined : parsedBody.teamId,
|
||||
bookingLimits: bookingLimits === null ? Prisma.DbNull : bookingLimits,
|
||||
durationLimits: durationLimits === null ? Prisma.DbNull : durationLimits,
|
||||
locations: locations === null ? Prisma.DbNull : locations,
|
||||
};
|
||||
|
||||
if (hosts) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { Prisma } from "@calcom/prisma/client";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
|
||||
import { schemaEventTypeCreateBodyParams, schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
||||
@@ -265,14 +265,17 @@ import ensureOnlyMembersAsHosts from "./_utils/ensureOnlyMembersAsHosts";
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isSystemWideAdmin, body } = req;
|
||||
const { userId: ctxUserId, isSystemWideAdmin, body } = req;
|
||||
|
||||
const {
|
||||
hosts = [],
|
||||
bookingLimits,
|
||||
durationLimits,
|
||||
locations,
|
||||
/** FIXME: Adding event-type children from API not supported for now */
|
||||
children: _,
|
||||
// if userId is not passed, we will use the userId from the context
|
||||
userId = ctxUserId,
|
||||
...parsedBody
|
||||
} = schemaEventTypeCreateBodyParams.parse(body || {});
|
||||
|
||||
@@ -282,6 +285,7 @@ async function postHandler(req: NextApiRequest) {
|
||||
users: !!parsedBody.teamId ? undefined : { connect: { id: userId } },
|
||||
bookingLimits: bookingLimits === null ? Prisma.DbNull : bookingLimits,
|
||||
durationLimits: durationLimits === null ? Prisma.DbNull : durationLimits,
|
||||
locations: locations === null ? Prisma.DbNull : locations,
|
||||
};
|
||||
|
||||
await checkPermissions(req);
|
||||
@@ -291,8 +295,8 @@ async function postHandler(req: NextApiRequest) {
|
||||
await checkUserMembership(req);
|
||||
}
|
||||
|
||||
if (isSystemWideAdmin && parsedBody.userId && !parsedBody.teamId) {
|
||||
data = { ...parsedBody, users: { connect: { id: parsedBody.userId } } };
|
||||
if (isSystemWideAdmin && userId && parsedBody.teamId === undefined) {
|
||||
data = { ...parsedBody, users: { connect: { id: userId } } };
|
||||
}
|
||||
|
||||
await checkTeamEventEditPermission(req, parsedBody);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { membershipIdSchema, schemaMembershipPublic } from "~/lib/validations/membership";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import {
|
||||
membershipEditBodySchema,
|
||||
@@ -43,7 +43,13 @@ export async function patchHandler(req: NextApiRequest) {
|
||||
const { query } = req;
|
||||
const userId_teamId = membershipIdSchema.parse(query);
|
||||
const data = membershipEditBodySchema.parse(req.body);
|
||||
const args: Prisma.MembershipUpdateArgs = { where: { userId_teamId }, data };
|
||||
const args: Prisma.MembershipUpdateArgs = {
|
||||
where: { userId_teamId },
|
||||
data: {
|
||||
...data,
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
};
|
||||
|
||||
await checkPermissions(req);
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaMembershipPublic } from "~/lib/validations/membership";
|
||||
import {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { membershipCreateBodySchema, schemaMembershipPublic } from "~/lib/validations/membership";
|
||||
|
||||
@@ -25,10 +25,7 @@ import { membershipCreateBodySchema, schemaMembershipPublic } from "~/lib/valida
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const data = membershipCreateBodySchema.parse(req.body);
|
||||
const args: Prisma.MembershipCreateArgs = {
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
...data,
|
||||
},
|
||||
data,
|
||||
};
|
||||
|
||||
await checkPermissions(req);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaSchedulePublic } from "~/lib/validations/schedule";
|
||||
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaCreateScheduleBodyParams, schemaSchedulePublic } from "~/lib/validations/schedule";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
@@ -6,6 +5,7 @@ import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import type { UpdateArguments } from "@calcom/lib/server/repository/selectedCalendar";
|
||||
import { SelectedCalendarRepository } from "@calcom/lib/server/repository/selectedCalendar";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import {
|
||||
schemaSelectedCalendarPublic,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import { SelectedCalendarRepository } from "@calcom/lib/server/repository/selectedCalendar";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import {
|
||||
schemaSelectedCalendarBodyParams,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
|
||||
import { schemaQueryTeamId } from "~/lib/validations/shared/queryTeamId";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaQueryTeamId } from "~/lib/validations/shared/queryTeamId";
|
||||
import { schemaTeamReadPublic } from "~/lib/validations/team";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { purchaseTeamOrOrgSubscription } from "@calcom/features/ee/teams/lib/payments";
|
||||
@@ -6,6 +5,7 @@ import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaTeamsReadPublic } from "~/lib/validations/team";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
import { schemaQuerySingleOrMultipleUserEmails } from "~/lib/validations/shared/queryUserEmail";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaQueryIdAsString } from "~/lib/validations/shared/queryIdString";
|
||||
import { schemaWebhookEditBodyParams, schemaWebhookReadPublic } from "~/lib/validations/webhook";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";
|
||||
import { schemaWebhookReadPublic } from "~/lib/validations/webhook";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaWebhookCreateBodyParams, schemaWebhookReadPublic } from "~/lib/validations/webhook";
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ describe("POST /api/attendees", () => {
|
||||
|
||||
const userBooking = { id: 1 };
|
||||
|
||||
prismaMock.booking.findFirst.mockResolvedValue(userBooking);
|
||||
prismaMock.booking.findFirst.mockResolvedValue(userBooking as any);
|
||||
|
||||
const attendeeData = {
|
||||
id: 1,
|
||||
|
||||
@@ -25,7 +25,7 @@ beforeEach(() => {
|
||||
id: userId,
|
||||
email: "test@example.com",
|
||||
name: "Test User",
|
||||
});
|
||||
} as any);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -20,7 +20,7 @@ beforeEach(() => {
|
||||
id: userId,
|
||||
email: "test@example.com",
|
||||
name: "Test User",
|
||||
});
|
||||
} as any);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import prismock from "../../../../../../tests/libs/__mocks__/prisma";
|
||||
|
||||
import type { Request, Response } from "express";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
import { describe, it, expect, test } from "vitest";
|
||||
import { describe, it, expect, test, beforeAll, afterAll } from "vitest";
|
||||
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { User, Team, Prisma } from "@calcom/prisma/client";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
|
||||
import authMiddleware from "../../../pages/api/bookings/[id]/_auth-middleware";
|
||||
@@ -12,229 +12,206 @@ import authMiddleware from "../../../pages/api/bookings/[id]/_auth-middleware";
|
||||
type CustomNextApiRequest = NextApiRequest & Request;
|
||||
type CustomNextApiResponse = NextApiResponse & Response;
|
||||
|
||||
const createEventTypeEventSelect = {
|
||||
bookings: true,
|
||||
} satisfies Prisma.EventTypeSelect;
|
||||
|
||||
describe("Booking ownership and access in Middleware", () => {
|
||||
const adminUserId = 1;
|
||||
const ownerUserId = 2;
|
||||
const memberUserId = 3;
|
||||
const orgOwnerUserId = 4;
|
||||
const adminUserEmail = "admin@example.com";
|
||||
const ownerUserEmail = "owner@example.com";
|
||||
const memberUserEmail = "member@example.com";
|
||||
const orgOwnerUserEmail = "org-owner@example.com";
|
||||
let adminUserRef: User;
|
||||
let ownerUserRef: User;
|
||||
let orgOwnerUserRef: User;
|
||||
let memberUserRef: User;
|
||||
let orgRef: Team;
|
||||
|
||||
let createEventResult1: Prisma.EventTypeGetPayload<{ select: typeof createEventTypeEventSelect }>;
|
||||
let createEventResult2: Prisma.EventTypeGetPayload<{ select: typeof createEventTypeEventSelect }>;
|
||||
|
||||
// mock user data
|
||||
function buildMockData() {
|
||||
beforeAll(async () => {
|
||||
//Create Users
|
||||
prismock.user.create({
|
||||
const createAdminUser = prisma.user.create({
|
||||
data: {
|
||||
id: adminUserId,
|
||||
username: "admin",
|
||||
username: `admin-${Date.now()}`,
|
||||
name: "Admin User",
|
||||
email: adminUserEmail,
|
||||
email: `admin+${Date.now()}@example.com`,
|
||||
},
|
||||
});
|
||||
prismock.user.create({
|
||||
const createOwnerUser = prisma.user.create({
|
||||
data: {
|
||||
id: ownerUserId,
|
||||
username: "owner",
|
||||
username: `owner-${Date.now()}`,
|
||||
name: "Owner User",
|
||||
email: ownerUserEmail,
|
||||
email: `owner+${Date.now()}@example.com`,
|
||||
},
|
||||
});
|
||||
prismock.user.create({
|
||||
const createOrgOwnerUser = prisma.user.create({
|
||||
data: {
|
||||
id: orgOwnerUserId,
|
||||
username: "org-owner",
|
||||
username: `org-owner-${Date.now()}`,
|
||||
name: "Org Owner",
|
||||
email: orgOwnerUserEmail,
|
||||
email: `org-owner+${Date.now()}@example.com`,
|
||||
},
|
||||
});
|
||||
prismock.user.create({
|
||||
const createMemberUser = prisma.user.create({
|
||||
data: {
|
||||
id: memberUserId,
|
||||
username: "member",
|
||||
username: `member-${Date.now()}`,
|
||||
name: "Member User",
|
||||
email: memberUserEmail,
|
||||
email: `member+${Date.now()}@example.com`,
|
||||
},
|
||||
});
|
||||
|
||||
[adminUserRef, ownerUserRef, orgOwnerUserRef, memberUserRef] = await Promise.all([
|
||||
createAdminUser,
|
||||
createOwnerUser,
|
||||
createOrgOwnerUser,
|
||||
createMemberUser,
|
||||
]);
|
||||
|
||||
//create Org & Team
|
||||
orgRef = await prisma.team.create({
|
||||
data: {
|
||||
name: "Org",
|
||||
slug: `org-${Date.now()}`,
|
||||
isOrganization: true,
|
||||
children: {
|
||||
create: {
|
||||
name: "Team 1",
|
||||
slug: `team1-${Date.now()}`,
|
||||
members: {
|
||||
createMany: {
|
||||
data: [
|
||||
{
|
||||
userId: adminUserRef.id,
|
||||
role: MembershipRole.ADMIN,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: ownerUserRef.id,
|
||||
role: MembershipRole.OWNER,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: memberUserRef.id,
|
||||
role: MembershipRole.MEMBER,
|
||||
accepted: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
members: {
|
||||
createMany: {
|
||||
data: [
|
||||
{
|
||||
userId: ownerUserRef.id,
|
||||
role: MembershipRole.OWNER,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: memberUserRef.id,
|
||||
role: MembershipRole.MEMBER,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: adminUserRef.id,
|
||||
role: MembershipRole.MEMBER,
|
||||
accepted: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
//create eventTypes
|
||||
const createEventTypeEvent1 = prisma.eventType.create({
|
||||
data: {
|
||||
title: "Event 1",
|
||||
slug: `event-1-${Date.now()}`,
|
||||
userId: ownerUserRef.id,
|
||||
length: 60,
|
||||
bookings: {
|
||||
create: {
|
||||
id: 2,
|
||||
uid: "2",
|
||||
uid: `booking-2-${Date.now()}`,
|
||||
title: "Booking 2",
|
||||
eventTypeId: 1,
|
||||
userId: memberUserRef.id,
|
||||
startTime: "2024-08-30T06:45:00.000Z",
|
||||
endTime: "2024-08-30T07:45:00.000Z",
|
||||
attendees: {
|
||||
create: {
|
||||
name: "Member User",
|
||||
email: memberUserEmail,
|
||||
email: memberUserRef.email,
|
||||
timeZone: "UTC",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
select: createEventTypeEventSelect,
|
||||
});
|
||||
//create team
|
||||
prismock.team.create({
|
||||
const createEventTypeEvent2 = prisma.eventType.create({
|
||||
data: {
|
||||
id: 1,
|
||||
name: "Team 1",
|
||||
slug: "team1",
|
||||
members: {
|
||||
createMany: {
|
||||
data: [
|
||||
{
|
||||
userId: adminUserId,
|
||||
role: MembershipRole.ADMIN,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: ownerUserId,
|
||||
role: MembershipRole.OWNER,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: memberUserId,
|
||||
role: MembershipRole.MEMBER,
|
||||
accepted: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
//create Org
|
||||
prismock.team.create({
|
||||
data: {
|
||||
id: 2,
|
||||
name: "Org",
|
||||
slug: "org",
|
||||
isOrganization: true,
|
||||
children: {
|
||||
connect: {
|
||||
id: 1,
|
||||
},
|
||||
},
|
||||
members: {
|
||||
createMany: {
|
||||
data: [
|
||||
{
|
||||
userId: orgOwnerUserId,
|
||||
role: MembershipRole.OWNER,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: memberUserId,
|
||||
role: MembershipRole.MEMBER,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: ownerUserId,
|
||||
role: MembershipRole.MEMBER,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
userId: adminUserId,
|
||||
role: MembershipRole.MEMBER,
|
||||
accepted: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
//create eventTypes
|
||||
prismock.eventType.create({
|
||||
data: {
|
||||
id: 1,
|
||||
title: "Event 1",
|
||||
slug: "event",
|
||||
length: 60,
|
||||
bookings: {
|
||||
connect: {
|
||||
id: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
prismock.eventType.create({
|
||||
data: {
|
||||
id: 2,
|
||||
title: "Event 2",
|
||||
slug: "event",
|
||||
slug: `event-2-${Date.now()}`,
|
||||
length: 60,
|
||||
teamId: 1,
|
||||
teamId: orgRef.id,
|
||||
bookings: {
|
||||
connect: {
|
||||
id: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
//link eventType to teams
|
||||
prismock.eventType.update({
|
||||
where: {
|
||||
id: 1,
|
||||
},
|
||||
data: {
|
||||
owner: {
|
||||
connect: {
|
||||
id: ownerUserId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
prismock.eventType.update({
|
||||
where: {
|
||||
id: 2,
|
||||
},
|
||||
data: {
|
||||
team: {
|
||||
connect: {
|
||||
id: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
//link team to org
|
||||
prismock.team.update({
|
||||
where: {
|
||||
id: 1,
|
||||
},
|
||||
data: {
|
||||
parentId: 2,
|
||||
},
|
||||
});
|
||||
// Call Prisma to create booking with attendees
|
||||
prismock.booking.create({
|
||||
data: {
|
||||
id: 1,
|
||||
uid: "1",
|
||||
title: "Booking 1",
|
||||
userId: 1,
|
||||
startTime: "2024-08-30T06:45:00.000Z",
|
||||
endTime: "2024-08-30T07:45:00.000Z",
|
||||
eventTypeId: 2,
|
||||
attendees: {
|
||||
create: {
|
||||
name: "Admin User",
|
||||
email: adminUserEmail,
|
||||
timeZone: "UTC",
|
||||
uid: `booking-1-${Date.now()}`,
|
||||
title: "Booking 1",
|
||||
userId: adminUserRef.id,
|
||||
startTime: "2024-08-30T06:45:00.000Z",
|
||||
endTime: "2024-08-30T07:45:00.000Z",
|
||||
attendees: {
|
||||
create: {
|
||||
name: "Admin User",
|
||||
email: adminUserRef.email,
|
||||
timeZone: "UTC",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
select: createEventTypeEventSelect,
|
||||
});
|
||||
}
|
||||
|
||||
[createEventResult1, createEventResult2] = await Promise.all([
|
||||
createEventTypeEvent1,
|
||||
createEventTypeEvent2,
|
||||
]);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
console.log("Cleaning up org", orgRef.id);
|
||||
await prisma.team.delete({
|
||||
where: {
|
||||
id: orgRef.id,
|
||||
},
|
||||
});
|
||||
console.log("Cleaning up users", [
|
||||
adminUserRef.id,
|
||||
ownerUserRef.id,
|
||||
orgOwnerUserRef.id,
|
||||
memberUserRef.id,
|
||||
]);
|
||||
await prisma.user.deleteMany({
|
||||
where: {
|
||||
id: {
|
||||
in: [adminUserRef.id, ownerUserRef.id, orgOwnerUserRef.id, memberUserRef.id],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("should not throw error for bookings where user is an attendee", async () => {
|
||||
console.log(createEventResult1.bookings[0].id);
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
id: 2,
|
||||
id: createEventResult1.bookings[0].id,
|
||||
},
|
||||
prisma: prismock,
|
||||
prisma,
|
||||
});
|
||||
buildMockData();
|
||||
req.userId = memberUserId;
|
||||
req.userId = memberUserRef.id;
|
||||
await expect(authMiddleware(req)).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
@@ -244,10 +221,9 @@ describe("Booking ownership and access in Middleware", () => {
|
||||
query: {
|
||||
id: 1,
|
||||
},
|
||||
prisma: prismock,
|
||||
prisma,
|
||||
});
|
||||
buildMockData();
|
||||
req.userId = memberUserId;
|
||||
req.userId = memberUserRef.id;
|
||||
|
||||
await expect(authMiddleware(req)).rejects.toThrow();
|
||||
});
|
||||
@@ -256,12 +232,11 @@ describe("Booking ownership and access in Middleware", () => {
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
id: 2,
|
||||
id: createEventResult2.bookings[0].id,
|
||||
},
|
||||
prisma: prismock,
|
||||
prisma,
|
||||
});
|
||||
buildMockData();
|
||||
req.userId = ownerUserId;
|
||||
req.userId = ownerUserRef.id;
|
||||
await expect(authMiddleware(req)).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
@@ -269,21 +244,19 @@ describe("Booking ownership and access in Middleware", () => {
|
||||
const { req: req1 } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
id: 1,
|
||||
id: createEventResult2.bookings[0].id,
|
||||
},
|
||||
prisma: prismock,
|
||||
prisma,
|
||||
});
|
||||
const { req: req2 } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
id: 1,
|
||||
id: createEventResult2.bookings[0].id,
|
||||
},
|
||||
prisma: prismock,
|
||||
prisma,
|
||||
});
|
||||
buildMockData();
|
||||
|
||||
req1.userId = adminUserId;
|
||||
req2.userId = ownerUserId;
|
||||
req1.userId = adminUserRef.id;
|
||||
req2.userId = ownerUserRef.id;
|
||||
|
||||
await expect(authMiddleware(req1)).resolves.not.toThrow();
|
||||
await expect(authMiddleware(req2)).resolves.not.toThrow();
|
||||
@@ -292,13 +265,12 @@ describe("Booking ownership and access in Middleware", () => {
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
id: 1,
|
||||
id: createEventResult2.bookings[0].id,
|
||||
},
|
||||
prisma: prismock,
|
||||
prisma,
|
||||
});
|
||||
buildMockData();
|
||||
|
||||
req.userId = memberUserId;
|
||||
req.userId = memberUserRef.id;
|
||||
|
||||
await expect(authMiddleware(req)).rejects.toThrow();
|
||||
});
|
||||
@@ -308,10 +280,9 @@ describe("Booking ownership and access in Middleware", () => {
|
||||
query: {
|
||||
id: 2,
|
||||
},
|
||||
prisma: prismock,
|
||||
prisma,
|
||||
});
|
||||
buildMockData();
|
||||
req.userId = adminUserId;
|
||||
req.userId = adminUserRef.id;
|
||||
req.isSystemWideAdmin = true;
|
||||
|
||||
await authMiddleware(req);
|
||||
@@ -323,12 +294,11 @@ describe("Booking ownership and access in Middleware", () => {
|
||||
query: {
|
||||
id: 1,
|
||||
},
|
||||
prisma: prismock,
|
||||
prisma,
|
||||
});
|
||||
buildMockData();
|
||||
req.userId = orgOwnerUserId;
|
||||
req.userId = orgOwnerUserRef.id;
|
||||
req.isOrganizationOwnerOrAdmin = true;
|
||||
|
||||
await authMiddleware(req);
|
||||
await expect(authMiddleware(req)).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,12 +30,13 @@ beforeEach(() => {
|
||||
id: userId,
|
||||
email: "test@example.com",
|
||||
name: "Test User",
|
||||
});
|
||||
} as any);
|
||||
(getAccessibleUsers as any).mockResolvedValue([userId]);
|
||||
(retrieveOrgScopedAccessibleUsers as any).mockResolvedValue([userId]);
|
||||
|
||||
prismaMock.membership.findMany.mockResolvedValue([
|
||||
{
|
||||
// @ts-expect-error Will be fixed by Prisma 6.7.0 upgrade mock changes - which uses vitest-mock-extended
|
||||
team: {
|
||||
id: 1,
|
||||
isOrganization: true,
|
||||
@@ -48,7 +49,7 @@ beforeEach(() => {
|
||||
id: userId,
|
||||
email: "test@example.com",
|
||||
},
|
||||
]);
|
||||
] as any);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -11,9 +11,9 @@ import { getEventTypesFromDB } from "@calcom/features/bookings/lib/handleNewBook
|
||||
import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
|
||||
import { ErrorCode } from "@calcom/lib/errorCodes";
|
||||
import { buildBooking, buildEventType, buildWebhook, buildUser } from "@calcom/lib/test/builder";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { Booking } from "@calcom/prisma/client";
|
||||
import { CreationSource } from "@calcom/prisma/enums";
|
||||
import { CreationSource, BookingStatus } from "@calcom/prisma/enums";
|
||||
|
||||
import handler from "../../../pages/api/bookings/_post";
|
||||
|
||||
@@ -303,6 +303,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({
|
||||
...buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } }),
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
profile: { organizationId: null },
|
||||
hosts: [],
|
||||
users: [buildUser()],
|
||||
@@ -340,6 +341,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({
|
||||
...buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } }),
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
profile: { organizationId: null },
|
||||
hosts: [],
|
||||
users: [buildUser()],
|
||||
@@ -376,6 +378,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({
|
||||
...buildEventType({ profileId: null }),
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
profile: { organizationId: null },
|
||||
hosts: [],
|
||||
users: [buildUser()],
|
||||
@@ -417,6 +420,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({
|
||||
...buildEventType({ profileId: null, length: 15 }),
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
profile: { organizationId: null },
|
||||
hosts: [],
|
||||
users: [buildUser()],
|
||||
@@ -468,7 +472,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.booking.findUnique.mockResolvedValue({
|
||||
...originalBooking,
|
||||
status: "cancelled",
|
||||
status: "CANCELLED",
|
||||
});
|
||||
|
||||
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
@@ -492,6 +496,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({
|
||||
...buildEventType({ profileId: null, length: 15 }),
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
profile: { organizationId: null },
|
||||
hosts: [],
|
||||
users: [buildUser()],
|
||||
@@ -532,7 +537,7 @@ describe("POST /api/bookings", () => {
|
||||
const previousBooking = await prisma.booking.findUnique({
|
||||
where: { uid: "original-booking-uid" },
|
||||
});
|
||||
expect(previousBooking?.status).toBe("cancelled");
|
||||
expect(previousBooking?.status).toBe(BookingStatus.CANCELLED);
|
||||
});
|
||||
|
||||
test("Creates source as api_v1", async () => {
|
||||
@@ -556,6 +561,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({
|
||||
...buildEventType({ profileId: null, length: 15 }),
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
profile: { organizationId: null },
|
||||
hosts: [],
|
||||
users: [buildUser()],
|
||||
@@ -627,6 +633,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({
|
||||
...buildEventType({ profileId: null, length: 15 }),
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
profile: { organizationId: null },
|
||||
hosts: [],
|
||||
users: [buildUser()],
|
||||
@@ -684,6 +691,7 @@ describe("POST /api/bookings", () => {
|
||||
|
||||
prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({
|
||||
...buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } }),
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
profile: { organizationId: null },
|
||||
hosts: [],
|
||||
users: [buildUser()],
|
||||
|
||||
@@ -50,6 +50,7 @@ describe("DELETE /api/event-types/[id]", () => {
|
||||
// Mocking team.findUnique
|
||||
prismaMock.team.findUnique.mockResolvedValue({
|
||||
id: teamId,
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
members: [
|
||||
{ userId: memberUser, role: MembershipRole.MEMBER, teamId: teamId },
|
||||
{ userId: adminUser, role: MembershipRole.ADMIN, teamId: teamId },
|
||||
|
||||
@@ -84,6 +84,7 @@ describe("GET /api/event-types/[id]", () => {
|
||||
|
||||
prismaMock.team.findFirst.mockResolvedValue({
|
||||
id: teamId,
|
||||
// @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now.
|
||||
members: [
|
||||
{
|
||||
userId,
|
||||
|
||||
@@ -79,7 +79,7 @@ describe("POST /api/selected-calendars", () => {
|
||||
integration: "google",
|
||||
externalId: "ext123",
|
||||
userId: 444444,
|
||||
id: "xxx-xxx",
|
||||
id: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||
eventTypeId: null,
|
||||
delegationCredentialId: null,
|
||||
domainWideDelegationCredentialId: null,
|
||||
@@ -120,7 +120,7 @@ describe("POST /api/selected-calendars", () => {
|
||||
req.userId = 333333;
|
||||
|
||||
prismaMock.selectedCalendar.create.mockResolvedValue({
|
||||
id: "xxx-xxx",
|
||||
id: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||
credentialId: 1,
|
||||
integration: "google",
|
||||
externalId: "ext123",
|
||||
|
||||
@@ -41,4 +41,5 @@ lerna-debug.log*
|
||||
.env.production.local
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.appStore.example
|
||||
!.env.appStore.example
|
||||
/client/*
|
||||
@@ -38,7 +38,7 @@
|
||||
"@axiomhq/winston": "^1.2.0",
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.344",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.354",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
"@calcom/prisma": "*",
|
||||
|
||||
@@ -18,7 +18,7 @@ import { UserRepositoryFixture } from "test/fixtures/repository/users.repository
|
||||
import { randomString } from "test/utils/randomString";
|
||||
|
||||
import { X_CAL_CLIENT_ID, X_CAL_SECRET_KEY } from "@calcom/platform-constants";
|
||||
import { User, PlatformOAuthClient, Team, RateLimit } from "@calcom/prisma/client";
|
||||
import type { User, PlatformOAuthClient, Team, RateLimit } from "@calcom/prisma/client";
|
||||
|
||||
describe("AppController", () => {
|
||||
describe("Rate limiting", () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { BookingsController_2024_04_15 } from "@/ee/bookings/2024-04-15/controllers/bookings.controller";
|
||||
import { PlatformBookingsService } from "@/ee/bookings/shared/platform-bookings.service";
|
||||
import { CalendarsRepository } from "@/ee/calendars/calendars.repository";
|
||||
import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service";
|
||||
import { CalendarsService } from "@/ee/calendars/services/calendars.service";
|
||||
import { EventTypesModule_2024_04_15 } from "@/ee/event-types/event-types_2024_04_15/event-types.module";
|
||||
import { EventTypesModule_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.module";
|
||||
@@ -41,6 +42,7 @@ import { Module } from "@nestjs/common";
|
||||
OAuthClientUsersService,
|
||||
PlatformBookingsService,
|
||||
CalendarsService,
|
||||
CalendarsCacheService,
|
||||
CredentialsRepository,
|
||||
AppsRepository,
|
||||
CalendarsRepository,
|
||||
|
||||
@@ -8,12 +8,10 @@ import { SchedulesModule_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/
|
||||
import { SchedulesService_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/services/schedules.service";
|
||||
import { PermissionsGuard } from "@/modules/auth/guards/permissions/permissions.guard";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { TokensModule } from "@/modules/tokens/tokens.module";
|
||||
import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { ApiKeysRepositoryFixture } from "test/fixtures/repository/api-keys.repository.fixture";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
@@ -22,9 +20,10 @@ import { UserRepositoryFixture } from "test/fixtures/repository/users.repository
|
||||
import { randomString } from "test/utils/randomString";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
|
||||
import { SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import { handleNewBooking } from "@calcom/platform-libraries";
|
||||
import { ApiSuccessResponse, ApiResponse, ApiErrorResponse } from "@calcom/platform-types";
|
||||
import type { ApiSuccessResponse, ApiErrorResponse } from "@calcom/platform-types";
|
||||
import type { User } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-04-15", () => {
|
||||
describe("User Authenticated", () => {
|
||||
|
||||
@@ -63,8 +63,8 @@ import {
|
||||
CancelBookingInput_2024_04_15,
|
||||
Status_2024_04_15,
|
||||
} from "@calcom/platform-types";
|
||||
import { ApiResponse } from "@calcom/platform-types";
|
||||
import { PrismaClient } from "@calcom/prisma";
|
||||
import type { ApiResponse } from "@calcom/platform-types";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
|
||||
type BookingRequest = Request & {
|
||||
userId?: number;
|
||||
|
||||
+1
-1
@@ -18,7 +18,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { PlatformOAuthClient, Team, User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { MembershipRepositoryFixture } from "test/fixtures/repository/membership.repository.fixture";
|
||||
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture";
|
||||
@@ -33,6 +32,7 @@ import {
|
||||
CreateEventTypeInput_2024_06_14,
|
||||
EventTypeOutput_2024_06_14,
|
||||
} from "@calcom/platform-types";
|
||||
import type { PlatformOAuthClient, Team, User } from "@calcom/prisma/client";
|
||||
|
||||
const CLIENT_REDIRECT_URI = "http://localhost:4321";
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { BookingReferencesFilterInput_2024_08_13 } from "@/ee/bookings/2024-08-13/inputs/booking-references-filter.input";
|
||||
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
@Injectable()
|
||||
export class BookingReferencesRepository_2024_08_13 {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { OutputBookingReferencesService_2024_08_13 } from "@/ee/bookings/2024-08
|
||||
import { OutputBookingsService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/output.service";
|
||||
import { PlatformBookingsService } from "@/ee/bookings/shared/platform-bookings.service";
|
||||
import { CalendarsRepository } from "@/ee/calendars/calendars.repository";
|
||||
import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service";
|
||||
import { CalendarsService } from "@/ee/calendars/services/calendars.service";
|
||||
import { EventTypesModule_2024_04_15 } from "@/ee/event-types/event-types_2024_04_15/event-types.module";
|
||||
import { EventTypesModule_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.module";
|
||||
@@ -71,6 +72,7 @@ import { Module } from "@nestjs/common";
|
||||
ApiKeysRepository,
|
||||
PlatformBookingsService,
|
||||
CalendarsService,
|
||||
CalendarsCacheService,
|
||||
CredentialsRepository,
|
||||
AppsRepository,
|
||||
CalendarsRepository,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
|
||||
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
@Injectable()
|
||||
export class BookingsRepository_2024_08_13 {
|
||||
|
||||
@@ -12,7 +12,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { ApiKeysRepositoryFixture } from "test/fixtures/repository/api-keys.repository.fixture";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
@@ -37,7 +36,7 @@ import {
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
CancelBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
import type { User, Team } from "@calcom/prisma/client";
|
||||
|
||||
jest.spyOn(AttendeeScheduledEmail.prototype as any, "getHtml").mockImplementation(async function () {
|
||||
return "<html><body>Mocked Email Content</body></html>";
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { BookingOutput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { Booking, PlatformOAuthClient, Team, User, EventType } from "@calcom/prisma/client";
|
||||
import type { Booking, PlatformOAuthClient, Team, User, EventType } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Booking fields", () => {
|
||||
@@ -117,6 +117,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
slug: seatedEventTypeSlug,
|
||||
length: 60,
|
||||
seatsPerTimeSlot: 3,
|
||||
seatsShowAttendees: true,
|
||||
},
|
||||
user.id
|
||||
);
|
||||
|
||||
@@ -9,7 +9,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -20,7 +19,7 @@ import { randomString } from "test/utils/randomString";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import { Booking, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
import type { User, Booking, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Calendar Links", () => {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -21,7 +20,7 @@ import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import { BookingOutput_2024_08_13, GetBookingOutput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { Booking, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
import type { User, Booking, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Bookings confirmation", () => {
|
||||
@@ -40,7 +39,6 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
let user: User;
|
||||
|
||||
let eventTypeId: number;
|
||||
const eventTypeSlug = `confirm-bookings-2024-08-13-event-type-${randomString()}`;
|
||||
|
||||
let createdBooking1: Booking;
|
||||
let createdBooking2: Booking;
|
||||
|
||||
+2
-6
@@ -1,19 +1,16 @@
|
||||
import { bootstrap } from "@/app";
|
||||
import { AppModule } from "@/app.module";
|
||||
import { CancelBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/cancel-booking.output";
|
||||
import { CreateBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/create-booking.output";
|
||||
import { RescheduleBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/reschedule-booking.output";
|
||||
import { CreateScheduleInput_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/inputs/create-schedule.input";
|
||||
import { SchedulesModule_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/schedules.module";
|
||||
import { SchedulesService_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/services/schedules.service";
|
||||
import { ApiAuthGuard } from "@/modules/auth/guards/api-auth/api-auth.guard";
|
||||
import { PermissionsGuard } from "@/modules/auth/guards/permissions/permissions.guard";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -35,14 +32,13 @@ import {
|
||||
OrganizerRequestEmail,
|
||||
AttendeeDeclinedEmail,
|
||||
} from "@calcom/platform-libraries/emails";
|
||||
import {
|
||||
import type {
|
||||
CreateBookingInput_2024_08_13,
|
||||
BookingOutput_2024_08_13,
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
GetBookingOutput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { CancelBookingInput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
import type { User, Team } from "@calcom/prisma/client";
|
||||
|
||||
jest
|
||||
.spyOn(AttendeeScheduledEmail.prototype, "getHtml")
|
||||
|
||||
+2
-3
@@ -11,7 +11,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
import { HostsRepositoryFixture } from "test/fixtures/repository/hosts.repository.fixture";
|
||||
@@ -34,13 +33,13 @@ import {
|
||||
OrganizerRescheduledEmail,
|
||||
OrganizerScheduledEmail,
|
||||
} from "@calcom/platform-libraries/emails";
|
||||
import {
|
||||
import type {
|
||||
BookingOutput_2024_08_13,
|
||||
CancelBookingInput_2024_08_13,
|
||||
CreateBookingInput_2024_08_13,
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
import type { User, Team } from "@calcom/prisma/client";
|
||||
|
||||
// Mock all email sending prototypes
|
||||
jest
|
||||
|
||||
+4
-5
@@ -13,7 +13,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -31,14 +30,14 @@ import {
|
||||
OrganizerCancelledEmail,
|
||||
AttendeeCancelledEmail,
|
||||
} from "@calcom/platform-libraries/emails";
|
||||
import {
|
||||
import type {
|
||||
CreateBookingInput_2024_08_13,
|
||||
BookingOutput_2024_08_13,
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
CancelBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { CancelBookingInput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
import type { User, Team } from "@calcom/prisma/client";
|
||||
|
||||
jest
|
||||
.spyOn(AttendeeScheduledEmail.prototype, "getHtml")
|
||||
@@ -378,7 +377,7 @@ describe("Bookings Endpoints 2024-08-13 user emails", () => {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(AttendeeScheduledEmail.prototype.getHtml).toHaveBeenCalled();
|
||||
expect(OrganizerScheduledEmail.prototype.getHtml).toHaveBeenCalled();
|
||||
emailsEnabledSetup.createdBookingUid = responseBody.data.uid;
|
||||
emailsEnabledSetup.createdBookingUid = data.uid;
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibly recurring bookings"
|
||||
|
||||
+1
-1
@@ -14,7 +14,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { PlatformOAuthClient, Team, User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -40,6 +39,7 @@ import {
|
||||
GetBookingOutput_2024_08_13,
|
||||
GetBookingsOutput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import type { PlatformOAuthClient, Team, User } from "@calcom/prisma/client";
|
||||
|
||||
const CLIENT_REDIRECT_URI = "http://localhost:4321";
|
||||
|
||||
|
||||
+2
-7
@@ -10,7 +10,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { Booking, User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -25,8 +24,8 @@ import { randomString } from "test/utils/randomString";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import { CreateBookingInput_2024_08_13, BookingOutput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
import type { CreateBookingInput_2024_08_13 } from "@calcom/platform-types";
|
||||
import type { Booking, User, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Reassign bookings", () => {
|
||||
@@ -321,10 +320,6 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
return client;
|
||||
}
|
||||
|
||||
function responseDataIsBooking(data: any): data is BookingOutput_2024_08_13 {
|
||||
return !Array.isArray(data) && typeof data === "object" && data && "id" in data;
|
||||
}
|
||||
|
||||
afterAll(async () => {
|
||||
await oauthClientRepositoryFixture.delete(oAuthClient.id);
|
||||
await teamRepositoryFixture.delete(organization.id);
|
||||
|
||||
+3
-5
@@ -10,7 +10,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -22,12 +21,12 @@ import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import { AttendeeCancelledEmail, OrganizerCancelledEmail } from "@calcom/platform-libraries/emails";
|
||||
import {
|
||||
import type {
|
||||
CreateRecurringBookingInput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
CancelBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { CancelBookingInput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
import type { User, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Creating recurring bookings", () => {
|
||||
@@ -48,7 +47,6 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
const maxRecurrenceCount = 3;
|
||||
let recurringEventTypeId: number;
|
||||
const recurringEventSlug = `recurring-bookings-2024-08-13-event-type-${randomString()}`;
|
||||
let createdRecurringBooking: RecurringBookingOutput_2024_08_13[];
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleRef = await withApiAuth(
|
||||
|
||||
@@ -11,7 +11,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import { DateTime } from "luxon";
|
||||
import * as request from "supertest";
|
||||
import { ApiKeysRepositoryFixture } from "test/fixtures/repository/api-keys.repository.fixture";
|
||||
@@ -23,7 +22,7 @@ import { UserRepositoryFixture } from "test/fixtures/repository/users.repository
|
||||
import { randomString } from "test/utils/randomString";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import {
|
||||
import type {
|
||||
CancelBookingInput_2024_08_13,
|
||||
CancelSeatedBookingInput_2024_08_13,
|
||||
CreateSeatedBookingOutput_2024_08_13,
|
||||
@@ -31,9 +30,9 @@ import {
|
||||
GetBookingsOutput_2024_08_13,
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
RescheduleSeatedBookingInput_2024_08_13,
|
||||
CreateBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { CreateBookingInput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
import type { Team, User } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Seated bookings", () => {
|
||||
@@ -53,8 +52,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
let apiKeyString: string;
|
||||
|
||||
let seatedEventTypeId: number;
|
||||
let seatedEventTypeIdAttendeesDisabledId: number;
|
||||
|
||||
const seatedEventSlug = `seated-bookings-event-type-${randomString()}`;
|
||||
const seatedEventSlugAttendeesDisabled = `seated-bookings-event-type-attendees-disabled-${randomString()}`;
|
||||
|
||||
let createdSeatedBooking: CreateSeatedBookingOutput_2024_08_13;
|
||||
let createdSeatedBooking2: CreateSeatedBookingOutput_2024_08_13;
|
||||
@@ -121,6 +122,28 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
);
|
||||
seatedEventTypeId = seatedEvent.id;
|
||||
|
||||
const seatedEventAttendeesDisabled = await eventTypesRepositoryFixture.create(
|
||||
{
|
||||
title: `seated-bookings-2024-08-13-event-type-attendees-disabled-${randomString()}`,
|
||||
slug: seatedEventSlugAttendeesDisabled,
|
||||
length: 60,
|
||||
seatsPerTimeSlot: 5,
|
||||
seatsShowAttendees: false,
|
||||
seatsShowAvailabilityCount: false,
|
||||
locations: [{ type: "inPerson", address: "via 10, rome, italy" }],
|
||||
metadata: {
|
||||
disableStandardEmails: {
|
||||
all: {
|
||||
attendee: true,
|
||||
host: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
user.id
|
||||
);
|
||||
seatedEventTypeIdAttendeesDisabledId = seatedEventAttendeesDisabled.id;
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
bootstrap(app as NestExpressApplication);
|
||||
|
||||
@@ -414,6 +437,63 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should book an event type with attendees disabled", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2030, 0, 9, 14, 0, 0)).toISOString(),
|
||||
eventTypeId: seatedEventTypeIdAttendeesDisabledId,
|
||||
attendee: {
|
||||
name: nameAttendeeOne,
|
||||
email: emailAttendeeOne,
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
bookingFieldsResponses: {
|
||||
codingLanguage: "TypeScript",
|
||||
},
|
||||
metadata: {
|
||||
userId: "100",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsCreateSeatedBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsCreateSeatedBooking(responseBody.data)) {
|
||||
const data: CreateSeatedBookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.seatUid).toBeDefined();
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(data.hosts[0].id).toEqual(user.id);
|
||||
expect(data.status).toEqual("accepted");
|
||||
expect(data.start).toEqual(body.start);
|
||||
expect(data.end).toEqual(
|
||||
DateTime.fromISO(body.start, { zone: "utc" }).plus({ hours: 1 }).toISO()
|
||||
);
|
||||
expect(data.duration).toEqual(60);
|
||||
expect(data.eventTypeId).toEqual(seatedEventTypeIdAttendeesDisabledId);
|
||||
expect(data.eventType).toEqual({
|
||||
id: seatedEventTypeIdAttendeesDisabledId,
|
||||
slug: seatedEventSlugAttendeesDisabled,
|
||||
});
|
||||
expect(data.attendees.length).toEqual(0);
|
||||
expect(data.location).toBeDefined();
|
||||
expect(data.absentHost).toEqual(false);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected seated booking but received non array response"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("cancel seated booking", () => {
|
||||
describe("cancel seated booking as attendee", () => {
|
||||
it("should cancel seated booking", async () => {
|
||||
|
||||
@@ -11,7 +11,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -26,7 +25,7 @@ import { randomString } from "test/utils/randomString";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import {
|
||||
import type {
|
||||
CreateBookingInput_2024_08_13,
|
||||
BookingOutput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
@@ -34,7 +33,7 @@ import {
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
import type { User, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Team bookings", () => {
|
||||
|
||||
@@ -14,7 +14,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { EventType, User, Workflow } from "@prisma/client";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
@@ -34,25 +33,22 @@ import {
|
||||
VERSION_2024_08_13,
|
||||
X_CAL_CLIENT_ID,
|
||||
} from "@calcom/platform-constants";
|
||||
import { AttendeeScheduledEmail, OrganizerScheduledEmail } from "@calcom/platform-libraries/emails";
|
||||
import { EventManager } from "@calcom/platform-libraries/event-types";
|
||||
import {
|
||||
import { FAILED_EVENT_TYPE_IDENTIFICATION_ERROR_MESSAGE } from "@calcom/platform-types";
|
||||
import type {
|
||||
CreateEventTypeInput_2024_06_14,
|
||||
FAILED_EVENT_TYPE_IDENTIFICATION_ERROR_MESSAGE,
|
||||
GetBookingOutput_2024_08_13,
|
||||
GetBookingsOutput_2024_08_13,
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import {
|
||||
CreateBookingInput_2024_08_13,
|
||||
BookingOutput_2024_08_13,
|
||||
CreateRecurringBookingInput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
MarkAbsentBookingInput_2024_08_13,
|
||||
CancelBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { CancelBookingInput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { Booking, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
import type { EventType, User, Workflow, Booking, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("User bookings", () => {
|
||||
@@ -2917,14 +2913,12 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
},
|
||||
};
|
||||
|
||||
const beforeCreate = new Date();
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const afterCreate = new Date();
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
|
||||
+2
-3
@@ -10,7 +10,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { EventType, User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
@@ -21,13 +20,13 @@ import { randomString } from "test/utils/randomString";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import {
|
||||
import type {
|
||||
CreateBookingInput_2024_08_13,
|
||||
BookingOutput_2024_08_13,
|
||||
CreateRecurringBookingInput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
import type { PlatformOAuthClient, Team, EventType, User } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("User bookings", () => {
|
||||
|
||||
@@ -62,8 +62,8 @@ import {
|
||||
RescheduleBookingInput,
|
||||
CancelBookingInput,
|
||||
} from "@calcom/platform-types";
|
||||
import { PrismaClient } from "@calcom/prisma";
|
||||
import { EventType, User, Team } from "@calcom/prisma/client";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import type { EventType, User, Team } from "@calcom/prisma/client";
|
||||
|
||||
type CreatedBooking = {
|
||||
hosts: { id: number }[];
|
||||
@@ -576,10 +576,13 @@ export class BookingsService_2024_08_13 {
|
||||
return this.outputService.getOutputRecurringBooking(booking);
|
||||
}
|
||||
if (isRecurring && isSeated) {
|
||||
return this.outputService.getOutputRecurringSeatedBooking(booking);
|
||||
return this.outputService.getOutputRecurringSeatedBooking(
|
||||
booking,
|
||||
!!booking.eventType?.seatsShowAttendees
|
||||
);
|
||||
}
|
||||
if (isSeated) {
|
||||
return this.outputService.getOutputSeatedBooking(booking);
|
||||
return this.outputService.getOutputSeatedBooking(booking, !!booking.eventType?.seatsShowAttendees);
|
||||
}
|
||||
return this.outputService.getOutputBooking(booking);
|
||||
}
|
||||
@@ -591,7 +594,10 @@ export class BookingsService_2024_08_13 {
|
||||
const ids = recurringBooking.map((booking) => booking.id);
|
||||
const isRecurringSeated = !!recurringBooking[0].eventType?.seatsPerTimeSlot;
|
||||
if (isRecurringSeated) {
|
||||
return this.outputService.getOutputRecurringSeatedBookings(ids);
|
||||
return this.outputService.getOutputRecurringSeatedBookings(
|
||||
ids,
|
||||
!!recurringBooking[0].eventType?.seatsShowAttendees
|
||||
);
|
||||
}
|
||||
|
||||
return this.outputService.getOutputRecurringBookings(ids);
|
||||
@@ -657,9 +663,19 @@ export class BookingsService_2024_08_13 {
|
||||
if (isRecurring && !isSeated) {
|
||||
formattedBookings.push(this.outputService.getOutputRecurringBooking(formatted));
|
||||
} else if (isRecurring && isSeated) {
|
||||
formattedBookings.push(this.outputService.getOutputRecurringSeatedBooking(formatted));
|
||||
formattedBookings.push(
|
||||
this.outputService.getOutputRecurringSeatedBooking(
|
||||
formatted,
|
||||
!!formatted.eventType?.seatsShowAttendees
|
||||
)
|
||||
);
|
||||
} else if (isSeated) {
|
||||
formattedBookings.push(await this.outputService.getOutputSeatedBooking(formatted));
|
||||
formattedBookings.push(
|
||||
await this.outputService.getOutputSeatedBooking(
|
||||
formatted,
|
||||
!!formatted.eventType?.seatsShowAttendees
|
||||
)
|
||||
);
|
||||
} else {
|
||||
formattedBookings.push(await this.outputService.getOutputBooking(formatted));
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import { z } from "zod";
|
||||
|
||||
import { CreationSource } from "@calcom/platform-libraries";
|
||||
import { EventTypeMetaDataSchema } from "@calcom/platform-libraries/event-types";
|
||||
import {
|
||||
import type {
|
||||
CancelBookingInput,
|
||||
CancelBookingInput_2024_08_13,
|
||||
CancelSeatedBookingInput_2024_08_13,
|
||||
@@ -44,8 +44,8 @@ import {
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
RescheduleSeatedBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { BookingInputLocation_2024_08_13 } from "@calcom/platform-types/bookings/2024-08-13/inputs/location.input";
|
||||
import { EventType } from "@calcom/prisma/client";
|
||||
import type { BookingInputLocation_2024_08_13 } from "@calcom/platform-types/bookings/2024-08-13/inputs/location.input";
|
||||
import type { EventType } from "@calcom/prisma/client";
|
||||
|
||||
type BookingRequest = NextApiRequest & {
|
||||
userId: number | undefined;
|
||||
|
||||
@@ -13,16 +13,19 @@ import { z } from "zod";
|
||||
|
||||
import { bookingMetadataSchema } from "@calcom/platform-libraries";
|
||||
import {
|
||||
BookingOutput_2024_08_13,
|
||||
CreateRecurringSeatedBookingOutput_2024_08_13,
|
||||
CreateSeatedBookingOutput_2024_08_13,
|
||||
GetRecurringSeatedBookingOutput_2024_08_13,
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
ReassignBookingOutput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
SeatedAttendee,
|
||||
BookingOutput_2024_08_13,
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { Booking, BookingSeat } from "@calcom/prisma/client";
|
||||
import type {
|
||||
CreateRecurringSeatedBookingOutput_2024_08_13,
|
||||
CreateSeatedBookingOutput_2024_08_13,
|
||||
ReassignBookingOutput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import type { Booking, BookingSeat } from "@calcom/prisma/client";
|
||||
import { BookingStatus } from "@calcom/prisma/enums";
|
||||
|
||||
export const bookingResponsesSchema = z
|
||||
.object({
|
||||
@@ -68,6 +71,7 @@ type DatabaseBooking = Booking & {
|
||||
eventType: {
|
||||
id: number;
|
||||
slug: string;
|
||||
seatsShowAttendees?: boolean | null;
|
||||
} | null;
|
||||
attendees: {
|
||||
name: string;
|
||||
@@ -167,6 +171,7 @@ export class OutputBookingsService_2024_08_13 {
|
||||
getUserDefinedMetadata(databaseMetadata: DatabaseMetadata) {
|
||||
if (databaseMetadata === null) return {};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { videoCallUrl, ...userDefinedMetadata } = databaseMetadata;
|
||||
|
||||
return userDefinedMetadata;
|
||||
@@ -223,8 +228,8 @@ export class OutputBookingsService_2024_08_13 {
|
||||
hosts: [this.getHost(databaseBooking.user)],
|
||||
status: databaseBooking.status.toLowerCase(),
|
||||
cancellationReason:
|
||||
databaseBooking.status === "CANCELLED" ? databaseBooking.cancellationReason : undefined,
|
||||
cancelledByEmail: databaseBooking.status === "CANCELLED" ? databaseBooking.cancelledBy : undefined,
|
||||
databaseBooking.status === BookingStatus.CANCELLED ? databaseBooking.cancellationReason : undefined,
|
||||
cancelledByEmail: databaseBooking.status === BookingStatus.CANCELLED ? databaseBooking.cancelledBy : undefined,
|
||||
reschedulingReason: bookingResponses?.rescheduledReason,
|
||||
rescheduledFromUid: databaseBooking.fromReschedule || undefined,
|
||||
start: databaseBooking.startTime,
|
||||
@@ -266,11 +271,14 @@ export class OutputBookingsService_2024_08_13 {
|
||||
databaseBooking: DatabaseBooking,
|
||||
seatUid: string
|
||||
): Promise<CreateSeatedBookingOutput_2024_08_13> {
|
||||
const getSeatedBookingOutput = await this.getOutputSeatedBooking(databaseBooking);
|
||||
const getSeatedBookingOutput = await this.getOutputSeatedBooking(
|
||||
databaseBooking,
|
||||
!!databaseBooking.eventType?.seatsShowAttendees
|
||||
);
|
||||
return { ...getSeatedBookingOutput, seatUid };
|
||||
}
|
||||
|
||||
async getOutputSeatedBooking(databaseBooking: DatabaseBooking) {
|
||||
async getOutputSeatedBooking(databaseBooking: DatabaseBooking, showAttendees: boolean) {
|
||||
const dateStart = DateTime.fromISO(databaseBooking.startTime.toISOString());
|
||||
const dateEnd = DateTime.fromISO(databaseBooking.endTime.toISOString());
|
||||
const duration = dateEnd.diff(dateStart, "minutes").minutes;
|
||||
@@ -293,7 +301,7 @@ export class OutputBookingsService_2024_08_13 {
|
||||
hosts: [this.getHost(databaseBooking.user)],
|
||||
status: databaseBooking.status.toLowerCase(),
|
||||
cancellationReason:
|
||||
databaseBooking.status === "CANCELLED" ? databaseBooking.cancellationReason : undefined,
|
||||
databaseBooking.status === BookingStatus.CANCELLED ? databaseBooking.cancellationReason : undefined,
|
||||
rescheduledFromUid: databaseBooking.fromReschedule || undefined,
|
||||
start: databaseBooking.startTime,
|
||||
end: databaseBooking.endTime,
|
||||
@@ -317,41 +325,43 @@ export class OutputBookingsService_2024_08_13 {
|
||||
const parsed = plainToClass(GetSeatedBookingOutput_2024_08_13, booking, { strategy: "excludeAll" });
|
||||
|
||||
// note(Lauris): I don't know why plainToClass erases booking.attendees[n].responses so attaching manually
|
||||
parsed.attendees = databaseBooking.attendees.map((attendee) => {
|
||||
const { responses } = safeParse(
|
||||
seatedBookingDataSchema,
|
||||
attendee.bookingSeat?.data,
|
||||
defaultSeatedBookingData,
|
||||
false
|
||||
);
|
||||
parsed.attendees = showAttendees
|
||||
? databaseBooking.attendees.map((attendee) => {
|
||||
const { responses } = safeParse(
|
||||
seatedBookingDataSchema,
|
||||
attendee.bookingSeat?.data,
|
||||
defaultSeatedBookingData,
|
||||
false
|
||||
);
|
||||
|
||||
const attendeeData = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
language: attendee.locale,
|
||||
absent: !!attendee.noShow,
|
||||
seatUid: attendee.bookingSeat?.referenceUid,
|
||||
bookingFieldsResponses: {},
|
||||
};
|
||||
const attendeeParsed = plainToClass(SeatedAttendee, attendeeData, { strategy: "excludeAll" });
|
||||
attendeeParsed.bookingFieldsResponses = responses || {};
|
||||
attendeeParsed.metadata = safeParse(
|
||||
seatedBookingMetadataSchema,
|
||||
attendee.bookingSeat?.metadata,
|
||||
defaultSeatedBookingMetadata,
|
||||
false
|
||||
);
|
||||
// note(Lauris): as of now email is not returned for privacy
|
||||
delete attendeeParsed.bookingFieldsResponses.email;
|
||||
const attendeeData = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
language: attendee.locale,
|
||||
absent: !!attendee.noShow,
|
||||
seatUid: attendee.bookingSeat?.referenceUid,
|
||||
bookingFieldsResponses: {},
|
||||
};
|
||||
const attendeeParsed = plainToClass(SeatedAttendee, attendeeData, { strategy: "excludeAll" });
|
||||
attendeeParsed.bookingFieldsResponses = responses || {};
|
||||
attendeeParsed.metadata = safeParse(
|
||||
seatedBookingMetadataSchema,
|
||||
attendee.bookingSeat?.metadata,
|
||||
defaultSeatedBookingMetadata,
|
||||
false
|
||||
);
|
||||
// note(Lauris): as of now email is not returned for privacy
|
||||
delete attendeeParsed.bookingFieldsResponses.email;
|
||||
|
||||
return attendeeParsed;
|
||||
});
|
||||
return attendeeParsed;
|
||||
})
|
||||
: [];
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
async getOutputRecurringSeatedBookings(bookingsIds: number[]) {
|
||||
async getOutputRecurringSeatedBookings(bookingsIds: number[], showAttendees: boolean) {
|
||||
const transformed = [];
|
||||
|
||||
for (const bookingId of bookingsIds) {
|
||||
@@ -361,7 +371,7 @@ export class OutputBookingsService_2024_08_13 {
|
||||
throw new Error(`Booking with id=${bookingId} was not found in the database`);
|
||||
}
|
||||
|
||||
transformed.push(this.getOutputRecurringSeatedBooking(databaseBooking));
|
||||
transformed.push(this.getOutputRecurringSeatedBooking(databaseBooking, showAttendees));
|
||||
}
|
||||
|
||||
return transformed.sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());
|
||||
@@ -386,11 +396,14 @@ export class OutputBookingsService_2024_08_13 {
|
||||
databaseBooking: DatabaseBooking,
|
||||
seatUid: string
|
||||
): CreateRecurringSeatedBookingOutput_2024_08_13 {
|
||||
const getRecurringSeatedBookingOutput = this.getOutputRecurringSeatedBooking(databaseBooking);
|
||||
const getRecurringSeatedBookingOutput = this.getOutputRecurringSeatedBooking(
|
||||
databaseBooking,
|
||||
!!databaseBooking.eventType?.seatsShowAttendees
|
||||
);
|
||||
return { ...getRecurringSeatedBookingOutput, seatUid };
|
||||
}
|
||||
|
||||
getOutputRecurringSeatedBooking(databaseBooking: DatabaseBooking) {
|
||||
getOutputRecurringSeatedBooking(databaseBooking: DatabaseBooking, showAttendees: boolean) {
|
||||
const dateStart = DateTime.fromISO(databaseBooking.startTime.toISOString());
|
||||
const dateEnd = DateTime.fromISO(databaseBooking.endTime.toISOString());
|
||||
const duration = dateEnd.diff(dateStart, "minutes").minutes;
|
||||
@@ -405,7 +418,7 @@ export class OutputBookingsService_2024_08_13 {
|
||||
hosts: [this.getHost(databaseBooking.user)],
|
||||
status: databaseBooking.status.toLowerCase(),
|
||||
cancellationReason:
|
||||
databaseBooking.status === "CANCELLED" ? databaseBooking.cancellationReason : undefined,
|
||||
databaseBooking.status === BookingStatus.CANCELLED ? databaseBooking.cancellationReason : undefined,
|
||||
rescheduledFromUid: databaseBooking.fromReschedule || undefined,
|
||||
start: databaseBooking.startTime,
|
||||
end: databaseBooking.endTime,
|
||||
@@ -430,35 +443,37 @@ export class OutputBookingsService_2024_08_13 {
|
||||
});
|
||||
|
||||
// note(Lauris): I don't know why plainToClass erases booking.attendees[n].responses so attaching manually
|
||||
parsed.attendees = databaseBooking.attendees.map((attendee) => {
|
||||
const { responses } = safeParse(
|
||||
seatedBookingDataSchema,
|
||||
attendee.bookingSeat?.data,
|
||||
defaultSeatedBookingData,
|
||||
false
|
||||
);
|
||||
parsed.attendees = showAttendees
|
||||
? databaseBooking.attendees.map((attendee) => {
|
||||
const { responses } = safeParse(
|
||||
seatedBookingDataSchema,
|
||||
attendee.bookingSeat?.data,
|
||||
defaultSeatedBookingData,
|
||||
false
|
||||
);
|
||||
|
||||
const attendeeData = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
language: attendee.locale,
|
||||
absent: !!attendee.noShow,
|
||||
seatUid: attendee.bookingSeat?.referenceUid,
|
||||
bookingFieldsResponses: {},
|
||||
};
|
||||
const attendeeParsed = plainToClass(SeatedAttendee, attendeeData, { strategy: "excludeAll" });
|
||||
attendeeParsed.bookingFieldsResponses = responses || {};
|
||||
attendeeParsed.metadata = safeParse(
|
||||
seatedBookingMetadataSchema,
|
||||
attendee.bookingSeat?.metadata,
|
||||
defaultSeatedBookingMetadata,
|
||||
false
|
||||
);
|
||||
// note(Lauris): as of now email is not returned for privacy
|
||||
delete attendeeParsed.bookingFieldsResponses.email;
|
||||
return attendeeParsed;
|
||||
});
|
||||
const attendeeData = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
timeZone: attendee.timeZone,
|
||||
language: attendee.locale,
|
||||
absent: !!attendee.noShow,
|
||||
seatUid: attendee.bookingSeat?.referenceUid,
|
||||
bookingFieldsResponses: {},
|
||||
};
|
||||
const attendeeParsed = plainToClass(SeatedAttendee, attendeeData, { strategy: "excludeAll" });
|
||||
attendeeParsed.bookingFieldsResponses = responses || {};
|
||||
attendeeParsed.metadata = safeParse(
|
||||
seatedBookingMetadataSchema,
|
||||
attendee.bookingSeat?.metadata,
|
||||
defaultSeatedBookingMetadata,
|
||||
false
|
||||
);
|
||||
// note(Lauris): as of now email is not returned for privacy
|
||||
delete attendeeParsed.bookingFieldsResponses.email;
|
||||
return attendeeParsed;
|
||||
})
|
||||
: [];
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { OAuthClientUsersService } from "@/modules/oauth-clients/services/oauth-
|
||||
import { UsersRepository } from "@/modules/users/users.repository";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
|
||||
import { PlatformOAuthClient } from "@calcom/prisma/client";
|
||||
import type { PlatformOAuthClient } from "@calcom/prisma/client";
|
||||
|
||||
@Injectable()
|
||||
export class PlatformBookingsService {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { BookingsRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/bookings
|
||||
import { CalendarsRepository } from "@/ee/calendars/calendars.repository";
|
||||
import { CalendarsController } from "@/ee/calendars/controllers/calendars.controller";
|
||||
import { AppleCalendarService } from "@/ee/calendars/services/apple-calendar.service";
|
||||
import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service";
|
||||
import { CalendarsService } from "@/ee/calendars/services/calendars.service";
|
||||
import { GoogleCalendarService } from "@/ee/calendars/services/gcal.service";
|
||||
import { IcsFeedService } from "@/ee/calendars/services/ics-feed.service";
|
||||
@@ -10,16 +11,18 @@ import { OutlookService } from "@/ee/calendars/services/outlook.service";
|
||||
import { AppsRepository } from "@/modules/apps/apps.repository";
|
||||
import { CredentialsRepository } from "@/modules/credentials/credentials.repository";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { RedisModule } from "@/modules/redis/redis.module";
|
||||
import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository";
|
||||
import { TokensModule } from "@/modules/tokens/tokens.module";
|
||||
import { UsersModule } from "@/modules/users/users.module";
|
||||
import { Module } from "@nestjs/common";
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, UsersModule, TokensModule],
|
||||
imports: [PrismaModule, UsersModule, TokensModule, RedisModule],
|
||||
providers: [
|
||||
CredentialsRepository,
|
||||
CalendarsService,
|
||||
CalendarsCacheService,
|
||||
OutlookService,
|
||||
GoogleCalendarService,
|
||||
AppleCalendarService,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
|
||||
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
const credentialForCalendarRepositorySelect = {
|
||||
id: true,
|
||||
|
||||
@@ -12,7 +12,6 @@ import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { PlatformOAuthClient, Team, User, Credential } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { CredentialsRepositoryFixture } from "test/fixtures/repository/credentials.repository.fixture";
|
||||
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture";
|
||||
@@ -33,6 +32,7 @@ import {
|
||||
import { OFFICE_365_CALENDAR_ID, OFFICE_365_CALENDAR_TYPE } from "@calcom/platform-constants";
|
||||
import { ICS_CALENDAR, ICS_CALENDAR_TYPE } from "@calcom/platform-constants/apps";
|
||||
import { IcsFeedCalendarService } from "@calcom/platform-libraries/app-store";
|
||||
import type { PlatformOAuthClient, Team, User, Credential } from "@calcom/prisma/client";
|
||||
|
||||
const CLIENT_REDIRECT_URI = "http://localhost:5555";
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user