From 2614f1a3ee0359668078f3c7319680ab466216d4 Mon Sep 17 00:00:00 2001 From: andrzej Date: Tue, 10 Sep 2024 12:29:26 +0200 Subject: [PATCH] debugging auth --- auth.config.ts | 8 +- auth.ts | 15 +++- prisma/dev.db | Bin 69632 -> 69632 bytes prisma/dev.db-journal | Bin 12824 -> 0 bytes src/app/layout.tsx | 15 ++++ src/app/lib/actions.ts | 25 ++++++ src/app/login/page.tsx | 4 +- src/app/tailwind.css | 174 ++++++++++++++++++++++++++++++++++++++ src/app/ui/login-form.tsx | 85 +++++++++++++++++++ 9 files changed, 318 insertions(+), 8 deletions(-) delete mode 100644 prisma/dev.db-journal create mode 100644 src/app/lib/actions.ts create mode 100644 src/app/ui/login-form.tsx diff --git a/auth.config.ts b/auth.config.ts index b728753..3fbe788 100644 --- a/auth.config.ts +++ b/auth.config.ts @@ -1,4 +1,5 @@ import type { NextAuthConfig } from 'next-auth'; +import Credentials from 'next-auth/providers/credentials'; export const authConfig = { pages: { @@ -7,15 +8,16 @@ export const authConfig = { callbacks: { authorized({ auth, request: { nextUrl } }) { const isLoggedIn = !!auth?.user; - const isOnDashboard = nextUrl.pathname.startsWith('/dashboard'); + console.log(`isLoggedIn: ${isLoggedIn}`) + const isOnDashboard = nextUrl.pathname.startsWith('/'); if (isOnDashboard) { if (isLoggedIn) return true; return false; // Redirect unauthenticated users to login page } else if (isLoggedIn) { - return Response.redirect(new URL('/dashboard', nextUrl)); + return Response.redirect(new URL('/', nextUrl)); } return true; }, }, - providers: [], // Add providers with an empty array for now + providers: [Credentials({})], // Add providers with an empty array for now } satisfies NextAuthConfig; diff --git a/auth.ts b/auth.ts index 10a9e6d..881bf9e 100644 --- a/auth.ts +++ b/auth.ts @@ -1,10 +1,15 @@ -import NextAuth, { User } from 'next-auth'; +import NextAuth from 'next-auth'; import { authConfig } from './auth.config'; import Credentials from 'next-auth/providers/credentials'; import { z } from 'zod'; import prisma from 'app/lib/db'; import bcrypt from 'bcrypt'; +export type User = { + id: number, + email: string, + password: string +} async function getUser(email: string): Promise { try { @@ -29,14 +34,20 @@ export const { auth, signIn, signOut } = NextAuth({ .object({ email: z.string().email(), password: z.string().min(6) }) .safeParse(credentials); + console.log(`parsed credentials: ${JSON.stringify(parsedCredentials)}`) if (parsedCredentials.success) { const { email, password } = parsedCredentials.data; const user = await getUser(email); + console.log(`USER:${user}`) if (!user) return null; + console.log(`checking string "ยท${password}" against hash "${user.password}"`) const passwordsMatch = await bcrypt.compare(password, user.password); - if (passwordsMatch) return user; + if (passwordsMatch) { + console.log("passwords match!") + return user + }; } console.log('Invalid credentials'); diff --git a/prisma/dev.db b/prisma/dev.db index 322c241573e2dda0fda54ab1ce694cd84d7ed7a0..142b51630041be2e00101d4c6ce44278530be5ec 100644 GIT binary patch delta 169 zcmZozz|ydQWr8%L-$WT_M!$^-OZ0gd`PVb>ujhZxKZCz*ThRPw_-0|Sgb^&$+)+#K_Ryo_?ZQ!MrTGtw+G$|9=LT{6sb z^c<55(+tci^nF5#+{^S`B7=GPzcH}!Z)4(r&3}^r0RMIVNBrA1D<;h4=LfMFIQW=F Q8AFRxi0Hr}T82|tP delta 169 zcmZozz|ydQWr8%L=R_H2M$e52OZ0gd1Q;0jZ}IQqpTXa_S<#`8e{!R}UTSJiS!%If zNosLPlpGTqgQ_wkhev)kyl}4V^G&+ZJ2Qwk6c=^9Eu<{>Z;(yJ5lK%kzb^b^En>Q;a%;o0?u^D(7^HR&>14@%vHXrbJ GH~;{v+Be7m diff --git a/prisma/dev.db-journal b/prisma/dev.db-journal deleted file mode 100644 index 43bde4ac88fc163286aecd02bdfdb60e33afe0c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12824 zcmeHNO^jPt74}OecH)dPDHRx0wR&-ik|BBR{lD*uO`XIOMx>K;erQub=HC16ZLG|U zC$^^{Dit_wfl8H97D$y4671=UMWrkP8#e6*)CGbCf(;8m2(d?S-t+&AOH-wEgWt^9 ze)s2`?|kPw_ugksE;qaW&lxyS0s`ibEaetbZ@j{F)r zX4i~?83Qv0W(>?2m@zP8V8*}{2D*j$;zqZWqq*FnBZ4wzDZx>KIF49sc%+0PQGyf0 zytZ0XsVG(`CPXF{VVkHJbL=#y#4*8Px)Mk#97~+gL@I8i

j#7|!Fw#fTunP>czN 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 self-hosted literary submission tracker.

+ +
{ + 'use server'; + await signOut(); + }} + > + +
+
diff --git a/src/app/lib/actions.ts b/src/app/lib/actions.ts new file mode 100644 index 0000000..d193ef9 --- /dev/null +++ b/src/app/lib/actions.ts @@ -0,0 +1,25 @@ +'use server'; + +import { signIn } from "../../../auth"; +import { AuthError } from 'next-auth'; + +// ... + +export async function authenticate( + prevState: string | undefined, + formData: FormData, +) { + try { + await signIn('credentials', formData); + } catch (error) { + if (error instanceof AuthError) { + switch (error.type) { + case 'CredentialsSignin': + return 'Invalid credentials.'; + default: + return 'Something went wrong.'; + } + } + throw error; + } +} diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 5c07299..8e37c7a 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -1,5 +1,4 @@ -import AcmeLogo from '@/app/ui/acme-logo'; -import LoginForm from '@/app/ui/login-form'; +import LoginForm from 'app/ui/login-form'; export default function LoginPage() { return ( @@ -7,7 +6,6 @@ export default function LoginPage() {
-
diff --git a/src/app/tailwind.css b/src/app/tailwind.css index 7d8b68c..1e22c18 100644 --- a/src/app/tailwind.css +++ b/src/app/tailwind.css @@ -634,6 +634,10 @@ body { border-width: 0; } +.pointer-events-none { + pointer-events: none; +} + .pointer-events-auto { pointer-events: auto; } @@ -666,6 +670,10 @@ body { left: 0.5rem; } +.left-3 { + left: 0.75rem; +} + .left-\[50\%\] { left: 50%; } @@ -686,6 +694,10 @@ body { top: 0px; } +.top-1\/2 { + top: 50%; +} + .top-2 { top: 0.5rem; } @@ -740,6 +752,10 @@ body { margin-bottom: 1.5rem; } +.mb-3 { + margin-bottom: 0.75rem; +} + .mb-4 { margin-bottom: 1rem; } @@ -764,6 +780,10 @@ body { margin-top: 1rem; } +.mt-5 { + margin-top: 1.25rem; +} + .mt-6 { margin-top: 1.5rem; } @@ -772,6 +792,10 @@ body { margin-top: auto; } +.block { + display: block; +} + .flex { display: flex; } @@ -792,6 +816,10 @@ body { display: grid; } +.hidden { + display: none; +} + .size-full { width: 100%; height: 100%; @@ -857,6 +885,14 @@ body { height: 1.2rem; } +.h-\[18px\] { + height: 18px; +} + +.h-\[48px\] { + height: 48px; +} + .h-\[var\(--radix-select-trigger-height\)\] { height: var(--radix-select-trigger-height); } @@ -922,10 +958,18 @@ body { width: 10rem; } +.w-5 { + width: 1.25rem; +} + .w-5\/6 { width: 83.333333%; } +.w-6 { + width: 1.5rem; +} + .w-7 { width: 1.75rem; } @@ -942,6 +986,10 @@ body { width: 1.2rem; } +.w-\[18px\] { + width: 18px; +} + .w-\[240px\] { width: 240px; } @@ -1000,10 +1048,18 @@ body { max-width: 20rem; } +.flex-1 { + flex: 1 1 0%; +} + .shrink-0 { flex-shrink: 0; } +.grow { + flex-grow: 1; +} + .caption-bottom { caption-side: bottom; } @@ -1012,6 +1068,11 @@ body { border-collapse: collapse; } +.-translate-y-1\/2 { + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .translate-x-\[-50\%\] { --tw-translate-x: -50%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -1191,6 +1252,12 @@ body { margin-bottom: calc(0.625rem * var(--tw-space-y-reverse)); } +.space-y-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); +} + .space-y-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); @@ -1269,6 +1336,11 @@ body { border-color: hsl(var(--destructive)); } +.border-gray-200 { + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); +} + .border-input { border-color: hsl(var(--input)); } @@ -1310,6 +1382,11 @@ body { background-color: hsl(var(--destructive)); } +.bg-gray-50 { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); +} + .bg-input { background-color: hsl(var(--input)); } @@ -1395,6 +1472,11 @@ body { padding-right: 1rem; } +.px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + .px-8 { padding-left: 2rem; padding-right: 2rem; @@ -1430,6 +1512,19 @@ body { padding-bottom: 1rem; } +.py-\[9px\] { + padding-top: 9px; + padding-bottom: 9px; +} + +.pb-4 { + padding-bottom: 1rem; +} + +.pl-10 { + padding-left: 2.5rem; +} + .pl-3 { padding-left: 0.75rem; } @@ -1458,6 +1553,10 @@ body { padding-top: 0.25rem; } +.pt-8 { + padding-top: 2rem; +} + .text-left { text-align: left; } @@ -1470,6 +1569,11 @@ body { vertical-align: middle; } +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + .text-3xl { font-size: 1.875rem; line-height: 2.25rem; @@ -1569,6 +1673,21 @@ body { color: hsl(var(--foreground) / 0.5); } +.text-gray-50 { + --tw-text-opacity: 1; + color: rgb(249 250 251 / var(--tw-text-opacity)); +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + .text-muted-foreground { color: hsl(var(--muted-foreground)); } @@ -1585,6 +1704,11 @@ body { color: hsl(var(--primary-foreground)); } +.text-red-500 { + --tw-text-opacity: 1; + color: rgb(239 68 68 / var(--tw-text-opacity)); +} + .text-secondary-foreground { color: hsl(var(--secondary-foreground)); } @@ -1648,6 +1772,10 @@ body { outline-style: solid; } +.outline-2 { + outline-width: 2px; +} + .ring-offset-background { --tw-ring-offset-color: hsl(var(--background)); } @@ -1925,6 +2053,16 @@ body { font-weight: 500; } +.placeholder\:text-gray-500::-moz-placeholder { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.placeholder\:text-gray-500::placeholder { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + .placeholder\:text-muted-foreground::-moz-placeholder { color: hsl(var(--muted-foreground)); } @@ -1973,10 +2111,20 @@ body { background-color: hsl(var(--secondary) / 0.8); } +.hover\:bg-sky-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(224 242 254 / var(--tw-bg-opacity)); +} + .hover\:text-accent-foreground:hover { color: hsl(var(--accent-foreground)); } +.hover\:text-blue-600:hover { + --tw-text-opacity: 1; + color: rgb(37 99 235 / var(--tw-text-opacity)); +} + .hover\:text-foreground:hover { color: hsl(var(--foreground)); } @@ -2106,6 +2254,11 @@ body { --tw-ring-offset-color: #dc2626; } +.peer:focus ~ .peer-focus\:text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + .peer:disabled ~ .peer-disabled\:cursor-not-allowed { cursor: not-allowed; } @@ -2382,6 +2535,10 @@ body { margin-top: -8rem; } + .md\:block { + display: block; + } + .md\:h-36 { height: 9rem; } @@ -2397,6 +2554,23 @@ body { .md\:max-w-\[420px\] { max-width: 420px; } + + .md\:flex-none { + flex: none; + } + + .md\:justify-start { + justify-content: flex-start; + } + + .md\:p-2 { + padding: 0.5rem; + } + + .md\:px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; + } } .\[\&\:has\(\[aria-selected\]\)\]\:bg-accent:has([aria-selected]) { diff --git a/src/app/ui/login-form.tsx b/src/app/ui/login-form.tsx new file mode 100644 index 0000000..ff65168 --- /dev/null +++ b/src/app/ui/login-form.tsx @@ -0,0 +1,85 @@ +'use client'; + +import { + AtSign, + KeyIcon, + CircleAlert, +} from 'lucide-react'; +import { Button } from '@/components/ui/button'; +// import { useActionState } from 'react'; +import { useFormState } from 'react-dom'; +import { authenticate } from 'app/lib/actions'; +import { ArrowRightIcon } from 'lucide-react'; + +export default function LoginForm() { + const [errorMessage, formAction, isPending] = useFormState( + authenticate, + undefined, + ); + + return ( +
+
+

+ Please log in to continue. +

+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ {errorMessage && ( + <> + +

{errorMessage}

+ + )} +
+
+
+ ); +}