agentsclimarketplace

Clickup enterprise rbac

Skill ComeOnOliver/skillshub/skills/jeremylongshore/claude-code-plugins-plus-skills/clickup-enterprise-rbac

🧠 The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.

Install
npx -y skills add ComeOnOliver/skillshub --skill clickup-enterprise-rbac

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Implement ClickUp Enterprise SSO, OAuth 2.0 multi-workspace access, role-based permissions, and organization management via API v2. Trigger: "clickup SSO", "clickup RBAC", "clickup enterprise", "clickup roles", "clickup permissions", "clickup OAuth app", "clickup multi-workspace".

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.2 KB, as published. Nobody here has run it

ClickUp Enterprise RBAC

Overview

Enterprise access patterns for ClickUp API v2. ClickUp's role system is built into the workspace, and the API surfaces roles via member objects. OAuth 2.0 enables multi-workspace apps where each user authorizes their own workspaces.

ClickUp Role Model

ClickUp workspace members have role IDs in the API:

Role IDRolePermissions
1OwnerFull control, billing, workspace settings
2AdminManage members, spaces, integrations
3MemberCreate/edit tasks, spaces (per permission)
4GuestLimited access to shared items only
// Get workspace members with roles
async function getWorkspaceMembers(teamId: string) {
  const data = await clickupRequest(`/team/${teamId}`);

  return data.team.members.map((m: any) => ({
    userId: m.user.id,
    username: m.user.username,
    email: m.user.email,
    role: m.user.role,       // 1=owner, 2=admin, 3=member, 4=guest
    roleLabel: { 1: 'owner', 2: 'admin', 3: 'member', 4: 'guest' }[m.user.role],
  }));
}

// Check if user can perform admin operations
function canAdminister(member: { role: number }): boolean {
  return member.role <= 2; // Owner or Admin
}

OAuth 2.0 Multi-Workspace App

Build apps that access multiple ClickUp workspaces on behalf of users.

// Step 1: Redirect user to ClickUp authorization
function getOAuthUrl(state: string): string {
  return `https://app.clickup.com/api?client_id=${process.env.CLICKUP_CLIENT_ID}&redirect_uri=${encodeURIComponent(process.env.CLICKUP_REDIRECT_URI!)}&state=${state}`;
}

// Step 2: Exchange code for token
async function handleOAuthCallback(code: string) {
  const response = await fetch('https://api.clickup.com/api/v2/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      client_id: process.env.CLICKUP_CLIENT_ID,
      client_secret: process.env.CLICKUP_CLIENT_SECRET,
      code,
    }),
  });

  const { access_token } = await response.json();

  // Step 3: Discover which workspaces user authorized
  const teamsResponse = await fetch('https://api.clickup.com/api/v2/team', {
    headers: { 'Authorization': access_token },
  });
  const { teams } = await teamsResponse.json();

  return {
    token: access_token,   // Doesn't expire (but can be revoked)
    workspaces: teams.map((t: any) => ({ id: t.id, name: t.name })),
  };
}

// Step 4: Store per-user tokens
interface UserClickUpAuth {
  userId: string;
  clickupToken: string;      // Encrypt at rest
  authorizedWorkspaces: string[];
  connectedAt: Date;
}

Permission Middleware

// Express middleware that checks ClickUp workspace access
function requireClickUpAccess(requiredRole: number = 3) {
  return async (req: any, res: any, next: any) => {
    const userToken = req.user.clickupToken;
    const teamId = req.params.teamId || req.body.teamId;

    if (!userToken) {
      return res.status(401).json({ error: 'ClickUp not connected' });
    }

    // Verify user still has access to this workspace
    const teamsRes = await fetch('https://api.clickup.com/api/v2/team', {
      headers: { 'Authorization': userToken },
    });

    if (!teamsRes.ok) {
      return res.status(401).json({ error: 'ClickUp token expired or revoked' });
    }

    const { teams } = await teamsRes.json();
    const workspace = teams.find((t: any) => t.id === teamId);

    if (!workspace) {
      return res.status(403).json({ error: 'No access to this ClickUp workspace' });
    }

    // Check role level
    const userMember = workspace.members.find(
      (m: any) => m.user.id === req.user.clickupUserId
    );

    if (!userMember || userMember.user.role > requiredRole) {
      return res.status(403).json({
        error: `Requires role ${requiredRole} or higher`,
      });
    }

    req.clickupWorkspace = workspace;
    next();
  };
}

// Usage
app.delete('/api/clickup/:teamId/space/:spaceId',
  requireClickUpAccess(2), // Admin required
  async (req, res) => { /* ... */ }
);

User Groups (API v2 "Teams")

GET    /api/v2/group                    Get User Groups
POST   /api/v2/team/{team_id}/group     Create User Group
PUT    /api/v2/group/{group_id}         Update User Group
DELETE /api/v2/group/{group_id}         Delete User Group
// Create a user group for engineering team
await clickupRequest(`/team/${teamId}/group`, {
  method: 'POST',
  body: JSON.stringify({
    name: 'Engineering',
    member_ids: [183, 456, 789],
  }),
});

Audit Trail

interface ClickUpAuditEntry {
  timestamp: string;
  userId: number;
  workspaceId: string;
  action: string;
  resource: string;
  resourceId: string;
  success: boolean;
}

function logClickUpAction(entry: Omit<ClickUpAuditEntry, 'timestamp'>): void {
  const log: ClickUpAuditEntry = {
    ...entry,
    timestamp: new Date().toISOString(),
  };
  console.log(JSON.stringify({ level: 'audit', service: 'clickup', ...log }));
}

Error Handling

IssueCauseSolution
OAUTH_023/027Workspace not authorizedUser must re-authorize via OAuth flow
Role check failsUser role changed in ClickUpRe-fetch member data from API
Token revokedUser disconnected appHandle 401, prompt re-auth
Guest access deniedEndpoint requires member+Check role field before API call

Resources

Next Steps

For major migrations, see clickup-migration-deep-dive.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.