diff --git a/app/users/signup/page.tsx b/app/users/signup/page.tsx index a080767..c4ecd59 100644 --- a/app/users/signup/page.tsx +++ b/app/users/signup/page.tsx @@ -1,8 +1,48 @@ 'use client'; import SignupForm from '@/components/users/signup/signup-form'; +import { useEffect, useState } from 'react'; +import { PublicKeyInfo } from '@/types/encryption/public-key-info'; +import { getPublicKeyInfo } from '@/components/encryption/getPublicKeyInfo'; +import { toast } from 'react-toastify'; +import { handleEncryptedSignup } from '@/components/encryption/encryptionSignup'; export default function Signup() { + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [baekjoonId, setBaekjoonId] = useState(''); + const [introduce, setIntroduce] = useState(''); + const [publicKeyInfo, setPublicKeyInfo] = useState( + null + ); + + useEffect(() => { + try { + getPublicKeyInfo(setPublicKeyInfo).then(() => { + if (publicKeyInfo != null && username != '' && password != '') { + handleEncryptedSignup( + { username, password, baekjoonId, introduce }, + publicKeyInfo + ); + } + }); + } catch (error) { + toast.error((error as Error).message); + } + }, []); + + const handleChangeSignupInfo = ( + username: string, + password: string, + baekjoonId: string, + introduce: string + ) => { + setUsername(username); + setPassword(password); + setBaekjoonId(baekjoonId); + setIntroduce(introduce); + }; + return (
@@ -10,7 +50,10 @@ export default function Signup() {

회원가입

- + handleChangeSignupInfo} + />
diff --git a/components/encryption/encryptionSignup.tsx b/components/encryption/encryptionSignup.tsx new file mode 100644 index 0000000..870e8f6 --- /dev/null +++ b/components/encryption/encryptionSignup.tsx @@ -0,0 +1,11 @@ +import { PublicKeyInfo } from '@/types/encryption/public-key-info'; +import { encryptData } from '@/components/encryption/getPublicKeyInfo'; +import { signup } from '@/lib/api/users/signup'; + +export const handleEncryptedSignup = async ( + signupInfo: Record, + publicKeyInfo: PublicKeyInfo +) => { + const encryptedData = encryptData(signupInfo, publicKeyInfo); + return await signup(publicKeyInfo.id, publicKeyInfo.version, encryptedData); +}; diff --git a/components/users/signup/signup-form.tsx b/components/users/signup/signup-form.tsx index dc96f19..7645223 100644 --- a/components/users/signup/signup-form.tsx +++ b/components/users/signup/signup-form.tsx @@ -1,16 +1,18 @@ -'use client'; - import { Button } from '@/components/ui/button/button'; import { Input } from '@/components/ui/input/input'; import { Textarea } from '@/components/ui/textarea/textarea'; -import { signup } from '@/lib/api/users/signup'; import { zodResolver } from '@hookform/resolvers/zod'; import { useRouter } from 'next/navigation'; import { FieldValues, useForm } from 'react-hook-form'; import { toast } from 'react-toastify'; import { z } from 'zod'; +import { handleEncryptedSignup } from '@/components/encryption/encryptionSignup'; +import { SignupFormProps } from '@/types/user/signup-form-props'; -export default function SignupForm() { +export default function SignupForm({ + publicKeyInfo, + handleChangeSignupInfo +}: SignupFormProps) { const router = useRouter(); const signupSchema = z .object({ @@ -39,10 +41,24 @@ export default function SignupForm() { }); const onSubmit = async (data: FieldValues) => { - const response = await signup(data); - if (response.status === 200) { - toast.success('회원가입이 완료되었습니다.'); - router.push('/login'); + try { + handleChangeSignupInfo( + data.username, + data.password, + data.baekjoonId, + data.introduce + ); + if (publicKeyInfo == null) { + toast.error('로그인 진행 중입니다. 잠시만 기다려주세요.'); + return; + } + const response = await handleEncryptedSignup(data, publicKeyInfo); + if (response.status === 200) { + toast.success('회원가입이 완료되었습니다.'); + router.push('/login'); + } + } catch (error) { + toast.error((error as Error).message); } }; diff --git a/lib/api/users/signup.ts b/lib/api/users/signup.ts index b1b1c95..eb33422 100644 --- a/lib/api/users/signup.ts +++ b/lib/api/users/signup.ts @@ -1,18 +1,33 @@ -import axios from 'axios'; -import { FieldValues } from 'react-hook-form'; +import axios, { AxiosError } from 'axios'; /** * 회원가입 API * body : username, password, baekjoonId, introduce */ -export async function signup({ - username, - password, - baekjoonId, - introduce -}: FieldValues) { - return await axios.post( - `${process.env.NEXT_PUBLIC_API_SERVER_URL}/api/v1/users/signup`, - { username, password, baekjoonId, introduce } - ); +export async function signup( + id: number, + version: number, + encryptedData: string +) { + try { + return await axios.post( + `${process.env.NEXT_PUBLIC_API_SERVER_URL}/api/v1/users/signup`, + { + id, + version, + encryptedData + }, + { + headers: { + 'Content-Type': 'application/json' + } + } + ); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response?.status === 409) { + throw new Error('이미 존재하는 아이디입니다.'); + } + throw new Error('회원가입에 실패했습니다.'); + } } diff --git a/types/user/signup-form-props.ts b/types/user/signup-form-props.ts new file mode 100644 index 0000000..c8f1363 --- /dev/null +++ b/types/user/signup-form-props.ts @@ -0,0 +1,11 @@ +import { PublicKeyInfo } from '@/types/encryption/public-key-info'; + +export interface SignupFormProps { + publicKeyInfo: PublicKeyInfo | null; + handleChangeSignupInfo: ( + username: string, + password: string, + baekjoonId: string, + introduce: string + ) => void; +}