Compare commits
4 Commits
d79cd11b41
...
718e7f9d76
| Author | SHA1 | Date | |
|---|---|---|---|
| 718e7f9d76 | |||
| 7d7cdd1c9a | |||
| cb89a45743 | |||
| 5856eea5f3 |
+1
-1
@@ -3,7 +3,7 @@ FROM denoland/deno:alpine
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN deno cache main.ts --allow-import flag
|
RUN deno cache --allow-import main.ts
|
||||||
RUN deno task build
|
RUN deno task build
|
||||||
|
|
||||||
USER deno
|
USER deno
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ import { AsyncRoute } from "$fresh/src/server/types.ts";
|
|||||||
|
|
||||||
interface AuthenticatedState {
|
interface AuthenticatedState {
|
||||||
isAuthenticated: true;
|
isAuthenticated: true;
|
||||||
|
isFromPolytech: boolean;
|
||||||
|
role: "etudiants" | "personnels" | "autres";
|
||||||
session: CasContent;
|
session: CasContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UnauthenticatedState {
|
interface UnauthenticatedState {
|
||||||
isAuthenticated: false;
|
isAuthenticated: false;
|
||||||
|
isFromPolytech: false;
|
||||||
session: undefined;
|
session: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,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_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_partials_index from "./routes/(apps)/students/partials/index.tsx";
|
||||||
import * as $_apps_students_partials_overview from "./routes/(apps)/students/partials/overview.tsx";
|
import * as $_apps_students_partials_overview from "./routes/(apps)/students/partials/overview.tsx";
|
||||||
|
import * as $_403 from "./routes/_403.tsx";
|
||||||
import * as $_404 from "./routes/_404.tsx";
|
import * as $_404 from "./routes/_404.tsx";
|
||||||
import * as $_app from "./routes/_app.tsx";
|
import * as $_app from "./routes/_app.tsx";
|
||||||
import * as $_middleware from "./routes/_middleware.ts";
|
import * as $_middleware from "./routes/_middleware.ts";
|
||||||
@@ -67,6 +68,7 @@ const manifest = {
|
|||||||
$_apps_students_partials_index,
|
$_apps_students_partials_index,
|
||||||
"./routes/(apps)/students/partials/overview.tsx":
|
"./routes/(apps)/students/partials/overview.tsx":
|
||||||
$_apps_students_partials_overview,
|
$_apps_students_partials_overview,
|
||||||
|
"./routes/_403.tsx": $_403,
|
||||||
"./routes/_404.tsx": $_404,
|
"./routes/_404.tsx": $_404,
|
||||||
"./routes/_app.tsx": $_app,
|
"./routes/_app.tsx": $_app,
|
||||||
"./routes/_middleware.ts": $_middleware,
|
"./routes/_middleware.ts": $_middleware,
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Head } from "$fresh/runtime.ts";
|
||||||
|
|
||||||
|
export default function Error403() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>403 - Forbidden</title>
|
||||||
|
</Head>
|
||||||
|
<p>403</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
+56
-5
@@ -21,10 +21,19 @@ const deleteKey = (user: string) => delete jwtKeyCache[user];
|
|||||||
* @returns `true` if the route is public, `false` otherwise.
|
* @returns `true` if the route is public, `false` otherwise.
|
||||||
*/
|
*/
|
||||||
function isRoutePublic(route: string): boolean {
|
function isRoutePublic(route: string): boolean {
|
||||||
return PUBLIC_ROUTES.includes(route) ||
|
return (
|
||||||
!!(route.match(/\..+$/)?.[0] ?? false);
|
PUBLIC_ROUTES.includes(route) || !!(route.match(/\..+$/)?.[0] ?? false)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given route is an API route.
|
||||||
|
* @param route The route to check.
|
||||||
|
* @returns `true` if the route is an API route, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function isRouteAnAPI(route: string): boolean {
|
||||||
|
return route.includes("/api/");
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Get the given user's key, creating it if not already existing.
|
* Get the given user's key, creating it if not already existing.
|
||||||
* @param user The key's user.
|
* @param user The key's user.
|
||||||
@@ -44,6 +53,7 @@ export function getKey(user: string): string {
|
|||||||
export const handler: MiddlewareHandler<State>[] = [
|
export const handler: MiddlewareHandler<State>[] = [
|
||||||
/**
|
/**
|
||||||
* Check if user is authenticated and add session to context accordingly.
|
* 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 request The HTTP incomming request.
|
||||||
* @param context The Fresh context object with custom `State`.
|
* @param context The Fresh context object with custom `State`.
|
||||||
* @returns The response from the next middleware.
|
* @returns The response from the next middleware.
|
||||||
@@ -55,6 +65,7 @@ export const handler: MiddlewareHandler<State>[] = [
|
|||||||
const cookies = getCookies(request.headers);
|
const cookies = getCookies(request.headers);
|
||||||
if (!cookies["sessionToken"]) {
|
if (!cookies["sessionToken"]) {
|
||||||
context.state.isAuthenticated = false;
|
context.state.isAuthenticated = false;
|
||||||
|
context.state.isFromPolytech = false;
|
||||||
return await context.next();
|
return await context.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +78,32 @@ export const handler: MiddlewareHandler<State>[] = [
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (context.state.isAuthenticated) {
|
if (context.state.isAuthenticated) {
|
||||||
const session: CasContent =
|
const session: CasContent = (
|
||||||
(getJwtPayload(cookies["sessionToken"]) as LoginJWT).user;
|
getJwtPayload(cookies["sessionToken"]) as LoginJWT
|
||||||
|
).user;
|
||||||
|
|
||||||
|
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;
|
context.state.session = session;
|
||||||
|
|
||||||
|
if (Object.values(session.memberOf).some(
|
||||||
|
(value) => typeof value === "string" && value.includes("cn=amu:ufr:polytech:personnels")
|
||||||
|
)) {
|
||||||
|
context.state.role = "personnels";
|
||||||
|
} else if (Object.values(session.memberOf).some(
|
||||||
|
(value) => typeof value === "string" && value.includes("cn=amu:ufr:polytech:etudiants")
|
||||||
|
)) {
|
||||||
|
context.state.role = "etudiants";
|
||||||
|
} else {
|
||||||
|
context.state.role = "autres";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return await context.next();
|
return await context.next();
|
||||||
@@ -87,7 +121,8 @@ export const handler: MiddlewareHandler<State>[] = [
|
|||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
|
|
||||||
if (!isRoutePublic(url.pathname) && !context.state.isAuthenticated) {
|
if (!isRoutePublic(url.pathname)) {
|
||||||
|
if (!context.state.isAuthenticated) {
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 302,
|
status: 302,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -96,6 +131,22 @@ export const handler: MiddlewareHandler<State>[] = [
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!context.state.isFromPolytech) {
|
||||||
|
return new Response(null, {
|
||||||
|
status: 403,
|
||||||
|
headers: {
|
||||||
|
Location: "/403",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRouteAnAPI(url.pathname) && !(context.state.role == "personnels")) {
|
||||||
|
return new Response(null, {
|
||||||
|
status: 403,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return await context.next();
|
return await context.next();
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user