diff --git a/.env.local.template b/.env.local.template new file mode 100644 index 0000000..6477a72 --- /dev/null +++ b/.env.local.template @@ -0,0 +1,5 @@ +GOOGLE_CLIENT_ID=your-google-client-id +GOOGLE_CLIENT_SECRET=your-google-client-secret + +NEXTAUTH_SECRET=your-secret-key +NEXTAUTH_URL=http://localhost:3000 diff --git a/app/admin/applications/page.tsx b/app/admin/applications/page.tsx new file mode 100644 index 0000000..7a56249 --- /dev/null +++ b/app/admin/applications/page.tsx @@ -0,0 +1,9 @@ +const ApplicationsPage = () => { + return ( +
+

Søknader

+
+ ); +}; + +export default ApplicationsPage; diff --git a/app/admin/layout.tsx b/app/admin/layout.tsx new file mode 100644 index 0000000..2e186b7 --- /dev/null +++ b/app/admin/layout.tsx @@ -0,0 +1,76 @@ +'use client'; + +import { signIn, signOut, useSession } from 'next-auth/react'; +import Button from '@/components/all/Button'; + +export default function AdminLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + const { data: session, status } = useSession(); + + const handleLogin = () => + signIn('google', { + callbackUrl: '/admin', + }); + + const handleLogout = () => signOut({ callbackUrl: '/' }); + + if (status === 'loading') { + return ( +
+
+
+

+ Laster inn administrasjonspanel... +

+

+ Vennligst vent mens vi henter informasjonen din +

+
+
+ ); + } + + if (!session) { + return ( +
+
+

Vennligst logg inn

+
+
+ ); + } + + if (session?.user?.role !== 'admin') { + console.log(session.user); + return ( +
+
+

Du har ikke tilgang til denne siden

+

{session.user?.name}

+
+
+ ); + } + if (session && session?.user?.role === 'admin') { + return ( +
+
+ {children} +
+
+ ); + } +} diff --git a/app/admin/members/page.tsx b/app/admin/members/page.tsx new file mode 100644 index 0000000..9124d90 --- /dev/null +++ b/app/admin/members/page.tsx @@ -0,0 +1,9 @@ +const MembersPage = () => { + return ( +
+

Medlemmer

+
+ ); +}; + +export default MembersPage; diff --git a/app/admin/page.tsx b/app/admin/page.tsx new file mode 100644 index 0000000..a254a5f --- /dev/null +++ b/app/admin/page.tsx @@ -0,0 +1,56 @@ +'use client'; + +import { useSession } from 'next-auth/react'; +import Link from 'next/link'; +import { CircleDollarSignIcon, PaperclipIcon, UserIcon } from 'lucide-react'; + +const AdminPage = () => { + const { data: session } = useSession(); + + const routes = [ + { + title: 'Portfølje', + href: '/admin/portfolio', + icon: CircleDollarSignIcon, + }, + { + title: 'Medlemmer', + href: '/admin/members', + icon: UserIcon, + }, + { + title: 'Søknader', + href: '/admin/applications', + icon: PaperclipIcon, + }, + ]; + + return ( +
+
+

{`Velkommen ${session?.user!.name}`}

+ +
+ {routes.map((route, index) => ( +
+ +
+
+

+ {route.title} +

+
+ +
+
+
+ +
+ ))} +
+
+
+ ); +}; + +export default AdminPage; diff --git a/app/admin/portfolio/page.tsx b/app/admin/portfolio/page.tsx new file mode 100644 index 0000000..b9009f3 --- /dev/null +++ b/app/admin/portfolio/page.tsx @@ -0,0 +1,9 @@ +const PortfolioPage = () => { + return ( +
+

Portfølje

+
+ ); +}; + +export default PortfolioPage; diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 0000000..03b1b98 --- /dev/null +++ b/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,54 @@ +import { getUserGroups } from '@/lib/auth/getUserGroups'; +import NextAuth from 'next-auth'; +import GoogleProvider from 'next-auth/providers/google'; + +const handler = NextAuth({ + providers: [ + GoogleProvider({ + clientId: process.env.GOOGLE_CLIENT_ID || '', + clientSecret: process.env.GOOGLE_CLIENT_SECRET || '', + authorization: { + params: { + scope: + 'openid email profile https://www.googleapis.com/auth/admin.directory.group.readonly', + }, + }, + }), + ], + pages: { + signIn: '/auth/signin', + signOut: '/auth/signout', + }, + callbacks: { + async jwt({ token, account, user }) { + if (account) { + token.accessToken = account.access_token; + } + + if (token.accessToken && user?.email) { + token.groups = await getUserGroups( + token.accessToken as string, + user.email, + ); + } + + return token; + }, + async session({ session, token }) { + session.user = { + id: token.sub ? parseInt(token.sub, 10) : 0, + name: session.user?.name || '', + role: + session.user?.email == 'fredrik.carsten.hansteen@online.ntnu.no' || + 'julian.ottosen@online.ntnu.no ' + ? 'admin' + : 'user', //TODO vente på dotkom + email: session.user?.email || '', + groups: (token.groups as string[]) || [], + }; + return session; + }, + }, +}); + +export { handler as GET, handler as POST }; diff --git a/app/layout.tsx b/app/layout.tsx index 91d2413..c440e63 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from 'next'; import './globals.css'; import Navbar from '@/components/all/Navbar'; import Footer from '@/components/all/Footer'; +import SessionWrapper from '@/lib/auth/SessionWrapper'; // TODO: add favicon, and maybe dynamic title and description based on page export const metadata: Metadata = { @@ -20,9 +21,11 @@ export default function RootLayout({ - - {children} -