Conversation
WalkthroughThis PR integrates PBAC across event types and workflows. It introduces server-side permission checks via PermissionCheckService/getResourcePermissions, a createEventPbacProcedure wrapper for TRPC mutations, and new use cases/utilities (TeamAccessUseCase, EventGroupBuilder, ProfilePermissionProcessor, filter/permission/transform utils). Event type routers (delete/update/duplicate) now use PBAC, and handlers for event types/workflows enforce read/create/update permissions with role fallbacks. Frontend adds an EventPermissionProvider, permission hooks/guards, and gates UI (workflows tab, actions) by permissions. Settings permission UI switches to scope-aware registries. Tests added for new utilities and handlers. No public API shape changes except minor prop additions/defaults and a context type inclusion. Possibly related PRs
Pre-merge checks (3 passed)✅ Passed checks (3 passed)
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. 📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ 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. Comment |
|
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: |
|
✅ No security or compliance issues detected. Reviewed everything up to 1bfed57. Security Overview
Detected Code Changes
Reply to this PR with |
a1d62f0 to
a4a0da4
Compare
* feat: add PBAC permission checks to insights - Add layout-level protection for insights pages with session.user.org.id check - Add API-level protection for insights tRPC endpoints using insightsPbacProcedure - Enhance routing form insights with PBAC team filtering - Use insights.read permission with OWNER/ADMIN fallback roles - Replace all userBelongsToTeamProcedure with insightsPbacProcedure in insights router - Fix lint issues: remove unused variables and functions, fix non-null assertion Implements Permission-Based Access Control (PBAC) for insights functionality following the same patterns as event type PBAC implementation from PR #22618. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: clean up unused imports in routing-forms - Remove unused isFormCreateEditAllowed import - Remove unused TRPCError import - Change MembershipRole to type import for better tree-shaking Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * address feedback * clean up permission check * revert unnecessary changes * fix procedure * allow MEMBER for insights * support teams not under orgs * fix type error * revert unnecessary changes --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| for (const membership of memberships) { | ||
| const orgMembership = teamMemberships.find( | ||
| (teamM) => teamM.teamId === membership.team.parentId | ||
| )?.membershipRole; | ||
|
|
||
| const effectiveRole = getEffectiveRole(orgMembership, membership.role); | ||
| const permissions = await getTeamPermissions(userId, membership.team.id, effectiveRole); | ||
|
|
||
| permissionsMap.set(membership.team.id, permissions); | ||
| } |
There was a problem hiding this comment.
I think would be good to parallelize this promises..
// pseudo - not tested
await Promise.all(
memberships.map(async (membership) => {
const orgMembership = orgRoleByTeamId.get(m.team.parentId) ?? 'member';
const effectiveRole = getEffectiveRole(orgMembership, membership.role);
const permissions = await getTeamPermissions(userId, membership.team.id, effectiveRole);
return [m.team.id, permissions] as const;
})| // Fallback: allow admin and owner roles | ||
| return profile.membershipRole === "ADMIN" || profile.membershipRole === "OWNER"; |
There was a problem hiding this comment.
All this "ADMIN"s and "OWNER"s I think would be good to live in a constants file.
|
|
||
| // System admins and users with org-level eventType.create permission can always create event types | ||
| if (!isSystemAdmin && !hasOrgEventTypeCreatePermission && !hasCreatePermission) { | ||
| console.warn(`User ${userId} does not have eventType.create permission for team ${teamId}`); |
packages/trpc/server/routers/viewer/eventTypes/heavy/create.handler.ts
Outdated
Show resolved
Hide resolved
volnei
left a comment
There was a problem hiding this comment.
Nit comments, other than that, looks great!
| }); | ||
|
|
||
| if (!hasMembership) { | ||
| console.warn(`User ${userId} is not a member of team ${teamId}`); |
There was a problem hiding this comment.
Can you remove this console?
| throw new TRPCError({ code: "UNAUTHORIZED" }); | ||
| } | ||
|
|
||
| const isSystemAdmin = ctx.user.role === "ADMIN"; |
There was a problem hiding this comment.
Do we have constants for roles?
| `PBAC check failed for user ${userId} on team ${teamId}, falling back to role check:`, | ||
| error | ||
| ); | ||
| hasCreatePermission = ["ADMIN", "OWNER"].includes(hasMembership.role); |
There was a problem hiding this comment.
Do we have constants for permissions?
| userId, | ||
| teamId: membership.team.id, | ||
| permission: "eventType.read", | ||
| fallbackRoles: ["ADMIN", "OWNER", "MEMBER"], // All roles can read event types by default |
There was a problem hiding this comment.
Can we use Membership constants here?
Will address these in a follow up! Lets get this merged |
Seed your database by "yarn seed-pbac"
Look at the roles created in orgs/teams roles and permissions in settings.
Create new roles/edit old ones to remove all permission from event type - assign it to a user.
Impersonate the user and try to CRUD an event type.
Tick on permissions in the role and keep testing the event type.
Impersonate a team without pbac enabled and ensure everything works as expected