From 85afa969f14e906fdce7b03613166499ff1f3521 Mon Sep 17 00:00:00 2001 From: Mona Mayrhofer Date: Thu, 3 Apr 2025 13:34:45 +0200 Subject: [PATCH] feat(auth): login state proof of concept --- bun.lockb | Bin 264020 -> 277908 bytes packages/web/app/auth/requiresLogin.tsx | 13 +++ packages/web/app/auth/serverAuthMiddleware.ts | 35 ++++++++ packages/web/app/root.tsx | 33 +++++--- packages/web/app/routes.ts | 18 +++- packages/web/app/routes/home.tsx | 13 ++- packages/web/app/routes/login.tsx | 30 +++++++ packages/web/app/routes/logout.tsx | 11 +++ packages/web/app/routes/temp_list.tsx | 32 ++++++++ packages/web/app/welcome/welcome.tsx | 77 ------------------ packages/web/package.json | 2 + packages/web/react-router.config.ts | 16 ++++ packages/web/tsconfig.json | 2 +- packages/web/vite.config.ts | 2 + 14 files changed, 188 insertions(+), 96 deletions(-) create mode 100644 packages/web/app/auth/requiresLogin.tsx create mode 100644 packages/web/app/auth/serverAuthMiddleware.ts create mode 100644 packages/web/app/routes/login.tsx create mode 100644 packages/web/app/routes/logout.tsx create mode 100644 packages/web/app/routes/temp_list.tsx delete mode 100644 packages/web/app/welcome/welcome.tsx diff --git a/bun.lockb b/bun.lockb index 078415fed95d5313804da30d06bb3ca04ef858c6..f24e64ac0e42f060ed336a1000eb75b078df35cb 100755 GIT binary patch delta 58756 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 + + + ); +} diff --git a/packages/web/app/auth/serverAuthMiddleware.ts b/packages/web/app/auth/serverAuthMiddleware.ts new file mode 100644 index 0000000..a273f2e --- /dev/null +++ b/packages/web/app/auth/serverAuthMiddleware.ts @@ -0,0 +1,35 @@ +"use server"; +import type { unstable_MiddlewareFunction } from "react-router"; +import { unstable_createContext } from "react-router"; +import { createCookie } from "react-router"; +import { redirect } from "react-router"; + +//TODO use session cookies: https://reactrouter.com/explanation/sessions-and-cookies#login-form-example + +export const authCookie = createCookie("tdk-session", { + //TODO Thnis is just a bit wonky + httpOnly: true, + path: "/", + sameSite: "lax", + secrets: ["dev-secret"], + secure: true, +}); + +export const serverAuthContext = unstable_createContext(); + +export const serverAuthMiddleware: unstable_MiddlewareFunction< + Response +> = async ({ request, context }, next) => { + const ac = await authCookie.parse(request.headers.get("Cookie")); + + console.log(ac); + + if (ac == null || typeof ac !== "string") { + throw redirect("/login"); + } + + context.set(serverAuthContext, ac); + + const res = await next(); + return res; +}; diff --git a/packages/web/app/root.tsx b/packages/web/app/root.tsx index 897cf5a..354ee02 100644 --- a/packages/web/app/root.tsx +++ b/packages/web/app/root.tsx @@ -9,23 +9,30 @@ import { import type { Route } from "./+types/root"; import "./app.css"; +import "@pigment-css/react/styles.css"; +import { css } from "@pigment-css/react"; + +const rootStyles = css({ + background: "black", + color: "white", +}); export const links: Route.LinksFunction = () => [ - { rel: "preconnect", href: "https://fonts.googleapis.com" }, - { - rel: "preconnect", - href: "https://fonts.gstatic.com", - crossOrigin: "anonymous", - }, - { - rel: "stylesheet", - href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap", - }, + // { rel: "preconnect", href: "https://fonts.googleapis.com" }, + // { + // rel: "preconnect", + // href: "https://fonts.gstatic.com", + // crossOrigin: "anonymous", + // }, + // { + // rel: "stylesheet", + // href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap", + // }, ]; export function Layout({ children }: { children: React.ReactNode }) { return ( - + @@ -62,11 +69,11 @@ export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) { } return ( -
+

{message}

{details}

{stack && ( -
+        
           {stack}
         
)} diff --git a/packages/web/app/routes.ts b/packages/web/app/routes.ts index 102b402..294169e 100644 --- a/packages/web/app/routes.ts +++ b/packages/web/app/routes.ts @@ -1,3 +1,17 @@ -import { type RouteConfig, index } from "@react-router/dev/routes"; +import { + type RouteConfig, + index, + layout, + route, +} from "@react-router/dev/routes"; -export default [index("routes/home.tsx")] satisfies RouteConfig; +export default [ + index("routes/home.tsx"), + + route("login", "routes/login.tsx"), + route("logout", "routes/logout.tsx"), + + layout("auth/requiresLogin.tsx", [ + route("temp_list", "routes/temp_list.tsx"), + ]), +] satisfies RouteConfig; diff --git a/packages/web/app/routes/home.tsx b/packages/web/app/routes/home.tsx index 4777829..7864be2 100644 --- a/packages/web/app/routes/home.tsx +++ b/packages/web/app/routes/home.tsx @@ -1,4 +1,7 @@ -import { Welcome } from "../welcome/welcome"; +import { useOutletContext } from "react-router"; +import type { LoaderFunctionArgs } from "react-router"; +import { unstable_createContext } from "react-router"; +import { NavLink } from "react-router"; import type { Route } from "./+types/home"; export function meta(m: Route.MetaArgs) { @@ -8,6 +11,10 @@ export function meta(m: Route.MetaArgs) { ]; } -export default function Home() { - return ; +export default function Home(p: Route.ComponentProps) { + return ( + + ); } diff --git a/packages/web/app/routes/login.tsx b/packages/web/app/routes/login.tsx new file mode 100644 index 0000000..9133092 --- /dev/null +++ b/packages/web/app/routes/login.tsx @@ -0,0 +1,30 @@ +import { data, redirect, useFetcher } from "react-router"; +import { authCookie } from "../auth/serverAuthMiddleware"; +import type { Route } from "./+types/login"; + +export async function loader(p: Route.LoaderArgs) { + const c = await authCookie.parse(p.request.headers.get("Cookie")); + if (c != null) { + return redirect("/"); + } + return data(""); +} + +export async function action(p: Route.ActionArgs) { + console.log("Logged in"); + return data("", { + headers: { "Set-Cookie": await authCookie.serialize("Blubby") }, + }); +} + +export default function Login(p: Route.ComponentProps) { + const fetcher = useFetcher(); + + return ( +
+ + + +
+ ); +} diff --git a/packages/web/app/routes/logout.tsx b/packages/web/app/routes/logout.tsx new file mode 100644 index 0000000..e79c4e6 --- /dev/null +++ b/packages/web/app/routes/logout.tsx @@ -0,0 +1,11 @@ +import { data } from "react-router"; +import { authCookie } from "../auth/serverAuthMiddleware"; +import type { Route } from "./+types/logout"; + +export async function action(p: Route.ActionArgs) { + return data("", { + headers: { + "Set-Cookie": await authCookie.serialize("", { expires: new Date(0) }), + }, + }); +} diff --git a/packages/web/app/routes/temp_list.tsx b/packages/web/app/routes/temp_list.tsx new file mode 100644 index 0000000..cc1fe30 --- /dev/null +++ b/packages/web/app/routes/temp_list.tsx @@ -0,0 +1,32 @@ +import type { unstable_MiddlewareFunction } from "react-router"; +import { useFetcher, useRouteError } from "react-router"; +import type { ShouldRevalidateFunctionArgs } from "react-router"; +import { + serverAuthContext, + serverAuthMiddleware, +} from "../auth/serverAuthMiddleware"; +import type { Route } from "./+types/temp_list"; + +export async function loader(p: Route.LoaderArgs) { + const authc = p.context.get(serverAuthContext); + return { + user: authc, + }; +} + +export const unstable_middleware: Route.unstable_MiddlewareFunction[] = [ + serverAuthMiddleware, +]; + +export default function TempList({ loaderData }: Route.ComponentProps) { + const logout = useFetcher(); + + return ( +
+

Route TempList User: {JSON.stringify(loaderData)}

+ + + +
+ ); +} diff --git a/packages/web/app/welcome/welcome.tsx b/packages/web/app/welcome/welcome.tsx deleted file mode 100644 index 22db177..0000000 --- a/packages/web/app/welcome/welcome.tsx +++ /dev/null @@ -1,77 +0,0 @@ -export function Welcome() { - return ( -
- -
- ); -} - -const resources = [ - { - href: "https://reactrouter.com/docs", - text: "React Router Docs", - icon: ( - // biome-ignore lint/a11y/noSvgWithoutTitle: - - - - ), - }, - { - href: "https://rmx.as/discord", - text: "Join Discord", - icon: ( - // biome-ignore lint/a11y/noSvgWithoutTitle: - - - - ), - }, -]; diff --git a/packages/web/package.json b/packages/web/package.json index ecc47c3..ffeb837 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -13,6 +13,7 @@ "test": "vitest" }, "dependencies": { + "@pigment-css/react": "0.0.30", "@react-router/node": "7.4.1", "@react-router/serve": "7.4.1", "effect": "3.14.5", @@ -25,6 +26,7 @@ }, "devDependencies": { "@biomejs/biome": "1.9.4", + "@pigment-css/vite-plugin": "0.0.30", "@react-router/dev": "7.4.1", "@types/lodash": "4.17.16", "@types/node": "22.13.17", diff --git a/packages/web/react-router.config.ts b/packages/web/react-router.config.ts index 6ff16f9..f4fd49c 100644 --- a/packages/web/react-router.config.ts +++ b/packages/web/react-router.config.ts @@ -1,7 +1,23 @@ import type { Config } from "@react-router/dev/config"; +import { type Future, Route } from "react-router"; + +declare module "react-router" { + interface Future { + unstable_middleware: true; // 👈 Enable middleware types + } + //AppLoadContext is replaced with the ContextAPI enabled by the unstable_middlewares flag + // interface AppLoadContext { + // remove_me_i_am_a_test: string; + // } +} export default { // Config options... // Server-side render by default, to enable SPA mode set this to `false` ssr: true, + future: { + //TODO Keep up to date with the unstable releases over at https://reactrouter.com/changelog + //See: https://github.com/remix-run/react-router/blob/release-next/decisions/0014-context-middleware.md + unstable_middleware: true, + }, } satisfies Config; diff --git a/packages/web/tsconfig.json b/packages/web/tsconfig.json index 9699591..0769318 100644 --- a/packages/web/tsconfig.json +++ b/packages/web/tsconfig.json @@ -1,7 +1,7 @@ { "files": [], "extends": "../../tsconfig.base.json", - "include": ["app"], + "include": ["app", "*.ts"], "compilerOptions": { "types": ["vitest/importMeta", "vite/client", "node"], "rootDirs": [".", "./.react-router/types"], diff --git a/packages/web/vite.config.ts b/packages/web/vite.config.ts index 389061b..2e230db 100644 --- a/packages/web/vite.config.ts +++ b/packages/web/vite.config.ts @@ -1,3 +1,4 @@ +import { pigment } from "@pigment-css/vite-plugin"; import { reactRouter } from "@react-router/dev/vite"; import { defineConfig } from "vite"; import checker from "vite-plugin-checker"; @@ -5,6 +6,7 @@ import checker from "vite-plugin-checker"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [ + pigment({}), checker({ biome: { command: "check", dev: { command: "lint" } }, typescript: true,