From e307ba44fbf66fe75b8021b8f136c1908f084a83 Mon Sep 17 00:00:00 2001 From: "tabler.developer@gmail.com" Date: Sun, 20 Aug 2023 16:43:59 +0200 Subject: [PATCH] add credentials provider --- site/app/api/register/route.ts | 42 +++ site/components/Signin.tsx | 83 +++++- site/components/Signup.tsx | 82 +++++- site/lib/auth.ts | 88 +++++- site/package.json | 1 + site/pnpm-lock.yaml | 254 ++++++++++++++++++ .../migration.sql | 1 + site/prisma/schema.prisma | 1 + 8 files changed, 529 insertions(+), 23 deletions(-) create mode 100644 site/app/api/register/route.ts rename site/prisma/migrations/{20230814193559_init => 20230819000033_init}/migration.sql (98%) diff --git a/site/app/api/register/route.ts b/site/app/api/register/route.ts new file mode 100644 index 00000000..f259012b --- /dev/null +++ b/site/app/api/register/route.ts @@ -0,0 +1,42 @@ +import prisma from '@/lib/prisma'; +import { hash } from 'bcrypt'; +import { NextResponse } from 'next/server'; + +export async function POST(req: Request) { + try { + const { name, email, password } = (await req.json()) as { + name: string; + email: string; + password: string; + }; + + if (!name || !email || !password) { + throw { message: 'all fields are required' }; + } + + const hashedPassword = await hash(password, 12); + + const user = await prisma.user.create({ + data: { + name, + email: email.toLowerCase(), + password: hashedPassword, + }, + }); + + return NextResponse.json({ + user: { + name: user.name, + email: user.email, + }, + }); + } catch (error: any) { + return new NextResponse( + JSON.stringify({ + status: 'error', + message: error.message, + }), + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/site/components/Signin.tsx b/site/components/Signin.tsx index a38a6cd3..ec558b42 100644 --- a/site/components/Signin.tsx +++ b/site/components/Signin.tsx @@ -1,17 +1,54 @@ 'use client'; import Link from '@/components/Link'; -import { useRouter } from 'next/navigation'; +import { useSearchParams, useRouter } from 'next/navigation'; import Icon from '@/components/Icon'; import { signIn } from 'next-auth/react'; +import { ChangeEvent, useState } from 'react'; export default function Signin() { - const router = useRouter();'/'; + const router = useRouter(); + const [loading, setLoading] = useState(false); + const [formValues, setFormValues] = useState({ + email: '', + password: '', + }); + const [error, setError] = useState(''); - const handleLogin = async (provider: 'github' | 'google'): Promise => { - await signIn(provider, {callbackUrl: '/'}); + const searchParams = useSearchParams(); + const callbackUrl = searchParams.get('callbackUrl') || '/'; + + const onSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + try { + setLoading(true); + setFormValues({ email: '', password: '' }); + + const res = await signIn('credentials', { + redirect: false, + email: formValues.email, + password: formValues.password, + callbackUrl, + }); + + setLoading(false); + + if (!res?.error) { + router.push(callbackUrl); + } else { + setError('invalid email or password'); + } + } catch (error: any) { + setLoading(false); + setError(error); + } }; + const handleChange = (event: ChangeEvent) => { + const { name, value } = event.target; + setFormValues({ ...formValues, [name]: value }); + }; + return ( <>
@@ -20,21 +57,47 @@ export default function Signin() {

Login to your account

-
+ { + error && +

{error}

+ } +
- +
- +
- +
@@ -42,13 +105,13 @@ export default function Signin() {
- handleLogin('google')} className="btn w-100"> + signIn('google', { callbackUrl })} className="btn w-100"> Login with Google diff --git a/site/components/Signup.tsx b/site/components/Signup.tsx index b7f8a932..071dde5b 100644 --- a/site/components/Signup.tsx +++ b/site/components/Signup.tsx @@ -2,30 +2,104 @@ import Link from '@/components/Link'; import { useRouter } from 'next/navigation'; +import { ChangeEvent, useState } from 'react'; +import { signIn } from 'next-auth/react'; export default function Signup() { const router = useRouter(); + const [loading, setLoading] = useState(false); + const [formValues, setFormValues] = useState({ + name: '', + email: '', + password: '', + }); + const [error, setError] = useState(''); + + const onSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + setFormValues({ name: '', email: '', password: '' }); + + try { + const res = await fetch('/api/register', { + method: 'POST', + body: JSON.stringify(formValues), + headers: { + 'Content-Type': 'application/json', + }, + }); + + setLoading(false); + if (!res.ok) { + setError((await res.json()).message); + return; + } + + signIn(undefined, { callbackUrl: '/' }); + } catch (error: any) { + setLoading(false); + setError(error); + } + }; + + const handleChange = (event: ChangeEvent) => { + const { name, value } = event.target; + setFormValues({ ...formValues, [name]: value }); + }; return ( <>
-
+

Create new account

+ { + error && +

{error}

+ } +
+ + +
- +
- +
- +
diff --git a/site/lib/auth.ts b/site/lib/auth.ts index c32f2d4e..fd9c9986 100644 --- a/site/lib/auth.ts +++ b/site/lib/auth.ts @@ -2,22 +2,92 @@ import prisma from '@/lib/prisma'; import { PrismaAdapter } from '@next-auth/prisma-adapter'; import GitHubProvider from 'next-auth/providers/github'; import GoogleProvider from 'next-auth/providers/google'; +import CredentialsProvider from 'next-auth/providers/credentials'; +import { User } from '@prisma/client'; +import { compare } from 'bcrypt'; export const authConfig = { providers: [ - GitHubProvider({ - clientId: process.env.GITHUB_ID as string, - clientSecret: process.env.GITHUB_SECRET as string, - }), - GoogleProvider({ - clientId: process.env.GOOGLE_ID as string, - clientSecret: process.env.GOOGLE_SECRET as string, - }), + CredentialsProvider({ + name: 'Login to your account', + credentials: { + email: { + label: 'Email address', + type: 'text', + placeholder: 'your@email.com"' + }, + password: { + label: 'Password', + type: 'password', + placeholder: 'Your password' + }, + }, + async authorize(credentials) { + if (!credentials || !credentials.email || !credentials.password) { + return null; + } + + const user = await prisma.user.findUnique({ + where: { email: credentials.email } + }); + + if (!user) { + return null; + } + + const isPasswordValid = await compare( + credentials.password, + user.password + ); + + if (!isPasswordValid) { + return null; + } + + const { password, ...userWithoutPassword } = user; + + return userWithoutPassword as User; + } + }), + GitHubProvider({ + clientId: process.env.GITHUB_ID as string, + clientSecret: process.env.GITHUB_SECRET as string, + }), + GoogleProvider({ + clientId: process.env.GOOGLE_ID as string, + clientSecret: process.env.GOOGLE_SECRET as string, + }), ], pages: { - signIn: '/signin', + signIn: '/signin' }, adapter: PrismaAdapter(prisma), secret: process.env.NEXTAUTH_SECRET, database: process.env.POSTGRES_PRISMA_URL, + session: { + strategy: 'jwt', + }, + callbacks: { + session: ({ session, token }) => { + return { + ...session, + user: { + ...session.user, + id: token.id, + randomKey: token.randomKey, + }, + }; + }, + jwt: ({ token, user }) => { + if (user) { + const u = user as unknown as any; + return { + ...token, + id: u.id, + randomKey: u.randomKey, + }; + } + return token; + }, + }, }; diff --git a/site/package.json b/site/package.json index ef51d298..5f59f589 100644 --- a/site/package.json +++ b/site/package.json @@ -48,6 +48,7 @@ "acorn-jsx": "^5.3.2", "aos": "^2.3.4", "autoprefixer": "^10.4.14", + "bcrypt": "^5.1.1", "clsx": "^2.0.0", "concurrently": "^8.2.0", "contentlayer": "^0.3.4", diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index 1d5a9e2e..1d81bffd 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -86,6 +86,9 @@ dependencies: autoprefixer: specifier: ^10.4.14 version: 10.4.14(postcss@8.4.27) + bcrypt: + specifier: ^5.1.1 + version: 5.1.1 clsx: specifier: ^2.0.0 version: 2.0.0 @@ -209,6 +212,9 @@ dependencies: react-syntax-highlighter: specifier: ^15.5.0 version: 15.5.0(react@18.2.0) + react-toastify: + specifier: ^9.1.3 + version: 9.1.3(react-dom@18.2.0)(react@18.2.0) rehype-autolink-headings: specifier: ^6.1.1 version: 6.1.1 @@ -2218,6 +2224,24 @@ packages: tslib: 2.4.1 dev: false + /@mapbox/node-pre-gyp@1.0.11: + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + dependencies: + detect-libc: 2.0.2 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.6.13 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.5.4 + tar: 6.1.15 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /@mdx-js/esbuild@2.3.0(esbuild@0.17.18): resolution: {integrity: sha512-r/vsqsM0E+U4Wr0DK+0EfmABE/eg+8ITW4DjvYdh3ve/tK2safaqHArNnaqbOk1DjYGrhxtoXoGaM3BY8fGBTA==} peerDependencies: @@ -3290,6 +3314,15 @@ packages: hasBin: true dev: false + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /ajv-keywords@3.5.2(ajv@6.12.6): resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -3342,6 +3375,18 @@ packages: lodash.throttle: 4.1.1 dev: false + /aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: false + + /are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + dev: false + /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} dependencies: @@ -3511,6 +3556,18 @@ packages: resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} dev: false + /bcrypt@5.1.1: + resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} + engines: {node: '>= 10.0.0'} + requiresBuild: true + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + node-addon-api: 5.1.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} dev: false @@ -3675,6 +3732,11 @@ packages: fsevents: 2.3.2 dev: false + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: false + /chrome-trace-event@1.0.3: resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} engines: {node: '>=6.0'} @@ -3712,6 +3774,11 @@ packages: wrap-ansi: 7.0.0 dev: false + /clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + dev: false + /clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} @@ -3738,6 +3805,11 @@ packages: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: false + /color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: false + /comma-separated-tokens@1.0.8: resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==} dev: false @@ -3808,6 +3880,10 @@ packages: proto-list: 1.2.4 dev: false + /console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: false + /contentlayer@0.3.4(esbuild@0.17.18)(markdown-wasm@1.2.0): resolution: {integrity: sha512-FYDdTUFaN4yqep0waswrhcXjmMJnPD5iXDTtxcUCGdklfuIrXM2xLx51xl748cHmGA6IsC+27YZFxU6Ym13QIA==} engines: {node: '>=14.18'} @@ -4022,11 +4098,20 @@ packages: object-keys: 1.1.1 dev: false + /delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: false + /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} dev: false + /detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + dev: false + /devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} dependencies: @@ -4786,6 +4871,13 @@ packages: universalify: 2.0.0 dev: false + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + /fs-monkey@1.0.3: resolution: {integrity: sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==} dev: false @@ -4820,6 +4912,21 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: false + /gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -5026,6 +5133,10 @@ packages: has-symbols: 1.0.3 dev: false + /has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: false + /has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} @@ -5256,6 +5367,16 @@ packages: resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} dev: false + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -5819,6 +5940,13 @@ packages: yallist: 4.0.0 dev: false + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: false + /map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -6852,6 +6980,32 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: false + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: false + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: false + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: false + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + /modern-async@1.1.3: resolution: {integrity: sha512-2ErvrRBESpOvzofl3r4Wk3J8ykMvAcTyFPciZKk8I8IvRzXEwNT9Z2H5lZ62wVjNtPUvfjKRYIvAeNrLGLIksw==} dependencies: @@ -7050,11 +7204,27 @@ packages: tslib: 2.4.1 dev: false + /node-addon-api@5.1.0: + resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} + dev: false + /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} dev: false + /node-fetch@2.6.13: + resolution: {integrity: sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + /node-fetch@3.3.1: resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -7068,6 +7238,14 @@ packages: resolution: {integrity: sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==} dev: false + /nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + /nopt@6.0.0: resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -7099,6 +7277,15 @@ packages: resolution: {integrity: sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==} dev: false + /npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + dev: false + /nprogress@0.2.0: resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} dev: false @@ -7579,6 +7766,17 @@ packages: refractor: 3.6.0 dev: false + /react-toastify@9.1.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==} + peerDependencies: + react: '>=16' + react-dom: '>=16' + dependencies: + clsx: 1.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} @@ -7607,6 +7805,15 @@ packages: path-type: 1.1.0 dev: false + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -8149,6 +8356,10 @@ packages: randombytes: 2.1.0 dev: false + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: false + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -8301,6 +8512,12 @@ packages: es-abstract: 1.21.0 dev: false + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /stringify-entities@4.0.3: resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} dependencies: @@ -8425,6 +8642,18 @@ packages: engines: {node: '>=6'} dev: false + /tar@6.1.15: + resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: false + /terser-webpack-plugin@5.3.7(esbuild@0.17.18)(webpack@5.88.2): resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} engines: {node: '>= 10.13.0'} @@ -8496,6 +8725,10 @@ packages: resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} dev: false + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + /tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -8781,6 +9014,10 @@ packages: punycode: 2.1.1 dev: false + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + /uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -8859,6 +9096,10 @@ packages: engines: {node: '>= 8'} dev: false + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + /webpack-sources@3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} @@ -8904,6 +9145,13 @@ packages: - uglify-js dev: false + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: @@ -8934,6 +9182,12 @@ packages: isexe: 2.0.0 dev: false + /wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: false + /word-wrap@1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} diff --git a/site/prisma/migrations/20230814193559_init/migration.sql b/site/prisma/migrations/20230819000033_init/migration.sql similarity index 98% rename from site/prisma/migrations/20230814193559_init/migration.sql rename to site/prisma/migrations/20230819000033_init/migration.sql index e785d42d..0b1b7ffb 100644 --- a/site/prisma/migrations/20230814193559_init/migration.sql +++ b/site/prisma/migrations/20230819000033_init/migration.sql @@ -33,6 +33,7 @@ CREATE TABLE "users" ( "name" TEXT, "email" TEXT, "email_verified" TIMESTAMP(3), + "password" TEXT, "image" TEXT, CONSTRAINT "users_pkey" PRIMARY KEY ("id") diff --git a/site/prisma/schema.prisma b/site/prisma/schema.prisma index b2483778..72ca276c 100644 --- a/site/prisma/schema.prisma +++ b/site/prisma/schema.prisma @@ -45,6 +45,7 @@ model User { name String? email String? @unique emailVerified DateTime? @map("email_verified") + password String? image String? accounts Account[] sessions Session[] -- GitLab