Skip to content

Latest commit

 

History

History
189 lines (145 loc) · 10.3 KB

File metadata and controls

189 lines (145 loc) · 10.3 KB

Cal.com Permission Documentation

This document maps existing role-based permission checks to the new PBAC (Permission-Based Access Control) system's permission strings in the format resource.action.

Permissions by Resource

Team Permissions

Permission String Description File Path Line
team.create Create teams packages/trpc/server/routers/viewer/teams/create.handler.ts 55-57
team.update Update team settings packages/trpc/server/routers/viewer/teams/update.handler.ts 18
team.changeMemberRole Change role of team members packages/trpc/server/routers/viewer/teams/changeMemberRole.handler.ts 18-21
team.remove Remove members from team packages/trpc/server/routers/viewer/teams/removeMember.handler.ts 35-36, 51-55
team.invite Invite members to team packages/trpc/server/routers/viewer/teams/invite.handler.ts -

Event Type Permissions

Permission String Description File Path Line
eventType.create Create event types packages/trpc/server/routers/viewer/eventTypes/create.handler.ts -
eventType.update Update event types packages/trpc/server/routers/viewer/eventTypes/update.handler.ts 162-164
eventType.delete Delete event types packages/trpc/server/routers/viewer/eventTypes/delete.handler.ts 13-31

Booking Permissions

Permission String Description File Path Line
booking.read Read booking details packages/trpc/server/routers/viewer/bookings/get.handler.ts 95-107, 132-134
booking.readTeamBookings Read team bookings packages/trpc/server/routers/viewer/bookings/get.handler.ts 240-252
booking.readOrgBookings Read organization bookings packages/trpc/server/routers/viewer/bookings/get.handler.ts 240-252

Organization Permissions

Permission String Description File Path Line
organization.read Read organization details packages/trpc/server/routers/viewer/organizations/get.handler.ts -
organization.listMembers List organization members packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts 68-76
organization.create Create organization packages/trpc/server/routers/viewer/organizations/create.handler.ts -

API Key Permissions

Permission String Description File Path Line
apiKey.create Create API keys packages/trpc/server/routers/viewer/apiKeys/create.handler.ts 25-26
apiKey.findKeyOfType Find API keys by type packages/trpc/server/routers/viewer/apiKeys/findKeyOfType.handler.ts 18-19

Helper Functions and Utilities

The following helper functions are commonly used for permission checks:

Function Description File Path
isTeamAdmin Checks if user is admin or owner of a team packages/lib/server/queries/teams/index.ts
isTeamOwner Checks if user is owner of a team packages/lib/server/queries/teams/index.ts
isTeamMember Checks if user is a member of a team packages/lib/server/queries/teams/index.ts
canEditEntity Checks if user can edit an entity packages/lib/entityPermissionUtils.ts
canAccessEntity Checks if user can access an entity packages/lib/entityPermissionUtils.ts
getEntityPermissionLevel Gets permission level for an entity packages/lib/entityPermissionUtils.ts
canCreateEntity Checks if user can create an entity packages/lib/entityPermissionUtils.ts
withRoleCanCreateEntity Checks if role allows entity creation packages/lib/entityPermissionUtils.ts

Permission Level Enums

The codebase uses several enums to define permission levels:

MembershipRole Enum

enum MembershipRole {
  OWNER = "OWNER",
  ADMIN = "ADMIN",
  MEMBER = "MEMBER"
}

Entity Permission Level Enum

enum ENTITY_PERMISSION_LEVEL {
  NONE,
  USER_ONLY_WRITE,
  TEAM_READ_ONLY,
  TEAM_WRITE
}

Common Permission Patterns

  1. Team Admin/Owner Check: Many operations require the user to be a team admin or owner.

    if (!(await isTeamAdmin(ctx.user?.id, input.teamId))) throw new TRPCError({ code: "UNAUTHORIZED" });
  2. Team Owner Check: Some operations (like changing an owner's role) require the user to be a team owner.

    if (input.role === MembershipRole.OWNER && !(await isTeamOwner(ctx.user?.id, input.teamId)))
      throw new TRPCError({ code: "UNAUTHORIZED" });
  3. Organization Admin Check: Operations within an organization require the user to be an organization admin.

    if (user.profile?.organizationId && !user.organization.isOrgAdmin) {
      throw new TRPCError({ code: "FORBIDDEN", message: "org_admins_can_create_new_teams" });
    }
  4. Entity Permission Check: Entity operations use permission level checks.

    const permissionLevel = await getEntityPermissionLevel(entity, userId);
    return permissionLevel === ENTITY_PERMISSION_LEVEL.TEAM_WRITE || 
           permissionLevel === ENTITY_PERMISSION_LEVEL.USER_ONLY_WRITE;
  5. Booking Access Control: Complex permission checks for retrieving bookings based on user roles and team/organization membership.

    const membershipIdsWhereUserIsAdminOwner = (
      await prisma.membership.findMany({
        where: {
          userId: user.id,
          role: {
            in: ["ADMIN", "OWNER"],
          },
        },
        select: {
          id: true,
        },
      })
    ).map((membership) => membership.id);

Migration to PBAC

When migrating to the new PBAC system, these existing role-based checks should be replaced with permission string checks using the permissionMatches function:

import { permissionMatches } from "@calcom/features/pbac/types/permission-registry";

// Instead of:
if (!(await isTeamAdmin(ctx.user?.id, input.teamId))) throw new TRPCError({ code: "UNAUTHORIZED" });

// Use:
if (!permissionMatches("team.update", userPermissions)) throw new TRPCError({ code: "UNAUTHORIZED" });

Permission String Alternatives for Helper Functions

The following table provides permission string alternatives for common helper functions:

Helper Function Permission String Alternative Description
isTeamAdmin team.* Grants all team permissions
isTeamAdmin team.update Update team settings
isTeamAdmin team.invite Invite team members
isTeamAdmin team.remove Remove team members
isTeamOwner team.changeMemberRole Change role of team members
isTeamOwner team.delete Delete team
isTeamMember team.read Read-only access to team

Entity Permission Functions and Resources

The following functions are used to check permissions for entities with userId and teamId properties:

Function Description Permission String Alternative
canEditEntity Checks if user can edit an entity {resource}.update
canAccessEntity Checks if user can access an entity {resource}.read
getEntityPermissionLevel Gets permission level for an entity N/A - Implementation detail
canCreateEntity Checks if user can create an entity {resource}.create

Resources Used with Entity Permission Functions

Resource canEditEntity Usage canAccessEntity Usage Permission String
routingForm packages/app-store/routing-forms/trpc/forms.handler.ts packages/app-store/routing-forms/trpc/getResponseWithFormFields.handler.ts routingForm.update, routingForm.read
routingForm packages/app-store/routing-forms/trpc/formMutation.handler.ts routingForm.update
routingForm packages/app-store/routing-forms/api/responses/[formId].ts routingForm.update

These functions can be used with any entity that has userId and teamId properties. When migrating to PBAC, replace these checks with appropriate permission string checks:

// Instead of:
if (!(await canEditEntity(form, user.id))) throw new TRPCError({ code: "UNAUTHORIZED" });

// Use:
if (!permissionMatches("routingForm.update", userPermissions)) throw new TRPCError({ code: "UNAUTHORIZED" });

This allows for more granular permission control and the creation of custom roles with specific permissions.