From 31a0c622d5fa41e3dcb87bba6ce591139422b592 Mon Sep 17 00:00:00 2001 From: Tim Howitz Date: Mon, 19 May 2025 13:11:02 +0100 Subject: [PATCH] Added auto get-user with jwt --- src/app/api/get-user/route.ts | 50 +++++++++++++++++++++++++++++++++++ src/app/layout.tsx | 36 ++++++++++++++++++------- 2 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 src/app/api/get-user/route.ts diff --git a/src/app/api/get-user/route.ts b/src/app/api/get-user/route.ts new file mode 100644 index 0000000..fcf1e36 --- /dev/null +++ b/src/app/api/get-user/route.ts @@ -0,0 +1,50 @@ +import { NextResponse } from "next/server"; +import { cookies } from "next/headers"; +import { env } from "@utils/env"; +import { PrismaClient } from "@prisma/client"; +import { verifyJwt } from "@utils/verifyJwt"; + +const prisma = new PrismaClient(); + +export async function POST(req: Request) { + let cookieStore; + try { + cookieStore = await cookies(); + const token = cookieStore.get("jwt")?.value; + + if (!token) { + return NextResponse.json({ error: "No JWT found" }, { status: 401 }); + } + + const payload = await verifyJwt({ token, secret: env.JWT_SECRET_KEY }); + + const user = await prisma.user.findUnique({ + where: { id: payload.userId }, + include: { + scientist: { + include: { + earthquakes: true, + observatories: true, + artefacts: true, + superior: true, + subordinates: true, + }, + }, + purchasedArtefacts: true, + }, + }); + + if (user) { + return NextResponse.json({ message: "Got user successfully", user }, { status: 200 }); + } else { + cookieStore.delete("jwt"); // Delete JWT cookie if user not found } + return NextResponse.json({ message: "Failed to get user" }, { status: 401 }); + } + } catch (error) { + console.error("Error in user endpoint:", error); + cookieStore?.delete("jwt"); // Delete JWT cookie on error + return NextResponse.json({ message: "Internal Server Error" }, { status: 500 }); + } finally { + await prisma.$disconnect(); + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6e1c55b..224fa85 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,8 +1,11 @@ "use client"; +import axios from "axios"; +import { useEffect } from "react"; import type { Metadata } from "next"; import "./globals.css"; import { action, createStore, StoreProvider } from "easy-peasy"; +import { useStoreActions } from "@hooks/store"; import { Inter } from "next/font/google"; import { StoreModel } from "@appTypes/StoreModel"; @@ -24,21 +27,33 @@ const store = createStore({ tickers: { GBP: "£", USD: "$", EUR: "€" }, }, user: null, - // user: { - // id: 123456, - // createdAt: new Date(8.64e15), - // email: "tim.howitz@dyson.com", - // passwordHash: "", - // name: "Tim Howitz", - // role: "ADMIN", - // scientist: undefined, - // purchasedArtefacts: [], - // }, setUser: action((state, payload) => { state.user = payload; }), }); +function UserFetcher() { + const setUser = useStoreActions((actions) => actions.setUser); + + useEffect(() => { + async function fetchUser() { + try { + const response = await axios.post("/api/get-user"); + if (response.status === 200 && response.data.user) { + setUser(response.data.user); + } else { + setUser(null); // Clear user if no user found + } + } catch (error) { + console.error("Error fetching user:", error); + setUser(null); + } + } + fetchUser(); + }, [setUser]); // Run once on mount + + return null; // No UI needed +} export default function RootLayout({ children, }: Readonly<{ @@ -48,6 +63,7 @@ export default function RootLayout({ +
{children}