* feat(bookings): add booking audit logging to instant bookings
wire up BookingEventHandlerService.onBookingCreated in
InstantBookingCreateService to emit audit events, matching the
pattern already used in RegularBookingService and
RecurringBookingService.
* refactor: extract fireBookingEvents and reuse existing orgId
* refactor: derive orgId once and pass to both webhook trigger and audit event
* fix: add missing return in webhook map callback
* refactor: make creationSource required for instant bookings
Both callers (WEBAPP and API_V2) always set creationSource, so validate
it upfront and use CreationSource enum type instead of string | null.
* fix: use ErrorWithCode instead of Error, pass userUuid to audit events
* fix: pass null for hostUserUuid in instant booking audit data
Instant bookings have status AWAITING_HOST with no assigned host,
so the booker's UUID should not be recorded as hostUserUuid.
* fix: address devin review - hostUserUuid and creationSource validation
* fix: address review - bookingMeta, getOrgIdFromMemberOrTeamId, required creationSource
- pass userUuid via bookingMeta instead of separate param (matches RegularBookingService pattern)
- restore getOrgIdFromMemberOrTeamId for proper org resolution instead of eventType.team.parentId
- make creationSource required with runtime validation instead of defaulting to WEBAPP
* fix: enforce creationSource at compile time instead of runtime
use Required<Pick<>> to make creationSource required in the type
signature. removes the runtime check since TypeScript catches
missing creationSource at build time.
* fix: simplify type signature and derive hostUserUuid from booking relation
- Replace Required<Pick<CreateInstantBookingData, 'creationSource'>> with inline { creationSource: CreationSource }
- Include user relation in booking create query to derive hostUserUuid
- Pass newBooking.user?.uuid instead of hardcoding null for userUuid in audit data
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* chore: trigger CI
* fix: add missing impersonatedByUserUuid to instant booking meta
The CreateBookingMeta type requires impersonatedByUserUuid. Set it to
null for non-impersonated instant bookings.
* fix: show 'awaiting host' in audit log for instant bookings
Use booking status AWAITING_HOST to display "Booked (awaiting host)"
instead of "Booked with Unknown" when no host has accepted yet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add booking audit for instant meeting accept via connect-and-join
Extract fireInstantBookingAcceptedAuditEvent to InstantBookingCreateService
and fire it right after the DB update, before side-effect notifications.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add audit logging tests for instant booking creation
* fix: simulate audit failure in resilience test (identified by cubic)
The test 'should not throw when booking audit event fails' was not
actually simulating an audit failure. Added vi.spyOn on
BookingEventHandlerService.prototype.onBookingCreated to reject with
an error, and assert the spy was called, proving the try/catch in
fireBookingEvents properly catches the error without breaking the
booking flow.
Co-Authored-By: bot_apk <apk@cognition.ai>
* test: add audit event tests for connectAndJoin and fix InstantBooking audit test
* test
---------
Co-authored-by: Hariom Balhara <1780212+hariombalhara@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: hariom@cal.com <hariombalhara@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: bot_apk <apk@cognition.ai>
29 lines
1.3 KiB
TypeScript
29 lines
1.3 KiB
TypeScript
import { InstantBookingCreateService } from "@calcom/features/bookings/lib/service/InstantBookingCreateService";
|
|
import { moduleLoader as bookingEventHandlerModuleLoader } from "@calcom/features/bookings/di/BookingEventHandlerService.module";
|
|
import { createModule, bindModuleToClassOnToken } from "@calcom/features/di/di";
|
|
import { moduleLoader as featuresRepositoryModuleLoader } from "@calcom/features/di/modules/FeaturesRepository";
|
|
import { DI_TOKENS } from "@calcom/features/di/tokens";
|
|
import { moduleLoader as prismaModuleLoader } from "@calcom/features/di/modules/Prisma";
|
|
|
|
export const instantBookingCreateServiceModule = createModule();
|
|
const token = DI_TOKENS.INSTANT_BOOKING_CREATE_SERVICE;
|
|
const moduleToken = DI_TOKENS.INSTANT_BOOKING_CREATE_SERVICE_MODULE;
|
|
const loadModule = bindModuleToClassOnToken({
|
|
module: instantBookingCreateServiceModule,
|
|
moduleToken,
|
|
token,
|
|
classs: InstantBookingCreateService,
|
|
depsMap: {
|
|
// TODO: In a followup PR, we aim to remove prisma dependency and instead inject the repositories as dependencies.
|
|
prismaClient: prismaModuleLoader,
|
|
bookingEventHandler: bookingEventHandlerModuleLoader,
|
|
featuresRepository: featuresRepositoryModuleLoader,
|
|
},
|
|
});
|
|
|
|
export type { InstantBookingCreateService };
|
|
export const moduleLoader = {
|
|
token,
|
|
loadModule,
|
|
};
|