## What does this PR do? This PR implements attributes PBAC - router checks + UI ## Visual Demo (For contributors especially) A visual demonstration is strongly recommended, for both the original and new change **(video / image - any one)**. #### Video Demo (if applicable): - Show screen recordings of the issue or feature. - Demonstrate how to reproduce the issue, the behavior before and after the change. #### Image Demo (if applicable): - Add side-by-side screenshots of the original and updated change. - Highlight any significant change(s). ## Mandatory Tasks (DO NOT REMOVE) - [ ] I have self-reviewed the code (A decent size PR without self-review might be rejected). - [ ] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). If N/A, write N/A here and check the checkbox. - [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works. ## How should this be tested? Enable PBAC on an org Create a custom role -> advanced -> organizations -> "editUser" Assign it to a user impersonate user test they have access to all things attributes remove permissions check they dont have permissions. ## Checklist <!-- Remove bullet points below that don't apply to you --> - I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md) - 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 <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds a new PBAC “editUsers” permission and read gating for Attributes, updating the UI and backend so users can view and edit attributes only when allowed. - **New Features** - Added CustomAction.EditUsers to the permission registry for organization-scoped attribute editing. - Settings computes canViewAttributes and shows the Attributes tab only when allowed. - Members page fetches Attributes permissions and exposes canViewAttributes and canEditAttributesForUser to the UI. - User Edit Sheet hides attributes without read permission and shows attribute editing and the bulk “Mass Assign Attributes” action only with editUsers; other user edits depend on changeMemberRole. - Attributes TRPC router gates create/edit/delete/toggle via PBAC and requires organization.attributes.editUsers for assign/bulk-assign; added a helper to create PBAC-aware procedures. - **Migration** - Run the new Prisma migration to seed the admin role with editUsers. - If using custom roles, grant Edit Users under Attributes as needed. <sup>Written for commit 856aa2e8e1521fc22cd71cb0fa6d720036efe8a2. Summary will update automatically on new commits.</sup> <!-- End of auto-generated description by cubic. -->
47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
import type { PermissionString } from "@calcom/features/pbac/domain/types/permission-registry";
|
|
import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service";
|
|
import type { MembershipRole } from "@calcom/prisma/enums";
|
|
|
|
import { TRPCError } from "@trpc/server";
|
|
|
|
import authedProcedure from "../../../procedures/authedProcedure";
|
|
|
|
/**
|
|
* Creates an attribute procedure with configurable PBAC permissions for organization-scoped operations
|
|
* @param permission - The specific permission required (e.g., "organization.attributes.editUsers", "organization.attributes.create")
|
|
* @param fallbackRoles - Roles to check when PBAC is disabled (defaults to ["ADMIN", "OWNER"])
|
|
* @returns A procedure that checks the specified permission
|
|
*/
|
|
export const createAttributePbacProcedure = (
|
|
permission: PermissionString,
|
|
fallbackRoles: MembershipRole[] = ["ADMIN", "OWNER"]
|
|
) => {
|
|
return authedProcedure.use(async ({ ctx, next }) => {
|
|
const org = ctx.user.organization;
|
|
|
|
if (!org?.id) {
|
|
throw new TRPCError({
|
|
code: "UNAUTHORIZED",
|
|
message: "You need to be part of an organization to use this feature",
|
|
});
|
|
}
|
|
|
|
const permissionCheckService = new PermissionCheckService();
|
|
const hasPermission = await permissionCheckService.checkPermission({
|
|
userId: ctx.user.id,
|
|
teamId: org.id,
|
|
permission,
|
|
fallbackRoles,
|
|
});
|
|
|
|
if (!hasPermission) {
|
|
throw new TRPCError({
|
|
code: "FORBIDDEN",
|
|
message: `Permission required: ${permission}`,
|
|
});
|
|
}
|
|
|
|
return next();
|
|
});
|
|
};
|