* fix: break circular dependency in messageDispatcher via dependency injection
Break the 4-file circular dependency chain:
credit-service → reminderScheduler → smsReminderManager → messageDispatcher → credit-service
Solution:
- Add optional creditCheckFn parameter to messageDispatcher functions
- Thread creditCheckFn through the call chain: scheduleWorkflowReminders → scheduleSMSReminder/scheduleWhatsappReminder → messageDispatcher
- When creditCheckFn is provided, use it; otherwise fall back to dynamic CreditService import for backward compatibility
- This breaks the workflows → billing import while preserving immediate fallback behavior
Changes:
- messageDispatcher: Accept optional creditCheckFn parameter, use it if provided
- smsReminderManager: Thread creditCheckFn through scheduleSMSReminder
- whatsappReminderManager: Thread creditCheckFn through scheduleWhatsappReminder
- reminderScheduler: Add creditCheckFn to ScheduleWorkflowRemindersArgs and pass through processWorkflowStep
All type checks, lint checks, and unit tests pass.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* feat: wire creditCheckFn from all callers to complete circular dependency fix
- Add creditCheckFn parameter to WorkflowService.scheduleFormWorkflows
- Wire creditCheckFn from all 10 entry points that call workflow scheduling:
* formSubmissionUtils.ts (form submissions)
* roundRobinManualReassignment.ts (round-robin reassignment)
* triggerFormSubmittedNoEventWorkflow.ts (form workflow trigger)
* handleBookingRequested.ts (booking requests)
* RegularBookingService.ts (2 calls - payment initiated & new bookings)
* handleSeats.ts (seated bookings)
* handleConfirmation.ts (2 calls - confirmation & payment)
* handleMarkNoShow.ts (no-show updates)
* confirm.handler.ts (booking rejection)
- Update test expectations to use expect.objectContaining()
- Fix pre-existing lint warning in handleMarkNoShow.ts (any type)
- This completes the messageDispatcher circular dependency fix by ensuring
creditCheckFn is actually passed through the call chain, breaking the
4-file circular dependency at runtime
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: use generic type with type guard in logFailedResults to fix type check error
- Replace constrained type with generic type parameter
- Add proper type guard for rejected promises
- Fixes CI type check failure in handleMarkNoShow.ts:385
- Avoids 'any' type while accepting any fulfilled value shape
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* wip
* wip
* wip
* revert
* revert
* feat: wire creditCheckFn from all remaining callers to eliminate fallbacks
- Wire creditCheckFn in packages/sms/sms-manager.ts (can safely import CreditService)
- Create makeHandler factory pattern for CRON endpoints (scheduleSMSReminders.ts, scheduleWhatsappReminders.ts)
- Wire creditCheckFn from apps/web CRON routes to factories
- Add warning log in messageDispatcher when fallback is used
- Complete creditCheckFn wiring from all direct callers (activateEventType.handler.ts, util.ts)
This eliminates all fallbacks to dynamic import except as a safety net for unforeseen call sites.
The circular dependency (workflows ↔ billing) remains acceptable as discussed with user (Option C).
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* test: update formSubmissionUtils tests to expect creditCheckFn parameter
The scheduleFormWorkflows function now receives creditCheckFn as a parameter.
Updated test assertions to use expect.objectContaining() with creditCheckFn: expect.any(Function)
to account for the new dependency injection parameter.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* test: update sms-manager test to expect creditCheckFn parameter
The sendSmsOrFallbackEmail function now receives creditCheckFn as a parameter.
Updated test assertion to use expect.objectContaining() with creditCheckFn: expect.any(Function)
to account for the new dependency injection parameter. Also removed teamId: undefined
assertion as the key may be omitted entirely from the actual call.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* feat: make creditCheckFn required to fully break circular dependency
This commit completes the circular dependency fix by making creditCheckFn
required throughout the call chain, eliminating the dynamic import fallback
entirely.
Changes:
- Make creditCheckFn required in messageDispatcher functions (sendSmsOrFallbackEmail, scheduleSmsOrFallbackEmail)
- Remove dynamic import fallback and warning log from messageDispatcher
- Make creditCheckFn required in ScheduleTextReminderArgs (smsReminderManager)
- Make creditCheckFn required in processWorkflowStep and ScheduleWorkflowRemindersArgs (reminderScheduler)
- Add creditCheckFn to SendCancelledRemindersArgs and wire from handleCancelBooking
The circular dependency is now fully broken - no more dynamic imports of
CreditService from within the workflows package. All callers must explicitly
provide creditCheckFn via dependency injection.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: make creditCheckFn required in WorkflowService.scheduleFormWorkflows
This commit fixes the CI type check error by making creditCheckFn required
in WorkflowService.scheduleFormWorkflows. Previously, creditCheckFn was
optional in scheduleFormWorkflows but required in scheduleWorkflowReminders,
causing a type mismatch.
Changes:
- Make creditCheckFn required in scheduleFormWorkflows signature
- Update WorkflowService.test.ts to pass mock creditCheckFn in all test cases
- Add responseId and routedEventTypeId to test calls for completeness
All callers of scheduleFormWorkflows already pass creditCheckFn, so this
change is safe and completes the circular dependency fix.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* remove
* fix
* refactor
* refactor
* refactor
* wip
* fix
* fix
* rm
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: Fix circular dependency in tanstack-table.d.ts
* fix: Re-export TextFilterOperator
* Unable to export non-type values from @calcom/types
* Refactor data-table types in a way that ensures type-safety as before
* Add FilterPopover and further fixups
* Fix further type errors missed earlier
* More hidden type errors
* Type error in useFilterValue
* add public client
* implement PKCE
* pass codeChallenge and codeChallengeMethod to handler
* fixes for secure oauth flow
* fix type error
* clean up refresh token endpoint
* only support S256
* fix type error
* remove comment
* add tests
* fix type errors in route.test.ts
* add missing support for refresh token
* add e2e test for public client refresh tokens
* allow pkce for confidential clients
* fix type error
* fix e2e
* fix option pkce for confidential clients
* e2e test improvements
* fix test
* remove only
* add delay
* fix e2e tests
* remove only
* don't skip pkce if codeChallenge is set
* add service functions for token endpoint
* use service function in refreshToken endpoint
* use repository
* remove return types
* e2e test fixes
* fix e2e test
* remove .only in e2e test
* remove pause
* fix error responses in token endpoints
* adjust tests to new error responses
* fix error responses
* e2e improvements
* redirect on error
* adjust tests
* Update apps/web/modules/auth/oauth2/authorize-view.tsx
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
## What does this PR do?
This PR implements attributes PBAC - router checks + UI
## Visual Demo (For contributors especially)
A visual demonstration is strongly recommended, for both the original and new change **(video / image - any one)**.
#### Video Demo (if applicable):
- Show screen recordings of the issue or feature.
- Demonstrate how to reproduce the issue, the behavior before and after the change.
#### Image Demo (if applicable):
- Add side-by-side screenshots of the original and updated change.
- Highlight any significant change(s).
## Mandatory Tasks (DO NOT REMOVE)
- [ ] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [ ] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). If N/A, write N/A here and check the checkbox.
- [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
Enable PBAC on an org
Create a custom role -> advanced -> organizations -> "editUser"
Assign it to a user
impersonate user
test they have access to all things attributes
remove permissions
check they dont have permissions.
## Checklist
<!-- Remove bullet points below that don't apply to you -->
- I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- My code doesn't follow the style guidelines of this project
- I haven't commented my code, particularly in hard-to-understand areas
- I haven't checked if my changes generate no new warnings
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds a new PBAC “editUsers” permission and read gating for Attributes, updating the UI and backend so users can view and edit attributes only when allowed.
- **New Features**
- Added CustomAction.EditUsers to the permission registry for organization-scoped attribute editing.
- Settings computes canViewAttributes and shows the Attributes tab only when allowed.
- Members page fetches Attributes permissions and exposes canViewAttributes and canEditAttributesForUser to the UI.
- User Edit Sheet hides attributes without read permission and shows attribute editing and the bulk “Mass Assign Attributes” action only with editUsers; other user edits depend on changeMemberRole.
- Attributes TRPC router gates create/edit/delete/toggle via PBAC and requires organization.attributes.editUsers for assign/bulk-assign; added a helper to create PBAC-aware procedures.
- **Migration**
- Run the new Prisma migration to seed the admin role with editUsers.
- If using custom roles, grant Edit Users under Attributes as needed.
<sup>Written for commit 856aa2e8e1521fc22cd71cb0fa6d720036efe8a2. Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
* fix: prevent calendar credentials from leaking into video adapter calls
Split getCredentialAndWarnIfNotFound into two category-specific functions:
- getVideoCredentialAndWarnIfNotFound: only searches video credentials
- getCalendarCredentialAndWarnIfNotFound: only searches calendar credentials
This prevents the bug where calendar credentials (like google_calendar) were
being passed to getVideoAdapters() during booking deletion, causing
'Couldn't get adapter for googlecalendar' errors.
The root cause was the fallback logic that searched both videoCredentials
and calendarCredentials when a credential wasn't found by ID. Now each
function only searches within its own credential category and validates
the returned credential has the expected type suffix (_video/_conferencing
or _calendar).
Also fixed pre-existing ESLint warnings in EventManager.ts:
- Prefixed unused delegatedCredentialLast with underscore
- Replaced 'any' types with 'unknown' for better type safety
- Fixed unused variable warning in updateAllCalendarEvents error handler
Fixes the issue where deleteVideoEventForBookingReference could receive
a calendar credential when the video credential was missing, leading to
errors in getVideoAdapters.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: remove shared helper and implement logic directly in each function
- Removed getCredentialInternal shared helper
- Implemented logic directly in getVideoCredentialAndWarnIfNotFound
- Implemented logic directly in getCalendarCredentialAndWarnIfNotFound
- Changed fallback to explicitly use this.videoCredentials and this.calendarCredentials
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* remove duplicate
* revert
* revert
* revert
* refactor
* add tests
* address
* clean up
* simplify
* simplify
* rename
* rename
* rename
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
* chore: refactor config files to prevent migration tool errors
* refactor: upgrade with the tailwind migration tool
* chore: restore pre-commit command + mc
* refactor(wip): update dependencies and migrate to Tailwind CSS v4 (mainly web)
* chore: resolve Tailwind v4 migration conflicts from merging main
* chore: remove unused Tailwind packages from config and update dependencies for v4 migration
* chore: uncomment Tailwind CSS utility classes in globals.css
* fix: resolve token conflicts between calcom and coss ui
* fix: textarea scrollbar
* Fix CUI-16
* fix: added @tailwindcss/forms plugin and cleaned up CSS classes in various components to remove unnecessary dark mode styles
* fix: selects and inputs of different sizes
* fix: remove unnecessary leading-20 class from modal titles in various components
* fix: update Checkbox component styles to remove unnecessary border on checked state
* fix: clean up styles in RequiresConfirmationController, Checkbox, and Radio components to enhance consistency
* fix: update button and filter component styles to remove unnecessary rounded classes for consistency
* fix: calendar
* fix: update KBarSearch
* fix: refine styles in Empty and Checkbox components for improved consistency
* Fix focus state email input
* fix: update button hover and active states to use 'not-disabled' instead of 'enabled'
* fix: line-height issues
* fix: update class name for muted background in BookingListItem component
* fix: sidebar spacing
* chore: update class names to use new Tailwind CSS color utilities
* fix embed
* chore: upgrade Tailwind CSS to version 4.1.16 and update related dependencies
* Map css variables and add a playground test for heavy css customization
* suggestion for coss-ui
* refactor: update CSS variable usage and clean up styles
- Replace instances of `--cal-brand-color` with `--cal-brand` in embed-related HTML files.
- Remove the now-unnecessary `addAppCssVars` function from the embed core.
- Import theme tokens in the embed core styles for better consistency.
- Clean up whitespace and formatting in CSS files for improved readability.
- Add a comment in `tokens.css` regarding its usage in both embed and webapp contexts.
* Handle within tokens.css instead of fixing coss-ui
* Remove initial, not needed. Also, remove tailwind.config.js as tailwidn scans the html automaically
* fix: examples app breaking
* fix: modal not resizing correctly
* feat: upgrade atoms to tailwind v4
* fix: atoms build breaking
* fix: atoms build breaking
* chore: upgrate examples/base to tailwind 4
* chore: update globals.css
* fix: add missing scheduler css variables
* fix: PlatformAdditionalCalendarSelector
* chore: update global styles
* chore: update tailwindcss and postcss dependencies to stable versions
* chore: remove unneeded class
* fix: dialog and toast animation
* fix: replace flex-shrink-0 with shrink-0 for consistent styling in various components
* fix: dialog modal for Apple connect
* add margin in SaveFilterSegmentButton
* Fix radix button nested states
* add cursor pointer to buttons but keep dsabled state
* Fix commandK selectors and adds cursor pointer
* Fix teams filter
* fix - round checkboxes
* fix filter checkbox
* fix select indicator's margin
* command group font size
* style: fix badge and tooltip radius
* chore: remove unneeded files
* Delete PR_REVIEW_MANAGED_EVENT_REASSIGNMENT.md
* remove ui-playground leftover
* fix: add missing react phone input styles in atoms
* Delete managed-event-reassignment-flow-and-architecture.mermaid
* fix: inter font not loading
* Add theme to skeleton container so that it can support dark mode
* fix: create custom stack-y-* utilities post tw4 upgrade
* fix: typo
* fix: atoms stack class + remove unused css file
* fix default radius valiue
* fix space-y in embed
* fix skeleton background
* Hardcode radius values to match production
* fix border in embed
* add missing externalThemeClass
* feat: create a custom stack-y-* utility
* fix: add stack utility to atom global css
* fix: Skeleton loader class modalbox
* Add stack-y utility in embed
* fix: add missing stack utilities in atoms globals.css
* update yarn.lock
* add popover portla
* update
---------
Co-authored-by: Sean Brydon <sean@cal.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Ryukemeister <sahalrajiv6900@gmail.com>
Co-authored-by: cal.com <morgan@cal.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
Co-authored-by: Anik Dhabal Babu <adhabal2002@gmail.com>
* feat: google ads conversion tracking
* gaClientid
* store gclid in stripe metadata
* tracking only in the us
* track google campaign id as well
* rename gclid -> google ads
* fix: build
* fix
* refactor
* fix: type check
* fix: type check
* fix: type check
* fix: type check
* fix: store it in cookie
* refactor
* fix
* cleanup
* linked ads tracking
* refactor checkout session tracking
* Change arg name from `bookingUId` to `bookingUid`
* Lint fix
* Use `BookingRepository` to find booking to reschedule
* Move early return further up if no booking is found
* Use `PermissionCheckService` if request rescheduling a team booking
* Remove redundent check
* Remove redundent eventType query
* Using `BookingRepository` to update the booking to rescheduled
* Update type in `getUsersCredentialsIncludeServiceAccountKey` to only
require params that are required
* Get booking organizer credentials
* Type fixes
* test: Add tests for team admin request reschedule with organizer credentials
- Add test for team admin requesting reschedule with proper permissions
- Add test verifying organizer's credentials are used (not requester's)
- Add test for team member without permissions (should fail)
These tests cover the fix in PR #24645 which ensures that when a team admin
requests a reschedule, the booking organizer's credentials are used to delete
calendar events instead of the requester's credentials.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: Address code review comments for request reschedule
- Change user: true to user: { select: { id, email } } to only fetch required fields
- Change eventType include to select with explicit fields including teamId
- Remove sensitive information (user object, cancellationReason) from debug log
- All integration tests passing locally
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Type fix
* Remove businesss logic references from repository methods.
* Move business logic to handler
* Type fix
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
## What does this PR do?
Improves the visual presentation of overlapping calendar events in the weekly view with two key enhancements:
- **Dynamic startHour per scenario**: Each playground scenario now displays the calendar starting at an appropriate hour based
on its earliest event time, rather than always starting at 6am
- **Full width for non-overlapping events**: Single events and non-overlapping events now display at 100% width (previously
80%) for maximum visibility
## Key Changes
### Overlapping Event Layout Algorithm
Replaces the previous uniform-width, fixed-offset layout with an intelligent spread algorithm:
**Previous behavior:**
- All overlapping events: 80% width with 8% offset steps
- Events clustered on the left side
**New behavior:**
- **2 overlapping events**: 80% and 50% widths
- **3 overlapping events**: 55%, ~42%, and 33% widths
- **4+ overlapping events**: Progressive narrowing from 40% down to minimum 25%
- **Spread algorithm**: Events distribute across the full width with the last event aligned to the right edge
- **Right edge distribution**: `ri = Rmin + (Rmax - Rmin) × i/(n-1)` for even spacing
### Visual Improvements
- Single/non-overlapping events: **100% width** (was 80%)
- Overlapping events: **Variable widths** based on cascade position (leftmost events wider, rightmost narrower)
- Last overlapping event: **Aligned to right border** for maximum scatter
- Minimum width: **25%** maintained for readability
**Devin session:** https://app.devin.ai/sessions/168d2227f5304c49ae4d34d17da5b025
**Requested by:** eunjae@cal.com (@eunjae-lee)
## Visual Demo
https://github.com/user-attachments/assets/693546fa-448d-470a-b041-c08f4697c177
## Mandatory Tasks (DO NOT REMOVE)
- [x] I have self-reviewed the code
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. **N/A** - playground-only changes
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
1. Navigate to `/settings/admin/playground/weekly-calendar`
2. Verify each scenario:
- **Non-Overlapping Events**: Both events should be 100% width, no offset
- **Touching Events**: Both events should be 100% width, no offset
- **Two Overlapping Events**: First event 80% width, second 50% width aligned to right
- **Three Overlapping Events**: Progressive narrowing with spread across full width
- **Four Overlapping Events**: Four events spread across full width
3. Verify startHour values:
- Most scenarios should start at 9am (events start at 10am)
- Dense day scenario should start at 8am (events start at 9am)
- Mixed statuses scenario should start at 1pm (events start at 2pm)
4. Test with real calendar data to ensure overlapping events look visually distinct
**Environment variables:** Standard Cal.com development setup
**Test data:** Use playground scenarios or create overlapping events in your calendar
## Human Review Checklist
**⚠️ CRITICAL ITEMS:**
1. **Visual verification in playground** (MOST IMPORTANT):
- Open `/settings/admin/playground/weekly-calendar`
- Verify non-overlapping events are 100% width (not 80%)
- Verify overlapping events spread properly across full width
- Verify last overlapping event aligns to right edge
- Verify each scenario starts at appropriate hour
2. **Algorithm correctness**:
- Single events: 100% width (was 80%)
- Two overlapping: 80%, 50% widths with last aligned to right
- Three overlapping: 55%, ~42%, 33% widths spread across full width
- Right-edge distribution: `ri = Rmin + (Rmax - Rmin) * i/(n-1)`
3. **Edge cases**:
- Test with 10+ overlapping events to ensure no overflow
- Verify minimum width (25%) is respected
- Verify backward compatibility: custom `baseWidthPercent`/`offsetStepPercent` should use legacy behavior
4. **Type safety**:
- `startHour` parameter now properly typed as `Hours` (union of 0-23)
- All scenarios use valid `Hours` values
**Known limitations:**
- Local visual testing was not completed due to environment issues
- Easing curve parameters (curveExponent: 1.3) were chosen based on examples but may need visual tuning
- No E2E tests for visual appearance (only unit tests for layout calculations)
## Checklist
- [x] I have read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- [x] My code follows the style guidelines of this project
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have checked if my changes generate no new warnings
2025-11-24 12:01:05 +00:00
Benny JooGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: break circular dependency between reminderScheduler and credit-service
- Created WorkflowReminderRepository to handle workflow reminder queries
- Refactored cancelScheduledMessagesAndScheduleEmails to accept userIdsWithoutCredits parameter
- Moved credit-checking logic from workflows to CreditService
- Changed dynamic import to static import in CreditService
- Updated tests to pass userIdsWithoutCredits parameter
- Removed unused imports (prisma, WorkflowMethods)
This creates a one-way dependency (billing -> workflows) and follows the repository pattern by removing direct Prisma usage from reminderScheduler.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: resolve type check errors in circular dependency fix
- Use MembershipRepository.listAcceptedTeamMemberIds instead of findAllAcceptedPublishedTeamMemberships
- Re-add prisma import to reminderScheduler.ts for UserRepository
- Update WorkflowReminderRepository to use WorkflowActions enum instead of string
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor
* refactor
* wip
* wip
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add backend validation for conflicting team slugs during org onboarding
- Added findOwnedTeamsByUserId method to TeamRepository
- Created buildTeamsAndInvites method in BaseOnboardingService that automatically:
- Detects teams with same slug as organization
- Marks conflicting teams for migration (isBeingMigrated: true)
- Filters empty team names and invite emails
- Updated BillingEnabledOrgOnboardingService to use new method
- Updated SelfHostedOnboardingService to use new method
- Added comprehensive tests for slug conflict scenarios
This ensures backend validation even if frontend is bypassed, preventing
slug conflicts during organization creation. All inheriting classes
automatically get this validation without code changes.
* refactor: use TeamRepository in listOwnedTeamsHandler
Refactored listOwnedTeamsHandler to use TeamRepository.findOwnedTeamsByUserId
instead of direct Prisma queries. This:
- Reduces code duplication
- Ensures consistency across the codebase
- Follows repository pattern
- Makes the handler more maintainable
* fix: update tests to use renamed buildTeamsAndInvites method
- Renamed testFilterTeamsAndInvites to testBuildTeamsAndInvites
- Made test wrapper method async to match the async buildTeamsAndInvites
- Added orgSlug parameter to all test calls
- Updated all 9 test cases to use await with the new method signature
- Fixed lint warnings by using proper types instead of 'any'
- Imported OnboardingIntentResult and User types
- Used Pick<User> for mockUser type
- Removed all 'as any' type casts
Fixes test failures where filterTeamsAndInvites was renamed to buildTeamsAndInvites in the base service.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: mock TeamRepository in tests to prevent database calls
Added vi.mock for TeamRepository to avoid database calls in unit tests.
The buildTeamsAndInvites method now calls ensureConflictingSlugTeamIsMigrated
which uses TeamRepository.findOwnedTeamsByUserId(). Mocking this prevents
Prisma errors in CI while keeping the tests focused on filtering logic.
The mock returns an empty array so no teams are found for migration,
allowing the tests to verify the filtering behavior without database access.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: improve readability of ensureConflictingSlugTeamIsMigrated
Refactored the conditional logic in ensureConflictingSlugTeamIsMigrated
for better readability while preserving exact behavior. Changed from
manual array manipulation to using .map() for updating team migration
status. This is a cosmetic change with no functional differences.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
* hotfix
* type fix and test fix
* update env example
* improvements
* more fix
* tada
---------
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
* Add check that event type belongs to team
* Add `findAcceptedMembershipsByUserIdsInTeam` to `MembershipRepository`
* Validate that passed `userIds` belong to a team
* Add tests
* Typo fix
2025-11-21 10:26:22 -05:00
Volnei MunhozGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Improve add users to org
* Improve add users to org
* test: Add comprehensive tests for handleUserEvents cross-tenant hijack prevention
- Add tests for cross-tenant hijack prevention security fix
- Test that users belonging to different organizations are blocked
- Test that users with null organizationId are blocked (prevents legacy user hijacking)
- Test that users belonging to correct organization succeed
- Test new user creation flow
- Test user activation/deactivation flows
- Test custom attribute syncing
- All 8 tests passing locally with proper type safety (no 'as any' usage)
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: Add trial days to organization subscriptions and workspace warning
- Add ORGANIZATION_TRIAL_DAYS environment variable for configurable trial periods
- Implement trial days in Stripe checkout session (only when env var is set)
- Add warning message to organization setup page about workspace structure
- Add translation string for organization trial workspace warning
- Add ORGANIZATION_TRIAL_DAYS to turbo.json env vars
- Fix pre-existing linting warnings in CreateANewOrganizationForm.tsx
- Add ESLint disable comments for turbo/no-undeclared-env-vars warnings
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Rename variable
* Add trial days to `purchaseTeamOrOrgSubscription`
* fix: Move organization trial warning to spot 3 below form card
- Add optional footer prop to WizardLayout component
- Use footer prop in create-new-view.tsx to render warning at spot 3
- Remove warning from inside CreateANewOrganizationForm component
- Warning now appears below the form card as requested
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: Add organization trial warning to all wizard steps
- Add warning footer to step 2 (about-view.tsx)
- Add warning footer to step 3 (add-teams-view.tsx)
- Add warning footer to step 4 (onboard-members-view.tsx)
- Add warning footer to step 5 (payment-status-view.tsx)
- Add warning footer to resume-view.tsx (step 1 resume page)
- Warning now appears on all steps of the organization creation wizard
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: Correct environment variable name to STRIPE_ORG_TRIAL_DAYS
- Changed ORGANIZATION_TRIAL_DAYS to STRIPE_ORG_TRIAL_DAYS in turbo.json
- This matches the actual usage in OrganizationPaymentService.ts and payments.ts
- Ensures the environment variable is properly recognized by the build system
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: Create shared OrganizationWizardLayout component
- Create OrganizationWizardLayout component that wraps WizardLayout
- Centralizes the trial warning footer logic in one place
- Update all 6 wizard pages to use the shared component:
- create-new-view.tsx
- about-view.tsx
- add-teams-view.tsx
- onboard-members-view.tsx
- payment-status-view.tsx
- resume-view.tsx
- Remove duplicate useLocale/Alert imports and footer props from pages
- Simplifies maintenance by having warning logic in a single location
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Fix lint error
* Add `ORG_TRIAL_DAYS` as constant
* Add comment
* Ensure no negative number is passed
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
* chore: Remove all code related to the old cache system
* Removed some redundant tests, some type fixes
* Further type fixes
* More type fixes re. tests
* Next iteration, couple of fixes remaining
* Remove cache from CredentialActionsDropdown
* Fix tests by mocking credential, instead of db queries
* Remove Cache DI wiring from v2
* Make sure apiv2 build passes
* Remove another cache cron
* Remove old tokens for calendar-cache v1
2025-11-20 18:02:18 +02:00
MorganGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Add hashedLink field to CalendarEvent type definition
- Add withHashedLink method to CalendarEventBuilder
- Pass hashedLink from booking request to CalendarEvent in RegularBookingService
- hashedLink will now be included in webhook payloads when booking via private API links
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Revamps onboarding with subtle route transitions, new org/teams illustrations, and clearer invite flows with real-time previews. Adds “Skip for now” on invites and guardrails to avoid incomplete team creation.
- **New Features**
- Added email invite pages for organizations and teams with shared EmailInviteForm and RoleSelector.
- Built a live invite browser preview that renders a 3×3 grid and updates as you type; works for orgs and teams.
- Applied route-keyed framer-motion transitions to layout, cards, and browser views for smoother page changes.
- Continuation prompt now detects saved org or team and routes to the right next step; localized copy.
- Added loading state to plan selection to prevent double navigation.
- Refreshed Organizations welcome modal with a new animated ring illustration and better scrolling.
- Added “Skip for now” to org and team invite-by-email steps to proceed without invites.
- Calendar browser preview now focuses on a time window around “now” for a more realistic demo.
- Added an optional floating footer to keep actions visible on long, scrollable lists.
- **Refactors and Fixes**
- Unified invite browser and replaced the org preview on the org email step.
- Split and simplified legacy invite views; team and org routes are cleaner and easier to extend.
- Streamlined the team invite step by removing a redundant action; non-admins are redirected to the email invite page.
- Prevented creating teams with empty details by redirecting back to team details.
- Minor UI cleanup: tighter borders, padding, and mobile max-heights across onboarding screens.
- Hide team select on org invites when no teams exist.
<sup>Written for commit ae7f5277ab998560ae6e2f3f9144852a7b4959a7. Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
* Revert "fix: revert bookings redesign (#25172)"
This reverts commit 1f102bf3b4.
* add bookings-v3 feature flag
* put things behind a feature flag
* remove no longer needed test
* revert e2e tests
* put back description
* revert AvatarGroup
* apply feedback
* remove "view" booking action
* remove Alert (When the bookings query errors, this branch now renders only the alert and skips the data-table filter/segment controls. Those controls moved into BookingsList, so in error states users can no longer clear or tweak filters to recover from the failure, effectively trapping them behind the alert.)
* address feedback
* revert useMediaQuery
2025-11-19 16:27:13 +01:00
Joe Au-YeungGitHubcubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Syed Ali Shahbaz
* Move TeamBillingRepositories
* WIP refactor team internal billing service
* Remove duplicate billing repository files
* Remove logic check in repository for billing is enabled
* Rename repository to `TeamBillingData`
* Use repository factory in main service
* Fix new import paths
* Rename to
* Ensure `IS_TEAM_BILLING_ENABLED` is of type boolean
* Rename classes to TeamBillingService and TeamBillingServiceFactory
* Implement DI in `BookingServiceFactory`
* `TeamBillingService` use repository in `getOrgIfNeeded`
* DI `isTeamBillingEnabled` to `TeamBillingServiceFactory`
* Rename files for consistency
* Return stub BillingRepository if billing is not enabled
* Move Stripe billing service to service folder
* Rename file
* `StripeBillingService.getSubscriptionStatus` return `SubscriptionStatus`
* Type fices in StripeBillingService
* Type fix in `stubTeamBillingService`
* DI the `BillingProviderService` into the `TeamBillingService`
* Implement DI in `skipTeamTrials.handler`
* Implement DI for team billing in `inviteMember.handler`
* `skipTeamTrials.handler` use `team.isOrganization`
* Implement DI for billing in `hasActiveTeamPlan.handler`
* Type fixes
* Implement DI in `bulkDeleteUsers.handler`
* Implement `BillingProviderServiceFactory` in `updateProfile.handler`
* Implment `BillingProviderServiceFactory` in `buyCredits.handler`
* Fix import in `stripeCustomer.handler`
* Add a constructor to `teamBillingServiceFactory`
* Add DI to `PrismaTeamBillingRepository`
* Add DI to `StripeBillingService`
* Implement singleton in `BillingProviderServiceFactory`
* Add DI folder and contents to billing folder
* Use `getTeamBillingServiceFactory` in `inviteMember.handler`
* Add `saveTeamBilling` method to `ITeamBillingService`
* Implement DI in new team route
* Implement DI in `teamService`
* Implement DI in `OrganizationPaymentService`
* Implement DI in `credit-service`
* In `StripeBillingService` remove `static` from status methods
* Implemnt DI in `_invoice.paid.org`
* Refactor `hasActiveTeamPlan` to use `getTeamBillingFactory`
* Refactor `skipTeamTrials` to use `getTeamBillingFactory`
* Refactor `skipTeamTrials` to use `getTeamBillingServiceFactory`
* `stripeCustomer.handler` to use `getBillingProviderService`
* Remove old factories
* Type fix
* Remove unused factory
* Refactor `updateProfile.handler` to use `getBillingProviderService`
* Change name to `TeamBillingDataRepositoryFactory`
* Type Prisma return in `prisma.module`
* Type fix
* Refactor `buyCredits.handler` to use `getBillingProviderService`
* Refactor `credit-service` to use billing DI containers
* Type fix
* Add `getTeamBillingDataRepository`
* Refactor `_invoice.paid.org` to use DI container
* Refactor `_customer.subscription.deleted.team-plan` to use DI container
* Refactor `calcomHandler` to use DI container
* Refactor `getCustomerAndCheckoutSession` to use DI container
* Refactor `verify-email` to use DI containers
* Refactor `api/create/route` to use DI container
* Refactor downgradeUsers to use DI container
* Type fix
* Clean up console.logs
* Add await to `this.billingRepository.create` in `saveTeamBilling`
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* Fix type errors
* Address comments
* fix: update tests to work with new DI pattern
- Update teamBillingService.test.ts to properly inject DI dependencies
- Remove unused billingModule import and mock
- Fix import naming in teamService.integration-test.ts (remove unused rename)
- Fix import path for TeamBillingPublishResponseStatus
All tests now properly mock IBillingProviderService, ITeamBillingDataRepository,
and IBillingRepository instead of using the old BillingRepositoryFactory pattern.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add compatibility layer and env setup for unit tests
- Add STRIPE_PRIVATE_KEY dummy value to vitest.config.ts to prevent DI module errors
- Fix import paths in credit-service.test.ts (StripeBillingService, TeamBillingService)
- Create compatibility barrel at packages/features/ee/billing/teams/index.ts for test mocking
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: update unit tests to mock DI container properly
- Update teamService.test.ts to mock getTeamBillingServiceFactory() instead of TeamBilling.findAndInit
- Update teamService.alternative.test.ts to mock DI container
- Update credit-service.test.ts to mock getBillingProviderService() and use SubscriptionStatus enum values
- Update OrganizationPaymentService.test.ts to mock DI container instead of direct StripeBillingService import
- Remove all 'as any' type casting to comply with Cal.com coding standards
- Fix unused variable warnings by prefixing with underscore
All 53 tests now passing (16 + 1 + 30 + 6)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: update remaining unit tests to use DI pattern
- Fix StripeBillingService.test.ts to inject mock Stripe client directly
- Fix teamBillingFactory.test.ts to mock getTeamBillingServiceFactory() from DI container
- Fix skipTeamTrials.test.ts to mock DI container and use SubscriptionStatus enum
All 11 previously failing tests now pass (5 + 5 + 1)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Undo changes made to Prisma module
* fix: address test-related PR comments
- Fix OrganizationPaymentService.test.ts mock path from @calcom/ee to @calcom/features/ee
- Refactor teamBillingFactory.test.ts to test real factory logic instead of mocking container
- Remove duplicate teamBillingService.test..ts file with incorrect double-dot filename
All three test files now pass successfully with proper DI patterns.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Address feedback
* fix: update teamService integration test to mock new DI factory pattern
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: remove duplicate imports in credit-service.test.ts
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Remove unused index file
* `getBySubscriptionId` to return team or null
* Address feedback
* Merge fix
* Refactor file names
* fix: correct mockStripe variable name to stripeMock in StripeBillingService.test.ts
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: update internal-team-billing.test.ts to use new DI structure with TeamBillingService
- Replace InternalTeamBilling with TeamBillingService
- Use constructor injection with mock dependencies instead of factory pattern
- Remove BillingRepositoryFactory mock and import
- Update all test cases to use mockBillingProviderService, mockTeamBillingDataRepository, and mockBillingRepository
- Simplify saveTeamBilling tests to focus on repository.create calls
- All 11 tests now pass with the new DI structure
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: update createWithPaymentIntent.handler.test.ts to mock DI container's getBillingProviderService
- OrganizationPaymentService now uses getBillingProviderService() from DI container
- Test was mocking @calcom/features/ee/payments/server/stripe directly, which no longer works
- Added mock for @calcom/features/ee/billing/di/containers/Billing module
- Mock returns fake billing provider that delegates to mockSharedStripe
- Preserves all existing test assertions and helpers
- Fixed lint error by prefixing unused lastCreatedSessionId with underscore
- All 11 tests now pass (1 skipped as expected)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
---------
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
* feat: Implement Booking Audit System with database architecture and repository interfaces
- Added `ARCHITECTURE.md` detailing the design and structure of the Booking Audit System, including core tables `AuditActor` and `BookingAudit`.
- Created repository interfaces `IAuditActorRepository` and `IBookingAuditRepository` for managing audit actor and booking audit records.
- Implemented `PrismaAuditActorRepository` and `PrismaBookingAuditRepository` for database interactions.
- Defined enums for `BookingAuditType`, `BookingAuditAction`, and `AuditActorType` in the Prisma schema.
- Added migration scripts to create necessary database tables and enums for the audit system.
This commit establishes a robust framework for tracking booking-related actions, ensuring compliance and data integrity.
* feat(audit): add system actor migration
* feat: add organization-level autofill disable setting
- Create DisableAutofillOnBookingPageSwitch component following existing patterns
- Add toggle to organization general page alongside other settings
- Update tRPC organizations update handler to support new field
- Add organization-level check to useShouldBeDisabledDueToPrefill hook
- Add translation keys for new autofill disable setting
- Include database migration for disableAutofillOnBookingPage field
- Maintain backward compatibility with individual field settings
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* feat: complete autofill disable implementation
- Add disableAutofillOnBookingPage to orgSettings type definition
- Update Prisma schema with new organization setting field
- Clean up test file formatting
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* fix: resolve tRPC mocking issues in tests and add missing disableAutofillOnBookingPage to organization repository
- Fix tRPC module mocking in useShouldBeDisabledDueToPrefill tests
- Add disableAutofillOnBookingPage to organization repository select and return statements
- All form builder tests now pass (24/24)
- Organization-level autofill disable tests working correctly
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* test: simplify autofill disable test to single focused test
- Replace multiple tests with one test that verifies org setting blocks autocomplete
- Test includes searchParams with prefill data to verify blocking behavior
- Removes unnecessary test complexity as requested
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* fix: add missing disableAutofillOnBookingPage to organizationSettings select statements
- Add disableAutofillOnBookingPage to both parent and main organizationSettings select statements in getTeamWithMembers
- Resolves TypeScript error in getServerSideProps.tsx where MinimumOrganizationSettings type requires this property
- Ensures organization settings type compatibility across the codebase
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* Remove disableAutofillOnBookingPage setting
Removed 'disableAutofillOnBookingPage' setting from organization configuration.
* update
* Remove duplicate settings in common.json
Removed duplicate entries for automatic transcription and autofill settings.
* Fix syntax error in common.json
* update
* add tests
* Remove comments for autofill disabled check
Removed comments explaining scenarios for autofill check.
* addressed review
* fix
* change
* Add handling for disableAutofillOnBookingPage input
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-11-19 08:25:46 +00:00
Volnei MunhozGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Fix cache to fetch only when it's available
* Non hierarchical feature check
* Fix tests: Add missing mock method and comprehensive CalendarCacheWrapper tests
- Add checkIfUserHasFeatureNonHierarchical to features.repository mock to fix failing GoogleCalendar tests
- Add comprehensive unit tests for CalendarCacheWrapper covering:
- Calendars with sync only (cache-only path)
- Calendars without sync only (original calendar path)
- Mixed calendars (both cache and original)
- Timezone handling with UTC defaults
- Edge cases (empty arrays, undefined methods, null ids)
- Use proper types instead of 'as any' to satisfy lint rules
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* Fix: Sanitize logging to avoid exposing PII
- Replace logging full selectedCalendars objects with only calendar IDs and count
- Prevents exposure of email fields and other sensitive information in logs
- Addresses AI code reviewer feedback
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* Apply suggestion from @volnei
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-11-19 01:11:52 +00:00
MorganGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: delegation credential error webhooks
* refactor: extract repeated delegation credential error webhook logic into helper methods
- Added private triggerDelegationCredentialError method in Office365CalendarService class
- Added triggerDelegationCredentialError helper function in TeamsVideoApiAdapter
- Replaced all 4 instances in Office365CalendarService with helper method call
- Replaced all 4 instances in TeamsVideoApiAdapter with helper function call
- Keeps code DRY by eliminating repeated if statement and webhook trigger logic
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-11-18 00:00:42 +02:00
MorganGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Rajiv Sahal
* feat: add defaultPhoneCountry prop to BookerPlatformWrapper
- Add defaultPhoneCountry to BookerStore type and implementation
- Add defaultPhoneCountry prop to BookerPlatformWrapper types
- Pass defaultPhoneCountry through store initialization
- Update PhoneInput to use defaultPhoneCountry from store
- Support default phone country extension for phone inputs in booker form
* feat: add strict typing for defaultPhoneCountry with ISO 3166-1 alpha-2 codes
- Define CountryCode type using ISO 3166-1 alpha-2 country codes
- Update defaultPhoneCountry prop type in BookerPlatformWrapper to use CountryCode
- Update defaultPhoneCountry type in BookerStore to use CountryCode
- Ensures type safety by only allowing valid country codes like 'us', 'gb', 'ee', etc.
- Fix lint warnings by prefixing type-only constants with underscore
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* refactor: export CountryCode from store to avoid duplication
- Export CountryCode type from packages/features/bookings/Booker/store.ts
- Import CountryCode in packages/platform/atoms/booker/types.ts from store
- Remove duplicate CountryCode definition from types.ts
- Maintains single source of truth for country code type definition
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: add type-safe casts for CountryCode in PhoneInput
- Import CountryCode type from store
- Add explicit type annotation to useState<CountryCode>
- Add safe type casts with isSupportedCountry validation
- Validate navigator.language country code before using it
- Fixes CI type error: string not assignable to CountryCode
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* docs: add defaultPhoneCountry prop documentation and changeset
- Add defaultPhoneCountry prop to booker.mdx documentation
- Add changeset for minor version bump
- Document ISO 3166-1 alpha-2 country code support
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in>
* fix: made show all columns work correctly
* test: added test for show all columns in ColumnVisibilityButton
---------
Co-authored-by: Pallav <90088723+Pallava-Joshi@users.noreply.github.com>
* fix: added timezonebadge to insights/routing which appears on timezone mismatch
* update: removed user repository and directly used prisma
* clean up code
---------
Co-authored-by: Eunjae Lee <hey@eunjae.dev>