Agent skill

role-based-access

Implement role-based access control (RBAC) with user roles (admin, lead, member) and permission middleware. Use when adding authorization or restricting endpoints by role.

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/role-based-access

SKILL.md

You implement RBAC for the QA Team Portal with three roles: admin, lead, and member.

Roles & Permissions

admin - Full access to everything

  • All CRUD operations
  • User management
  • System configuration

lead - Content management

  • Create/Edit/Delete content (team, updates, tools, resources, research)
  • View audit logs
  • Cannot manage users

member - Read-only

  • View public pages only
  • No admin portal access

Implementation

1. Permission Decorator

Location: backend/app/core/permissions.py

python
from functools import wraps
from fastapi import HTTPException
from app.models.user import User

def require_role(*allowed_roles: str):
    """
    Decorator to require specific roles.

    Usage:
        @require_role("admin", "lead")
        async def update_team_member(...):
            ...
    """
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, current_user: User = None, **kwargs):
            if not current_user:
                raise HTTPException(401, "Authentication required")

            if current_user.role not in allowed_roles:
                raise HTTPException(
                    403,
                    f"Requires role: {' or '.join(allowed_roles)}"
                )

            return await func(*args, current_user=current_user, **kwargs)
        return wrapper
    return decorator

2. Permission Dependencies

Location: backend/app/api/deps.py

python
async def get_current_admin(
    current_user: User = Depends(get_current_user)
) -> User:
    """Require admin role."""
    if current_user.role != "admin":
        raise HTTPException(403, "Admin access required")
    return current_user

async def get_current_lead_or_admin(
    current_user: User = Depends(get_current_user)
) -> User:
    """Require lead or admin role."""
    if current_user.role not in ["admin", "lead"]:
        raise HTTPException(403, "Lead or admin access required")
    return current_user

3. Apply to Endpoints

Location: backend/app/api/v1/endpoints/team_members.py

python
from app.api.deps import get_current_user, get_current_lead_or_admin

@router.get("/team-members")
async def get_team_members():
    """Public endpoint - no auth required."""
    ...

@router.post("/admin/team-members")
async def create_team_member(
    data: TeamMemberCreate,
    current_user: User = Depends(get_current_lead_or_admin)
):
    """Lead or admin can create team members."""
    ...

@router.delete("/admin/team-members/{id}")
async def delete_team_member(
    id: UUID,
    current_user: User = Depends(get_current_admin)
):
    """Only admin can delete."""
    ...

4. Resource-Level Permissions

python
# Check if user can modify specific resource
async def can_modify_resource(
    user: User,
    resource_id: UUID,
    db: Session
) -> bool:
    """Check if user can modify resource."""
    if user.role == "admin":
        return True  # Admin can modify anything

    # Lead can only modify their own resources
    if user.role == "lead":
        resource = await crud.resource.get(db, id=resource_id)
        return resource and resource.created_by == user.id

    return False  # Members cannot modify

Frontend Authorization

Location: frontend/src/hooks/useAuth.ts

typescript
export const useAuth = () => {
  const { user } = useContext(AuthContext)

  const hasRole = (...roles: string[]) => {
    return user && roles.includes(user.role)
  }

  const isAdmin = () => hasRole('admin')
  const isLead = () => hasRole('lead', 'admin')
  const isMember = () => hasRole('member', 'lead', 'admin')

  return {
    user,
    hasRole,
    isAdmin,
    isLead,
    isMember
  }
}

Usage in Components:

typescript
const { isAdmin, isLead } = useAuth()

return (
  <div>
    {isLead() && (
      <Button onClick={handleEdit}>Edit</Button>
    )}

    {isAdmin() && (
      <Button onClick={handleDelete}>Delete</Button>
    )}
  </div>
)

Testing

python
def test_admin_can_delete(client, admin_token):
    response = client.delete(
        "/api/v1/admin/team-members/123",
        headers={"Authorization": f"Bearer {admin_token}"}
    )
    assert response.status_code == 204

def test_lead_cannot_delete(client, lead_token):
    response = client.delete(
        "/api/v1/admin/team-members/123",
        headers={"Authorization": f"Bearer {lead_token}"}
    )
    assert response.status_code == 403

def test_member_cannot_access_admin(client, member_token):
    response = client.get(
        "/api/v1/admin/dashboard",
        headers={"Authorization": f"Bearer {member_token}"}
    )
    assert response.status_code == 403

Report

✅ RBAC implemented with 3 roles ✅ Permission middleware created ✅ Endpoints protected by role ✅ Frontend authorization hooks added ✅ Tests passing

Didn't find tool you were looking for?

Be as detailed as possible for better results