Commit 1563c9a4 authored by 한규민's avatar 한규민
Browse files

핸드폰인증, 마이페이지

parent 64d60802
......@@ -5,7 +5,6 @@ const getUser = async () => {
const url = `${baseUrl}/api/auth/user`
const { data } = await axios.get(url)
return data
}
const login = async (login) => {
......@@ -31,8 +30,14 @@ const compareId = async (userId) => {
return data
}
const confirmMbnum = async (id, token) => {
const url = `${baseUrl}/api/auth/${id}/${token}`
const confirmMbnum = async (phone) => {
const url = `${baseUrl}/api/auth/phone/${phone}`
const { data } = await axios.post(url)
return data
}
const confirmNum = async (num) => {
const url = `${baseUrl}/api/auth/num/${num}`
const { data } = await axios.get(url)
return data
}
......@@ -66,6 +71,7 @@ const authApi = {
signup,
compareId,
confirmMbnum,
confirmNum,
profile,
getMember,
comparePw,
......
......@@ -92,6 +92,7 @@ const MyInfo = () => {
setLoading(() => (true));
const pw = presentPw;
const confirmPw = await authApi.comparePw(pw);
console.log("confirmPw : "+ confirmPw);
if (confirmPw) {
setPage(false);
} else {
......
......@@ -9,7 +9,17 @@ img{
width: 40%;
}
.confirm{
color: black;
padding-right: 8px;
text-align: center;
display: flex;
align-items: center;
}
.input2 {
width: 9.01rem;
}
.userName{
color: white;
font-size: 1.3rem;
......
......@@ -15,9 +15,11 @@ const Signup = () => {
userRePassword: ""
})
const [number, setNumber] = useState(null);
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
//각 타입별 error 유무 state
const [mbError,setMbError] = useState(false);
const [error, setError] = useState("");
const [errorMsg, setErrorMsg] = useState({
errorId: null,
......@@ -30,6 +32,7 @@ const Signup = () => {
})
// id중복확인 여부 state와 가입하기 누르면 id 임시 저장
const [overlapId, setOverlapId] = useState(false);
const [confirmMb, setConfirmMb] = useState(false);
const [preId, setPreId] = useState("");
//입력할때마다 state에 저장
......@@ -82,12 +85,47 @@ const Signup = () => {
}
const handleOnClickMbnum = async (e) => {
e.preventDefault();
try {
const id = "AC01ecdbffb36dc0766cfea487a54a4c6e";
const token = "1d86d5d43760b5dce5582badf7b0a775";
await authApi.confirmMbnum(id,token);
setError("");
setLoading(true)
const phone = user.userMbnum;
console.log("phone : ", phone)
const message = await authApi.confirmMbnum(phone);
console.log("message : ", message);
if(message.isSuccess){
console.log("mberror: "+mbError);
setMbError("보냄");
}
} catch (error) {
console.log('twilio error'+ error)
console.log('error'+ error)
}finally {
setLoading(false);
}
}
const handleOnChangeMb = (e) => {
setNumber(String(e.target.value));
}
const handleOnClickMbConfirm = async (e) => {
e.preventDefault();
try {
setError("");
setLoading(true)
const confirmNum = number;
console.log(confirmNum)
const message = await authApi.confirmNum(confirmNum);
console.log(message);
setMbError(message);
if(message === "성공"){
setConfirmMb(true);
console.log("인증완료");
}
} catch (error) {
catchErrors(error, setError);
}finally {
setLoading(false);
}
}
......@@ -148,17 +186,26 @@ const Signup = () => {
vaildationIdPw(user.userPassword.length, 8, "errorPassword");
// 비밀번호 확인 유효성 검사
vaildationData(user.userRePassword, user.userPassword, "errorRePassword");
let validation = false;
validation = (Object.values(errorMsg).some((element) => (element)) === false);
// 최종 유효성 검사
if (overlapId && (Object.values(errorMsg).some((element) => (element)) === false)) {
} else if (!overlapId && (Object.values(errorMsg).some((element) => (element)) === false)) {
if (overlapId) {
if(confirmMb){
if(!validation){
throw new Error("유효하지 않은 데이터입니다.");
}else{
console.log("가입성공");
return true
}
}else{
throw new Error("휴대폰 인증도 해주세요");
}
}else{
setErrorMsg(errorMsg => ({ ...errorMsg, errorId: false }));
throw new Error("먼저 아이디 중복확인을 해주세요");
} else {
throw new Error("유효하지 않은 데이터입니다.");
}
}
if (success) {
return <Redirect to="/login" />;
}
......@@ -208,12 +255,29 @@ const Signup = () => {
<div className={styles.inputContent}>
<label className={styles.signupLabel}>휴대폰 번호</label>
<div className="d-flex col-md-auto">
<input className={`${styles.input}`} type="number" name="userMbnum" placeholder="-없이 11자리 입력" onChange={handleUserOnChange} min="" max="99999999999" required />
<button type="button" disabled={loading} name="errorId" className={`rounded-2 mt-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} onClick={handleOnClickMbnum}>인증번호받기</button>
<input className={`${styles.input} ${styles.input2}`} type="number" name="userMbnum" placeholder="-없이 11자리 입력" onChange={handleUserOnChange} min="" max="99999999999" required />
<button type="button" disabled={loading} className={`rounded-2 mt-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample" onClick={handleOnClickMbnum}>인증번호받기</button>
</div>
</div>
{errorMsg.errorMbnum && <p className={styles.passwordConfirmError}>-없이 숫자 11자리를 입력해주세요.</p>}
<div class="collapse" id="collapseExample">
{/* <div className="d-flex col-md-auto justify-content-end"> */}
<div className="d-flex justify-content-between mt-3">
<label className={`${styles.confirm}`}>인증하기</label>
<div>
<input className={`${styles.input} ${styles.input2}`} type="number" placeholder="인증번호를 입력" onChange={handleOnChangeMb} require />
<button type="button" className={`rounded-2 py-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} onClick={handleOnClickMbConfirm}>확인</button>
<button type="button" className={`rounded-2 py-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} onClick={handleOnClickMbnum}>재전송</button>
</div>
</div>
{(mbError === "재전송") && <p className={styles.passwordConfirmError}>유효시간이 만료되었습니다. 재전송해주세요.</p>}
{(mbError === "보냄") && <p className={styles.passwordConfirmError}>5분이내에 입력해주세요.</p>}
{(mbError === "성공") && <p className={styles.passwordConfirmError}>인증되었습니다.</p>}
{(mbError === "실패") && <p className={styles.passwordConfirmError}>인증번호를 다시 입력해주세요.</p>}
</div>
</div>
<div className="d-flex flex-column">
<div className={`${styles.inputContent}`}>
<label className={styles.signupLabel}>비밀번호</label>
......
......@@ -5,7 +5,13 @@
font-size: 1.7rem;
margin-top: 2rem;
}
.confirm{
color: white;
padding-right: 8px;
text-align: center;
display: flex;
align-items: center;
}
.contents{
display: flex;
width: 100%;
......@@ -31,7 +37,9 @@
border-radius: 3px;
text-align: center;
}
.input2 {
width: 9.01rem;
}
input[type=password]{
font-family: 'Courier New', Courier, monospace;
}
......
......@@ -421,6 +421,11 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"crypto-js": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
"integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
},
"crypto-random-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
......
import jwt from "jsonwebtoken";
import config from "../config/app.config.js";
import { User, Role } from '../db/index.js';
<<<<<<< HEAD
import fs from "fs";
=======
<<<<<<< HEAD
>>>>>>> master
import CryptoJS from "crypto-js";
import axios from "axios";
const getUser = async (req, res) => {
try {
......@@ -21,9 +20,6 @@ const getUser = async (req, res) => {
return res.status(500).send("유저를 가져오지 못했습니다.");
}
}
=======
// import Twilio from "twilio";
>>>>>>> jiwon
const login = async (req, res) => {
try {
......@@ -98,23 +94,111 @@ const compareId = async (req, res) => {
}
}
const confirmMbnum = async (req, res) => {
// const id = req.params.id;
// const token = req.params.token;
// 휴대폰 인증
const NCP_serviceID = 'ncp:sms:kr:270376424445:butterstudio';
const NCP_accessKey = 'GQmVCT2ZFxnEaJOWbrQs';
const NCP_secretKey = 'XLQQ8sd9WxW40hNi0xNBTOG0T8ksRsr8c8sUIEvy';
const date = Date.now().toString();
const uri = NCP_serviceID;
const secretKey = NCP_secretKey;
const accessKey = NCP_accessKey;
const method = 'POST';
const space = " ";
const newLine = "\n";
const url = `https://sens.apigw.ntruss.com/sms/v2/services/${uri}/messages`;
const url2 = `/sms/v2/services/${uri}/messages`;
//시크릿 키를 암호화하는 작업
const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, secretKey);
// const client = Twilio(id, token);
// // console.log(client);
// client.messages
// .create({
// to: '+8201086074580',
// from: '+14159428621',
// body: '[config.cookieName] 인증번호[1234]를 입력해주세요',
// })
// .then(message => console.log(message.sid))
// .catch(e => console.log(error));
// console.log("id = ", id, "token = ", token);
res.json(true);
hmac.update(method);
hmac.update(space);
hmac.update(url2);
hmac.update(newLine);
hmac.update(date);
hmac.update(newLine);
hmac.update(accessKey);
const hash = hmac.finalize();
const signature = hash.toString(CryptoJS.enc.Base64);
let inherentNum = "";
// 유효시간 5분 설정
const time = () => {
inherentNum = false;
return inherentNum
}
// 인증번호 발송
const confirmMbnum = async (req, res) => {
try {
const phoneNumber = req.params.phone;
console.log(phoneNumber);
//인증번호 생성
const verifyCode = Math.floor(Math.random() * (999999 - 100000)) + 100000;
console.log("verifyCode : ",verifyCode);
let result = await axios({
method: method,
json: true,
url: url,
headers: {
'Content-Type': "application/json",
'x-ncp-apigw-timestamp': date,
'x-ncp-iam-access-key': accessKey,
'x-ncp-apigw-signature-v2': signature,
},
data: {
type: 'SMS',
contentType: 'COMM',
countryCode: '82',
from: '01086074580',
content: `[본인 확인] 인증번호 [${verifyCode}]를 입력해주세요.`,
messages: [
{
to: `${phoneNumber}`,
},
],
},
});
const resultMs = result.data.messages;
console.log('resultMs', resultMs);
console.log('response', res.data, res['data']);
inherentNum = String(verifyCode);
// 5분 유효시간 설정
setTimeout(time, 300000);
res.json({ isSuccess: true, code: 202, message: "본인인증 문자 발송 성공", result: res.data });
} catch (error) {
console.log("error: ", error);
if (error.res == undefined) {
res.json({ isSuccess: true, code: 200, message: "본인인증 문자 발송 성공", result: res.data });
}
else res.json({ isSuccess: true, code: 204, message: "본인인증 문자 발송에 문제가 있습니다.", result: error.res });
}
};
// 인증번호 확인
const confirmNum = async (req, res) => {
try {
const verifyCode = inherentNum;
const confirmNum = req.params.num;
if(!verifyCode){
res.send("재전송")
}else{
if (confirmNum !== verifyCode) {
res.send("실패");
}else {
res.send("성공");
}
}
} catch (error) {
console.error("error : ", error.message);
res.status(500).send("잘못된 접근입니다.");
}
};
const signup = async (req, res) => {
const { userId, userEmail, userNickName, userBirthday, userMbnum, userPassword } = req.body;
......@@ -138,6 +222,7 @@ const signup = async (req, res) => {
birth: userBirthday,
phoneNumber: userMbnum,
password: userPassword,
img:"",
roleId: role.id
});
res.json(newUser);
......@@ -154,7 +239,7 @@ const getMember = async (req, res) => {
const decoded = jwt.verify(token, config.jwtSecret);
if (decoded.role === "member") {
const user = await User.findOne({ where: { id: decoded.id } });
res.json({nickname : user.nickname, img : user.img});
res.json({ nickname: user.nickname, img: user.img });
} else {
res.status(401).send("잘못된 접근입니다.");
}
......@@ -172,17 +257,17 @@ const uploadProfile = async (req, res) => {
const decoded = jwt.verify(token, config.jwtSecret);
if (decoded) {
const img = await User.findOne({ where: { id:decoded.id }, attributes : ["img"]});
const img = await User.findOne({ where: { id: decoded.id }, attributes: ["img"] });
console.log("여기여기");
fs.unlink( "upload"+`\\${img.img}`, function(data){ console.log(data);});
fs.unlink("upload" + `\\${img.img}`, function (data) { console.log(data); });
const user = await User.update({
img: image
}, { where: { id: decoded.id } });
if(user){
const success = await User.findOne({ where: { id: decoded.id }, attributes: ["img"]});
if (user) {
const success = await User.findOne({ where: { id: decoded.id }, attributes: ["img"] });
res.json(success)
}else{
} else {
throw new Error("프로필 등록 실패")
}
}
......@@ -201,6 +286,7 @@ const comparePw = async (req, res) => {
const user = await User.scope("withPassword").findOne({ where: { id: decoded.id } });
//입력한 비번과 해당 행 비번을 비교
const passwordMatch = await user.comparePassword(req.params.pw);
console.log("passwordMatch : ", passwordMatch);
//클라이언트로 동일여부를 전송
if (passwordMatch) {
return res.json(true)
......@@ -213,35 +299,35 @@ const comparePw = async (req, res) => {
}
}
<<<<<<< HEAD
const overlap = async (decoded, dataType, data) => {
try {
let overlap = await User.findOne({ where: { id: decoded.id } });
console.log("overlap : ", overlap, "overlap[dataType] : ", overlap[dataType]);
console.log("기존 데이터 : ", overlap, "변경할 데이터 : ", data);
if (overlap[dataType] === data) {
console.log("여기여기")
return true
} else {
overlap = await User.findOne({ where: { id: decoded.id }, attributes: [dataType] });
if (overlap) {
let overlap2 = await User.findOne({ attributes: [dataType] });
console.log(overlap2)
if (overlap2[dataType] === data) {
return false
} else {
return true
}
}
}catch(error){
} catch (error) {
console.error(error.message);
}
}
=======
<<<<<<< HEAD
>>>>>>> master
const modifyUser = async (req, res) => {
try {
const token = req.cookies.butterStudio;
const decoded = jwt.verify(token, config.jwtSecret);
const { userEmail, userNickName, userMbnum, userPassword } = req.body;
console.log(userEmail);
console.log(userMbnum);
const overlapEmail = await overlap(decoded, "email", userEmail);
const overlapMbnum = await overlap(decoded, "phoneNumber", userMbnum);
console.log("overlapEmail", overlapEmail, " overlapMbnum : ", overlapMbnum);
......@@ -258,7 +344,7 @@ const modifyUser = async (req, res) => {
} else if (!overlapEmail && overlapMbnum) {
res.status(500).send("이미 있는 이메일입니다.");
} else if (overlapEmail && !overlapMbnum) {
res.status(500).send("이미 있는 이메일입니다.");
res.status(500).send("이미 있는 핸드폰번호입니다.");
} else {
res.status(500).send("이미 있는 이메일, 핸드폰번호입니다.");
}
......@@ -267,21 +353,19 @@ const modifyUser = async (req, res) => {
res.status(500).send("수정 에러. 나중에 다시 시도 해주세요");
}
};
=======
const getUserInfo = async (req,res)=>{
const {id} = req.body
const getUserInfo = async (req, res) => {
const { id } = req.body
console.log(id)
try {
const userInfo = await User.findOne({
where:{id:id},
attributes:["userId","email","nickname","birth","phoneNumber"]
where: { id: id },
attributes: ["userId", "email", "nickname", "birth", "phoneNumber"]
})
res.json(userInfo)
} catch (error) {
console.log(error)
}
}
>>>>>>> jiwon
export default {
getUser,
......@@ -289,17 +373,12 @@ export default {
logout,
compareId,
confirmMbnum,
confirmNum,
signup,
<<<<<<< HEAD
getMember,
uploadProfile,
=======
getNickName,
<<<<<<< HEAD
>>>>>>> master
getUser,
comparePw,
modifyUser
=======
modifyUser,
getUserInfo
>>>>>>> jiwon
}
......@@ -27,10 +27,11 @@ sequelize
birth: "990926",
phoneNumber: "01086074580",
password: "admin!",
img: "970aaa79673a39331d45d4b55ca05d25",
roleId: adminRole?.id,
});
} else {}
} else { }
app.listen(appConfig.port, () => {
console.log(`Server is running on port ${appConfig.port}`);
});
......
......@@ -5,7 +5,6 @@ import theaterRouter from "./theater.route.js";
import cinemaRouter from "./cinema.route.js";
import kakaopayRouter from "./kakaopay.route.js";
import emailRouter from './email.route.js'
import theaterRouter from './theater.route.js'
import reservationRouter from './reservation.route.js'
const router = express.Router();
......
......@@ -43,12 +43,12 @@ router
.get(userCtrl.compareId)
router
.route("/:id/:token")
.get(userCtrl.confirmMbnum)
.route("/phone/:phone")
.post(userCtrl.confirmMbnum)
// router
// .route("/:iddd")
// .get(userCtrl.getNickName)
router
.route("/num/:num")
.get(userCtrl.confirmNum)
router.route('/getuserinfo')
.post(userCtrl.getUserInfo)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment