From 8ea0e9e96f92b3ffe32d5f7416e2f7d7088de94f Mon Sep 17 00:00:00 2001 From: Sangwoo Park Date: Sun, 22 Aug 2021 23:09:10 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=ED=94=84=EB=A1=A0=ED=8A=B8=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/css/auth.css | 15 ++++ public/js/sign-up.js | 95 +++++++++++++++++++++++ views/includes/auth/sign-up-container.ejs | 64 +++++++-------- views/sign-up.ejs | 49 ++++++------ 4 files changed, 168 insertions(+), 55 deletions(-) create mode 100644 public/js/sign-up.js diff --git a/public/css/auth.css b/public/css/auth.css index e09dc5f..eb3fa74 100644 --- a/public/css/auth.css +++ b/public/css/auth.css @@ -1,4 +1,9 @@ :root { + --font-size-large: 20px; + --font-size-default: 16px; + --font-size-medium: 14px; + --font-size-small: 12px; + --font-size-x-small: 9px; /* form */ --input-width: 240px; --input-height: 40px; @@ -66,6 +71,7 @@ .sign-up-form__input { width: var(--input-width); height: var(--input-height); + margin: 5% 0; } .sign-up-form__submit { @@ -73,3 +79,12 @@ height: var(--submit-height); margin: var(--submit-margin); } + +.sign-up-form__email, +.sign-up-form__pwd, +.sign-up-form__pwd2, +.sign-up-form__name { + min-height: 10px; + font-size: var(--font-size-x-small); + color: red; +} diff --git a/public/js/sign-up.js b/public/js/sign-up.js new file mode 100644 index 0000000..b9414fc --- /dev/null +++ b/public/js/sign-up.js @@ -0,0 +1,95 @@ +const form = document.querySelector('.sign-up-form'); +const emailInput = document.querySelector('.sign-up-form__input[name=email]'); +const pwdInput = document.querySelector('.sign-up-form__input[name=pwd]'); +const pwd2Input = document.querySelector('.sign-up-form__input[name=pwd2]'); +const nameInput = document.querySelector('.sign-up-form__input[name=nickname]'); +const submitBtn = document.querySelector('.sign-up-form__submit'); + +const emailValidDiv = document.querySelector('.sign-up-form__email'); +const pwdValidDiv = document.querySelector('.sign-up-form__pwd'); +const pwd2ValidDiv = document.querySelector('.sign-up-form__pwd2'); +const nameValidDiv = document.querySelector('.sign-up-form__name'); + +function showIsValid(element, text) { + element.innerText = text; +} + +function checkValidEmail() { + const regExp = + /^[\w!#$%&'*+/=?^_{|}~-]+(?:\.[\w!#$%&'*+/=?^_{|}~-]+)*@(?:\w+\.)+\w+$/; + + if (emailInput.value === '' || regExp.test(emailInput.value)) { + showIsValid(emailValidDiv, ''); + return true; + } else { + showIsValid(emailValidDiv, '올바른 이메일 주소를 입력해 주세요.'); + return false; + } +} + +function checkStrongPwd() { + const regExp = + /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]).{8,16}$/; + + if (pwdInput.value === '' || regExp.test(pwdInput.value)) { + showIsValid(pwdValidDiv, ''); + return true; + } else { + showIsValid( + pwdValidDiv, + '8~16자 영문 대 소문자, 숫자, 특수문자를 사용해 주세요.' + ); + return false; + } +} + +function checkEqualPwd() { + if (pwd2Input.value !== '' && pwdInput.value === pwd2Input.value) { + showIsValid(pwd2ValidDiv, ''); + return true; + } else { + showIsValid(pwd2ValidDiv, '비밀번호가 일치하지 않습니다.'); + return false; + } +} + +function checkValidName() { + if (nameInput.value === '' || nameInput.value.length <= 10) { + showIsValid(nameValidDiv, ''); + return true; + } else { + showIsValid(nameValidDiv, '10자 이하를 입력해 주세요.'); + return false; + } +} + +function checkValidAll() { + const inputs = [emailInput, pwdInput, pwd2Input, nameInput]; + const divs = [emailValidDiv, pwdValidDiv, pwd2ValidDiv, nameValidDiv]; + + inputs.forEach((Item, i) => { + if (!Item.value) { + showIsValid(divs[i], '필수 정보입니다.'); + } + }); + + if ( + checkValidEmail() && + checkStrongPwd() && + checkEqualPwd() && + checkValidName() + ) { + form.submit(); + } +} + +function init() { + emailInput.addEventListener('keyup', checkValidEmail); + pwdInput.addEventListener('keyup', checkStrongPwd); + pwdInput.addEventListener('keyup', checkEqualPwd); + pwd2Input.addEventListener('keyup', checkEqualPwd); + nameInput.addEventListener('keyup', checkValidName); + submitBtn.addEventListener('click', checkValidAll); +} + +init(); diff --git a/views/includes/auth/sign-up-container.ejs b/views/includes/auth/sign-up-container.ejs index c2bb6cf..8e649b4 100644 --- a/views/includes/auth/sign-up-container.ejs +++ b/views/includes/auth/sign-up-container.ejs @@ -1,31 +1,33 @@ -
- - - - - -
\ No newline at end of file +
+ + + + + + + + + +
diff --git a/views/sign-up.ejs b/views/sign-up.ejs index f55ec9d..8447121 100644 --- a/views/sign-up.ejs +++ b/views/sign-up.ejs @@ -1,24 +1,25 @@ - - - - - - - Document - - - - - - -
- <%- include('includes/auth/auth-logo'); %> -
- -
- <%- include('includes/auth/sign-up-container'); %> -
- - <%- include('includes/footer'); %> - - + + + + + + + Document + + + + + + +
+ <%- include('includes/auth/auth-logo'); %> +
+ +
+ <%- include('includes/auth/sign-up-container'); %> +
+ + <%- include('includes/footer'); %> + + + From da0d8f3769ce4b916d962aaf5c36f36ad5916b92 Mon Sep 17 00:00:00 2001 From: Sangwoo Park Date: Mon, 30 Aug 2021 02:00:59 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EB=B0=B1=EC=97=94=EB=93=9C=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routes/auth.js | 67 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/routes/auth.js b/routes/auth.js index 1fc34ac..a77d174 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -190,31 +190,58 @@ router.get('/sign-up', (req, res, next) => { res.render('sign-up'); }); +// 회원가입 유효성 검증 +function checkValidEmail(userInput) { + const regExp = + /^[\w!#$%&'*+/=?^_{|}~-]+(?:\.[\w!#$%&'*+/=?^_{|}~-]+)*@(?:\w+\.)+\w+$/; + + return regExp.test(userInput) ? true : false; +} + +function checkStrongPwd(userInput) { + const regExp = + /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]).{8,16}$/; + + return regExp.test(userInput) ? true : false; +} + +function checkEqualPwd(pwd1, pwd2) { + return pwd1 === pwd2 ? true : false; +} + +function checkValidName(userInput) { + return userInput.length <= 10 ? true : false; +} + // Sign-up_process Route // POST request 암호화 필요 router.post('/sign-up_process', (req, res, next) => { - const post = req.body; const id = nanoid(); - const { email } = post; - const { pwd } = post; - const { pwd2 } = post; - const { nickname } = post; - if (pwd !== pwd2) { - console.log('비밀번호가 일치하지 않습니다'); - } else { - const salt = randomBytes(64).toString('base64'); - const secret = pbkdf2Sync(pwd, salt, 100000, 64, 'sha512').toString( - 'base64' - ); - const sql = - 'INSERT INTO user (id, email, secret, salt, nickname, create_date) VALUES (?, ?, ?, ?, ?, NOW())'; - db.query(sql, [id, email, secret, salt, nickname], err => { - if (err) { - next(err); - } - res.redirect('/auth/sign-in'); - }); + const { email, pwd1, pwd2, nickname } = req.body; + + if ( + !checkValidEmail(email) || + !checkEqualPwd(pwd1, pwd2) || + !checkStrongPwd(pwd1) || + !checkValidName(nickname) + ) { + console.log('Invalid User Input'); + return; } + + const salt = randomBytes(64).toString('base64'); + const secret = pbkdf2Sync(pwd1, salt, 100000, 64, 'sha512').toString( + 'base64' + ); + const sql = + 'INSERT INTO user (id, email, secret, salt, nickname, create_date) VALUES (?, ?, ?, ?, ?, NOW())'; + + db.query(sql, [id, email, secret, salt, nickname], err => { + if (err) { + next(err); + } + res.redirect('/auth/sign-in'); + }); }); // Sign-in Route From ae664d955114a10bbe4eee65b5308073c997c2e1 Mon Sep 17 00:00:00 2001 From: Sangwoo Park Date: Mon, 30 Aug 2021 03:33:11 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC/?= =?UTF-8?q?=EB=8B=89=EB=84=A4=EC=9E=84=20=EC=A4=91=EB=B3=B5=20=EA=B2=80?= =?UTF-8?q?=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/js/sign-up.js | 35 ++++++++++++++++++++- routes/auth.js | 73 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/public/js/sign-up.js b/public/js/sign-up.js index b9414fc..e09b0b3 100644 --- a/public/js/sign-up.js +++ b/public/js/sign-up.js @@ -14,6 +14,35 @@ function showIsValid(element, text) { element.innerText = text; } +async function checkDuplicateEmail() { + const userInput = emailInput.value; + const res = await fetch(`http://localhost:3000/auth/check-duplicate-email`, { + method: 'POST', + body: userInput + }); + const isValid = await res.json(); + if (!isValid) { + showIsValid(emailValidDiv, '이미 사용 중인 이메일입니다.'); + } + return isValid; +} + +async function checkDuplicateName() { + const userInput = nameInput.value; + const res = await fetch( + `http://localhost:3000/auth/check-duplicate-nickname`, + { + method: 'POST', + body: userInput + } + ); + const isValid = await res.json(); + if (!isValid) { + showIsValid(nameValidDiv, '이미 사용 중인 닉네임입니다.'); + } + return isValid; +} + function checkValidEmail() { const regExp = /^[\w!#$%&'*+/=?^_{|}~-]+(?:\.[\w!#$%&'*+/=?^_{|}~-]+)*@(?:\w+\.)+\w+$/; @@ -77,7 +106,9 @@ function checkValidAll() { checkValidEmail() && checkStrongPwd() && checkEqualPwd() && - checkValidName() + checkValidName() && + checkDuplicateEmail() && + checkDuplicateName() ) { form.submit(); } @@ -85,10 +116,12 @@ function checkValidAll() { function init() { emailInput.addEventListener('keyup', checkValidEmail); + emailInput.addEventListener('focusout', checkDuplicateEmail); pwdInput.addEventListener('keyup', checkStrongPwd); pwdInput.addEventListener('keyup', checkEqualPwd); pwd2Input.addEventListener('keyup', checkEqualPwd); nameInput.addEventListener('keyup', checkValidName); + nameInput.addEventListener('focusout', checkDuplicateName); submitBtn.addEventListener('click', checkValidAll); } diff --git a/routes/auth.js b/routes/auth.js index a77d174..e74d5d2 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -205,34 +205,91 @@ function checkStrongPwd(userInput) { return regExp.test(userInput) ? true : false; } -function checkEqualPwd(pwd1, pwd2) { - return pwd1 === pwd2 ? true : false; +function checkEqualPwd(userInputA, userInputB) { + return userInputA === userInputB ? true : false; } function checkValidName(userInput) { return userInput.length <= 10 ? true : false; } +function checkDuplicateEmail(userInput) { + const sql_user = 'SELECT * FROM user WHERE email=?'; + db.query(sql_user, [userInput], (err, results) => { + if (err) { + next(err); + } else if (results[0]) { + return false; + } else { + return true; + } + }); +} + +function checkDuplicateName(userInput) { + const sql_user = 'SELECT * FROM user WHERE nickname=?'; + db.query(sql_user, [userInput], (err, results) => { + if (err) { + next(err); + } else if (results[0]) { + return false; + } else { + return true; + } + }); +} + +router.post('/check-duplicate-email', (req, res, next) => { + const email = req.body; + const sql_user = 'SELECT * FROM user WHERE email=?'; + db.query(sql_user, [email], (err, results) => { + if (err) { + next(err); + } else if (results[0]) { + res.send(false); + } else { + res.send(true); + } + }); +}); + +router.post('/check-duplicate-nickname', (req, res, next) => { + const nickname = req.body; + const sql_user = 'SELECT * FROM user WHERE nickname=?'; + db.query(sql_user, [nickname], (err, results) => { + if (err) { + next(err); + } else if (results[0]) { + res.send(false); + } else { + res.send(true); + } + }); +}); + // Sign-up_process Route // POST request 암호화 필요 router.post('/sign-up_process', (req, res, next) => { const id = nanoid(); - const { email, pwd1, pwd2, nickname } = req.body; + const { email, pwd, pwd2, nickname } = req.body; if ( !checkValidEmail(email) || - !checkEqualPwd(pwd1, pwd2) || - !checkStrongPwd(pwd1) || + !checkEqualPwd(pwd, pwd2) || + !checkStrongPwd(pwd) || !checkValidName(nickname) ) { console.log('Invalid User Input'); return; } + if (!checkDuplicateEmail(email) || !checkDuplicateName(nickname)) { + console.log('Duplicate User Input'); + return; + } + const salt = randomBytes(64).toString('base64'); - const secret = pbkdf2Sync(pwd1, salt, 100000, 64, 'sha512').toString( - 'base64' - ); + const secret = pbkdf2Sync(pwd, salt, 100000, 64, 'sha512').toString('base64'); const sql = 'INSERT INTO user (id, email, secret, salt, nickname, create_date) VALUES (?, ?, ?, ?, ?, NOW())'; From 2122b9ee1a27b8107e3a268959a207d0eddce87d Mon Sep 17 00:00:00 2001 From: Sangwoo Park Date: Fri, 3 Sep 2021 00:14:55 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=EC=A4=91=EB=B3=B5=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EC=95=88=20=EB=90=98=EA=B3=A0=20=EC=84=9C=EB=B2=84?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=84=EC=86=A1=EB=90=98=EB=8A=94=20=ED=98=84?= =?UTF-8?q?=EC=83=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/js/sign-up.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/public/js/sign-up.js b/public/js/sign-up.js index e09b0b3..728db28 100644 --- a/public/js/sign-up.js +++ b/public/js/sign-up.js @@ -92,7 +92,7 @@ function checkValidName() { } } -function checkValidAll() { +async function checkValidAll() { const inputs = [emailInput, pwdInput, pwd2Input, nameInput]; const divs = [emailValidDiv, pwdValidDiv, pwd2ValidDiv, nameValidDiv]; @@ -102,15 +102,19 @@ function checkValidAll() { } }); + const isDuplicateEmail = await checkDuplicateEmail(); + const isDuplicateName = await checkDuplicateName(); + if ( checkValidEmail() && checkStrongPwd() && checkEqualPwd() && - checkValidName() && - checkDuplicateEmail() && - checkDuplicateName() + isDuplicateEmail && + isDuplicateName ) { form.submit(); + } else { + alert('입력하신 정보를 확인하세요.'); } }