* refactor: migrate TeamEventTypeForm to use PBAC instead of isTeamAdminOrOwner
- Replace isTeamAdminOrOwner prop with permissions.canCreateEventType
- Move permission checks to server-side using PermissionCheckService
- Use eventType.create permission string as specified in PBAC guide
- Update all parent components: CreateEventTypeDialog, event-types-view, CreateEventTypePlatformWrapper
- Follow existing PBAC patterns from event-types-listing-view.tsx
- Maintain backward compatibility with role-based fallback
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: implement proper server-side PBAC permission checks
- Add eventType.create permission checks to TRPC teams.get handler
- Add PBAC permission checks to platform /organizations/{orgId}/teams/me endpoint
- Update all three components to use server-side permission data instead of client-side async calls
- Add canCreateEventTypes property to platform team types
- Maintain backward compatibility with role-based fallbacks
- Remove unused imports and variables
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: update client components to use server-side PBAC permission data
- Update event-types-view.tsx to use team.canCreateEventTypes from server
- Update CreateEventTypeDialog.tsx to use team.canCreateEventTypes with fallback
- Update CreateEventTypePlatformWrapper.tsx to use team.canCreateEventTypes with fallback
- Remove hardcoded permission values and role-based checks
- Maintain backward compatibility with existing role-based logic as fallback
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* apply correct PBAC for event type creation
* revert unexpected changes
* clean up
* address feedback
* fix type error
* clean up
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: replace isTeamAdminOrOwner with PBAC team.listMembers permission
- Add canListMembers prop to BookingsProps interface
- Implement server-side permission check using PermissionCheckService
- Handle organization vs team context as specified
- Use ADMIN/OWNER fallback roles for backward compatibility
- Replace user?.isTeamAdminOrOwner check in bookings column filter
- Fix React Hook dependency arrays for ESLint compliance
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: wrap canListMembers in permissions object and simplify server logic
- Wrap canListMembers in permissions object for future extensibility
- Simplify server-side logic to only use getTeamIdsWithPermission
- Remove unused imports (prisma, MembershipRole)
- Address user feedback on PR #24006
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* docs: add comment explaining canListMembers UI logic
- Clarify that teamIdsWithPermission.length > 0 check is for UI purposes
- Actual accurate filtering happens server-side for filter values
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add e2e test for member filter visibility
- Verify that users with the MEMBER role cannot see the member filter
- Test creates team with ADMIN and MEMBER users
- Confirms UI correctly reflects PBAC permissions
- Address user feedback on PR #24006
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: correct e2e test team member creation pattern
- Replace invalid teamId property with hasTeam and teammates pattern
- Fix TypeScript error in booking-filters.e2e.ts
- Resolve CI type check failure
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix e2e test
* remove booking.read permission from member
* add guide
* update
* resource scope
* fix markdown
* update usage
* update guide
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* feat: add availability and ooo permissions to PBAC registry
- Add Availability and OutOfOffice resources to Resource enum
- Add CRUD permissions for both resources with empty scope arrays
- Create migration to seed admin_role with all CRUD permissions
- Create migration to seed member_role with read-only permissions
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add i18n entries for availability and ooo permissions
- Add pbac_resource_availability and pbac_resource_out_of_office resource names
- Add description entries for all CRUD operations on both resources
- Follow existing PBAC i18n pattern for consistency
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add fallbackRoles parameter to getTeamIdsWithPermissions method
- Add fallbackRoles parameter to method signature in interface and implementation
- Implement second query for teams without PBAC where user has fallback roles
- Combine and deduplicate results from both PBAC-enabled and fallback role teams
- Supports fallback to role-based permissions when PBAC is disabled
- Fix linting issue in getUserMemberships method by replacing include with select
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix usages
* revert some change
* fix unit tests
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: adds user plan info in `useHasPaidPlan` for intercom
* add to support api route
* Update constants.ts
* sql migration to backfill plans and create/change plans on upgrade/downgrade/create of teams and orgs
* fix: breaking unit tests
* test: add comprehensive tests for billing plan service and team/org flows
- Add unit tests for BillingPlanService.getUserPlanByMemberships() covering all plan determination scenarios
- Add tests for team creation handler verifying TEAMS vs ORGANIZATIONS plan assignment
- Add tests for hasTeamPlan handler integration with BillingPlanService
- Add tests for MembershipRepository.findAllMembershipsByUserIdForBilling() data fetching
- Add tests for InternalTeamBilling upgrade/downgrade flows with proper mocking
- All tests follow existing vitest patterns with proper Prisma and service mocking
- Covers both self-serve and platform billing scenarios with comprehensive edge cases
Co-Authored-By: amit@cal.com <samit91848@gmail.com>
* Revert "test: add comprehensive tests for billing plan service and team/org flows"
This reverts commit 58e511f15caf8757c3ec45f6d026caf96ee1a75e.
* fix: make `BillingPlanService` instantiable and use `TeamRepository`
* Revert "fix: make `BillingPlanService` instantiable and use `TeamRepository`"
This reverts commit ae1ff8f15b725566b828864a217d8d0e308b520f.
* revert to runtime calculations. review fixes
* remove uneccessary changes and logs
* review fixes
* review fixes
* fix: type check
---------
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: use kysely types instead of prisma types in atoms
* fixup! chore: use kysely types instead of prisma types in atoms
* fixup! Merge branch 'main' into reduce-atoms-bundle-size-prisma-types
* fix: check if team is platform or not when sending billingPortalUrl
* update team repository
* fix: pass teamId explicitely for platform team
* fix: coderabbit feedback
* fix: merge conflicts
* fix: merge conflicts
* fix: make sure we pass in the correct subsciption id
* fix: implement PR feedback
2025-09-24 20:07:46 +00:00
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Replace prismaMock. mocks with BookingRepository.getTotalBookingDuration mocks
- Update return values from [{ totalMinutes: X }] to X to match repository method signature
- Follow existing repository mocking pattern used in other test files
- All tests pass with the new mocking approach
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: replace isTeamAdminOrOwner with PBAC permissions
- Remove isTeamAdminOrOwner from team-members-view.tsx, rely on server-side permissions
- Replace role checks in addMembersToEventTypes.handler.ts with eventType.update permission
- Follow PBAC refactoring guide patterns for consistent permission checking
- Fix TypeScript any type usage and unused variable warnings
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* use enum
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add BillingCacheService with 1-hour TTL for team subscription data
- Create BillingCacheService following CalendarsCacheService pattern
- Use teamId-based cache keys with 1-hour TTL (3,600,000 ms)
- Integrate caching into getBillingData method in BillingService
- Add cache invalidation to all webhook handlers:
- handleStripeSubscriptionDeleted
- handleStripePaymentSuccess
- handleStripePaymentFailed
- handleStripePaymentPastDue
- handleStripeCheckoutEvents
- Add cache invalidation to cancelTeamSubscription method
- Add RedisModule import to billing module
- Add BillingCacheService to billing module providers
- Add findTeamByPlatformBillingId method to OrganizationsRepository for cache invalidation
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* refactor: implement BillingServiceCachingProxy pattern
- Extract IBillingService interface with all public methods
- Create BillingServiceCachingProxy that implements caching logic
- Remove all caching logic from original BillingService
- Simplify cache invalidation using billing.id = team.id
- Update module to use proxy with proper dependency injection
- Update controller to inject proxy interface
- Remove unused BillingService import from controller
This follows the proxy pattern requested in PR feedback, separating
caching concerns from core billing logic for better maintainability.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* chore: add e2e for billing check
* chore: eslint rule for blocking importing features from appstore, lib, prisma (#23832)
* eslint rule
* improve
* fix
* improve msg
* chore: fix any types set by devin
* fix: add mising expect in test
* refactor: move cache methods into BillingServiceCachingProxy
- Remove BillingCacheService abstraction as suggested by @keithwillcode
- Move cache methods directly into proxy as private methods
- Update proxy to inject RedisService directly
- Move BillingData type to interface for better type safety
- Remove BillingCacheService from module providers
- Delete unused billing-cache.service.ts file
This simplifies the architecture by removing unnecessary abstraction
and follows standard caching proxy patterns.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: test and legacy starter
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: morgan@cal.com <morgan@cal.com>
Co-authored-by: Benny Joo <sldisek783@gmail.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
2025-09-24 07:36:02 -03:00
Eunjae LeeGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: implement PBAC for team member listing
- Replace membership-based team filtering with getTeamIdsWithPermission
- Use team.listMembers permission for access control
- Maintain fallback to original logic when PBAC fails
- Add comprehensive PBAC refactoring guide for future use
Fixes team fetching logic to use Permission-Based Access Control
while preserving existing functionality and privacy checks.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* docs: move PBAC refactoring guide to packages/features/pbac/
Move the PBAC refactoring guide to the appropriate location within
the PBAC feature package for better organization and discoverability.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: remove unnecessary try-catch wrapper
The getTeamIdsWithPermission method already handles all errors internally
and returns an empty array instead of throwing exceptions, making the
try-catch wrapper redundant. Simplified to use direct fallback logic
based on empty array return.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: simplify PBAC implementation
- Remove flawed fallback logic that assumed empty array meant PBAC failure
- Use direct string 'team.listMembers' instead of PermissionMapper
- Remove unused imports (PermissionMapper, Resource, CustomAction)
- Empty array from getTeamIdsWithPermission is legitimate (no permissions)
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* docs: simplify PBAC refactoring guide
- Reduce from 260 to 87 lines by removing bloated content
- Focus on core pattern: direct permission strings, no fallback logic
- Align with actual PR implementation
- Remove verbose theoretical sections and complex patterns
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Fallback to org admin
* Prevent accidental privilege escalation as code changes in the future
* When org admin, we don't actually need to do the db query
* Use findMany and Map to drill down permission adjustments
* Exclude .MEMBER from overriding role, we likely don't want to demote
* refactor logic
* Add tests for services/factories + removeHandler
* fix type check
---------
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Sean Brydon <sean@cal.com>
* feat: add createdAt and updatedAt fields to EventType model
- Add timestamp fields to EventType schema with backward compatibility
- Update all EventType select statements across API v1, v2, and tRPC
- Update platform API output types to include timestamp fields
- Generate migration for existing database records
- Fix test files to handle new timestamp fields properly
The timestamp fields are added as optional (DateTime?) to ensure backward
compatibility - existing EventType records will have null values for these
fields, while new records will automatically get timestamps.
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* fix: remove @default(now()) from EventType createdAt to prevent existing records from getting current timestamp
- Remove @default(now()) from createdAt field in schema to ensure backward compatibility
- Create migration that only drops DEFAULT constraint without updating existing records
- Existing EventType records will keep null timestamps
- New records will get timestamps via application logic
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* feat: add createdAt and updatedAt timestamps to all EventType creation locations
- Update all seed scripts to set timestamps for new EventType records
- Ensure consistency across all EventType creation patterns
- Maintain backward compatibility with nullable timestamp fields
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* feat: add timestamps to remaining EventType creation locations in test files
- Update integration test files to include createdAt and updatedAt
- Ensure consistency across all EventType creation patterns
- Complete comprehensive update of all EventType creation locations
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* add migration
* few left
* feat: implement Prisma extension for automatic EventType timestamps
- Create eventTypeTimestampsExtension to automatically set createdAt and updatedAt
- Handle both eventType.create and eventType.createMany operations
- Revert all manual timestamp setting from application code
- Extension only sets timestamps if not already provided
- Maintains backward compatibility - existing records keep null timestamps
- New records get automatic timestamps via Prisma extension
- Follows existing Cal.com extension patterns and architecture
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* feat: remove hardcoded timestamp settings from test files
- Remove manual createdAt/updatedAt settings from routing forms controller test
- Remove manual timestamp settings from event types repository fixture
- Prisma extension now handles timestamps automatically for all EventType operations
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* update
* Update event-type.output.ts
* fix test
---------
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>