Skip to content

Comments

feat: pbac - org pages check update permissions#24164

Merged
hbjORbj merged 6 commits intomainfrom
chore/check-pbac-permision-org-pages
Oct 2, 2025
Merged

feat: pbac - org pages check update permissions#24164
hbjORbj merged 6 commits intomainfrom
chore/check-pbac-permision-org-pages

Conversation

@sean-brydon
Copy link
Member

What does this PR do?

This PR allows members who have been upgraded to a custom role (user.role stays as Member) to access organization resources with the PBAC permission. Perviously we still were checking for apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrgAdmin.tsx hasOrgAdmin.

This is the edgecasae when you enable PBAC on current org (not new org) and users who are members get made into a cus

How should this be tested?

Enable PBAC on an org.
Manually update a customrole_id of a memebrship to admin_role -> Leave role as "member"
navigate around the organisation settings and veirfy you can view the pages

Checklist

  • I haven't read the contributing guide
  • 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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 30, 2025

Walkthrough

This PR replaces organization admin-only guards with general organization or permission-based validation across several organization settings pages. Calls to validateUserHasOrgAdmin were switched to either validateUserHasOrg or validateUserHasOrgPerms. validateUserHasOrgPerms is invoked with explicit permission strings (e.g., "organization.attributes.create", "organization.attributes.update", "organization.update") and fallbackRoles [MembershipRole.OWNER, MembershipRole.ADMIN]; MembershipRole is imported from @calcom/prisma/enums where used. Import paths and call-site signatures were updated accordingly; page/component exports and metadata generation were not changed.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title loosely references the shift to PBAC-based permission checks on organization pages but is phrased awkwardly and lacks clarity on the exact change; it reads more like fragments than a concise sentence and could be misunderstood by someone skimming the changelog. Consider rewording the title to clearly state the main change, for example: “feat: switch org settings pages to PBAC permission checks,” so that it reads as a concise, self-contained sentence summarizing the update.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed The description directly explains the problem being solved—enabling PBAC permissions for members with custom roles—and outlines testing steps, matching the code changes that replace admin-only checks with permission guards.
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 chore/check-pbac-permision-org-pages

📜 Recent 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 d548aea and 8308bab.

📒 Files selected for processing (1)
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/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)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/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)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/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)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/page.tsx
🧬 Code graph analysis (1)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/page.tsx (2)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrgPerms.tsx (1)
  • validateUserHasOrgPerms (9-34)
packages/platform/libraries/index.ts (1)
  • MembershipRole (34-34)
🔇 Additional comments (3)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/page.tsx (3)

5-5: LGTM! Missing import resolved.

The MembershipRole import has been added, addressing the critical issue flagged in the previous review.


7-7: LGTM! Import updated for permission-based validation.

The import has been correctly updated from validateUserHasOrgAdmin to validateUserHasOrgPerms, supporting the PBAC permission model as intended by this PR.


21-24: Confirm permission string granularity for delegation credentials.

The call to validateUserHasOrgPerms with "organization.update" and the existing fallbackRoles is correct, but please verify that the generic "organization.update" permission is intended for delegation credential management. If finer-grained control is required, define a new permission (e.g. "organization.delegation.update"), update the permission registry and tests accordingly, and replace the string here.


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.

@graphite-app graphite-app bot requested a review from a team September 30, 2025 09:39
@keithwillcode keithwillcode added consumer core area: core, team members only labels Sep 30, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Sep 30, 2025

Hey there and thank you for opening this pull request! 👋🏼

We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted.

Details:

Unknown release type "feaat" found in pull request title "feaat: pbac - org pages check update permissions". 

Available types:
 - feat: A new feature
 - fix: A bug fix
 - docs: Documentation only changes
 - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
 - refactor: A code change that neither fixes a bug nor adds a feature
 - perf: A code change that improves performance
 - test: Adding missing tests or correcting existing tests
 - build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
 - ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
 - chore: Other changes that don't modify src or test files
 - revert: Reverts a previous commit

Comment on lines 29 to 39
const { canEdit } = await getResourcePermissions({
userId: session.user.id,
teamId: session.user.profile.organizationId,
resource: Resource.Organization,
userRole: session.user.org.role,
fallbackRoles: {
update: {
roles: [MembershipRole.ADMIN, MembershipRole.OWNER],
},
},
});
Copy link
Member Author

Choose a reason for hiding this comment

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

Permission check happens here

Comment on lines 30 to 43
const { canRead, canEdit } = await getResourcePermissions({
userId: session.user.id,
teamId: session.user.profile.organizationId,
resource: Resource.Organization,
userRole: session.user.org.role,
fallbackRoles: {
read: {
roles: [MembershipRole.MEMBER, MembershipRole.ADMIN, MembershipRole.OWNER],
},
update: {
roles: [MembershipRole.ADMIN, MembershipRole.OWNER],
},
},
});
Copy link
Member Author

Choose a reason for hiding this comment

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

Permission check happens here

Comment on lines 24 to 34
const { canEdit } = await getResourcePermissions({
userId: session.user.id,
teamId: session.user.profile.organizationId,
resource: Resource.Organization,
userRole: session.user.org.role,
fallbackRoles: {
update: {
roles: [MembershipRole.ADMIN, MembershipRole.OWNER],
},
},
});
Copy link
Member Author

Choose a reason for hiding this comment

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

Permission check happens here

Comment on lines 25 to 44
const { canRead, canEdit, canDelete, canCreate } = await getResourcePermissions({
userId: session.user.id,
teamId: session.user.profile.organizationId,
resource: Resource.Attributes,
userRole: session.user.org.role,
fallbackRoles: {
read: {
roles: [MembershipRole.MEMBER, MembershipRole.ADMIN, MembershipRole.OWNER],
},
update: {
roles: [MembershipRole.ADMIN, MembershipRole.OWNER],
},
delete: {
roles: [MembershipRole.ADMIN, MembershipRole.OWNER],
},
create: {
roles: [MembershipRole.ADMIN, MembershipRole.OWNER],
},
},
});
Copy link
Member Author

Choose a reason for hiding this comment

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

Permission check happens here

@vercel
Copy link

vercel bot commented Sep 30, 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 Oct 1, 2025 7:15am
cal-eu Ignored Ignored Oct 1, 2025 7:15am

hbjORbj
hbjORbj previously approved these changes Sep 30, 2025
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

🧹 Nitpick comments (2)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/privacy/page.tsx (1)

26-28: Redundant validation after validateUserHasOrg.

The validateUserHasOrg function (line 24) already validates these exact conditions and redirects if they fail. This additional check is unnecessary and adds maintenance overhead.

Apply this diff to remove the redundant validation:

  const session = await validateUserHasOrg();

- if (!session?.user.id || !session?.user.profile?.organizationId || !session?.user.org) {
-   return redirect("/settings/profile");
- }
-
  const { canRead, canEdit } = await getResourcePermissions({
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/sso/page.tsx (1)

25-27: Redundant validation after validateUserHasOrg.

The validateUserHasOrg function (line 23) already validates these conditions and redirects if they fail. This additional check is unnecessary.

Apply this diff to remove the redundant validation:

  const session = await validateUserHasOrg();

- if (!session?.user.id || !session?.user.profile?.organizationId || !session?.user.org) {
-   return redirect("/settings/organizations/general");
- }
-
  const { canEdit } = await getResourcePermissions({
📜 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 2ef627b and d548aea.

📒 Files selected for processing (7)
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/[id]/edit/page.tsx (2 hunks)
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/create/page.tsx (2 hunks)
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/page.tsx (2 hunks)
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/page.tsx (2 hunks)
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/dsync/page.tsx (2 hunks)
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/privacy/page.tsx (2 hunks)
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/sso/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)/settings/(settings-layout)/organizations/(org-admin-only)/privacy/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/dsync/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/create/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/sso/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/[id]/edit/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/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)/settings/(settings-layout)/organizations/(org-admin-only)/privacy/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/dsync/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/create/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/sso/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/[id]/edit/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/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)/settings/(settings-layout)/organizations/(org-admin-only)/privacy/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/dsync/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/create/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/sso/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/[id]/edit/page.tsx
  • apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/page.tsx
🧬 Code graph analysis (7)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/privacy/page.tsx (2)
packages/features/auth/lib/next-auth-options.ts (1)
  • session (746-771)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrg.tsx (1)
  • validateUserHasOrg (19-30)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/page.tsx (2)
packages/features/auth/lib/next-auth-options.ts (1)
  • session (746-771)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrg.tsx (1)
  • validateUserHasOrg (19-30)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/dsync/page.tsx (2)
packages/features/auth/lib/next-auth-options.ts (1)
  • session (746-771)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrg.tsx (1)
  • validateUserHasOrg (19-30)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/create/page.tsx (2)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrgPerms.tsx (1)
  • validateUserHasOrgPerms (9-34)
packages/platform/libraries/index.ts (1)
  • MembershipRole (34-34)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/sso/page.tsx (2)
packages/features/auth/lib/next-auth-options.ts (1)
  • session (746-771)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrg.tsx (1)
  • validateUserHasOrg (19-30)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/[id]/edit/page.tsx (2)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrgPerms.tsx (1)
  • validateUserHasOrgPerms (9-34)
packages/platform/libraries/index.ts (1)
  • MembershipRole (34-34)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/page.tsx (2)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/actions/validateUserHasOrgPerms.tsx (1)
  • validateUserHasOrgPerms (9-34)
packages/platform/libraries/index.ts (1)
  • MembershipRole (34-34)
⏰ 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: Codacy Static Code Analysis
🔇 Additional comments (10)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/privacy/page.tsx (2)

10-10: LGTM! Permission check successfully migrated to PBAC model.

The change from validateUserHasOrgAdmin to validateUserHasOrg correctly enables PBAC-based access control, allowing members with custom admin roles to access this page.

Also applies to: 24-24


30-43: Permission model correctly implements read/write separation.

The fallback roles appropriately allow all members to read privacy settings while restricting updates to admins and owners, aligning with the PR's PBAC objectives.

apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/[id]/edit/page.tsx (1)

4-4: LGTM! Correctly migrated to permission-based validation.

The change to validateUserHasOrgPerms with explicit permission "organization.attributes.update" and fallback roles [OWNER, ADMIN] properly restricts attribute editing to authorized users while enabling PBAC for custom roles.

Also applies to: 6-6, 18-21

apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/create/page.tsx (1)

4-4: LGTM! Permission-based validation correctly implemented.

The migration to validateUserHasOrgPerms with permission "organization.attributes.create" and fallback roles [OWNER, ADMIN] maintains appropriate access control while enabling PBAC support for custom roles.

Also applies to: 6-6, 18-21

apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/sso/page.tsx (2)

10-10: LGTM! Permission check migrated to PBAC model.

The change from validateUserHasOrgAdmin to validateUserHasOrg correctly enables PBAC-based access control for SSO configuration.

Also applies to: 23-23


29-39: Permission model appropriately restricts SSO configuration.

The update permission with fallback roles [ADMIN, OWNER] correctly limits SSO configuration changes to authorized administrators, aligning with security best practices.

apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/dsync/page.tsx (2)

9-9: LGTM! Permission check migrated to PBAC model.

The change from validateUserHasOrgAdmin to validateUserHasOrg correctly enables PBAC-based access control for directory sync configuration.

Also applies to: 22-22


24-34: Permission model appropriately restricts directory sync configuration.

The update permission with fallback roles [ADMIN, OWNER] correctly limits directory sync changes to authorized administrators. The implementation cleanly avoids redundant validation checks present in other files.

apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/page.tsx (1)

10-10: LGTM! Permission model correctly updated.

The change from validateUserHasOrgAdmin to validateUserHasOrg enables the PBAC flow described in the PR objectives. Users with custom roles (where role="Member" but custom_role_id is set to an admin role) will now pass the initial organization check, and the actual authorization is properly enforced via getResourcePermissions with the fallbackRoles configuration on lines 25-44.

Also applies to: 23-23

apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/delegation-credential/page.tsx (1)

6-6: Permissions are consistent across org-admin pages.
Each validateUserHasOrgPerms call uses a page-specific permission string with the same fallback roles (MembershipRole.OWNER, MembershipRole.ADMIN), so no changes needed.

@hbjORbj hbjORbj changed the title feaat: pbac - org pages check update permissions feat: pbac - org pages check update permissions Oct 1, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Oct 1, 2025

E2E results are ready!

@hbjORbj hbjORbj merged commit 858d525 into main Oct 2, 2025
84 of 87 checks passed
@hbjORbj hbjORbj deleted the chore/check-pbac-permision-org-pages branch October 2, 2025 11:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

consumer core area: core, team members only ready-for-e2e size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants