diff --git a/app/(auth)/change-password/action/route.ts b/app/(auth)/change-password/action/route.ts new file mode 100644 index 0000000..a9b497e --- /dev/null +++ b/app/(auth)/change-password/action/route.ts @@ -0,0 +1,51 @@ +import { NextRequest, NextResponse } from 'next/server' +import type { ChangePasswordSchema } from '@/(auth)/change-password/schema' +import { createClient } from '@/(auth)/supabase/with-request' + +const assertVerifyOldPassword = async ( + supabase: ReturnType['supabase'], + data: ChangePasswordSchema +): Promise< + | { kind: 'verified' } + | { kind: 'noSession'; message: string } + | { kind: 'wrongPassword'; message: string } +> => { + const { + data: { session }, + error + } = await supabase.auth.getSession() + if (error || !session?.user.email) { + return { kind: 'noSession', message: 'user session is not detected' } + } + + const { + error: signInError, + data: { session: signInSession } + } = await supabase.auth.signInWithPassword({ + email: session.user.email, + password: data.oldPassword + }) + if (signInError || !signInSession) { + return { kind: 'wrongPassword', message: 'Old Password is not correct' } + } + return { kind: 'verified' } +} + +export const POST = async (req: NextRequest): Promise => { + const { supabase } = createClient(req) + + const data = (await req.json()) as ChangePasswordSchema + const res = await assertVerifyOldPassword(supabase, data) + if (res.kind !== 'verified') { + return NextResponse.json(res.message, { status: 401 }) + } + + const { error } = await supabase.auth.updateUser({ + password: data.newPassword + }) + if (error) { + return NextResponse.json(error.message, { status: 500 }) + } else { + return NextResponse.json('ok', { status: 200 }) + } +} diff --git a/app/(auth)/change-password/page.tsx b/app/(auth)/change-password/page.tsx index 88be7c6..00088cf 100644 --- a/app/(auth)/change-password/page.tsx +++ b/app/(auth)/change-password/page.tsx @@ -12,7 +12,7 @@ import { useToast, useBoolean } from '@chakra-ui/react' -import { changePassword } from '@/(auth)/change-password/action' +import { useRouter } from 'next/navigation' import { changePasswordResolver, ChangePasswordSchema @@ -25,6 +25,7 @@ export default function ChangePassword() { const [toastId, setToastId] = useState | undefined>( undefined ) + const router = useRouter() const { register, @@ -36,27 +37,27 @@ export default function ChangePassword() { const changePasswordHandler = handleSubmit( async (data: ChangePasswordSchema) => { - try { - setIsLoading.on() - await changePassword(data) - } catch (error) { - if (!toastId) { - const res = toast({ - title: "We're sorry, but you failed to sign in.", - description: - error instanceof Error ? error.message : 'unknown error', - status: 'error', - duration: 5000, - isClosable: true, - position: 'top', - onCloseComplete() { - setToastId(undefined) - } - }) - setToastId(res) - } - } finally { - setIsLoading.off() + setIsLoading.on() + const response = await fetch('/change-password/action', { + method: 'POST', + body: JSON.stringify(data) + }) + setIsLoading.off() + if (response.ok) { + router.push('/') + } else if (!toastId) { + const res = toast({ + title: "We're sorry, but you failed to change your password.", + description: await response.json(), + status: 'error', + duration: 5000, + isClosable: true, + position: 'top', + onCloseComplete() { + setToastId(undefined) + } + }) + setToastId(res) } } )