← back to Hub

middleware.ts

51 lines

import { NextRequest, NextResponse } from 'next/server';
import { verifyAuth } from '@/lib/auth';
import { capabilityGate } from '@dw/nextjs-admin-login';
import { registry } from '@/lib/accounts';

/**
 * Hub middleware — capability gate only (added 2026-06-01 with guest logins).
 *
 * Hub gates auth per-route (no central auth middleware historically), so this
 * file intentionally does NOT add an auth gate — it only layers the capability
 * check on top:
 *   - no session → pass through (per-route verifyAuth still handles 401);
 *   - auth routes (login/logout/session) → never gated, so guests can log
 *     in/out and read their own session;
 *   - logged-in session → block mutating methods for read-only tiers (403).
 *
 * Because capabilityGate only blocks when canWrite/canUseAI is false, admin
 * and the write-capable 'guest' tier are never affected — the only behavior
 * change is that read-only 'viewer'/'demo' accounts get a 403 on writes.
 *
 * Hub has no AI routes today, so isAiRoute is false.
 */
export const config = {
  runtime: 'nodejs',
  matcher: ['/api/:path*'],
};

const PUBLIC_API = new Set([
  '/api/auth/login',
  '/api/auth/logout',
  '/api/auth/session',
]);

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;
  if (PUBLIC_API.has(pathname)) return NextResponse.next();

  const username = verifyAuth(request);
  if (!username) return NextResponse.next(); // per-route auth handles 401

  const gate = capabilityGate({
    capabilities: registry.getCapabilities(username),
    method: request.method,
    isAiRoute: false,
  });
  if (!gate.ok) {
    return NextResponse.json({ error: gate.error }, { status: gate.status });
  }
  return NextResponse.next();
}