All files / src middleware.ts

100% Statements 57/57
100% Branches 20/20
100% Functions 1/1
100% Lines 57/57

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83      1x 1x     1x 1x             1x   1x 17x 17x   17x 17x 2x 2x   2x 1x 1x 1x 1x   1x 1x 2x   17x 1x 1x   16x 17x   3x 1x 1x   2x   3x 1x 1x 1x 1x 1x 1x 1x 3x     17x 2x 2x 2x 2x 2x 2x 2x 2x     17x 2x 2x 2x 2x 2x 2x 2x   10x 10x  
import type { MiddlewareHandler } from 'astro';
 
// Constants
import { PRIVATE_ROUTES, ROUTES } from './constants/routes';
import { COOKIE_KEYS } from './constants/auth';
 
// Utils
import { proxyRequest } from './utils/proxy';
import {
  checkPermission,
  findMatchedRoute,
  isTokenExpired,
} from './utils/auth';
 
// Services
import { getRefreshToken } from '@/services/auth';
 
export const onRequest: MiddlewareHandler = async (context, next) => {
  const user = await context.session?.get('user');
  const { pathname, search } = context.url;
 
  const tokenShared = context.cookies.get(COOKIE_KEYS.TOKEN_SHARED)?.value;
  if (!!tokenShared && !!user?.token && isTokenExpired(user?.token)) {
    const { data } = await getRefreshToken({ token: tokenShared });
    const token = data?.id_token || '';
 
    if (token) {
      const newUser = {
        ...user,
        token,
      };
 
      await context.session?.set('user', newUser);
    }
  }
 
  if (user && pathname === ROUTES.SIGN_IN) {
    return Response.redirect(new URL(ROUTES.HOME, context.url), 302);
  }
 
  const matchedPrivateRoute = findMatchedRoute(pathname, PRIVATE_ROUTES);
  if (!!matchedPrivateRoute) {
    // If user is not logged in → redirect to sign-in
    if (!user) {
      return Response.redirect(new URL(ROUTES.SIGN_IN, context.url), 302);
    }
 
    const isNoPermission = !checkPermission(user, matchedPrivateRoute);
    // If user is logged in but does not have the required role → return 404
    if (isNoPermission) {
      const url404 = new URL(ROUTES.NOT_FOUND, context.url);
      const res = await next(new Request(url404, context.request));
      return new Response(await res.text(), {
        status: 404,
        headers: res.headers,
      });
    }
  }
 
  // Proxy /rpc requests
  if (pathname.startsWith('/rpc')) {
    const res = await proxyRequest(context, pathname, {
      body: JSON.stringify({ json: {} }),
    });
    return new Response(await res.text(), {
      status: res.status,
      headers: res.headers,
    });
  }
 
  // Proxy /ws requests (WebSocket)
  if (pathname.startsWith('/ws')) {
    const res = await proxyRequest(context, pathname + search);
    return new Response(null, {
      status: res.status,
      headers: res.headers,
      ...((res as any).webSocket && { webSocket: (res as any).webSocket }),
    });
  }
 
  return next();
};