chatbot-template/app/signup/actions.ts

112 lines
2.4 KiB
TypeScript
Raw Normal View History

2024-03-14 20:00:52 +03:00
'use server'
import { signIn } from '@/auth'
2024-03-19 04:37:30 +03:00
import { ResultCode, getStringFromBuffer } from '@/lib/utils'
2024-03-14 20:00:52 +03:00
import { z } from 'zod'
2024-03-19 04:37:30 +03:00
import { kv } from '@vercel/kv'
import { getUser } from '../login/actions'
import { AuthError } from 'next-auth'
export async function createUser(
email: string,
hashedPassword: string,
salt: string
) {
const existingUser = await getUser(email)
if (existingUser) {
return {
type: 'error',
resultCode: ResultCode.UserAlreadyExists
}
} else {
const user = {
id: crypto.randomUUID(),
email,
password: hashedPassword,
salt
}
await kv.hmset(`user:${email}`, user)
return {
type: 'success',
resultCode: ResultCode.UserCreated
}
}
}
interface Result {
type: string
resultCode: ResultCode
}
2024-03-14 20:00:52 +03:00
export async function signup(
2024-03-19 04:37:30 +03:00
_prevState: Result | undefined,
2024-03-14 20:00:52 +03:00
formData: FormData
2024-03-19 04:37:30 +03:00
): Promise<Result | undefined> {
2024-03-14 20:00:52 +03:00
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)
try {
2024-03-19 04:37:30 +03:00
const result = await createUser(email, hashedPassword, salt)
2024-03-14 20:00:52 +03:00
2024-03-19 04:37:30 +03:00
if (result.resultCode === ResultCode.UserCreated) {
await signIn('credentials', {
email,
password,
redirect: false
})
}
2024-03-14 20:00:52 +03:00
2024-03-19 04:37:30 +03:00
return result
2024-03-14 20:00:52 +03:00
} catch (error) {
2024-03-19 04:37:30 +03:00
if (error instanceof AuthError) {
switch (error.type) {
case 'CredentialsSignin':
return {
type: 'error',
resultCode: ResultCode.InvalidCredentials
}
default:
return {
type: 'error',
resultCode: ResultCode.UnknownError
}
}
2024-03-14 20:00:52 +03:00
} else {
return {
type: 'error',
2024-03-19 04:37:30 +03:00
resultCode: ResultCode.UnknownError
2024-03-14 20:00:52 +03:00
}
}
}
} else {
return {
type: 'error',
2024-03-19 04:37:30 +03:00
resultCode: ResultCode.InvalidCredentials
2024-03-14 20:00:52 +03:00
}
}
}