-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d88c1c3
commit 32ffe87
Showing
15 changed files
with
268 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1 @@ | ||
APP_URL="http://localhost:3000" | ||
|
||
DATABASE_URL="mysql://root:prisma@mysql:3306/database" | ||
|
||
GOOGLE_CLIENT_ID="" | ||
GOOGLE_CLIENT_SECRET="" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { validateSessionToken } from '@/server/auth/validateSession'; | ||
import { redirect } from 'next/navigation'; | ||
import React, { ReactNode } from 'react'; | ||
import { Toaster } from 'sonner'; | ||
|
||
const Layout = async ({ children }: { children: ReactNode }) => { | ||
const user = await validateSessionToken(); | ||
|
||
if (user !== null) { | ||
return redirect('/dashboard'); | ||
} | ||
|
||
return ( | ||
<html lang="en"> | ||
<body className={`min-h-[100dvh]`}> | ||
{children} | ||
<Toaster /> | ||
</body> | ||
</html> | ||
); | ||
}; | ||
|
||
export default Layout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,51 @@ | ||
'use client'; | ||
|
||
import Logo from '@/components/icons/logo'; | ||
import { Button } from '@/components/ui/button'; | ||
import { Input } from '@/components/ui/input'; | ||
import { login } from '@/server/auth/login'; | ||
import { useEffect } from 'react'; | ||
import { useFormState } from 'react-dom'; | ||
import { toast } from 'sonner'; | ||
|
||
const Page = () => { | ||
return <div></div>; | ||
const [state, formAction] = useFormState(login, {}); | ||
|
||
useEffect(() => { | ||
if (state.message) { | ||
toast.success(state.message); | ||
} | ||
|
||
if (state.error) { | ||
toast.error(state.error); | ||
} | ||
}, [state]); | ||
|
||
return ( | ||
<main className="grid items-center justify-center w-full bg-neutral-100 h-[100dvh]"> | ||
<form className="grid gap-8 w-[350px]" action={formAction}> | ||
<div className="grid gap-2"> | ||
<Logo className="mb-2" /> | ||
<h3 className="font-bold text-[22px] leading-7 tracking-[-0.02em]"> | ||
Login to Medialog | ||
</h3> | ||
<p className="text-sm text-muted-foreground"> | ||
Welcome to <i>your</i> website for rating Movies, Books, and TV | ||
Shows | ||
</p> | ||
</div> | ||
<div className="grid gap-4"> | ||
<div className="grid gap-2"> | ||
<Input placeholder="Email" name="email" /> | ||
<Input placeholder="Password" type="password" name="password" /> | ||
</div> | ||
<Button className="w-full" size="sm"> | ||
Log in | ||
</Button> | ||
</div> | ||
</form> | ||
</main> | ||
); | ||
}; | ||
|
||
export default Page; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { cn } from '@/lib/utils'; | ||
import React, { SVGProps } from 'react'; | ||
|
||
const Logo = ({ className, ...props }: SVGProps<SVGSVGElement>) => { | ||
return ( | ||
<svg | ||
width="64" | ||
height="64" | ||
viewBox="0 0 64 64" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
className={cn('size-11 rounded-lg', className)} | ||
{...props} | ||
> | ||
<rect width="64" height="64" rx="8" fill="#D74323" /> | ||
<rect width="64" height="60" rx="8" fill="#E05F43" /> | ||
<path | ||
d="M18.2283 40H13L17.8261 20H24.462L28.6848 33.2673L32.9076 20H40.5489V35.6436H50V40H35.5217V25.5446L30.8967 40H25.6685L21.8478 25.5446L18.2283 40Z" | ||
fill="white" | ||
/> | ||
</svg> | ||
); | ||
}; | ||
|
||
export default Logo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
const getDaysInMonth = (year: number, month: number) => | ||
new Date(year, month, 0).getDate(); | ||
|
||
export const addMonths = (input: Date, months: number) => { | ||
const date = new Date(input); | ||
date.setDate(1); | ||
date.setMonth(date.getMonth() + months); | ||
date.setDate( | ||
Math.min( | ||
input.getDate(), | ||
getDaysInMonth(date.getFullYear(), date.getMonth() + 1) | ||
) | ||
); | ||
return date; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
'use server'; | ||
|
||
import { z } from 'zod'; | ||
import prisma from '../db'; | ||
import bcrypt from 'bcrypt'; | ||
import { addMonths } from '@/lib/addMonths'; | ||
import { cookies, headers } from 'next/headers'; | ||
import { generateToken } from '@/lib/generateToken'; | ||
|
||
const genericLoginError = 'Invalid email or password'; | ||
|
||
export const login = async ( | ||
prevState: any, | ||
formData: FormData | ||
): Promise<{ error?: string; message?: string }> => { | ||
const schema = z.object({ | ||
email: z.string(), | ||
password: z.string(), | ||
}); | ||
|
||
const validatedFields = schema.safeParse({ | ||
email: formData.get('email'), | ||
password: formData.get('password'), | ||
}); | ||
|
||
if (!validatedFields.success) { | ||
return { | ||
error: Object.entries(validatedFields.error.flatten().fieldErrors) | ||
.map(entry => entry[1].map(error => error).join(' ')) | ||
.join(' '), | ||
}; | ||
} | ||
|
||
const email = validatedFields.data.email; | ||
const password = validatedFields.data.password; | ||
|
||
const user = await prisma.user.findFirst({ | ||
where: { | ||
email, | ||
}, | ||
}); | ||
|
||
if (!user) { | ||
return { | ||
error: genericLoginError, | ||
}; | ||
} | ||
|
||
if (!bcrypt.compareSync(password, user.password.replace(/^\$2y/, '$2a'))) { | ||
return { | ||
error: genericLoginError, | ||
}; | ||
} | ||
|
||
const session = await prisma.session.create({ | ||
data: { | ||
userId: user.id, | ||
expiry: addMonths(new Date(), 6), | ||
ipAddress: (headers().get('x-forwarded-for') ?? '127.0.0.1').split( | ||
',' | ||
)[0]!, | ||
userAgent: headers().get('User-Agent') ?? 'No user agent found', | ||
token: generateToken(64), | ||
}, | ||
}); | ||
|
||
cookies().set('mlSessionToken', session.token, { | ||
expires: new Date().getTime() + 1000 * 60 * 60 * 24 * 31 * 6, | ||
}); | ||
|
||
return { | ||
message: 'Login successfull', | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { cookies } from 'next/headers'; | ||
import prisma from '../db'; | ||
import { cache } from 'react'; | ||
|
||
export const validateSessionToken = cache(async () => { | ||
const sessionToken = cookies().get('mlSessionToken'); | ||
|
||
if (sessionToken === null || sessionToken === undefined) { | ||
return null; | ||
} | ||
|
||
const session = await prisma.session.findFirst({ | ||
where: { | ||
token: sessionToken.value, | ||
}, | ||
}); | ||
|
||
if (session === null) { | ||
return null; | ||
} | ||
|
||
if (session.expiry && session.expiry < new Date()) { | ||
cookies().delete('mlSessionToken'); | ||
return null; | ||
} | ||
|
||
return await prisma.user.findFirst({ | ||
where: { | ||
id: session.userId, | ||
}, | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters