import { redirect } from "@remix-run/node"; import { getUser, requireUserId } from "./auth.server"; import { requireAuthLevel } from "./auth-helpers.server"; import type { AuthLevel, SafeUser, RouteProtectionOptions } from "~/types/auth"; import { AUTH_LEVELS, USER_STATUS } from "~/types/auth"; import { AUTH_ERRORS } from "./auth-constants"; // Enhanced middleware for protecting routes that require authentication export async function requireAuthentication( request: Request, options: RouteProtectionOptions = {} ): Promise { const { allowInactive = false, redirectTo = "/signin" } = options; await requireUserId(request, redirectTo); const user = await getUser(request); if (!user) { throw redirect(redirectTo); } // Check if user is active (unless explicitly allowed) if (!allowInactive && user.status !== USER_STATUS.ACTIVE) { throw redirect("/signin?error=account_inactive"); } return user; } // Middleware for protecting admin routes (admin and superadmin) export async function requireAdmin( request: Request, options: RouteProtectionOptions = {} ): Promise { return requireAuthLevel(request, AUTH_LEVELS.ADMIN, options); } // Middleware for protecting superadmin routes export async function requireSuperAdmin( request: Request, options: RouteProtectionOptions = {} ): Promise { return requireAuthLevel(request, AUTH_LEVELS.SUPERADMIN, options); } // Middleware for protecting routes with custom auth level export async function requireAuth( request: Request, authLevel: AuthLevel, options: RouteProtectionOptions = {} ): Promise { return requireAuthLevel(request, authLevel, options); } // Middleware for redirecting authenticated users away from auth pages export async function redirectIfAuthenticated( request: Request, redirectTo: string = "/dashboard" ) { const user = await getUser(request); if (user && user.status === USER_STATUS.ACTIVE) { throw redirect(redirectTo); } } // Middleware for optional authentication (user may or may not be logged in) export async function getOptionalUser(request: Request): Promise { try { const user = await getUser(request); return user && user.status === USER_STATUS.ACTIVE ? user : null; } catch { return null; } } // Session validation middleware export async function validateSession(request: Request): Promise<{ isValid: boolean; user: SafeUser | null; error?: string; }> { try { const user = await getUser(request); if (!user) { return { isValid: false, user: null, error: "no_user", }; } if (user.status !== USER_STATUS.ACTIVE) { return { isValid: false, user: null, error: "inactive_user", }; } return { isValid: true, user, }; } catch { return { isValid: false, user: null, error: "session_error", }; } } // Route-specific protection functions export async function protectUserManagementRoute(request: Request): Promise { const user = await requireAdmin(request); // Additional business logic: ensure user can manage users if (user.authLevel > AUTH_LEVELS.ADMIN) { throw redirect("/dashboard?error=insufficient_permissions"); } return user; } export async function protectFinancialRoute(request: Request): Promise { // Financial routes require at least admin level return requireAdmin(request); } export async function protectCustomerRoute(request: Request): Promise { // Customer routes require authentication but any auth level can access return requireAuthentication(request); } export async function protectVehicleRoute(request: Request): Promise { // Vehicle routes require authentication but any auth level can access return requireAuthentication(request); } export async function protectMaintenanceRoute(request: Request): Promise { // Maintenance routes require authentication but any auth level can access return requireAuthentication(request); } // Utility function to check specific permissions export function checkPermission( user: SafeUser, permission: 'view_all_users' | 'create_users' | 'manage_finances' | 'view_reports' ): boolean { switch (permission) { case 'view_all_users': return user.authLevel === AUTH_LEVELS.SUPERADMIN; case 'create_users': return user.authLevel <= AUTH_LEVELS.ADMIN; case 'manage_finances': return user.authLevel <= AUTH_LEVELS.ADMIN; case 'view_reports': return user.authLevel <= AUTH_LEVELS.ADMIN; default: return false; } } // Error handling for unauthorized access export function createUnauthorizedResponse(message?: string) { const errorMessage = message || AUTH_ERRORS.INSUFFICIENT_PERMISSIONS; return new Response(errorMessage, { status: 403, headers: { 'Content-Type': 'text/plain; charset=utf-8' } }); }