From 2eaccd52e4475b7986c2aa1e93228a59dd0f0153 Mon Sep 17 00:00:00 2001 From: Fayorg Date: Fri, 15 Dec 2023 15:21:51 +0100 Subject: [PATCH] add: using nextauth WIP --- app/api/auth/[...nextauth]/route.ts | 6 ++ app/dashboard/page.tsx | 5 ++ app/page.tsx | 35 ++++---- lib/authenticate.ts | 73 ++++++++++++++++ package-lock.json | 124 +++++++++++++++++++++++++++- package.json | 1 + types/next-auth.d.ts | 28 +++++++ 7 files changed, 255 insertions(+), 17 deletions(-) create mode 100644 app/api/auth/[...nextauth]/route.ts create mode 100644 lib/authenticate.ts create mode 100644 types/next-auth.d.ts diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 0000000..4ac2005 --- /dev/null +++ b/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,6 @@ +import NextAuth from "next-auth"; + +import { authOptions } from "@lib/authenticate"; + +const handler = NextAuth(authOptions); +export { handler as GET, handler as POST }; \ No newline at end of file diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index 7cf6c54..1ea4753 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -1,5 +1,6 @@ import prisma from '@/lib/prisma'; import ActiveCard from './ActiveCard'; +import { getAuthServerSession } from '@/lib/authenticate'; export default async function Dashboard() { const tests = await prisma.test.findMany({ select: { isActive: true, isPassed: true, id: true, testOf: { select: { id: true, firstName: true, lastName: true, isTeacher: true } } } }); @@ -7,6 +8,10 @@ export default async function Dashboard() { const activeTests = tests.filter((test) => test.isActive); const passedTests = tests.filter((test) => test.isPassed); + const authSession = await getAuthServerSession(); + + console.log(authSession); + return (

Dashboard

diff --git a/app/page.tsx b/app/page.tsx index f0bd99a..3949590 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,14 +1,15 @@ 'use client'; -import { Poppins } from 'next/font/google' -import { Check } from 'lucide-react' +import { Poppins } from 'next/font/google'; +import { Check } from 'lucide-react'; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import logo from '../images/logo.svg'; -import Image from "next/image"; -import {Input} from "@components/ui/input"; -import {white} from "next/dist/lib/picocolors"; +import Image from 'next/image'; +import { Input } from '@components/ui/input'; +import { white } from 'next/dist/lib/picocolors'; +import { signIn } from 'next-auth/react'; export default function Home() { const [password, setPassword] = useState(''); @@ -20,21 +21,27 @@ export default function Home() { } }, [router]); - function handleSubmit(event: React.FormEvent) { + async function handleSubmit(event: React.FormEvent) { event.preventDefault(); - localStorage.setItem('@password', password); - router.push('/play'); + // localStorage.setItem('@password', password); + // router.push('/play'); + + console.log('Trying to sign in'); + const result = await signIn('credentials', { + key: password, + callbackUrl: '/play', + }); } return ( -
- {"Logo"} -
+
+ {'Logo'} + setPassword(e.target.value)}> - -
diff --git a/lib/authenticate.ts b/lib/authenticate.ts new file mode 100644 index 0000000..409f9aa --- /dev/null +++ b/lib/authenticate.ts @@ -0,0 +1,73 @@ +import Credentials from "next-auth/providers/credentials"; +import prisma from "./prisma"; +import { getServerSession, RequestInternal, type NextAuthOptions, User } from "next-auth"; + +export async function authenticate(key: string) { + console.log("Running authenticate function with key: " + key); + const user = await prisma.users.findUnique({ + select: { + id: true, + firstName: true, + lastName: true, + isTeacher: true + }, + where: { + key: key + } + }); + + console.log("Found user: " + JSON.stringify(user)); + + if(!user) return null; + + return user; +} + +export const authOptions: NextAuthOptions = { + session: { + strategy: "jwt", + }, + callbacks: { + async jwt({ token, user }) { + if (user) { + token.userId = user.id; + token.firstName = user.firstName; + token.lastName = user.lastName; + token.isTeacher = user.isTeacher; + } + return token; + }, + async session({ session, token, user }) { + session.user.id = token.userId; + session.user.firstName = token.firstName; + session.user.lastName = token.lastName; + session.user.isTeacher = token.isTeacher; + return session; + }, + }, + pages: { + signIn: '/', + }, + providers: [ + Credentials({ + name: "Credentials", + credentials: { + key: { label: "Key", type: "password" } + }, + async authorize(credentials: Record<"key", string> | undefined, req: Pick) { + const { key } = credentials as { + key: string + }; + console.log("Running authorize function with key: " + key) + + const user = await authenticate(key) as User | null + + console.log("Found user in authorize: " + JSON.stringify(user)); + + return user; + } + }) + ], + }; + +export const getAuthServerSession = () => getServerSession(authOptions); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3f0538a..de67b82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "clsx": "^2.0.0", "lucide-react": "^0.294.0", "next": "14.0.3", + "next-auth": "^4.24.5", "prisma": "^5.6.0", "react": "^18", "react-chartjs-2": "^5.2.0", @@ -425,6 +426,14 @@ "node": ">= 8" } }, + "node_modules/@panva/hkdf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.1.1.tgz", + "integrity": "sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/@prisma/client": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.6.0.tgz", @@ -3498,6 +3507,14 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jose": { + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz", + "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3649,7 +3666,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -3815,6 +3831,41 @@ } } }, + "node_modules/next-auth": { + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.5.tgz", + "integrity": "sha512-3RafV3XbfIKk6rF6GlLE4/KxjTcuMCifqrmD+98ejFq73SRoj2rmzoca8u764977lH/Q7jo6Xu6yM+Re1Mz/Og==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@panva/hkdf": "^1.0.2", + "cookie": "^0.5.0", + "jose": "^4.11.4", + "oauth": "^0.9.15", + "openid-client": "^5.4.0", + "preact": "^10.6.3", + "preact-render-to-string": "^5.1.19", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "next": "^12.2.5 || ^13 || ^14", + "nodemailer": "^6.6.5", + "react": "^17.0.2 || ^18", + "react-dom": "^17.0.2 || ^18" + }, + "peerDependenciesMeta": { + "nodemailer": { + "optional": true + } + } + }, + "node_modules/next-auth/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -3865,6 +3916,11 @@ "node": ">=0.10.0" } }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3990,6 +4046,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oidc-token-hash": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", + "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==", + "engines": { + "node": "^10.13.0 || >=12.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3998,6 +4062,28 @@ "wrappy": "1" } }, + "node_modules/openid-client": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.6.1.tgz", + "integrity": "sha512-PtrWsY+dXg6y8mtMPyL/namZSYVz8pjXz3yJiBNZsEdCnu9miHLB4ELVC85WvneMKo2Rg62Ay7NkuCpM0bgiLQ==", + "dependencies": { + "jose": "^4.15.1", + "lru-cache": "^6.0.0", + "object-hash": "^2.2.0", + "oidc-token-hash": "^5.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/openid-client/node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "engines": { + "node": ">= 6" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -4267,6 +4353,26 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/preact": { + "version": "10.19.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.3.tgz", + "integrity": "sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/preact-render-to-string": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz", + "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==", + "dependencies": { + "pretty-format": "^3.8.0" + }, + "peerDependencies": { + "preact": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4276,6 +4382,11 @@ "node": ">= 0.8.0" } }, + "node_modules/pretty-format": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", + "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" + }, "node_modules/prisma": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.6.0.tgz", @@ -5316,6 +5427,14 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -5463,8 +5582,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "2.3.4", diff --git a/package.json b/package.json index 84282f2..58cf82e 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "clsx": "^2.0.0", "lucide-react": "^0.294.0", "next": "14.0.3", + "next-auth": "^4.24.5", "prisma": "^5.6.0", "react": "^18", "react-chartjs-2": "^5.2.0", diff --git a/types/next-auth.d.ts b/types/next-auth.d.ts new file mode 100644 index 0000000..e139bbc --- /dev/null +++ b/types/next-auth.d.ts @@ -0,0 +1,28 @@ +import NextAuth, { DefaultSession, DefaultJWT, DefaultUser } from "next-auth"; +import { JWT } from "next-auth/jwt"; + +declare module "next-auth" { + interface Session extends Omit { + user: { + id: number; + firstName: string; + lastName: string + isTeacher: boolean; + }; + } + interface User { + id: number; + firstName: string; + lastName: string + isTeacher: boolean; + } +} + +declare module "next-auth/jwt" { + interface JWT { + userId: number; + firstName: string; + lastName: string + isTeacher: boolean; + } +} \ No newline at end of file