-
Notifications
You must be signed in to change notification settings - Fork 10.2k
feat: enable PBAC checking on organization settings page #22467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✅ No security or compliance issues detected. Reviewed everything up to 3b03b59. Security Overview
Detected Code Changes
Reply to this PR with |
Graphite Automations"Add consumer team as reviewer" took an action on this PR • (07/14/25)1 reviewer was added to this PR based on Keith Williams's automation. "Add foundation team as reviewer" took an action on this PR • (07/14/25)1 reviewer was added to this PR based on Keith Williams's automation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cubic found 2 issues across 25 files. Review them in cubic.dev
React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai
to give specific feedback.
packages/prisma/migrations/20250714075355_add_attributes_pbac_permissions/migration.sql
Show resolved
Hide resolved
packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts
Outdated
Show resolved
Hide resolved
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 2 Skipped Deployments
|
WalkthroughThis change introduces comprehensive, resource-based permission enforcement for organization-related settings and attribute management across the application. It implements a new Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (1)
packages/prisma/migrations/20250714075355_add_attributes_pbac_permissions/migration.sql (1)
4-4
: Use timezone-aware NOW() function for consistent timestamps.Direct usage of NOW() without timezone specification can lead to inconsistent timestamp data across different database environments.
Apply this diff to ensure UTC consistency:
- gen_random_uuid(), 'admin_role', resource, action, NOW() + gen_random_uuid(), 'admin_role', resource, action, NOW() AT TIME ZONE 'UTC'- gen_random_uuid(), 'member_role', resource, action, NOW() + gen_random_uuid(), 'member_role', resource, action, NOW() AT TIME ZONE 'UTC'Also applies to: 17-17
🧹 Nitpick comments (6)
packages/trpc/server/routers/viewer/attributes/toggleActive.handler.ts (2)
20-28
: Consider optimizing the database query for membership role.The current implementation performs a separate database query to fetch the user's membership role, but this information might already be available in the user context or could be fetched more efficiently.
Consider if the membership role is already available in
ctx.user.organization
or if it can be included in the initial user context to avoid the additional database query:- const { role: userOrgRole } = await prisma.membership.findFirst({ - where: { - userId: ctx.user.id, - organizationId: org.id, - }, - select: { - role: true, - }, - }); + const userOrgRole = org.role || await prisma.membership.findFirst({ + where: { + userId: ctx.user.id, + organizationId: org.id, + }, + select: { + role: true, + }, + }).then(result => result?.role);
30-35
: Improve error message clarity and consistency.The error message "You need to be apart of an organization to use this feature" contains a typo and could be more specific about what's missing.
Apply this diff to improve the error message:
- message: "You need to be apart of an organization to use this feature", + message: "You need to be a part of an organization to use this feature",apps/web/public/static/locales/en/common.json (2)
283-286
: Avoid overly-generic translation keys ("confirmation"
)A single, top-level key named
"confirmation"
is extremely generic and is likely to collide with existing or future keys.
Consider renaming it to something more specific, e.g."booking_confirmation_title"
or"confirmation_label"
, to keep the namespace clear and avoid accidental overwrites during i18n merges.
1837-1839
: Keep admin-only helper keys consistentThese three new helper messages follow the pattern of earlier ones (
only_admin_can_manage_sso_org
, etc.) – 👍.
Minor: for readability and translator context, consider adding a trailing period or rewriting to second-person (“Only organization admins or owners can manage …”).
Not blocking.apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/sso/page.tsx (1)
31-41
: Consider checking read permissions as well.The current implementation only checks
canEdit
permission. For consistency and better access control, consider also checkingcanRead
permission to ensure users can at least view the SSO configuration before attempting to edit.- const { canEdit } = await getResourcePermissions({ + 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], }, }, });And update the component prop:
- <OrgSSOView permissions={{ canEdit }} /> + <OrgSSOView permissions={{ canRead, canEdit }} />apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/dsync/page.tsx (1)
31-41
: Consider adding read permission check for consistency.Similar to the SSO page, this only checks
canEdit
. Consider addingcanRead
permission check for consistency with the general page implementation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (27)
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)/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)apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/general/page.tsx
(2 hunks)apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/profile/page.tsx
(2 hunks)apps/web/public/static/locales/en/common.json
(4 hunks)packages/features/ee/dsync/page/team-dsync-view.tsx
(2 hunks)packages/features/ee/organizations/pages/components/DisablePhoneOnlySMSNotificationsSwitch.tsx
(1 hunks)packages/features/ee/organizations/pages/components/LockEventTypeSwitch.tsx
(3 hunks)packages/features/ee/organizations/pages/components/NoSlotsNotificationSwitch.tsx
(1 hunks)packages/features/ee/organizations/pages/settings/attributes/attributes-list-view.tsx
(4 hunks)packages/features/ee/organizations/pages/settings/general.tsx
(5 hunks)packages/features/ee/organizations/pages/settings/privacy.tsx
(1 hunks)packages/features/ee/organizations/pages/settings/profile.tsx
(2 hunks)packages/features/ee/sso/page/orgs-sso-view.tsx
(1 hunks)packages/features/pbac/domain/mappers/PermissionMapper.ts
(1 hunks)packages/features/pbac/domain/types/permission-registry.ts
(2 hunks)packages/features/pbac/infrastructure/mappers/RoleOutputMapper.ts
(2 hunks)packages/features/pbac/lib/__tests__/resource-permissions.test.ts
(1 hunks)packages/features/pbac/lib/resource-permissions.ts
(1 hunks)packages/prisma/migrations/20250714075355_add_attributes_pbac_permissions/migration.sql
(1 hunks)packages/trpc/server/routers/viewer/attributes/create.handler.ts
(2 hunks)packages/trpc/server/routers/viewer/attributes/delete.handler.ts
(2 hunks)packages/trpc/server/routers/viewer/attributes/edit.handler.ts
(2 hunks)packages/trpc/server/routers/viewer/attributes/toggleActive.handler.ts
(2 hunks)packages/trpc/server/routers/viewer/organizations/update.handler.ts
(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
apps/web/public/static/locales/en/common.json (1)
undefined
<retrieved_learning>
Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.201Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.
</retrieved_learning>
🧬 Code Graph Analysis (5)
packages/trpc/server/routers/viewer/attributes/edit.handler.ts (1)
packages/platform/libraries/index.ts (2)
TRPCError
(56-56)MembershipRole
(98-98)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/page.tsx (2)
packages/features/auth/lib/getServerSession.ts (1)
getServerSession
(32-135)packages/platform/libraries/index.ts (1)
MembershipRole
(98-98)
packages/features/pbac/lib/resource-permissions.ts (4)
packages/platform/libraries/index.ts (1)
MembershipRole
(98-98)packages/features/flags/features.repository.ts (1)
FeaturesRepository
(18-252)packages/features/pbac/services/permission-check.service.ts (1)
PermissionCheckService
(13-264)packages/features/pbac/domain/mappers/PermissionMapper.ts (1)
PermissionMapper
(7-120)
packages/trpc/server/routers/viewer/organizations/update.handler.ts (2)
packages/platform/libraries/index.ts (2)
TRPCError
(56-56)MembershipRole
(98-98)scripts/prepare-local-for-delegation-credentials-testing.js (1)
org
(42-44)
packages/features/ee/organizations/pages/settings/attributes/attributes-list-view.tsx (1)
packages/ui/components/dropdown/Dropdown.tsx (5)
Dropdown
(12-12)DropdownMenuTrigger
(15-26)DropdownMenuContent
(34-51)DropdownMenuItem
(63-71)DropdownItem
(161-181)
⏰ Context from checks skipped due to timeout of 90000ms. 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: Security Check
🔇 Additional comments (40)
packages/features/pbac/infrastructure/mappers/RoleOutputMapper.ts (1)
14-14
: Good refactor for static method clarity.Using explicit class name references (
RoleOutputMapper.toDomainPermission
andRoleOutputMapper.toDomain
) instead ofthis
for static methods improves code readability and follows static method best practices.Also applies to: 31-31
packages/trpc/server/routers/viewer/attributes/edit.handler.ts (1)
1-2
: Excellent implementation of PBAC permission checking.The permission checking logic is well-structured:
- Proper membership role validation
- Appropriate use of
getResourcePermissions
utility- Clear fallback roles for backward compatibility
- Specific error messages for unauthorized access
This implementation aligns perfectly with the PBAC framework described in the PR objectives.
Also applies to: 5-5, 23-57
packages/trpc/server/routers/viewer/attributes/delete.handler.ts (1)
1-2
: Consistent and secure permission implementation.The delete handler properly implements the PBAC pattern with:
- Consistent permission checking flow matching other handlers
- Appropriate fallback roles for delete operations (ADMIN, OWNER)
- Proper error handling and user feedback
The implementation maintains security while providing clear authorization feedback.
Also applies to: 4-4, 21-55
packages/features/ee/organizations/pages/components/NoSlotsNotificationSwitch.tsx (1)
9-11
: Good architectural improvement for centralized permission handling.Removing the component-level
isAdminOrOwner
check aligns with the broader PBAC refactor. This centralizes permission logic at higher levels and allows for more granular permission control through the new permission system.Also applies to: 13-13
packages/trpc/server/routers/viewer/attributes/toggleActive.handler.ts (1)
37-54
: PBAC permission check implementation looks solid.The permission checking logic correctly uses the
getResourcePermissions
utility with appropriate fallback roles for admin and owner users. The error handling is appropriate and the permission check aligns with the PR objectives.packages/features/ee/organizations/pages/settings/privacy.tsx (2)
7-7
: Good refactoring to externalize permission logic.The component now properly separates concerns by accepting permissions as props instead of checking roles internally. This aligns well with the centralized PBAC approach.
11-11
: Verify the permission logic combines correctly with invite status.The disabled state logic correctly combines both permission checking and invite status. This ensures that users without edit permissions OR users with pending invites cannot modify the privacy settings.
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/privacy/page.tsx (3)
26-30
: Verify session validation covers all edge cases.The session validation checks for user ID, organization ID, and organization data. This looks comprehensive for preventing unauthorized access.
32-45
: Permission configuration aligns with expected access patterns.The fallback roles configuration correctly implements the expected access pattern:
- All members (MEMBER, ADMIN, OWNER) can read organization privacy settings
- Only admins and owners can update privacy settings
This matches the typical organization permission hierarchy.
47-49
: Appropriate redirect for unauthorized users.The redirect to
/settings/profile
for users without read permissions is appropriate and consistent with the pattern used for missing session data.packages/features/ee/organizations/pages/components/DisablePhoneOnlySMSNotificationsSwitch.tsx (1)
15-15
: Confirmed parent permission guard in general settingsThe
DisablePhoneOnlySMSNotificationsSwitch
is wrapped in apermissions.canEdit && (…)
check in
packages/features/ee/organizations/pages/settings/general.tsx
, ensuring it only renders for authorized users. No further changes needed.packages/features/ee/dsync/page/team-dsync-view.tsx (3)
14-18
: Good defensive programming with optional permissions prop.The permissions prop is correctly defined as optional, which provides flexibility for different usage contexts while maintaining type safety.
45-53
: Excellent user experience for unauthorized access.The implementation handles unauthorized access gracefully by showing a clear message instead of hiding the component entirely. This provides better user experience by explaining why the feature is not available.
45-45
: Secure default for permission checking.Using
permissions?.canEdit ?? false
ensures that the component defaults to the most restrictive state when permissions are not provided, which is a good security practice.packages/features/pbac/domain/mappers/PermissionMapper.ts (1)
49-52
: LGTM! Smart improvement to support hierarchical resource names.The change from left-to-right splitting to right-to-left splitting elegantly handles resource names with dots (like "organization.attributes") while maintaining backward compatibility. The implementation correctly identifies the action as the substring after the last dot, ensuring proper parsing of hierarchical resource structures.
The existing validation logic ensures robustness, and the added comment clearly explains the intent.
apps/web/public/static/locales/en/common.json (2)
868-872
: No duplicate i18n keys found for OAuth clientsI’ve searched for each of the four keys and confirmed they each appear only once in common.json—there are no exact duplicates elsewhere in the file. It’s safe to merge.
• "oauth_clients" (at line 868)
• "oauth_clients_description" (at line 869)
• "create_oauth_client" (at line 870)
• "create_oauth_client_description" (at line 871)
3293-3299
: No duplicate PBAC permission keys detectedI’ve verified that each of the new
pbac_desc_manage_roles
andpbac_desc_*_organization_attributes
entries appears exactly once inapps/web/public/static/locales/en/common.json
. There are no duplicate keys, so no action is needed.apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/profile/page.tsx (2)
31-47
: LGTM! Permission fetching logic is well-structured.The permission fetching implementation follows best practices:
- Uses proper resource type (Resource.Organization)
- Includes appropriate user context (userId, teamId, userRole)
- Defines sensible fallback roles for organization management
- Fetches all necessary CRUD permissions
54-60
: LGTM! Props passing is consistent with the new permission model.The permissions are properly passed to the LegacyPage component, enabling permission-aware rendering throughout the organization profile functionality.
packages/trpc/server/routers/viewer/attributes/create.handler.ts (2)
26-41
: LGTM! Membership role query is efficient and correct.The membership role query properly:
- Targets the correct user-organization relationship
- Uses select to fetch only the required role field
- Includes proper validation for organization membership
43-60
: LGTM! Permission checking implementation is comprehensive.The permission checking logic is well-implemented:
- Uses the correct resource type (Resource.Attributes)
- Includes proper user context and role information
- Defines appropriate fallback roles for create operations
- Provides clear error messages for unauthorized access
packages/features/ee/organizations/pages/settings/profile.tsx (2)
78-86
: LGTM! Props interface is well-defined.The permissions prop interface properly defines the expected permission structure with optional boolean flags for read, edit, and delete operations.
136-177
: LGTM! Conditional rendering logic is appropriate.The conditional rendering properly:
- Shows editable form and appearance settings when canEdit is true
- Displays read-only view with essential information when canEdit is false
- Includes functionality to copy organization link in read-only mode
- Maintains good user experience across permission levels
packages/features/pbac/domain/types/permission-registry.ts (2)
6-6
: LGTM! Resource enum addition follows naming conventions.The new
Attributes
resource with value"organization.attributes"
follows the established pattern and clearly indicates its scope within the organization context.
279-307
: LGTM! Permission registry entry is comprehensive and well-structured.The attributes permission registry entry properly includes:
- Resource internationalization key
- All CRUD operations (Read, Update, Delete, Create)
- Consistent categorization as "attributes"
- Proper internationalization keys for actions and descriptions
- Descriptive permission details
packages/features/ee/sso/page/orgs-sso-view.tsx (3)
10-15
: LGTM! Props interface is properly defined.The
OrgSSOViewProps
interface correctly defines the expected permissions structure with an optionalcanEdit
boolean flag.
22-22
: LGTM! Session loading state fix is necessary.The fix properly returns the
SkeletonLoader
component during session loading, preventing potential rendering issues.
28-39
: LGTM! Conditional rendering logic is appropriate.The conditional rendering properly:
- Extracts canEdit from permissions with sensible default
- Shows SSO configuration when user has edit permissions
- Displays informative message when editing is not allowed
- Maintains good user experience across permission levels
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/general/page.tsx (2)
28-30
: Verify redirect destination consistency.This page redirects to
/settings/profile
while the SSO and dsync pages redirect to/settings/organizations/general
. Please verify if this difference is intentional.
32-49
: Well-implemented permission checks!Good implementation with both read and edit permissions properly configured with appropriate fallback roles for all membership levels.
packages/features/ee/organizations/pages/components/LockEventTypeSwitch.tsx (1)
21-29
: LGTM! Aligns with the new permission model.The removal of
isAdminOrOwner
prop is consistent with the migration to permission-based access control. The parent component now handles permission checks.packages/features/pbac/lib/resource-permissions.ts (2)
78-85
: Good defensive programming with nullish coalescing.The use of
?? false
ensures that undefined permissions default to false, which is the secure default.
71-77
: Error handling confirmed for getResourcePermissionsThe
getResourcePermissions
method is already wrapped in a try–catch that logs errors viathis.logger.error(error)
and returns an empty array on failure, satisfying the original request.• File: packages/features/pbac/services/permission-check.service.ts
• Method: getResourcePermissions (lines ~70–95)No further changes required.
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/(org-admin-only)/attributes/page.tsx (1)
23-61
: Well-implemented server-side permission checks!The implementation properly validates the session, retrieves permissions with appropriate fallback roles, and passes only the necessary permissions to the child component. The redirect logic for unauthorized access is also correctly implemented.
packages/trpc/server/routers/viewer/organizations/update.handler.ts (1)
127-140
: Good implementation of resource-based permissionsThe permission check implementation correctly uses the new
getResourcePermissions
function with appropriate fallback roles, ensuring only owners and admins can update organization settings.packages/features/ee/organizations/pages/settings/attributes/attributes-list-view.tsx (2)
36-133
: Excellent implementation of permission-based UI controlsThe conditional rendering of UI elements based on permissions is well-implemented. The toggle switch, dropdown menu, and individual actions are properly gated, ensuring users only see actions they're authorized to perform.
135-213
: Consistent permission handling throughout the componentThe
OrganizationAttributesPage
component properly accepts and propagates permissions, with create buttons appropriately gated in both list and empty states.packages/features/ee/organizations/pages/settings/general.tsx (2)
42-99
: Clean refactoring to permission-based access controlThe migration from
isAdminOrOwner
to a granularpermissions
object is well-executed. Getting the locale directly from the session is more efficient than a separate query.
151-233
: Proper permission gating in form controlsThe form's disabled state and submit button visibility are correctly controlled by
permissions.canEdit
, ensuring consistent behavior throughout the component.packages/features/pbac/lib/__tests__/resource-permissions.test.ts (1)
1-278
: Comprehensive test coverage for permission systemExcellent test implementation with thorough coverage of:
- PBAC disabled scenarios with fallback roles
- PBAC enabled scenarios with permission service
- Conditional role access
- Edge cases and error handling
The test structure is clean, well-organized, and properly uses mocks for isolation.
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) }); | ||
const t = await getTranslate(); | ||
|
||
if (!session?.user.id || !session?.user.profile?.organizationId || !session?.user.org) { | ||
return redirect("/settings/profile"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix session validation logic.
The session validation check has a logical issue. The redirect happens when the user lacks a valid session, but the check should also ensure the user is properly authenticated and has organization access.
- if (!session?.user.id || !session?.user.profile?.organizationId || !session?.user.org) {
+ if (!session?.user?.id || !session?.user?.profile?.organizationId || !session?.user?.org) {
return redirect("/settings/profile");
}
The optional chaining on session?.user.id
should be session?.user?.id
to properly handle cases where session.user
might be undefined.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) }); | |
const t = await getTranslate(); | |
if (!session?.user.id || !session?.user.profile?.organizationId || !session?.user.org) { | |
return redirect("/settings/profile"); | |
} | |
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) }); | |
const t = await getTranslate(); | |
if (!session?.user?.id || !session?.user?.profile?.organizationId || !session?.user.org) { | |
return redirect("/settings/profile"); | |
} |
🤖 Prompt for AI Agents
In
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/profile/page.tsx
around lines 24 to 29, update the session validation logic to correctly check
for user authentication and organization access. Change the optional chaining
from session?.user.id to session?.user?.id to safely handle cases where
session.user might be undefined. Ensure the condition verifies that session,
session.user, session.user.id, session.user.profile.organizationId, and
session.user.org all exist before proceeding; otherwise, redirect to
"/settings/profile".
packages/trpc/server/routers/viewer/organizations/update.handler.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/public/static/locales/en/common.json
(3 hunks)packages/features/pbac/domain/types/permission-registry.ts
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/features/pbac/domain/types/permission-registry.ts
🧰 Additional context used
🧠 Learnings (1)
apps/web/public/static/locales/en/common.json (2)
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.917Z
Learning: Applies to docs/api-reference/v2/openapi.json : When docs changes are made in /docs/api-reference/v2/openapi.json
, ensure 'summary' fields are short, concise, do not end with a period, and are written in proper American English
Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.
🪛 Biome (2.1.2)
apps/web/public/static/locales/en/common.json
[error] 3311-3311: The key pbac_desc_manage_roles was already declared.
This where a duplicated key was declared again.
If a key is defined multiple times, only the last definition takes effect. Previous definitions are ignored.
(lint/suspicious/noDuplicateObjectKeys)
E2E results are ready! |
There was a problem hiding this 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: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/profile/page.tsx
(2 hunks)packages/features/ee/dsync/page/team-dsync-view.tsx
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/profile/page.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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:
packages/features/ee/dsync/page/team-dsync-view.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:
packages/features/ee/dsync/page/team-dsync-view.tsx
🧠 Learnings (1)
packages/features/ee/dsync/page/team-dsync-view.tsx (1)
Learnt from: Anshumancanrock
PR: #22570
File: apps/web/modules/signup-view.tsx:253-253
Timestamp: 2025-07-21T21:33:23.371Z
Learning: In signup-view.tsx, when checking if redirectUrl contains certain strings, using explicit && checks (redirectUrl && redirectUrl.includes()) is preferred over optional chaining (redirectUrl?.includes()) to ensure the result is always a boolean rather than potentially undefined. This approach provides cleaner boolean contracts for downstream conditional logic.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Detect changes
🔇 Additional comments (1)
packages/features/ee/dsync/page/team-dsync-view.tsx (1)
15-15
: LGTM: Clean prop interface for PBAC integration.The optional
permissions
prop withcanEdit
boolean follows the established pattern for PBAC integration across organization settings components.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice improvements!
* fix: resolve username constraint violation in removeMember - Update username to - format when removing users from organizations - Fix unique constraint violation on (username, organizationId) when organizationId is null - Add test case to verify username format change and successful removal - Fix skipped test by adding proper imports and removing describe.skip Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * test: update removeMember test to verify constraint violation scenario - Create two users with same username (one with null orgId, one with orgId) - Verify removing org user updates username without unique constraint error - Test ensures username gets updated to - format Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * test: add comprehensive unit tests for handleInstantMeeting - Revert previous removeMember changes - Add full test coverage for instant meeting functionality - Test team validation, booking creation, token generation - Test webhook triggers and browser notifications - Mock external dependencies for isolated unit tests - Translation issue to be addressed in future iteration Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * update * Update handleInstantMeeting.test.ts * fix: redir parameter for connect atoms (#22815) * encode redirect url to make sure it has all parameters * add changesets * feat: Support an array response for a field when used as `Value of Field` (#22740) * Passing tests and fixed * self review addressed adn more tests * fix: flaky e2e (#22819) * fix: merge working hours when adjacent (#21912) * fix: Adjacency issue when working hours connect over multiple days * Add tests to validate the new merging of day end logic * Update to correct annotation. Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Implement subsequent date ranges for date overrides also * The map needs to be updated on successful resolve. * test: add failing test for overlapping ranges with same end time Demonstrates bug where overlapping working hour ranges (6:00-10:00 and 8:00-10:00) lose the earlier portion (6:00-8:00), showing only 8:00 and 9:00 slots instead of all 4 slots (6:00, 7:00, 8:00, 9:00). Related to Carina's comment on PR #21912. Co-Authored-By: alex@cal.com <me@alexvanandel.com> * fix: properly merge overlapping ranges with same end time Fixes bug where overlapping working hour ranges with the same end time (e.g., 6:00-10:00 and 8:00-10:00) would lose the earlier portion of the first range. The merging logic now correctly preserves the earliest start time when ranges overlap and share the same end time. This ensures all expected time slots are available (6:00, 7:00, 8:00, 9:00) instead of losing the earlier slots (6:00, 7:00). Resolves the issue identified in Carina's comment on PR #21912. Co-Authored-By: alex@cal.com <me@alexvanandel.com> * perf: optimize overlapping range detection from O(n²) to O(n) Replaces Object.keys().find() with Map-based lookup for ranges with same end time. This optimization handles 2000+ date ranges efficiently, reducing complexity from 4M operations to linear time while maintaining the same merging behavior. Performance improvement for high-volume event types with many availability ranges. Co-Authored-By: alex@cal.com <me@alexvanandel.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> * feat: Improving Booking Visibility at Month-End (#22770) * remove first weeks and add last * fix added last week * prefetch availability of next month * don't switch month * On hover show month * only show new UI in monthly view * show month tooldtip only when needed * show month on first day of month * remove isFirstDayOfNextMonth * fix prefetching next month * fix datePicker tests * preventMonthSwitching in monthly view * add tests * code clean up * code clean up * code clena up for ooo days * push first day of month * remove bg color for the month badge * fix text colour * remove not needed * use object param * revert: use object param * use object param * fix DatePicker tests --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Sean Brydon <sean@cal.com> Co-authored-by: Eunjae Lee <hey@eunjae.dev> * chore: Refactor logs (#22824) * Refactor logs * Add specific info to log * fix: Errors in org onboarding in some edge cases (#22711) * Automatically enable migration of a team that conflicts with Orgs slug * Allow changing the orgs slug and name if user goes back and changes it * avoid crashing on some scenarios * Revert "Allow changing the orgs slug and name if user goes back and changes it" This reverts commit f8872b0. * fix: handle unpublished teams gracefully in org migration - Change 'No oldSlug for team' from error to warning for unpublished teams - Keep 'No slug for team' as error since org onboarding ensures teams have names - Add test for migrating unpublished teams without oldSlug - Add clarifying comments about when each condition can occur * feat: enable PBAC checking on organization settings page (#22467) * refactor: convert checkBookingLimits to class service with dependency injection (#22768) * refactor: convert checkBookingLimits to class service with dependency injection - Create CheckBookingLimitsService class following AvailableSlotsService pattern - Add countBookingsByEventTypeAndDateRange method to BookingRepository - Move direct prisma calls from service to repository layer - Implement dependency injection with proper DI tokens and modules - Update all usage points to use the new service through DI - Maintain backward compatibility with error-throwing wrapper functions - Update tests to use the new service pattern - Resolve TODO comment in AvailableSlotsService for DI integration Co-Authored-By: morgan@cal.com <morgan@cal.com> * chore: DI CheckBookingLimitsService in v2 slots service * chore: bump libraries * chore: create getCheckBookingLimitsService * refactor: convert checkBookingAndDurationLimits to service class with DI - Create CheckBookingAndDurationLimitsService class following DI pattern - Add DI tokens and module for the new service - Update booking-limits container to provide the new service - Refactor handleNewBooking.ts to use service through DI - Maintain backward compatibility with deprecated function export - Preserve all existing functionality while improving code organization Co-Authored-By: morgan@cal.com <morgan@cal.com> * chore: CheckBookingAndDurationLimitsService * chore: bump platform libs --------- 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: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> * fix: Return empty available days if error querying calendar (#22828) * Return a busy block placeholder if calendar throws an error * Refactor `getCalendarsEvents` to return an object with a success prop * Throw error in `getBusyTimes` if failed to fetch calendar availability * Return empty available days if error getting busy times * yeet. * Type fix * Fix type error in getLuckyUsers * Type fixes * Type fix * Type fix * Fix test * Fix test mocks * Refactor calendars.service to use new calendarBusyTimesQuery --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> * chore: release v5.5.9 * include mobile layout (#22836) Co-authored-by: CarinaWolli <wollencarina@gmail.com> * test: fix handleInstantMeeting test with setupAndTeardown and proper mocking - Add setupAndTeardown() for proper test environment setup - Use mockNoTranslations() to fix translation function mocking - Simplify NextApiRequest mock to resolve TypeScript errors - Both test cases now pass successfully Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * fix typo --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Sean Brydon <sean@cal.com> Co-authored-by: Eunjae Lee <hey@eunjae.dev> Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com> Co-authored-by: morgan@cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Overview
This PR implements comprehensive Permission-Based Access Control (PBAC) for organization
settings pages, replacing basic role-based authorization with a more granular permission
system. The implementation includes proper fallback mechanisms for when PBAC is disabled
via feature flags.
Changes Made
🔧 Core Infrastructure
(packages/features/pbac/lib/tests/resource-permissions.test.ts) - 283 lines of tests
covering all scenarios
🎯 Frontend Permission Integration
Updated all organization settings pages to use PBAC:
Pages Updated:
Permission Matrix
When PBAC is ENABLED (Feature Flag ON)
Permissions are determined by the user's assigned roles and the organization's PBAC
configuration.
When PBAC is DISABLED (Feature Flag OFF - Fallback Mode)
🟧 - Users have some access to reads.
How to Test
🧪 Testing PBAC Enabled
INSERT INTO "TeamFeatures" ("teamId", "featureId", "assignedBy", "assignedAt", "updatedAt") VALUES (7, 'pbac', 'WHOAREYOU', '2025-07-14 09:03:52.825', '2025-07-14 09:03:52.825');
🧪 Testing PBAC Disabled (Fallback)