UNPKG

nuxt-supabase-team-auth

Version:

Drop-in Nuxt 3 module for team-based authentication with Supabase

65 lines (64 loc) 3 kB
import { useTeamAuth } from "../composables/useTeamAuth.js"; import { navigateTo, defineNuxtRouteMiddleware, useRuntimeConfig } from "#imports"; const ROLE_HIERARCHY = { super_admin: 4, owner: 3, admin: 2, member: 1 }; export function createRequireRoleMiddleware(requiredRole, options = {}) { return defineNuxtRouteMiddleware(async (to) => { const { currentUser, currentRole, isLoading } = useTeamAuth(); if (isLoading.value) { let attempts = 0; const maxAttempts = 20; while (isLoading.value && attempts < maxAttempts) { await new Promise((resolve) => setTimeout(resolve, 100)); attempts++; if (currentUser.value !== void 0 && currentRole.value !== void 0) { break; } } if (isLoading.value && attempts >= maxAttempts) { console.warn("[Team Auth] Auth loading timeout in require-role middleware, proceeding anyway"); } } if (!currentUser.value) { const redirectUrl = `${to.path}${to.search ? `?${new URLSearchParams(to.query).toString()}` : ""}`; const config = useRuntimeConfig(); const loginPage = config.public.teamAuth?.loginPage || "/signin"; return navigateTo(`${loginPage}?redirect=${encodeURIComponent(redirectUrl)}`); } if (!currentRole.value) { console.error("[Team Auth] Authenticated user missing role - data integrity issue. User ID:", currentUser.value.id); return navigateTo("/signin?error=account_misconfigured"); } const userRoleLevel = ROLE_HIERARCHY[currentRole.value]; const requiredRoleLevel = ROLE_HIERARCHY[requiredRole]; if (!userRoleLevel || !requiredRoleLevel) { console.error("Invalid role detected:", { userRole: currentRole.value, requiredRole }); return navigateTo("/dashboard?error=invalid_role"); } const hasPermission = options.strict ? userRoleLevel === requiredRoleLevel : userRoleLevel >= requiredRoleLevel; if (!hasPermission) { const redirectTo = options.redirectTo || "/dashboard"; const errorParam = options.errorMessage || "insufficient_permissions"; return navigateTo(`${redirectTo}?error=${errorParam}`); } }); } export const requireAdmin = createRequireRoleMiddleware("admin"); export const requireOwner = createRequireRoleMiddleware("owner"); export const requireSuperAdmin = createRequireRoleMiddleware("super_admin"); export const requireAdminOnly = createRequireRoleMiddleware("admin", { strict: true }); export const requireOwnerOnly = createRequireRoleMiddleware("owner", { strict: true }); export const requireSuperAdminOnly = createRequireRoleMiddleware("super_admin", { strict: true }); export default defineNuxtRouteMiddleware(async (to, _from) => { const requiredRole = to.meta.requireRole; if (!requiredRole) { console.warn("require-role middleware used without specifying required role in route meta"); return; } const middleware = createRequireRoleMiddleware(requiredRole); return middleware(to, _from); });