Skip to main content
Designing Our Role-Based Access Control System

Designing Our Role-Based Access Control System

Andrius LukminasAndrius LukminasJanuary 11, 20265 min read110 views

The Requirements

Our platform serves different user types with different needs:

  • OWNER - Full platform control
  • ADMIN - System administration
  • MANAGER - Team and project management
  • DEVELOPER - Development access
  • CLIENT - Orders and billing only

Implementation Approach

Role Guards

We created reusable guard functions:

// src/lib/auth/protection/guards.ts
export async function requireRole(...allowedRoles: UserRole[]) {
  const { user } = await validateRequest();

  if (!user) {
    throw redirect('/sign-in');
  }

  if (!allowedRoles.includes(user.role)) {
    throw redirect('/unauthorized');
  }

  return user;
}

Zone-Based Protection

Each route group (admin, manager, developer, client) has its own protection zone defined in constants:

export const ZONE_CONFIG = {
  admin: {
    allowedRoles: ['OWNER', 'ADMIN'],
    basePath: '/admin',
  },
  manager: {
    allowedRoles: ['OWNER', 'ADMIN', 'MANAGER'],
    basePath: '/manager',
  },
  // ...
};

API Protection

API routes use the same guards:

export async function GET() {
  const user = await requireRole('ADMIN', 'OWNER');
  // Only admins and owners reach this code
}

Benefits

This system is easy to reason about, test, and extend. Adding a new role is straightforward.

Related Articles

Comments

0/5000 characters

Comments from guests require moderation.