fix: Organization User Events' Spam#24468
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
WalkthroughReplaces direct extraction of eventOrganizationId in the new-booking flow with a new helper Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleNewBooking.ts (1)
1227-1236: Use eventType.profile and precomputed eventOrganizationId; remove extra profile queryCurrent code fetches the first profile for the organizer (findFirst by userId) to derive organizerOrganizationId and usernameInOrg. If the user has multiple org profiles, this can pick the wrong org, producing incorrect bookerUrl and usernameInOrg for user events linked to a specific org profile.
You already computed eventOrganizationId earlier (Line 515) from team?.parentId or eventType.profile?.organizationId. Use that and the event’s profile to avoid mismatches and an extra DB call.
Apply these diffs:
- Replace the extra profile query and compute bookerUrl from eventOrganizationId:
- const organizerOrganizationProfile = await prisma.profile.findFirst({ - where: { - userId: organizerUser.id, - }, - }); - - const organizerOrganizationId = organizerOrganizationProfile?.organizationId; - const bookerUrl = eventType.team - ? await getBookerBaseUrl(eventType.team.parentId) - : await getBookerBaseUrl(organizerOrganizationId ?? null); + const bookerUrl = await getBookerBaseUrl(eventOrganizationId);
- Use the event’s profile for usernameInOrg:
- usernameInOrg: organizerOrganizationProfile?.username || undefined, + usernameInOrg: eventType.profile?.username || undefined,To support this, ensure getEventTypesFromDB selects profile.username:
packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.tsprofile: { select: { - organizationId: true, + organizationId: true, + username: true, }, },This removes an extra DB hit, aligns URLs/usernames with the correct org, and adheres to the “select only what you need” Prisma guideline. As per coding guidelines
Also applies to: 1284-1292, 515-516
🧹 Nitpick comments (3)
packages/features/eventtypes/lib/defaultEvents.ts (1)
217-217: Prefer named exports over default exportsConsider replacing default export with a named export for better tree-shaking and refactoring ergonomics.
As per coding guidelines
-export default defaultEvents; +export { defaultEvents };packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts (1)
35-39: Select profile.username to avoid extra queries and ensure correct org contexthandleNewBooking reads organizer profile username for usernameInOrg and should use the event’s profile to avoid mismatches when users have multiple org profiles. Add username to the existing profile select so callers don’t need an extra query.
profile: { select: { - organizationId: true, + organizationId: true, + username: true, }, },This also enables removing a redundant prisma.profile.findFirst in handleNewBooking.ts. As per coding guidelines
packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts (1)
124-124: Remove debug logging from testsconsole.log("watchlists", …) adds noise to CI logs. Please remove.
- console.log("watchlists", await prisma.watchlist.findMany()); + // Removed noisy debug log
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
packages/features/bookings/lib/handleNewBooking.ts(5 hunks)packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts(2 hunks)packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts(2 hunks)packages/features/eventtypes/lib/defaultEvents.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/features/eventtypes/lib/defaultEvents.tspackages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.tspackages/features/bookings/lib/handleNewBooking.tspackages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/features/eventtypes/lib/defaultEvents.tspackages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.tspackages/features/bookings/lib/handleNewBooking.tspackages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/features/eventtypes/lib/defaultEvents.tspackages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.tspackages/features/bookings/lib/handleNewBooking.tspackages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.
Applied to files:
packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Applied to files:
packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.
Applied to files:
packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.
Applied to files:
packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: In the Cal.com codebase, some calendar integrations like google-calendar already use SelectedCalendarRepository.create for selectedCalendar creation, which automatically triggers reconnection logic, while others like feishucalendar use direct prisma.selectedCalendar.create calls that bypass the repository hooks.
Applied to files:
packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts
🧬 Code graph analysis (1)
packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts (2)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1)
getNewBookingHandler(15-17)apps/web/test/utils/bookingScenario/bookingScenario.ts (8)
createOrganization(1040-1079)getBooker(2250-2264)getOrganizer(1539-1598)TestData(1258-1530)getGoogleCalendarCredential(1211-1219)createBookingScenario(997-1028)getScenarioData(1600-1688)mockCalendarToHaveNoBusySlots(1989-2002)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (7)
packages/features/eventtypes/lib/defaultEvents.ts (1)
101-101: Good addition: ensure profile field exists on defaultsAdding profile: null keeps eventType.profile access safe downstream (org-aware flows). No further issues.
packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts (1)
198-201: isOrgTeamEvent computation looks correctUsing team presence and profile?.organizationId is a solid signal for org-scoped events, including managed and user-profiled events.
packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts (2)
789-983: Great coverage for org watchlist behavior in user vs personal eventsNew tests clearly validate org-scoped blocking for user events, managed variants, and personal fail-open. Nicely done.
81-92: Ensure Prisma assertions use the same test mockFile: packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts (lines 81–92)
bookingScenario helpers use prismock but expectNoBookingInDatabase calls prisma.booking.findMany — confirm setupAndTeardown remaps "@calcom/prisma" to that prismock; if it does not, change this assertion to use the same mock client (e.g., import/use prismock from tests/libs/mocks/prisma).packages/features/bookings/lib/handleNewBooking.ts (3)
39-49: Import changes look correctgetBookerBaseUrl and WorkflowRepository imports align with new usage; DI type imports match IBookingServiceDependencies.
514-516: Org resolution for spam checks is correctFallback to eventType.profile?.organizationId covers user events associated with org profiles. Good fix.
1428-1496: Decoy response shape is safeNo sensitive organizer data is exposed; email is null. Property isShortCircuitedBooking is fine for internal consumers/tests.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
packages/features/bookings/lib/handleNewBooking.ts(5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/features/bookings/lib/handleNewBooking.ts
🧠 Learnings (1)
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Applied to files:
packages/features/bookings/lib/handleNewBooking.ts
🧬 Code graph analysis (1)
packages/features/bookings/lib/handleNewBooking.ts (1)
packages/features/ee/organizations/lib/orgDomains.ts (1)
getOrgSlug(16-59)
🔇 Additional comments (1)
packages/features/bookings/lib/handleNewBooking.ts (1)
527-530: LGTM!The fallback logic for resolving
eventOrganizationIdis clear and correctly prioritizesteam.parentIdbefore falling back toeventType.profile?.organizationId. Safe navigation operators prevent null reference errors.
| if (hostname) { | ||
| const { getOrgSlug } = await import("@calcom/features/ee/organizations/lib/orgDomains"); | ||
| const { OrganizationRepository } = await import( | ||
| "@calcom/features/ee/organizations/repositories/OrganizationRepository" | ||
| ); | ||
|
|
||
| const orgSlug = getOrgSlug(hostname, forcedSlug); | ||
| if (orgSlug) { | ||
| const organization = await OrganizationRepository.findBySlug({ slug: orgSlug }); | ||
| eventOrganizationId = organization?.id ?? null; | ||
| } | ||
| } |
There was a problem hiding this comment.
Add error handling for organization resolution to prevent booking failures.
The organization resolution logic lacks error handling around the dynamic imports and database lookup. If getOrgSlug or OrganizationRepository.findBySlug throws an error, the entire booking process will crash. Since the spam check can function with a null organizationId, this code should fail gracefully.
Apply this diff to add error handling:
let eventOrganizationId: number | null = null;
- if (hostname) {
- const { getOrgSlug } = await import("@calcom/features/ee/organizations/lib/orgDomains");
- const { OrganizationRepository } = await import(
- "@calcom/features/ee/organizations/repositories/OrganizationRepository"
- );
-
- const orgSlug = getOrgSlug(hostname, forcedSlug);
- if (orgSlug) {
- const organization = await OrganizationRepository.findBySlug({ slug: orgSlug });
- eventOrganizationId = organization?.id ?? null;
- }
- }
+ if (hostname) {
+ try {
+ const { getOrgSlug } = await import("@calcom/features/ee/organizations/lib/orgDomains");
+ const { OrganizationRepository } = await import(
+ "@calcom/features/ee/organizations/repositories/OrganizationRepository"
+ );
+
+ const orgSlug = getOrgSlug(hostname, forcedSlug);
+ if (orgSlug) {
+ const organization = await OrganizationRepository.findBySlug({ slug: orgSlug });
+ eventOrganizationId = organization?.id ?? null;
+ }
+ } catch (error) {
+ loggerWithEventDetails.warn("Failed to resolve organization from hostname", { hostname, error });
+ // Continue with null organizationId - spam check can handle it
+ }
+ }🤖 Prompt for AI Agents
In packages/features/bookings/lib/handleNewBooking.ts around lines 514 to 525,
the dynamic imports and OrganizationRepository.findBySlug call are not guarded;
any thrown error will crash booking creation. Wrap the entire hostname/orgSlug
resolution block in a try/catch, and on error set eventOrganizationId = null (do
not rethrow) so booking can continue; inside the catch log the error using the
module's logger (or console.error if none available) with context like "failed
to resolve organization for hostname" to aid debugging.
d754a41 to
0aa2c51
Compare
|
|
||
| const createdBooking = await handleNewBooking({ | ||
| bookingData: mockBookingData, | ||
| forcedSlug: org.slug, |
There was a problem hiding this comment.
Using forcedSlug approach to tell the slug instead of hostname as it is not easily possible to mock ALLOWED_HOSTNAMES right now
0aa2c51 to
7ce1fd9
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
packages/features/bookings/lib/handleNewBooking.ts(7 hunks)packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts(2 hunks)packages/features/ee/organizations/lib/orgDomains.ts(1 hunks)packages/features/profile/repositories/ProfileRepository.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/features/ee/organizations/lib/orgDomains.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/features/bookings/lib/handleNewBooking.tspackages/features/profile/repositories/ProfileRepository.tspackages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/features/bookings/lib/handleNewBooking.tspackages/features/profile/repositories/ProfileRepository.tspackages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/features/bookings/lib/handleNewBooking.tspackages/features/profile/repositories/ProfileRepository.tspackages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts
**/*Repository.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Repository files must include
Repositorysuffix, prefix with technology if applicable (e.g.,PrismaAppRepository.ts), and use PascalCase matching the exported class
Files:
packages/features/profile/repositories/ProfileRepository.ts
🧠 Learnings (2)
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Applied to files:
packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.
Applied to files:
packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts
🧬 Code graph analysis (2)
packages/features/bookings/lib/handleNewBooking.ts (1)
packages/features/profile/repositories/ProfileRepository.ts (1)
ProfileRepository(66-734)
packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts (1)
apps/web/test/utils/bookingScenario/bookingScenario.ts (8)
createOrganization(1040-1079)getBooker(2250-2264)getOrganizer(1539-1598)TestData(1258-1530)getGoogleCalendarCredential(1211-1219)createBookingScenario(997-1028)getScenarioData(1600-1688)mockCalendarToHaveNoBusySlots(1989-2002)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Tests / Unit
- GitHub Check: Production builds / Build Web App
- GitHub Check: Linters / lint
- GitHub Check: Production builds / Build API v2
- GitHub Check: Production builds / Build Atoms
- GitHub Check: Production builds / Build API v1
- GitHub Check: Type check / check-types
🔇 Additional comments (2)
packages/features/bookings/lib/handleNewBooking.ts (1)
551-555: LGTM! Organization ID derivation integrated correctly.The call to
getEventOrganizationIdproperly derives the organization ID before initiating the spam check, which aligns with the PR objective of fixing organization-level spam detection for user events.However, ensure the underlying profile lookup is fixed (per separate comment on
getEventOrganizationId) to prevent non-deterministic behavior.packages/features/bookings/lib/handleNewBooking/test/spam-booking.integration-test.ts (1)
789-871: LGTM! Comprehensive test coverage for user events in organizations.This test case properly validates that organization-level watchlist blocking works for user events (non-team events) when the user has a profile linking them to an organization. The test:
- Correctly creates an organization without a team (
withTeam: false)- Sets up a user event type with
userId: 101(noteamId)- Links the organizer to the organization via
organizationId- Validates the decoy response and absence of database booking
This fills an important gap in test coverage for the organization spam detection feature.
| if (process.env.NEXT_PUBLIC_IS_E2E || process.env.INTEGRATION_TEST_MODE) { | ||
| log.debug("Using provided forcedSlug in E2E/Integration Test mode", { |
There was a problem hiding this comment.
I think it is better to keep it still(not needed right now though) because it could be useful while integration testing in future
e1535e7 to
3304a7f
Compare
3304a7f to
811796d
Compare
E2E results are ready! |
What does this PR do?
Fixes organization-level spam detection for user events by deriving the organization ID from the hostname instead of relying solely on team hierarchy or user profile data. This ensures spam checks use the correct organization context based on the domain/subdomain being accessed.
Key Changes
1. Hostname-based Organization Resolution
team?.parentId ?? eventType.profile?.organizationIdto determine the organization2. Implementation Details
In
handleNewBooking.ts:getOrgSlug()andOrganizationRepository.findBySlug()spamCheckService.startCheck()In
getEventTypesFromDB.ts:withSelectedCalendars()for hosts and userseventType.profile?.organizationIdIn
defaultEvents.ts:profile: nullto commons object for consistencyIn
orgDomains.ts:3. Comprehensive Test Coverage
Added integration tests in
spam-booking.integration-test.ts:Why This Change?
In multi-tenant deployments where organizations use custom domains/subdomains:
Example Scenario
Before:
After:
Testing
Related Issues
Fixes organization user event spam detection issues where domain-based spam blocks were not being applied correctly.