fix(api): return original email without OAuth suffix in bookings (#25593)
* fix(api): remove OAuth client ID suffix from email in booking API responses Fixes #25494 | Linear: CAL-6843 When managed users create or receive bookings, their emails were being returned with an internal OAuth client ID suffix (e.g., bob+cuid123@example.com). This suffix is used internally for user identification but should not be exposed in API responses. Changes: - Add cleanOAuthEmailSuffix() helper using CUID regex pattern - Clean email suffix in hosts[], attendees[], bookingFieldsResponses.email, bookingFieldsResponses.guests[], and reassignedTo.email - Pattern consistent with google-calendar.service.ts implementation Affected output methods: - getOutputBooking - getOutputRecurringBooking - getOutputSeatedBooking - getOutputRecurringSeatedBooking - getOutputReassignedBooking - getHost * refactor(api): preserve original email, add displayEmail field Per team discussion, keep original email unchanged to avoid breaking changes for platform customers. Add displayEmail field with CUID suffix removed for display purposes * feat(api): add displayEmail to booking output DTOs Add displayEmail property to BookingAttendee, BookingHost and ReassignedToDto for API documentation and type safety * test(api): add e2e tests for displayEmail fields in managed user bookings Add tests to verify that displayEmail fields correctly strip CUID suffix from OAuth managed user emails in booking API responses: - Test host displayEmail returns email without CUID suffix - Test attendee displayEmail returns email without CUID suffix - Test bookingFieldsResponses.displayEmail returns clean email - Test displayGuests array returns emails without CUID suffix * false positive breaking change * false positive breaking change * test(api): update existing e2e tests to expect displayEmail field * fix(api): add missing displayEmail to seated booking test assertions The seated booking tests were missing displayEmail in the attendee assertions for the second booking test and cancel-as-host test, causing CI test failures --------- Co-authored-by: cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
co-authored by
cal.com
Morgan
parent
3e7e376100
commit
0994050b0f
@@ -2,3 +2,9 @@ GET /v2/event-types/{eventTypeId} added to the 'data' response property 'oneOf'
|
||||
GET /v2/event-types/{eventTypeId} added '#/components/schemas/EventTypeOutput_2024_06_14, #/components/schemas/TeamEventTypeOutput_2024_06_14' to the 'data' response property 'oneOf' list for the response status '200'
|
||||
GET /v2/bookings/{bookingUid}/recordings added the new required 'header' request parameter 'Authorization'
|
||||
GET /v2/bookings/{bookingUid}/transcripts added the new required 'header' request parameter 'Authorization'
|
||||
POST /v2/bookings added 'subschema #2, subschema #4' to the 'data' response property 'oneOf' list for the response status '201'
|
||||
GET /v2/bookings/{bookingUid} added 'subschema #3, subschema #6' to the 'data' response property 'oneOf' list for the response status '200'
|
||||
POST /v2/bookings/{bookingUid}/cancel added 'subschema #3, subschema #6' to the 'data' response property 'oneOf' list for the response status '200'
|
||||
POST /v2/bookings/{bookingUid}/confirm added 'subschema #3, subschema #6' to the 'data' response property 'oneOf' list for the response status '200'
|
||||
POST /v2/bookings/{bookingUid}/decline added 'subschema #3, subschema #6' to the 'data' response property 'oneOf' list for the response status '200'
|
||||
POST /v2/bookings/{bookingUid}/guests added 'subschema #3, subschema #6' to the 'data' response property 'oneOf' list for the response status '200'
|
||||
@@ -177,6 +177,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
|
||||
+85
@@ -624,6 +624,91 @@ describe("Managed user bookings 2024-08-13", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("displayEmail fields", () => {
|
||||
it("should return displayEmail without CUID suffix for host", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2030, 0, 7, 10, 0, 0)).toISOString(),
|
||||
eventTypeId: firstManagedUserEventTypeId,
|
||||
attendee: {
|
||||
name: "External Attendee",
|
||||
email: "external-display-email-test@example.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "en",
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
};
|
||||
|
||||
const response = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingData = response.body.data;
|
||||
|
||||
// Host email should have CUID, displayEmail should not
|
||||
expect(bookingData.hosts[0].email).toEqual(firstManagedUser.user.email);
|
||||
expect(bookingData.hosts[0].displayEmail).toEqual(firstManagedUserEmail);
|
||||
});
|
||||
|
||||
it("should return displayEmail without CUID suffix for attendee", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2030, 0, 7, 10, 30, 0)).toISOString(),
|
||||
eventTypeId: firstManagedUserEventTypeId,
|
||||
attendee: {
|
||||
name: secondManagedUser.user.name!,
|
||||
email: secondManagedUser.user.email,
|
||||
timeZone: secondManagedUser.user.timeZone,
|
||||
language: secondManagedUser.user.locale,
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
};
|
||||
|
||||
const response = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingData = response.body.data;
|
||||
|
||||
// Attendee email should have CUID, displayEmail should not
|
||||
expect(bookingData.attendees[0].email).toEqual(secondManagedUser.user.email);
|
||||
expect(bookingData.attendees[0].displayEmail).toEqual(secondManagedUserEmail);
|
||||
|
||||
// bookingFieldsResponses should also have displayEmail
|
||||
expect(bookingData.bookingFieldsResponses.email).toEqual(secondManagedUser.user.email);
|
||||
expect(bookingData.bookingFieldsResponses.displayEmail).toEqual(secondManagedUserEmail);
|
||||
});
|
||||
|
||||
it("should return displayGuests without CUID suffix", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2030, 0, 7, 11, 0, 0)).toISOString(),
|
||||
eventTypeId: firstManagedUserEventTypeId,
|
||||
attendee: {
|
||||
name: "External Attendee",
|
||||
email: "external-display-guests-test@example.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "en",
|
||||
},
|
||||
guests: [secondManagedUser.user.email],
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
};
|
||||
|
||||
const response = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingData = response.body.data;
|
||||
|
||||
// guests should have CUID, displayGuests should not
|
||||
expect(bookingData.bookingFieldsResponses.guests).toContain(secondManagedUser.user.email);
|
||||
expect(bookingData.bookingFieldsResponses.displayGuests).toContain(secondManagedUserEmail);
|
||||
});
|
||||
});
|
||||
|
||||
describe("booking confirmation by org admin", () => {
|
||||
it("should allow org admin managed user to confirm booking using access token", async () => {
|
||||
const bookingRequiringConfirmation = await bookingsRepositoryFixture.create({
|
||||
|
||||
@@ -492,6 +492,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
id: teamUser2.id,
|
||||
name: teamUser2.name,
|
||||
email: teamUser2.email,
|
||||
displayEmail: teamUser2.email,
|
||||
});
|
||||
|
||||
const reassigned = await bookingsRepositoryFixture.getByUid(roundRobinBooking.uid);
|
||||
@@ -532,6 +533,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
id: teamUser1.id,
|
||||
name: teamUser1.name,
|
||||
email: teamUser1.email,
|
||||
displayEmail: teamUser1.email,
|
||||
});
|
||||
|
||||
const reassigned = await bookingsRepositoryFixture.getByUid(roundRobinBooking.uid);
|
||||
|
||||
@@ -185,6 +185,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(firstBooking.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -206,6 +207,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(secondBooking.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -262,6 +264,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(firstBooking.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -284,6 +287,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(secondBooking.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -304,6 +308,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(thirdBooking.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
|
||||
@@ -201,6 +201,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -276,6 +277,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(firstAttendee).toEqual({
|
||||
name: createdSeatedBooking.attendees[0].name,
|
||||
email: createdSeatedBooking.attendees[0].email,
|
||||
displayEmail: createdSeatedBooking.attendees[0].displayEmail,
|
||||
timeZone: createdSeatedBooking.attendees[0].timeZone,
|
||||
language: createdSeatedBooking.attendees[0].language,
|
||||
absent: false,
|
||||
@@ -291,6 +293,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(secondAttendee).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -418,6 +421,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: attendee?.name,
|
||||
email: attendee?.email,
|
||||
displayEmail: attendee?.displayEmail,
|
||||
timeZone: attendee?.timeZone,
|
||||
language: attendee?.language,
|
||||
absent: false,
|
||||
@@ -841,6 +845,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
|
||||
@@ -519,6 +519,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -573,6 +574,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: "919876543210@sms.cal.com",
|
||||
displayEmail: "919876543210@sms.cal.com",
|
||||
phoneNumber: body.attendee.phoneNumber,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
@@ -629,6 +631,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -636,6 +639,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[1]).toEqual({
|
||||
name: teamUser2.name,
|
||||
email: teamUser2.email,
|
||||
displayEmail: teamUser2.email,
|
||||
timeZone: teamUser2.timeZone,
|
||||
language: teamUser2.locale,
|
||||
absent: false,
|
||||
@@ -690,6 +694,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -744,6 +749,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -927,6 +933,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: phoneBasedBooking.attendees[0].name,
|
||||
email: phoneBasedBooking.attendees[0].email,
|
||||
displayEmail: phoneBasedBooking.attendees[0].displayEmail,
|
||||
phoneNumber: phoneBasedBooking.attendees[0].phoneNumber,
|
||||
timeZone: phoneBasedBooking.attendees[0].timeZone,
|
||||
language: phoneBasedBooking.attendees[0].language,
|
||||
@@ -1010,6 +1017,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
|
||||
@@ -483,6 +483,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -493,8 +494,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.bookingFieldsResponses).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
...body.bookingFieldsResponses,
|
||||
guests: body.guests,
|
||||
displayGuests: body.guests,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
@@ -566,6 +569,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(firstBooking.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -588,6 +592,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(secondBooking.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -609,6 +614,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(thirdBooking.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -2077,6 +2083,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -2087,8 +2094,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.bookingFieldsResponses).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
...body.bookingFieldsResponses,
|
||||
guests: body.guests,
|
||||
displayGuests: body.guests,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
@@ -2527,6 +2536,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
phoneNumber: body.attendee.phoneNumber,
|
||||
@@ -2535,6 +2545,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.bookingFieldsResponses).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
attendeePhoneNumber: body.attendee.phoneNumber,
|
||||
smsReminderNumber: body.attendee.phoneNumber,
|
||||
});
|
||||
|
||||
@@ -93,6 +93,10 @@ type DatabaseMetadata = z.infer<typeof bookingMetadataSchema>;
|
||||
export class OutputBookingsService_2024_08_13 {
|
||||
constructor(private readonly bookingsRepository: BookingsRepository_2024_08_13) {}
|
||||
|
||||
private getDisplayEmail(email: string): string {
|
||||
return email.replace(/\+[a-zA-Z0-9]{25}/, "");
|
||||
}
|
||||
|
||||
async getOutputBooking(databaseBooking: DatabaseBooking) {
|
||||
const dateStart = DateTime.fromISO(databaseBooking.startTime.toISOString());
|
||||
const dateEnd = DateTime.fromISO(databaseBooking.endTime.toISOString());
|
||||
@@ -127,6 +131,7 @@ export class OutputBookingsService_2024_08_13 {
|
||||
attendees: databaseBooking.attendees.map((attendee) => ({
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
displayEmail: this.getDisplayEmail(attendee.email),
|
||||
timeZone: attendee.timeZone,
|
||||
language: attendee.locale,
|
||||
absent: !!attendee.noShow,
|
||||
@@ -149,6 +154,25 @@ export class OutputBookingsService_2024_08_13 {
|
||||
// note(Lauris): I don't know why plainToClass erases bookings responses and metadata so attaching manually
|
||||
bookingTransformed.bookingFieldsResponses = bookingResponses;
|
||||
bookingTransformed.metadata = this.getUserDefinedMetadata(metadata);
|
||||
|
||||
if (
|
||||
bookingTransformed.bookingFieldsResponses?.email &&
|
||||
typeof bookingTransformed.bookingFieldsResponses.email === "string"
|
||||
) {
|
||||
bookingTransformed.bookingFieldsResponses.displayEmail = this.getDisplayEmail(
|
||||
bookingTransformed.bookingFieldsResponses.email
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
bookingTransformed.bookingFieldsResponses?.guests &&
|
||||
Array.isArray(bookingTransformed.bookingFieldsResponses.guests)
|
||||
) {
|
||||
bookingTransformed.bookingFieldsResponses.displayGuests = bookingTransformed.bookingFieldsResponses.guests.map(
|
||||
(guest: string) => this.getDisplayEmail(guest)
|
||||
);
|
||||
}
|
||||
|
||||
return bookingTransformed;
|
||||
}
|
||||
|
||||
@@ -192,12 +216,14 @@ export class OutputBookingsService_2024_08_13 {
|
||||
id: "unknown",
|
||||
name: "unknown",
|
||||
email: "unknown",
|
||||
displayEmail: "unknown",
|
||||
username: "unknown",
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...user,
|
||||
displayEmail: this.getDisplayEmail(user.email),
|
||||
username: user.username || "unknown",
|
||||
};
|
||||
}
|
||||
@@ -249,6 +275,7 @@ export class OutputBookingsService_2024_08_13 {
|
||||
attendees: databaseBooking.attendees.map((attendee) => ({
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
displayEmail: this.getDisplayEmail(attendee.email),
|
||||
timeZone: attendee.timeZone,
|
||||
language: attendee.locale,
|
||||
absent: !!attendee.noShow,
|
||||
@@ -272,6 +299,25 @@ export class OutputBookingsService_2024_08_13 {
|
||||
// note(Lauris): I don't know why plainToClass erases bookings responses and metadata so attaching manually
|
||||
bookingTransformed.bookingFieldsResponses = bookingResponses;
|
||||
bookingTransformed.metadata = this.getUserDefinedMetadata(metadata);
|
||||
|
||||
if (
|
||||
bookingTransformed.bookingFieldsResponses?.email &&
|
||||
typeof bookingTransformed.bookingFieldsResponses.email === "string"
|
||||
) {
|
||||
bookingTransformed.bookingFieldsResponses.displayEmail = this.getDisplayEmail(
|
||||
bookingTransformed.bookingFieldsResponses.email
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
bookingTransformed.bookingFieldsResponses?.guests &&
|
||||
Array.isArray(bookingTransformed.bookingFieldsResponses.guests)
|
||||
) {
|
||||
bookingTransformed.bookingFieldsResponses.displayGuests = bookingTransformed.bookingFieldsResponses.guests.map(
|
||||
(guest: string) => this.getDisplayEmail(guest)
|
||||
);
|
||||
}
|
||||
|
||||
return bookingTransformed;
|
||||
}
|
||||
|
||||
@@ -337,6 +383,7 @@ export class OutputBookingsService_2024_08_13 {
|
||||
const attendeeData = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
displayEmail: this.getDisplayEmail(attendee.email),
|
||||
timeZone: attendee.timeZone,
|
||||
language: attendee.locale,
|
||||
absent: !!attendee.noShow,
|
||||
@@ -465,6 +512,7 @@ export class OutputBookingsService_2024_08_13 {
|
||||
const attendeeData = {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
displayEmail: this.getDisplayEmail(attendee.email),
|
||||
timeZone: attendee.timeZone,
|
||||
language: attendee.locale,
|
||||
absent: !!attendee.noShow,
|
||||
@@ -497,6 +545,9 @@ export class OutputBookingsService_2024_08_13 {
|
||||
id: databaseBooking?.user?.id || 0,
|
||||
name: databaseBooking?.user?.name || "unknown",
|
||||
email: databaseBooking?.user?.email || "unknown",
|
||||
displayEmail: databaseBooking?.user?.email
|
||||
? this.getDisplayEmail(databaseBooking.user.email)
|
||||
: "unknown",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
+4
@@ -335,6 +335,7 @@ describe("Organizations Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -388,6 +389,7 @@ describe("Organizations Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -441,6 +443,7 @@ describe("Organizations Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: orgUserEmail,
|
||||
displayEmail: orgUserEmail,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -494,6 +497,7 @@ describe("Organizations Bookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: orgUserEmail2,
|
||||
displayEmail: orgUserEmail2,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
|
||||
+1
@@ -250,6 +250,7 @@ describe("Organizations TeamsBookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
|
||||
+3
@@ -233,6 +233,7 @@ describe("Organizations UsersBookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -291,6 +292,7 @@ describe("Organizations UsersBookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
@@ -347,6 +349,7 @@ describe("Organizations UsersBookings Endpoints 2024-08-13", () => {
|
||||
expect(data.attendees[0]).toEqual({
|
||||
name: body.attendee.name,
|
||||
email: body.attendee.email,
|
||||
displayEmail: body.attendee.email,
|
||||
timeZone: body.attendee.timeZone,
|
||||
language: body.attendee.language,
|
||||
absent: false,
|
||||
|
||||
@@ -31712,6 +31712,11 @@
|
||||
"type": "string",
|
||||
"example": "jane100@example.com"
|
||||
},
|
||||
"displayEmail": {
|
||||
"type": "string",
|
||||
"example": "jane100@example.com",
|
||||
"description": "Clean email for display purposes"
|
||||
},
|
||||
"username": {
|
||||
"type": "string",
|
||||
"example": "jane100"
|
||||
@@ -31721,10 +31726,11 @@
|
||||
"example": "America/Los_Angeles"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"email",
|
||||
"displayEmail",
|
||||
"username",
|
||||
"timeZone"
|
||||
]
|
||||
@@ -31757,6 +31763,11 @@
|
||||
"type": "string",
|
||||
"example": "john@example.com"
|
||||
},
|
||||
"displayEmail": {
|
||||
"type": "string",
|
||||
"example": "john@example.com",
|
||||
"description": "Clean email for display purposes"
|
||||
},
|
||||
"timeZone": {
|
||||
"type": "string",
|
||||
"example": "America/New_York"
|
||||
@@ -31819,9 +31830,10 @@
|
||||
"example": "+1234567890"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"required": [
|
||||
"name",
|
||||
"email",
|
||||
"displayEmail",
|
||||
"timeZone",
|
||||
"absent"
|
||||
]
|
||||
@@ -32168,6 +32180,11 @@
|
||||
"type": "string",
|
||||
"example": "john@example.com"
|
||||
},
|
||||
"displayEmail": {
|
||||
"type": "string",
|
||||
"example": "john@example.com",
|
||||
"description": "Clean email for display purposes"
|
||||
},
|
||||
"timeZone": {
|
||||
"type": "string",
|
||||
"example": "America/New_York"
|
||||
@@ -32247,9 +32264,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"required": [
|
||||
"name",
|
||||
"email",
|
||||
"displayEmail",
|
||||
"timeZone",
|
||||
"absent",
|
||||
"seatUid",
|
||||
@@ -33342,12 +33360,18 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"displayEmail": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com",
|
||||
"description": "Clean email for display purposes"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"email"
|
||||
"email",
|
||||
"displayEmail"
|
||||
]
|
||||
},
|
||||
"ReassignBookingOutput_2024_08_13": {
|
||||
|
||||
@@ -29,6 +29,11 @@ class BookingAttendee {
|
||||
@Expose()
|
||||
email!: string;
|
||||
|
||||
@ApiProperty({ type: String, example: "john@example.com", description: "Clean email for display purposes" })
|
||||
@IsString()
|
||||
@Expose()
|
||||
displayEmail!: string;
|
||||
|
||||
@ApiProperty({ type: String, example: "America/New_York" })
|
||||
@IsTimeZone()
|
||||
@Expose()
|
||||
@@ -95,6 +100,11 @@ class BookingHost {
|
||||
@Expose()
|
||||
email!: string;
|
||||
|
||||
@ApiProperty({ type: String, example: "jane100@example.com", description: "Clean email for display purposes" })
|
||||
@IsString()
|
||||
@Expose()
|
||||
displayEmail!: string;
|
||||
|
||||
@ApiProperty({ type: String, example: "jane100" })
|
||||
@IsString()
|
||||
@Expose()
|
||||
@@ -395,6 +405,11 @@ class ReassignedToDto {
|
||||
@IsEmail()
|
||||
@Expose()
|
||||
email!: string;
|
||||
|
||||
@ApiProperty({ type: String, example: "john.doe@example.com", description: "Clean email for display purposes" })
|
||||
@IsString()
|
||||
@Expose()
|
||||
displayEmail!: string;
|
||||
}
|
||||
|
||||
export class ReassignBookingOutput_2024_08_13 {
|
||||
|
||||
Reference in New Issue
Block a user