Use kv datastore for auth (#272)

This commit is contained in:
Jeremy 2024-03-19 04:37:30 +03:00 committed by GitHub
parent d741351e26
commit b6cab643ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 143 additions and 173 deletions

View file

@ -1,15 +1,50 @@
'use server'
import { signIn } from '@/auth'
import { db } from '@vercel/postgres'
import { getStringFromBuffer } from '@/lib/utils'
import { ResultCode, getStringFromBuffer } from '@/lib/utils'
import { z } from 'zod'
import { AuthResult } from '@/lib/types'
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
}
export async function signup(
_prevState: AuthResult | undefined,
_prevState: Result | undefined,
formData: FormData
) {
): Promise<Result | undefined> {
const email = formData.get('email') as string
const password = formData.get('password') as string
@ -34,42 +69,43 @@ export async function signup(
)
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;
`
const result = await createUser(email, hashedPassword, salt)
await signIn('credentials', {
email,
password,
redirect: false
})
if (result.resultCode === ResultCode.UserCreated) {
await signIn('credentials', {
email,
password,
redirect: false
})
}
return { type: 'success', message: 'Account created!' }
return result
} 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.' }
if (error instanceof AuthError) {
switch (error.type) {
case 'CredentialsSignin':
return {
type: 'error',
resultCode: ResultCode.InvalidCredentials
}
default:
return {
type: 'error',
resultCode: ResultCode.UnknownError
}
}
} else {
return {
type: 'error',
message: 'Something went wrong! Please try again.'
resultCode: ResultCode.UnknownError
}
}
} finally {
client.release()
}
} else {
return {
type: 'error',
message: 'Invalid entries, please try again!'
resultCode: ResultCode.InvalidCredentials
}
}
}