Перейти к основному содержимому

Once we know who you are, what may you do? Roles, guards, and the deliberate 404-not-403 pattern.

Role simulator

Sandbox
Simulated role

Client-only — your real session is untouched and this value never leaves the browser.

Access decision matrix

Sandbox
Route (placeholder) Requires As guest
/area/public Anyone 200 OK
/area/dashboard Signed-in 404 Not Found
/area/studio Blog-author grant 404 Not Found
/area/console Admin only 404 Not Found

Guard contract (recorded)

Recorded

The real guard contract, verbatim except the isAdmin body (elided so this public page never prints the admin-gate mechanism).

guards.ts (excerpt)
// src/lib/server/auth/guards.ts (excerpt)

export function requireAuth(locals: App.Locals) {
  if (!locals.user) throw redirect(303, '/auth/login');
  return locals.user;
}

export function requireAdmin(locals: App.Locals) {
  const user = requireAuth(locals);
  // 404, NOT 403 — an admin surface must not confirm it exists.
  if (!isAdmin(user)) throw error(404, 'Not Found');
  return user;
}

export function requireBlogAuthor(locals: App.Locals) {
  const user = requireAuth(locals);
  // Grants array is populated per-request by the populateGrants hook
  // from auth.grant rows where revoked_at IS NULL.
  if (!isAdmin(user) && !locals.grants?.includes('blog-author')) {
    throw error(403, 'Forbidden');
  }
  return user;
}

function isAdmin(user: { id: string; email: string }): boolean {
  /* admin identity check elided */
}

Думаете, этот паттерн можно сделать лучше? Расскажите как.

Оставить отзыв