From 4ff76fdf6fbda8a2370116e903d9e8f59c6c2f7c Mon Sep 17 00:00:00 2001 From: Kevin FEDYNA Date: Mon, 27 Jan 2025 10:39:42 +0100 Subject: [PATCH] Added hidden admin only page prop effect --- defaults/interfaces.ts | 3 ++- deno.json | 1 + fresh.config.ts | 2 ++ fresh.gen.ts | 2 ++ routes/(apps)/_layout.tsx | 11 ++++------- routes/(apps)/_middleware.ts | 36 ++++++++++++++++++++++++++++++++++++ 6 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 routes/(apps)/_middleware.ts diff --git a/defaults/interfaces.ts b/defaults/interfaces.ts index a5a6268..f385846 100644 --- a/defaults/interfaces.ts +++ b/defaults/interfaces.ts @@ -1,9 +1,10 @@ import { type RegularTagNode, type TextNode } from "@melvdouc/xml-parser"; import { AsyncRoute } from "$fresh/src/server/types.ts"; -interface AuthenticatedState { +export interface AuthenticatedState { isAuthenticated: true; session: CasContent; + availablePages: Record; } interface UnauthenticatedState { diff --git a/deno.json b/deno.json index a7635bb..45c5870 100644 --- a/deno.json +++ b/deno.json @@ -29,6 +29,7 @@ "@popov/jwt": "jsr:@popov/jwt@^1.0.1", "@psych/sheet": "jsr:@psych/sheet@^1.0.6", "@std/cli": "jsr:@std/cli@^1.0.10", + "@std/dotenv": "jsr:@std/dotenv@^0.225.3", "preact": "https://esm.sh/preact@10.22.0", "preact/": "https://esm.sh/preact@10.22.0/", "@preact/signals": "https://esm.sh/*@preact/signals@1.2.2", diff --git a/fresh.config.ts b/fresh.config.ts index 5881650..ebe1722 100644 --- a/fresh.config.ts +++ b/fresh.config.ts @@ -1,6 +1,8 @@ import { defineConfig } from "$fresh/server.ts"; import ensureDatabases from "$root/databases/ensure.ts"; +import { load } from "@std/dotenv"; +await load({ envPath: "./.env.development.local", export: true }); await ensureDatabases(); export default defineConfig({ server: { diff --git a/fresh.gen.ts b/fresh.gen.ts index 2b0c7d3..2beb32c 100644 --- a/fresh.gen.ts +++ b/fresh.gen.ts @@ -3,6 +3,7 @@ // This file is automatically updated during development when running `dev.ts`. import * as $_apps_layout from "./routes/(apps)/_layout.tsx"; +import * as $_apps_middleware from "./routes/(apps)/_middleware.ts"; import * as $_apps_mobility_api_insert_mobility from "./routes/(apps)/mobility/api/insert_mobility.ts"; import * as $_apps_mobility_index from "./routes/(apps)/mobility/index.tsx"; import * as $_apps_mobility_partials_admin_edit_mobility from "./routes/(apps)/mobility/partials/(admin)/edit_mobility.tsx"; @@ -39,6 +40,7 @@ import type { Manifest } from "$fresh/server.ts"; const manifest = { routes: { "./routes/(apps)/_layout.tsx": $_apps_layout, + "./routes/(apps)/_middleware.ts": $_apps_middleware, "./routes/(apps)/mobility/api/insert_mobility.ts": $_apps_mobility_api_insert_mobility, "./routes/(apps)/mobility/index.tsx": $_apps_mobility_index, diff --git a/routes/(apps)/_layout.tsx b/routes/(apps)/_layout.tsx index ee3b43e..9694880 100644 --- a/routes/(apps)/_layout.tsx +++ b/routes/(apps)/_layout.tsx @@ -1,22 +1,19 @@ import { FreshContext } from "$fresh/server.ts"; import { Partial } from "$fresh/runtime.ts"; -import { State } from "$root/defaults/interfaces.ts"; -import { AppProperties } from "$root/defaults/interfaces.ts"; +import { AuthenticatedState } from "$root/defaults/interfaces.ts"; import Navbar from "$root/routes/(_islands)/Navbar.tsx"; +// deno-lint-ignore require-await export default async function AppLayout( request: Request, - context: FreshContext, + context: FreshContext, ) { const pathname = new URL(request.url).pathname; const currentApp = pathname.split("/")[1]; - const properties: AppProperties = (await import( - `./${currentApp}/(_props)/props.ts` - )).default; return (
- +
diff --git a/routes/(apps)/_middleware.ts b/routes/(apps)/_middleware.ts new file mode 100644 index 0000000..abb11cc --- /dev/null +++ b/routes/(apps)/_middleware.ts @@ -0,0 +1,36 @@ +import { FreshContext, MiddlewareHandler } from "$fresh/server.ts"; +import { + AppProperties, + AuthenticatedState, +} from "$root/defaults/interfaces.ts"; + +export const handler: MiddlewareHandler[] = [ + /** + * Check if user is authenticated and add session to context accordingly. + * @param request The HTTP incomming request. + * @param context The Fresh context object with custom `AuthenticatedState`. + * @returns The response from the next middleware. + */ + async function checkAuthentication( + request: Request, + context: FreshContext, + ): Promise { + const pathname = new URL(request.url).pathname; + const currentApp = pathname.split("/")[1]; + const properties: AppProperties = (await import( + `./${currentApp}/(_props)/props.ts` + )).default; + + context.state.availablePages = properties.pages; + if ( + context.state.session.eduPersonPrimaryAffiliation == "student" && + Deno.env.get("LOCAL") != "true" + ) { + properties.adminOnly.forEach((page) => + delete context.state.availablePages[page] + ); + } + + return await context.next(); + }, +];