Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ describe("Event types Endpoints", () => {
.expect(404);
});

it("should not be able to create phone-only event type", async () => {
it("should be able to create phone-only event type", async () => {
const body: CreateEventTypeInput_2024_06_14 = {
title: "Phone coding consultation",
slug: "phone-coding-consultation",
Expand Down Expand Up @@ -397,6 +397,43 @@ describe("Event types Endpoints", () => {
],
};

await request(app.getHttpServer())
.post("/api/v2/event-types")
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
.set("Authorization", `Bearer ${apiKeyString}`)
.send(body)
.expect(200);
});

it("should throw error while both email and phone are hidden", async () => {
const body: CreateEventTypeInput_2024_06_14 = {
title: "Phone coding consultation",
slug: "phone-coding-consultation",
description: "Our team will review your codebase.",
lengthInMinutes: 60,
locations: [
{
type: "integration",
integration: "cal-video",
},
],
bookingFields: [
{
type: "email",
required: false,
label: "Email",
hidden: true,
},
{
type: "phone",
slug: "attendeePhoneNumber",
required: false,
label: "Phone number",
hidden: true,
},
],
};

const response = await request(app.getHttpServer())
.post("/api/v2/event-types")
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
Expand All @@ -405,7 +442,7 @@ describe("Event types Endpoints", () => {
.expect(400);

expect(response.body.error.message).toBe(
"checkIsEmailUserAccessible - Email booking field must be required and visible"
"Booking fields validation failed: visible and required email or visible and required attendee phone field is needed."
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
updateEventType,
getEventTypesPublic,
EventTypesPublic,
ensureEmailOrPhoneNumberIsPresent,
} from "@calcom/platform-libraries/event-types";
import type { GetEventTypesQuery_2024_06_14, SortOrderType } from "@calcom/platform-types";
import type { EventType } from "@calcom/prisma/client";
Expand All @@ -40,7 +41,7 @@ export class EventTypesService_2024_06_14 {

async createUserEventType(user: UserWithProfile, body: InputEventTransformed_2024_06_14) {
if (body.bookingFields) {
this.checkHasUserAccessibleEmailBookingField(body.bookingFields);
ensureEmailOrPhoneNumberIsPresent(body.bookingFields);
}
await this.checkCanCreateEventType(user.id, body);
const eventTypeUser = await this.getUserToCreateEvent(user);
Expand Down Expand Up @@ -117,16 +118,6 @@ export class EventTypesService_2024_06_14 {
await this.checkUserOwnsSchedule(userId, body.scheduleId);
}

checkHasUserAccessibleEmailBookingField(bookingFields: (SystemField | CustomField)[]) {
const emailField = bookingFields.find((field) => field.type === "email" && field.name === "email");
const isEmailFieldRequiredAndVisible = emailField?.required && !emailField?.hidden;
if (!isEmailFieldRequiredAndVisible) {
throw new BadRequestException(
"checkIsEmailUserAccessible - Email booking field must be required and visible"
);
}
}

async getEventTypeByUsernameAndSlug(params: {
username: string;
eventTypeSlug: string;
Expand Down Expand Up @@ -307,7 +298,7 @@ export class EventTypesService_2024_06_14 {
user: UserWithProfile
) {
if (body.bookingFields) {
this.checkHasUserAccessibleEmailBookingField(body.bookingFields);
ensureEmailOrPhoneNumberIsPresent(body.bookingFields);
}
await this.checkCanUpdateEventType(user.id, eventTypeId, body.scheduleId);
const eventTypeUser = await this.getUserToUpdateEvent(user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ describe("Organizations Event Types Endpoints", () => {
return request(app.getHttpServer()).post(`/v2/teams/${team.id}/event-types`).send(body).expect(404);
});

it("should not be able to create phone-only event type", async () => {
it("should be able to create phone-only event type", async () => {
const body: CreateTeamEventTypeInput_2024_06_14 = {
title: "Phone coding consultation",
slug: "phone-coding-consultation",
Expand Down Expand Up @@ -273,12 +273,59 @@ describe("Organizations Event Types Endpoints", () => {
],
};

await request(app.getHttpServer())
.post(`/v2/teams/${team.id}/event-types`)
.send(body)
.expect(200);
});

it("should throw error while both email and phone are hidden", async () => {
const body: CreateTeamEventTypeInput_2024_06_14 = {
title: "Phone coding consultation",
slug: "phone-coding-consultation",
description: "Our team will review your codebase.",
lengthInMinutes: 60,
locations: [
{
type: "integration",
integration: "cal-video",
},
{
type: "organizersDefaultApp",
},
],
schedulingType: "COLLECTIVE",
hosts: [
{
userId: teamMember1.id,
},
{
userId: teamMember2.id,
},
],
bookingFields: [
{
type: "email",
required: false,
label: "Email",
hidden: true,
},
{
type: "phone",
slug: "attendeePhoneNumber",
required: false,
label: "Phone number",
hidden: true,
},
],
};

const response = await request(app.getHttpServer())
.post(`/v2/teams/${team.id}/event-types`)
.send(body)
.expect(400);
expect(response.body.error.message).toBe(
"checkIsEmailUserAccessible - Email booking field must be required and visible"
"Booking fields validation failed: visible and required email or visible and required attendee phone field is needed."
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Injectable, NotFoundException, Logger } from "@nestjs/common";

import type { SortOrderType } from "@calcom/platform-types";

import { createEventType, updateEventType } from "@calcom/platform-libraries/event-types";
import { createEventType, ensureEmailOrPhoneNumberIsPresent, updateEventType } from "@calcom/platform-libraries/event-types";

@Injectable()
export class TeamsEventTypesService {
Expand All @@ -32,9 +32,8 @@ export class TeamsEventTypesService {
teamId: number,
body: TransformedCreateTeamEventTypeInput
): Promise<DatabaseTeamEventType | DatabaseTeamEventType[]> {
// note(Lauris): once phone only event types / bookings are enabled for simple users remove checkHasUserAccessibleEmailBookingField check
if (body.bookingFields) {
this.eventTypesService.checkHasUserAccessibleEmailBookingField(body.bookingFields);
ensureEmailOrPhoneNumberIsPresent(body.bookingFields);
}
const eventTypeUser = await this.getUserToCreateTeamEvent(user);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -116,8 +115,7 @@ export class TeamsEventTypesService {
isOrg: boolean
): Promise<DatabaseTeamEventType | DatabaseTeamEventType[]> {
if (!isOrg && body.bookingFields) {
// note(Lauris): once phone only event types / bookings are enabled for simple users remove checkHasUserAccessibleEmailBookingField check
this.eventTypesService.checkHasUserAccessibleEmailBookingField(body.bookingFields);
ensureEmailOrPhoneNumberIsPresent(body.bookingFields);
}
await this.validateEventTypeExists(teamId, eventTypeId);
const eventTypeUser = await this.eventTypesService.getUserToUpdateEvent(user);
Expand Down
2 changes: 2 additions & 0 deletions packages/platform/libraries/event-types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import EventManager from "@calcom/features/bookings/lib/EventManager";

export { ensureEmailOrPhoneNumberIsPresent } from "@calcom/trpc/server/routers/viewer/eventTypes/util";

export { getPublicEvent, type PublicEventType } from "@calcom/features/eventtypes/lib/getPublicEvent";

export { getBulkUserEventTypes, getBulkTeamEventTypes } from "@calcom/app-store/_utils/getBulkEventTypes";
Expand Down
Loading