Skip to content

Comments

refactor: replace checkAdminOrOwner with PBAC availability.read permission#24115

Merged
sean-brydon merged 2 commits intomainfrom
devin/availability-read-permission-1758898720
Sep 29, 2025
Merged

refactor: replace checkAdminOrOwner with PBAC availability.read permission#24115
sean-brydon merged 2 commits intomainfrom
devin/availability-read-permission-1758898720

Conversation

@eunjae-lee
Copy link
Contributor

What does this PR do?

Refactors the availability page to replace role-based permission checking (checkAdminOrOwner) with Cal.com's Permission-Based Access Control (PBAC) system using the availability.read permission. This change aligns with the ongoing PBAC migration initiative.

Key Changes:

  • Replaces checkAdminOrOwner(session?.user?.org?.role) with PermissionCheckService.getTeamIdsWithPermission()
  • Uses availability.read permission with OWNER and ADMIN fallback roles
  • Maintains existing organization privacy logic (|| !isOrgPrivate)
  • Follows established PBAC pattern from bookings implementation

Context: This addresses a Slack request from @eunjae-lee to migrate away from checkAdminOrOwner usage in favor of PBAC's availability.read permission.

How should this be tested?

⚠️ Critical: This change affects access control logic and requires thorough testing with different user types:

  1. Organization Admin/Owner: Should be able to view team availability toggle and access team availability page
  2. Organization Member: Should only see team availability if organization is not private
  3. Team Admin/Owner: Should be able to view team availability for their teams
  4. Team Member: Should not see team availability toggle (unless org is public)
  5. Non-member: Should not have any team availability access

Test scenarios:

  • Navigate to /availability with different user roles
  • Verify "Team Availability" toggle appears/disappears correctly
  • Verify team availability page loads when ?type=team is selected
  • Test in both private and public organizations

Visual Demo

No UI changes expected - this is a backend permission logic change that should preserve existing behavior.

Mandatory Tasks

  • I have self-reviewed the code
  • I have updated the developer docs if needed (N/A - internal refactor)
  • I confirm automated tests are in place that prove my fix is effective or that my feature works

⚠️ Critical Review Areas

Security & Access Control:

  • Verify permission check behavior is equivalent to original checkAdminOrOwner logic
  • Confirm availability.read is the correct permission string for this use case
  • Validate fallback roles (OWNER, ADMIN) match original admin/owner scope
  • Test null safety: original code had session?.user?.org?.role optional chaining vs new session.user.id

Behavioral Verification:

  • Ensure no legitimate users lose access to team availability features
  • Verify organization privacy logic (|| !isOrgPrivate) still works correctly
  • Confirm team-level permissions don't inadvertently grant broader access than org-level roles

Link to Devin run: https://app.devin.ai/sessions/42aa58f552d247148068f19b884b63b1
Requested by: @eunjae-lee via Slack

…ssion

- Replace role-based check with PermissionCheckService
- Use availability.read permission with OWNER/ADMIN fallback roles
- Maintain existing privacy logic for organizations
- Follow established PBAC pattern from bookings implementation

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 26, 2025

Walkthrough

Replaces admin/owner role checks with a permission-based guard using PermissionCheckService for the "availability.read" permission. Computes team access by retrieving team IDs with that permission, with a fallback to OWNER/ADMIN roles. Updates canViewTeamAvailability to depend on the presence of permitted team IDs and the organization privacy state. Applies this logic to the main availability page and the team availability toggle, enabling team visibility when the user has the required permission and the org is not private. No exported/public API changes.

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly captures the pull request’s main change by indicating the replacement of role-based admin/owner checks with the PBAC availability.read permission. It directly relates to the core refactor and avoids unnecessary detail or noise.
Description Check ✅ Passed The pull request description clearly explains the context and rationale for migrating from checkAdminOrOwner to PBAC using the availability.read permission, including key changes, testing instructions, and critical review points. It is directly related to the code modifications described in the changeset and provides relevant details for reviewers without being off-topic.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/availability-read-permission-1758898720

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@keithwillcode keithwillcode added consumer core area: core, team members only labels Sep 26, 2025
@eunjae-lee eunjae-lee marked this pull request as ready for review September 26, 2025 15:36
@graphite-app graphite-app bot requested a review from a team September 26, 2025 15:36
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between d261a23 and 6626ff0.

📒 Files selected for processing (1)
  • apps/web/app/(use-page-wrapper)/(main-nav)/availability/page.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • apps/web/app/(use-page-wrapper)/(main-nav)/availability/page.tsx
**/*.{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:

  • apps/web/app/(use-page-wrapper)/(main-nav)/availability/page.tsx
**/*.{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:

  • apps/web/app/(use-page-wrapper)/(main-nav)/availability/page.tsx
🧠 Learnings (4)
📓 Common learnings
Learnt from: ShashwatPS
PR: calcom/cal.com#23638
File: packages/trpc/server/routers/viewer/calendars/setDestinationReminder.handler.test.ts:198-199
Timestamp: 2025-09-06T11:00:34.372Z
Learning: In calcom/cal.com PR #23638, the maintainer ShashwatPS determined that authorization checks in the setDestinationReminder handler are "not applicable" when CodeRabbit suggested adding user-scoped WHERE clauses to prevent users from modifying other users' destination calendar reminder settings.
Learnt from: eunjae-lee
PR: calcom/cal.com#24006
File: apps/web/app/(use-page-wrapper)/(main-nav)/bookings/[status]/page.tsx:37-48
Timestamp: 2025-09-24T11:53:40.185Z
Learning: In bookings listing views, when checking permissions for the member filter UI, use "booking.read" permission rather than "team.listMembers" because the filter's purpose is to read bookings of other team members, not just to list the members themselves. The permission check should align with the actual capability being granted.
📚 Learning: 2025-08-20T17:36:46.521Z
Learnt from: mdm317
PR: calcom/cal.com#23221
File: packages/features/schedules/components/NewScheduleButton.tsx:35-35
Timestamp: 2025-08-20T17:36:46.521Z
Learning: PR #20804 "perf: server-side fetching for /availability" moved availability data fetching from TRPC to server-side in the Cal.com codebase. This means TRPC cache updates like `utils.viewer.availability.list.setData()` have no effect on the availability page, making server actions like `revalidateAvailabilityList()` necessary for proper cache invalidation.

Applied to files:

  • apps/web/app/(use-page-wrapper)/(main-nav)/availability/page.tsx
📚 Learning: 2025-08-20T17:34:35.004Z
Learnt from: mdm317
PR: calcom/cal.com#23221
File: packages/features/schedules/components/NewScheduleButton.tsx:1-1
Timestamp: 2025-08-20T17:34:35.004Z
Learning: In the Cal.com codebase, server actions like `revalidateAvailabilityList()` from `app/(use-page-wrapper)/(main-nav)/availability/actions` are imported and called directly in client components within mutation `onSuccess` callbacks. This pattern is consistently used across availability-related components (both in availability-view.tsx for updates and NewScheduleButton.tsx for creates) to ensure the availability list cache is fresh after mutations.

Applied to files:

  • apps/web/app/(use-page-wrapper)/(main-nav)/availability/page.tsx
📚 Learning: 2025-09-24T11:53:40.185Z
Learnt from: eunjae-lee
PR: calcom/cal.com#24006
File: apps/web/app/(use-page-wrapper)/(main-nav)/bookings/[status]/page.tsx:37-48
Timestamp: 2025-09-24T11:53:40.185Z
Learning: In bookings listing views, when checking permissions for the member filter UI, use "booking.read" permission rather than "team.listMembers" because the filter's purpose is to read bookings of other team members, not just to list the members themselves. The permission check should align with the actual capability being granted.

Applied to files:

  • apps/web/app/(use-page-wrapper)/(main-nav)/availability/page.tsx
🧬 Code graph analysis (1)
apps/web/app/(use-page-wrapper)/(main-nav)/availability/page.tsx (2)
packages/features/pbac/services/permission-check.service.ts (1)
  • PermissionCheckService (19-306)
packages/features/auth/lib/next-auth-options.ts (1)
  • session (746-771)
⏰ 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)
  • GitHub Check: Install dependencies / Yarn install & cache
  • GitHub Check: Detect changes

@sean-brydon sean-brydon enabled auto-merge (squash) September 29, 2025 07:27
@vercel
Copy link

vercel bot commented Sep 29, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Sep 29, 2025 7:27am
cal-eu Ignored Ignored Sep 29, 2025 7:27am

@sean-brydon sean-brydon merged commit b7cf893 into main Sep 29, 2025
35 checks passed
@sean-brydon sean-brydon deleted the devin/availability-read-permission-1758898720 branch September 29, 2025 07:59
@github-actions
Copy link
Contributor

E2E results are ready!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants