From a9d4fbedcfe027319c9b17b85f0950000a4f4643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi?= Date: Sun, 5 Jan 2025 01:09:03 +0100 Subject: [PATCH] fix: auth ssr to rendering admin btn and username --- src/app/admin/page.tsx | 14 +++++++ src/app/components/Header/admin.tsx | 32 ++++++++++++++++ src/app/components/Header/index.tsx | 38 ++++--------------- .../ThemeSwitcher/ThemeSwitcher.tsx | 22 ++++++----- src/app/page.tsx | 8 +++- src/app/types/next-auth.d.ts | 12 +++++- src/authOptions.ts | 16 +++++++- 7 files changed, 95 insertions(+), 47 deletions(-) create mode 100644 src/app/admin/page.tsx create mode 100644 src/app/components/Header/admin.tsx diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx new file mode 100644 index 0000000..2323c42 --- /dev/null +++ b/src/app/admin/page.tsx @@ -0,0 +1,14 @@ +import { Metadata } from "next"; +import { AdminHeader } from "../components/Header/admin"; +import { getServerSession } from "next-auth"; +import { authOptions } from "@/authOptions"; + +export const metadata: Metadata = { + title: "Toogether Admin", +}; + +export default async function AdminPage() { + const session = await getServerSession(authOptions); + + return ; +} diff --git a/src/app/components/Header/admin.tsx b/src/app/components/Header/admin.tsx new file mode 100644 index 0000000..33c3278 --- /dev/null +++ b/src/app/components/Header/admin.tsx @@ -0,0 +1,32 @@ +"use client"; + +export const AdminHeader = () => { + return ( + <> + + + + ); +}; diff --git a/src/app/components/Header/index.tsx b/src/app/components/Header/index.tsx index e88053b..bf2df76 100644 --- a/src/app/components/Header/index.tsx +++ b/src/app/components/Header/index.tsx @@ -1,4 +1,5 @@ "use client"; +import { User } from "@/app/types/next-auth"; import { Avatar, Button, @@ -11,11 +12,8 @@ import { NavbarContent, NavbarItem, } from "@nextui-org/react"; -import { useSession } from "next-auth/react"; -import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher"; -import { axiosInstance } from "@/app/lib/axios"; -import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; +import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher"; const getInitials = (name: string) => { if (!name) return ""; @@ -31,31 +29,10 @@ const getInitials = (name: string) => { return firstInitial + secondInitial; }; -export const Header = () => { - const { data: session } = useSession(); +export const Header = ({ user }: { user?: User }) => { const router = useRouter(); - const [userProfile, setUserProfile] = useState<{ - id: string; - username: string; - role: "ADMIN" | "STUDENT"; - }>(); - - const initials = session?.user?.name ? getInitials(session.user.name) : ""; - - const fetchUserProfile = async () => { - return await axiosInstance<{ - id: string; - username: string; - role: "ADMIN" | "STUDENT"; - }>("/@me"); - }; - - useEffect(() => { - fetchUserProfile().then((r) => { - setUserProfile(r.data); - }); - }, []); + const initials = user?.name ? getInitials(user.name) : ""; return ( @@ -64,7 +41,7 @@ export const Header = () => { - {userProfile?.role === "ADMIN" ? ( + {user?.roles.includes("admin") ? ( ) : null} + @@ -94,9 +72,7 @@ export const Header = () => {

Signed in as

-

- {session?.user?.name} -

+

{user?.name}

Settings { setMounted(true); }, []); - if (!mounted) return null; - return ( - +
+ +
); }; diff --git a/src/app/page.tsx b/src/app/page.tsx index 54687c1..b7f4a44 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,4 +1,6 @@ +import { authOptions } from "@/authOptions"; import { Metadata } from "next"; +import { getServerSession } from "next-auth"; import { Header } from "./components/Header"; import { RoomTable } from "./components/Room/Table"; @@ -8,10 +10,12 @@ export const metadata: Metadata = { "Toogether is a platform that allows you to create and join rooms to study together.", }; -export default function HomePage() { +export default async function HomePage() { + const session = await getServerSession(authOptions); + return ( <> -
+
diff --git a/src/app/types/next-auth.d.ts b/src/app/types/next-auth.d.ts index d0cbdeb..4d94253 100644 --- a/src/app/types/next-auth.d.ts +++ b/src/app/types/next-auth.d.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { Moment } from "moment"; -import NextAuth, { DefaultSession } from "next-auth"; -import { JWT } from "next-auth/jwt"; +import { DefaultSession } from "next-auth"; +import "next-auth/jwt"; interface User { id: string; @@ -10,6 +10,14 @@ interface User { preferred_username: string; given_name: string; family_name: string; + email: string; + roles: string[]; +} + +export interface JWTDecoded { + realm_access: { + roles: string[]; + }; } declare module "next-auth" { diff --git a/src/authOptions.ts b/src/authOptions.ts index 5aac6ab..3e6f86f 100644 --- a/src/authOptions.ts +++ b/src/authOptions.ts @@ -2,6 +2,8 @@ import axios from "axios"; import moment from "moment"; import { AuthOptions, Session } from "next-auth"; import { JWT } from "next-auth/jwt"; +import jsonwebtoken from "jsonwebtoken"; +import { JWTDecoded } from "./app/types/next-auth"; moment.locale("fr"); @@ -16,7 +18,7 @@ export const authOptions: AuthOptions = { authorization: { url: process.env.OAUTH_AUTHORIZATION_URL, params: { - scope: "openid profile offline_access", + scope: "openid email profile offline_access", response_type: "code", }, }, @@ -33,6 +35,7 @@ export const authOptions: AuthOptions = { profile.name || profile.preferred_username || `${profile.given_name} ${profile.family_name}`, + email: profile.email, }; }, }, @@ -45,7 +48,16 @@ export const authOptions: AuthOptions = { account.expires_at * 1000, ).subtract(5, "s"); token.refreshToken = account.refresh_token; - token.user = user; + + const accessTokenDecode = jsonwebtoken.decode( + account.access_token, + ) as JWTDecoded; + + token.user = { + ...user, + roles: accessTokenDecode.realm_access.roles, + }; + return token; }