mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-08 23:15:24 +02:00
refactor
This commit is contained in:
parent
e405fb80f6
commit
22ade8b42b
1 changed files with 57 additions and 42 deletions
|
@ -4,6 +4,7 @@ import CredentialsProvider from 'next-auth/providers/credentials'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { PrismaClient, type Prisma } from '@prisma/client'
|
import { PrismaClient, type Prisma } from '@prisma/client'
|
||||||
import { PrismaAdapter } from '@auth/prisma-adapter'
|
import { PrismaAdapter } from '@auth/prisma-adapter'
|
||||||
|
import type { SharedType } from '@maybe-finance/shared'
|
||||||
import bcrypt from 'bcrypt'
|
import bcrypt from 'bcrypt'
|
||||||
|
|
||||||
let prismaInstance: PrismaClient | null = null
|
let prismaInstance: PrismaClient | null = null
|
||||||
|
@ -17,20 +18,56 @@ function getPrismaInstance() {
|
||||||
|
|
||||||
const prisma = getPrismaInstance()
|
const prisma = getPrismaInstance()
|
||||||
|
|
||||||
async function createAuthUser(
|
async function createAuthUser(data: Prisma.AuthUserCreateInput) {
|
||||||
data: Prisma.AuthUserCreateInput & { firstName: string; lastName: string }
|
|
||||||
) {
|
|
||||||
const authUser = await prisma.authUser.create({ data: { ...data } })
|
const authUser = await prisma.authUser.create({ data: { ...data } })
|
||||||
return authUser
|
return authUser
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAuthUserByEmail(email: string) {
|
async function getAuthUserByEmail(email: string) {
|
||||||
if (!email) throw new Error('No email provided')
|
if (!email) throw new Error('No email provided.')
|
||||||
return await prisma.authUser.findUnique({
|
return await prisma.authUser.findUnique({
|
||||||
where: { email },
|
where: { email },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function validateCredentials(credentials: any): Promise<z.infer<typeof authSchema>> {
|
||||||
|
const authSchema = z.object({
|
||||||
|
firstName: z.string().optional(),
|
||||||
|
lastName: z.string().optional(),
|
||||||
|
email: z.string().email({ message: 'Invalid email address.' }),
|
||||||
|
password: z.string().min(6),
|
||||||
|
})
|
||||||
|
|
||||||
|
const parsed = authSchema.safeParse(credentials)
|
||||||
|
if (!parsed.success) {
|
||||||
|
throw new Error(parsed.error.issues.map((issue) => issue.message).join(', '))
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed.data
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createNewAuthUser(credentials: {
|
||||||
|
firstName: string
|
||||||
|
lastName: string
|
||||||
|
email: string
|
||||||
|
password: string
|
||||||
|
}): Promise<SharedType.AuthUser> {
|
||||||
|
const { firstName, lastName, email, password } = credentials
|
||||||
|
|
||||||
|
if (!firstName || !lastName) {
|
||||||
|
throw new Error('Both first name and last name are required.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const hashedPassword = await bcrypt.hash(password, 10)
|
||||||
|
return createAuthUser({
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
name: `${firstName} ${lastName}`,
|
||||||
|
email,
|
||||||
|
password: hashedPassword,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const authPrisma = {
|
const authPrisma = {
|
||||||
account: prisma.authAccount,
|
account: prisma.authAccount,
|
||||||
user: prisma.authUser,
|
user: prisma.authUser,
|
||||||
|
@ -60,51 +97,29 @@ export const authOptions = {
|
||||||
password: { label: 'Password', type: 'password' },
|
password: { label: 'Password', type: 'password' },
|
||||||
},
|
},
|
||||||
async authorize(credentials) {
|
async authorize(credentials) {
|
||||||
const parsedCredentials = z
|
const { firstName, lastName, email, password } = await validateCredentials(
|
||||||
.object({
|
credentials
|
||||||
firstName: z.string().optional(),
|
|
||||||
lastName: z.string().optional(),
|
|
||||||
email: z.string().email({ message: 'Invalid email address' }),
|
|
||||||
password: z.string().min(6),
|
|
||||||
})
|
|
||||||
.safeParse(credentials)
|
|
||||||
|
|
||||||
if (parsedCredentials.success) {
|
|
||||||
const { firstName, lastName, email, password } = parsedCredentials.data
|
|
||||||
|
|
||||||
const authUser = await getAuthUserByEmail(email)
|
|
||||||
|
|
||||||
if (!authUser) {
|
|
||||||
if (!firstName || !lastName)
|
|
||||||
throw new Error(`Could not find an account with that email`)
|
|
||||||
const hashedPassword = await bcrypt.hash(password, 10)
|
|
||||||
const newAuthUser = await createAuthUser({
|
|
||||||
firstName,
|
|
||||||
lastName,
|
|
||||||
name: `${firstName} ${lastName}`,
|
|
||||||
email,
|
|
||||||
password: hashedPassword,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (newAuthUser) return newAuthUser
|
|
||||||
throw new Error('Could not create user')
|
|
||||||
}
|
|
||||||
|
|
||||||
const passwordsMatch = await bcrypt.compare(password, authUser.password!)
|
|
||||||
if (passwordsMatch) return authUser
|
|
||||||
throw new Error('Email or password is invalid')
|
|
||||||
} else {
|
|
||||||
const errorMessages = parsedCredentials.error.issues.map(
|
|
||||||
(issue) => issue.message
|
|
||||||
)
|
)
|
||||||
throw new Error(errorMessages.join(', '))
|
|
||||||
|
const existingUser = await getAuthUserByEmail(email)
|
||||||
|
if (existingUser) {
|
||||||
|
const isPasswordMatch = await bcrypt.compare(password, existingUser.password!)
|
||||||
|
if (!isPasswordMatch) throw new Error('Email or password is invalid.')
|
||||||
|
|
||||||
|
return existingUser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!firstName || !lastName) {
|
||||||
|
throw new Error('Invalid credentials provided.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return createNewAuthUser({ firstName, lastName, email, password })
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
callbacks: {
|
callbacks: {
|
||||||
async jwt({ token, user: authUser, account }: { token: any; user: any; account: any }) {
|
async jwt({ token, user: authUser }: { token: any; user: any }) {
|
||||||
if (authUser && account) {
|
if (authUser) {
|
||||||
token.sub = authUser.id
|
token.sub = authUser.id
|
||||||
token['https://maybe.co/email'] = authUser.email
|
token['https://maybe.co/email'] = authUser.email
|
||||||
token.firstName = authUser.firstName
|
token.firstName = authUser.firstName
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue