UNPKG

nuxt-supabase-team-auth

Version:

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

81 lines (80 loc) 3.23 kB
import { useTeamAuth } from "../composables/useTeamAuth.js"; import { navigateTo, defineNuxtRouteMiddleware, useRuntimeConfig } from "#imports"; export default defineNuxtRouteMiddleware(async (to) => { if (import.meta.server) return; const { currentUser, currentTeam, currentRole, isLoading, isImpersonating } = 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) { break; } } if (isLoading.value && attempts >= maxAttempts) { console.warn("[Team Auth] Auth loading timeout in middleware, proceeding anyway"); } } const config = useRuntimeConfig(); const teamAuthConfig = config.public.teamAuth || {}; const defaultProtection = teamAuthConfig.defaultProtection || "public"; const configuredProtectedRoutes = teamAuthConfig.protectedRoutes || ["/dashboard"]; const configuredPublicRoutes = teamAuthConfig.publicRoutes || []; const authRoutes = [ "/login", "/signin", "/signup", "/auth", "/confirm", "/reset-password", "/forgot-password", "/accept-invite" ]; let protectedRoutes; let publicRoutes; if (defaultProtection === "public") { protectedRoutes = configuredProtectedRoutes; publicRoutes = ["/", ...authRoutes, ...configuredPublicRoutes]; } else { protectedRoutes = ["/dashboard", "/team", "/teams", "/admin", "/profile", "/settings"]; publicRoutes = ["/", ...authRoutes, ...configuredPublicRoutes]; } const currentPath = to.path; const isPublicRoute = publicRoutes.some( (route) => currentPath === route || currentPath.startsWith(route + "/") ); if (isPublicRoute) { return; } const isProtectedRoute = protectedRoutes.some( (route) => currentPath.startsWith(route) ); if (isProtectedRoute && !currentUser.value) { const redirectUrl = `${currentPath}${to.search ? `?${new URLSearchParams(to.query).toString()}` : ""}`; const loginPage = teamAuthConfig.loginPage || "/signin"; return navigateTo(`${loginPage}?redirect=${encodeURIComponent(redirectUrl)}`); } if (isImpersonating.value) { if (currentPath.startsWith("/admin/") && !currentPath.includes("/impersonate/stop")) { return navigateTo("/dashboard?error=admin_blocked_during_impersonation"); } } if (currentPath.includes("/admin/impersonate") || currentPath.includes("/impersonate")) { if (currentRole.value !== "super_admin") { return navigateTo("/dashboard?error=insufficient_permissions"); } } if (currentPath.startsWith("/teams/") && currentPath !== "/teams") { const teamIdFromRoute = currentPath.split("/teams/")[1]?.split("/")[0]; if (teamIdFromRoute && currentTeam.value?.id !== teamIdFromRoute) { return navigateTo("/teams?error=unauthorized_team_access"); } } const teamRequiredRoutes = ["/team/", "/dashboard"]; const requiresTeam = teamRequiredRoutes.some((route) => currentPath.startsWith(route)); if (requiresTeam && currentUser.value && !currentTeam.value) { return navigateTo("/teams?message=select_team_first"); } });