76 lines
1.8 KiB
TypeScript
76 lines
1.8 KiB
TypeScript
|
|
'use server'
|
||
|
|
|
||
|
|
import { signIn } from '@/auth'
|
||
|
|
import { db } from '@vercel/postgres'
|
||
|
|
import { getStringFromBuffer } from '@/lib/utils'
|
||
|
|
import { z } from 'zod'
|
||
|
|
import { AuthResult } from '@/lib/types'
|
||
|
|
|
||
|
|
export async function signup(
|
||
|
|
_prevState: AuthResult | undefined,
|
||
|
|
formData: FormData
|
||
|
|
) {
|
||
|
|
const email = formData.get('email') as string
|
||
|
|
const password = formData.get('password') as string
|
||
|
|
|
||
|
|
const parsedCredentials = z
|
||
|
|
.object({
|
||
|
|
email: z.string().email(),
|
||
|
|
password: z.string().min(6)
|
||
|
|
})
|
||
|
|
.safeParse({
|
||
|
|
email,
|
||
|
|
password
|
||
|
|
})
|
||
|
|
|
||
|
|
if (parsedCredentials.success) {
|
||
|
|
const salt = crypto.randomUUID()
|
||
|
|
|
||
|
|
const encoder = new TextEncoder()
|
||
|
|
const saltedPassword = encoder.encode(password + salt)
|
||
|
|
const hashedPasswordBuffer = await crypto.subtle.digest(
|
||
|
|
'SHA-256',
|
||
|
|
saltedPassword
|
||
|
|
)
|
||
|
|
const hashedPassword = getStringFromBuffer(hashedPasswordBuffer)
|
||
|
|
|
||
|
|
const client = await db.connect()
|
||
|
|
|
||
|
|
try {
|
||
|
|
await client.sql`
|
||
|
|
INSERT INTO users (email, password, salt)
|
||
|
|
VALUES (${email}, ${hashedPassword}, ${salt})
|
||
|
|
ON CONFLICT (id) DO NOTHING;
|
||
|
|
`
|
||
|
|
|
||
|
|
await signIn('credentials', {
|
||
|
|
email,
|
||
|
|
password,
|
||
|
|
redirect: false
|
||
|
|
})
|
||
|
|
|
||
|
|
return { type: 'success', message: 'Account created!' }
|
||
|
|
} catch (error) {
|
||
|
|
const { message } = error as Error
|
||
|
|
|
||
|
|
if (
|
||
|
|
message.startsWith('duplicate key value violates unique constraint')
|
||
|
|
) {
|
||
|
|
return { type: 'error', message: 'User already exists! Please log in.' }
|
||
|
|
} else {
|
||
|
|
return {
|
||
|
|
type: 'error',
|
||
|
|
message: 'Something went wrong! Please try again.'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} finally {
|
||
|
|
client.release()
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
return {
|
||
|
|
type: 'error',
|
||
|
|
message: 'Invalid entries, please try again!'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|