diff --git a/defaults/interfaces.ts b/defaults/interfaces.ts index f385846..de6698f 100644 --- a/defaults/interfaces.ts +++ b/defaults/interfaces.ts @@ -3,12 +3,14 @@ import { AsyncRoute } from "$fresh/src/server/types.ts"; export interface AuthenticatedState { isAuthenticated: true; + isFromPolytech: boolean; session: CasContent; availablePages: Record; } interface UnauthenticatedState { isAuthenticated: false; + isFromPolytech: false; session: undefined; } diff --git a/fresh.gen.ts b/fresh.gen.ts index eeb5302..b6a8e70 100644 --- a/fresh.gen.ts +++ b/fresh.gen.ts @@ -19,6 +19,7 @@ import * as $_apps_students_partials_admin_consult from "./routes/(apps)/student import * as $_apps_students_partials_admin_upload from "./routes/(apps)/students/partials/(admin)/upload.tsx"; import * as $_apps_students_partials_index from "./routes/(apps)/students/partials/index.tsx"; import * as $_apps_students_types_d from "./routes/(apps)/students/types.d.ts"; +import * as $_403 from "./routes/_403.tsx"; import * as $_404 from "./routes/_404.tsx"; import * as $_app from "./routes/_app.tsx"; import * as $_middleware from "./routes/_middleware.ts"; @@ -64,6 +65,7 @@ const manifest = { "./routes/(apps)/students/partials/index.tsx": $_apps_students_partials_index, "./routes/(apps)/students/types.d.ts": $_apps_students_types_d, + "./routes/_403.tsx": $_403, "./routes/_404.tsx": $_404, "./routes/_app.tsx": $_app, "./routes/_middleware.ts": $_middleware, diff --git a/routes/_403.tsx b/routes/_403.tsx new file mode 100644 index 0000000..ffae6dd --- /dev/null +++ b/routes/_403.tsx @@ -0,0 +1,12 @@ +import { Head } from "$fresh/runtime.ts"; + +export default function Error403() { + return ( + <> + + 403 - Forbidden + +

403

+ + ); +} diff --git a/routes/_middleware.ts b/routes/_middleware.ts index 01b449e..a2653a4 100644 --- a/routes/_middleware.ts +++ b/routes/_middleware.ts @@ -44,6 +44,7 @@ export function getKey(user: string): string { export const handler: MiddlewareHandler[] = [ /** * Check if user is authenticated and add session to context accordingly. + * Only authenticated users who are members of Polytech are allowed. * @param request The HTTP incomming request. * @param context The Fresh context object with custom `State`. * @returns The response from the next middleware. @@ -55,6 +56,7 @@ export const handler: MiddlewareHandler[] = [ const cookies = getCookies(request.headers); if (!cookies["sessionToken"]) { context.state.isAuthenticated = false; + context.state.isFromPolytech = false; return await context.next(); } @@ -69,7 +71,16 @@ export const handler: MiddlewareHandler[] = [ if (context.state.isAuthenticated) { const session: CasContent = (getJwtPayload(cookies["sessionToken"]) as LoginJWT).user; - context.state.session = session; + const isFromPolytech = Object.values(session.memberOf).some( + (value) => + typeof value === "string" && value.includes("cn=amu:ufr:polytech"), + ); + + context.state.isFromPolytech = isFromPolytech; + + if (isFromPolytech) { + context.state.session = session; + } } return await context.next(); @@ -87,13 +98,24 @@ export const handler: MiddlewareHandler[] = [ ): Promise { const url = new URL(request.url); - if (!isRoutePublic(url.pathname) && !context.state.isAuthenticated) { - return new Response(null, { - status: 302, - headers: { - Location: "/login", - }, - }); + if (!isRoutePublic(url.pathname)) { + if (!context.state.isAuthenticated) { + return new Response(null, { + status: 302, + headers: { + Location: "/login", + }, + }); + } + + if (context.state.isAuthenticated && !context.state.isFromPolytech) { + return new Response(null, { + status: 403, + headers: { + Location: "/403", + }, + }); + } } return await context.next();