- {ticketInfo
- ?

- :
영화선택
}
+
+
+
+
+
+ 일반
+
+
+
+
+
+ 청소년
+
+ {ticketInfo.adult
+ ?
+
+ :
+
+ }
+
+
+
+ 경로우대
+
+
+
+
+
+
+
+
+
{ticketInfo.cinema} | {ticketInfo.selectedTheater}관
+
{ticketInfo.title}
+
{ticketInfo.time}
+
-
-
극장선택
- {ticketInfo
- ?
- - 영화: {ticketInfo.title}
- - 극장: {ticketInfo.theater}
- - 일시: 2021/07/21 10:00
- - 상영관: 3관
- - 좌석: {selectedSeats}
-
- :
}
+
+
+
+
+
+
+
+ 선택됨
+
+
+
+ 선택불가
+
+
-
-
결제하기
- {ticketInfo
- ?
-
-

-
- :
-

+
+
+ {ticketInfo
+ ?

+ :
영화선택
}
+
+
+ {ticketInfo
+ ?
+ - 영화: {ticketInfo.title}
+ - 극장: {ticketInfo.cinema}
+ - 일시: 2021/07/21 10:00
+ - 상영관: {ticketInfo.selectedTheater}관
+ - 좌석: {selectedSeats.map(el => String.fromCharCode(parseInt(el.split('-')[0]) + 64) + el.split('-')[1]) + ' '}
+
+ :
+
극장선택
+ }
+
+
+ {selectedSeats
+ ?
+
+ - 성인: {count.adult}명
+ - 청소년: {count.youth}명
+ - 경로: {count.senior}명
+ - 총 결제금액: {count.adult * ticketFee.adult + count.youth * ticketFee.youth + count.senior * ticketFee.senior}원
+
+ : <>>}
+
+
+
결제하기
+ {selectedSeats.length > 0 && count.adult + count.youth + count.senior === selectedSeats.length
+ ?
+
+ :
+
- }
+ }
+
-
+ >
)
}
diff --git a/client/src/utils/auth.js b/client/src/utils/auth.js
index 6cf8c67aceb27d9663cd554bb847087dc3d1a8f6..16ea0d2030367be82c1ef37fc8a4c3c64d9b827b 100644
--- a/client/src/utils/auth.js
+++ b/client/src/utils/auth.js
@@ -1,13 +1,13 @@
-import config from "./clientConfig";
+import clientConfig from "./clientConfig";
export function handleLogin(user) {
if (user) {
- localStorage.setItem(config.loginUser, JSON.stringify(user));
+ localStorage.setItem(clientConfig.loginUser, JSON.stringify(user));
}
}
export function getLocalUser() {
- const userData = localStorage.getItem(config.loginUser);
+ const userData = localStorage.getItem(clientConfig.loginUser);
let user = null;
if (userData) {
user = JSON.parse(userData);
diff --git a/package-lock.json b/package-lock.json
index f6917553ba6a00127f529efc51026d08c2fc81a6..2fa437d02b400f958e28678323a6be924b0508d9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -39,29 +39,6 @@
"negotiator": "0.6.2"
}
},
- "agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "requires": {
- "debug": "4"
- },
- "dependencies": {
- "debug": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
- "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
- "requires": {
- "ms": "2.1.2"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
- }
- }
- },
"ansi-align": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
@@ -124,11 +101,6 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
- "asap": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
- },
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
@@ -267,15 +239,6 @@
}
}
},
- "call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "requires": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
- }
- },
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
@@ -458,17 +421,17 @@
"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",
"integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
"dev": true
},
- "dayjs": {
- "version": "1.10.6",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.6.tgz",
- "integrity": "sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw=="
- },
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -666,6 +629,11 @@
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
+ "fs": {
+ "version": "0.0.1-security",
+ "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
+ "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
+ },
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@@ -673,21 +641,6 @@
"dev": true,
"optional": true
},
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
- },
- "get-intrinsic": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
- "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
- "requires": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1"
- }
- },
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
@@ -740,25 +693,12 @@
"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
"dev": true
},
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
- "has-symbols": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
- "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
- },
"has-yarn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
@@ -783,30 +723,6 @@
"toidentifier": "1.0.0"
}
},
- "https-proxy-agent": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
- "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
- "requires": {
- "agent-base": "6",
- "debug": "4"
- },
- "dependencies": {
- "debug": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
- "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
- "requires": {
- "ms": "2.1.2"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
- }
- }
- },
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -1247,11 +1163,6 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
- "object-inspect": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
- "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg=="
- },
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -1378,11 +1289,6 @@
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
"dev": true
},
- "pop-iterate": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/pop-iterate/-/pop-iterate-1.0.1.tgz",
- "integrity": "sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M="
- },
"postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
@@ -1451,26 +1357,11 @@
"escape-goat": "^2.0.0"
}
},
- "q": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/q/-/q-2.0.3.tgz",
- "integrity": "sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=",
- "requires": {
- "asap": "^2.0.0",
- "pop-iterate": "^1.0.1",
- "weak-map": "^1.0.5"
- }
- },
"qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
- "querystringify": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
- "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
- },
"range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -1537,11 +1428,6 @@
"rc": "^1.2.8"
}
},
- "requires-port": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
- },
"responselike": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
@@ -1559,11 +1445,6 @@
"any-promise": "^1.3.0"
}
},
- "rootpath": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/rootpath/-/rootpath-0.1.2.tgz",
- "integrity": "sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms="
- },
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -1574,11 +1455,6 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
- "scmp": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz",
- "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q=="
- },
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -1668,6 +1544,11 @@
"requires": {
"lru-cache": "^6.0.0"
}
+ },
+ "validator": {
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
+ "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
}
}
},
@@ -1692,16 +1573,6 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
- "side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
- "requires": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
- }
- },
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
@@ -1860,34 +1731,6 @@
"nopt": "~1.0.10"
}
},
- "twilio": {
- "version": "3.66.0",
- "resolved": "https://registry.npmjs.org/twilio/-/twilio-3.66.0.tgz",
- "integrity": "sha512-2jek7akXcRMusoR20EWA1+e5TQp9Ahosvo81wTUoeS7H24A1xbVQJV4LfSWQN4DLUY1oZ4d6tH2oCe/+ELcpNA==",
- "requires": {
- "axios": "^0.21.1",
- "dayjs": "^1.8.29",
- "https-proxy-agent": "^5.0.0",
- "jsonwebtoken": "^8.5.1",
- "lodash": "^4.17.21",
- "q": "2.0.x",
- "qs": "^6.9.4",
- "rootpath": "^0.1.2",
- "scmp": "^2.1.0",
- "url-parse": "^1.5.0",
- "xmlbuilder": "^13.0.2"
- },
- "dependencies": {
- "qs": {
- "version": "6.10.1",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
- "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
- "requires": {
- "side-channel": "^1.0.4"
- }
- }
- }
- },
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
@@ -1966,15 +1809,6 @@
"xdg-basedir": "^4.0.0"
}
},
- "url-parse": {
- "version": "1.5.3",
- "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
- "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
- "requires": {
- "querystringify": "^2.1.1",
- "requires-port": "^1.0.0"
- }
- },
"url-parse-lax": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
@@ -2000,20 +1834,15 @@
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"validator": {
- "version": "10.11.0",
- "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
- "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
+ "version": "13.6.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz",
+ "integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
- "weak-map": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz",
- "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes="
- },
"widest-line": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
@@ -2055,11 +1884,6 @@
"integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
"dev": true
},
- "xmlbuilder": {
- "version": "13.0.2",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz",
- "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ=="
- },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
index 60832a559303a99b95c1a2138d55bb46169a0351..ae45c1be5ae9daca4fd275b32caa22e61431a36a 100644
--- a/package.json
+++ b/package.json
@@ -19,8 +19,10 @@
"axios": "^0.21.1",
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.5",
+ "crypto-js": "^4.1.1",
"dotenv": "^10.0.0",
"express": "^4.17.1",
+ "fs": "0.0.1-security",
"jsonwebtoken": "^8.5.1",
"moment": "^2.29.1",
"multer": "^1.4.2",
@@ -28,7 +30,7 @@
"pg": "^8.6.0",
"pg-hstore": "^2.3.4",
"sequelize": "^6.6.4",
- "twilio": "^3.66.0"
+ "validator": "^13.6.0"
},
"devDependencies": {
"nodemon": "^2.0.12"
diff --git a/server/app.js b/server/app.js
index 4f403218899412e463068574ba06aad746e08221..430cf6c3a482ce35c5e0b05a48a72a65d991a399 100644
--- a/server/app.js
+++ b/server/app.js
@@ -7,8 +7,7 @@ const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(cookieParser())
-
+app.use('/upload', express.static('upload'))
app.use('/api', mainRouter)
-
export default app
\ No newline at end of file
diff --git a/server/config/app.config.js b/server/config/app.config.js
index 6ad02e97268803c03428deb7f2f7e130fc51e2d5..020f5db6d709694b7c9d60455163bdfb8c839329 100644
--- a/server/config/app.config.js
+++ b/server/config/app.config.js
@@ -4,6 +4,7 @@ const config = {
jwtSecret: 'dfkasf23i$efksdfks!',
jwtExpires: '7d',
cookieName: 'butterStudio',
+ cookieNameMb: 'confirmNum',
cookieMaxAge: 60 * 60 * 24 * 7 * 1000,
kakaoAdminKey: 'e3ce7106688a35e072e2630daa9d7250',
}
diff --git a/server/controllers/email.controller.js b/server/controllers/email.controller.js
index 7b96848148d25528baceb6c370c27c823b48dc83..61c46ec7f7151553dcf0186faff218ebb2846cee 100644
--- a/server/controllers/email.controller.js
+++ b/server/controllers/email.controller.js
@@ -1,49 +1,55 @@
import nodemailer from "nodemailer"
-const SendMail = async (req,res) => {
- // console.log(req.body)
- const {email} = req.body
- console.log(email)
- const sendMail = async (email) => {
- // 메일을 전달해줄 객체
- const transporter = nodemailer.createTransport({
- // service: "gmail",
- host: 'smtp.gmail.com',
- port: 465,
- secure: true,
- auth: {
- type: "OAuth2",
- user: "angelayoon99@gmail.com",
- clientId: process.env.GMAIL_CLIENTID,
- clientSecret: process.env.GMAIL_CLIENTSECRET,
- accessToken: process.env.GMAIL_ACCESS_TOKEN,
- refreshToken: process.env.GMAIL_REFRESH_TOKEN,
- },
- tls: {
- rejectUnauthorized: false,
- },
- });
-
- // 메일 옵션
- const mailOptions = {
- from: `윤지원
`,
- to: "jiwon5393@naver.com",
- subject: "사용자 계정 확인용 메일.",
- text: "Test Mail from Test Server.",
- };
-
- // 메일 전송
- try {
- const mailResult = await transporter.sendMail(mailOptions);
- console.log(`Mail sent - ID : ${mailResult.messageId}`);
- } catch (err) {
- console.log("Mail Sending Failuer.");
- console.log(err);
- }
- }
-
- sendMail(email);
-}
+const SendMail = async (req, res) => {
+ const { email, name, nickname } = req.body.userData
+ const { title, cinema, time, theater } = req.body
+ const selectedSeats = req.body.reservationData.map(el => String.fromCharCode(el.row + 64) + el.col)
+ const sendMail = async (email, title, cinema, theater, time, name, selectedSeats, nickname) => {
+ const transporter = nodemailer.createTransport({
+ host: 'smtp.gmail.com',
+ port: 465,
+ secure: true,
+ auth: {
+ type: "OAuth2",
+ user: "angelayoon99@gmail.com",
+ clientId: process.env.GMAIL_CLIENTID,
+ clientSecret: process.env.GMAIL_CLIENTSECRET,
+ refreshToken: process.env.GMAIL_REFRESH_TOKEN,
+ },
+ tls: {
+ rejectUnauthorized: false,
+ },
+ });
+ // 메일 옵션
+ const mailOptions = {
+ from: `${cinema} `,
+ to: `${email}`,
+ subject: `${cinema} 예매확인내역: ${title}`,
+ html: `
+
+ ${name || nickname}님의 예매
+
+
+ 영화: ${title}
+
+
+ 장소: ${cinema} ${theater}관
+
+
+ 일시 및 좌석: ${time} / ${selectedSeats.map(el => el + ' ')}
+
+
`
+ };
+ try {
+ const mailResult = await transporter.sendMail(mailOptions);
+ console.log(`Mail sent - ID : ${mailResult.messageId}`);
+ } catch (err) {
+ console.log("Mail Sending Failuer.");
+ console.log(err);
+ }
+ }
+ sendMail(email, title, cinema, theater, time, name, selectedSeats, nickname);
+}
export default { SendMail }
\ No newline at end of file
diff --git a/server/controllers/kakaopay.controller.js b/server/controllers/kakaopay.controller.js
index 1a7bf37dc91584bc9ab1a9d71a4516d4f3d6410d..ad55e2e1702bad8e3b4ec3503553ddd429f49c61 100644
--- a/server/controllers/kakaopay.controller.js
+++ b/server/controllers/kakaopay.controller.js
@@ -36,12 +36,10 @@ const singleTest = async (req, res) => {
},
})
const resp = response.data
- console.log('resp', resp)
res.json({ redirect_url: resp.next_redirect_pc_url })
} catch (error) {
console.log(error)
}
-
}
export default { success, fail, cancel, singleTest }
\ No newline at end of file
diff --git a/server/controllers/movie.controller.js b/server/controllers/movie.controller.js
index e89336f33d0e052455e619f8ebd7d7fee2aa4f29..3f6e96aa11dfb52bf9826011e9537d7cea188153 100644
--- a/server/controllers/movie.controller.js
+++ b/server/controllers/movie.controller.js
@@ -12,48 +12,6 @@ const getListfromDB = async (req, res) => {
}
}
-const getMovieByCategory = async (req, res, next, category) => {
- try {
- const TMDBmovieIds = []
- const movieIds = []
- const response = await axios.get(`https://api.themoviedb.org/3/movie/${category}?api_key=${process.env.TMDB_APP_KEY}&language=ko-KR&page=1`)
- const TMDBmovies = response.data.results
-
- TMDBmovies.forEach(element => {
- TMDBmovieIds.push(element.id)
- })
- const responseAfterCompare = await Movie.findAll({
- where: {
- movieId: {
- [Op.or]: TMDBmovieIds
- }
- }
- })
- responseAfterCompare.forEach(el => {
- movieIds.push(el.movieId)
- })
- req.movieIds = movieIds
- next()
- } catch (error) {
- return res.status(500).send(error.message || "영화 가져오기 중 에러 발생");
- }
-}
-
-const getMovieById = async (req, res) => {
- try {
- const movieIds = req.movieIds
- const elements = await Promise.all(
- movieIds.map(async (movieId) => {
- const movie = await axios.get(`https://api.themoviedb.org/3/movie/${movieId}?api_key=${process.env.TMDB_APP_KEY}&language=ko-KR`)
- return movie.data
- })
- )
- res.json(elements)
- } catch (error) {
- return res.status(500).send(error.message || "영화 가져오기 중 에러 발생");
- }
-}
-
const movieforAdmin = async (req, res) => {
try {
const TMDBmovieIds = []
@@ -111,6 +69,7 @@ const getAllMovie = async (req, res, next) => {
const getMovieList = async (req, res) => {
try {
+ const { category } = req.params
const movieList = await Movie.findAll()
const movieIds = []
movieList.forEach(el => {
@@ -119,10 +78,45 @@ const getMovieList = async (req, res) => {
const elements = await Promise.all(
movieIds.map(async (movieId) => {
const movie = await axios.get(`https://api.themoviedb.org/3/movie/${movieId}?api_key=${process.env.TMDB_APP_KEY}&language=ko-KR`)
- return movie.data
+ const cols = await Movie.findOne({
+ where: { "movieId": movieId },
+ attributes: ["ticket_sales", "vote_average"]
+ })
+ const totalReservationRate = await Movie.findAll({
+ attributes: [[sequelize.fn('SUM', sequelize.col('ticket_sales')), 'totalReservationRate']]
+ });
+ return { ...movie.data, ticket_sales: cols.ticket_sales, vote_average: cols.vote_average, totalReservationRate: totalReservationRate[0] }
+
})
)
- res.json(elements)
+ if (category === "popular") {
+ for (let i = 0; i < elements.length; i++) {
+ if (new Date(elements[i].release_date) > new Date()) {
+ elements.splice(i, 1);
+ i--;
+ }
+ }
+ elements.sort(function (a, b) {
+ return b.popularity - a.popularity
+ })
+ res.json(elements)
+ } else if (category === "upcoming") {
+ for (let i = 0; i < elements.length; i++) {
+ if (new Date(elements[i].release_date) <= new Date()) {
+ elements.splice(i, 1);
+ i--;
+ }
+ }
+ elements.sort(function (a, b) {
+ return a.release_date - b.release_date
+ })
+ res.json(elements)
+ } else {
+ elements.sort(function (a, b) {
+ return a.title - b.title
+ })
+ res.json(elements)
+ }
} catch (error) {
return res.status(500).send(error.message || "영화 정보 가져오는 중 에러 발생")
}
@@ -165,7 +159,14 @@ const findonlyTitle = async (req, res) => {
const elements = await Promise.all(
movieIds.map(async (movieId) => {
const movie = await axios.get(`https://api.themoviedb.org/3/movie/${movieId}?api_key=${process.env.TMDB_APP_KEY}&language=ko-KR`)
- return movie.data
+ const cols = await Movie.findOne({
+ where: { "movieId": movieId },
+ attributes: ["ticket_sales", "vote_average"]
+ })
+ const totalReservationRate = await Movie.findAll({
+ attributes: [[sequelize.fn('SUM', sequelize.col('ticket_sales')), 'totalReservationRate']]
+ });
+ return { ...movie.data, ticket_sales: cols.ticket_sales, vote_average: cols.vote_average, totalReservationRate: totalReservationRate[0] }
})
)
return res.json({ count: movieIds.length, results: elements })
@@ -189,8 +190,6 @@ const findaboutAll = async (req, res, next) => {
export default {
getListfromDB,
- getMovieByCategory,
- getMovieById,
getAllMovie,
getMovieList,
create,
diff --git a/server/controllers/reservation.controller.js b/server/controllers/reservation.controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..88fb62ee400d0ffb4b245ea4ec9041de97f41c33
--- /dev/null
+++ b/server/controllers/reservation.controller.js
@@ -0,0 +1,84 @@
+import axios from 'axios'
+import { Movie, Reservation, Theater } from '../db/index.js'
+import sequelize from 'sequelize'
+const { Op } = sequelize
+
+const findReservedSeats = async (req, res) => {
+ const { timetable } = req.body
+ try {
+ const reservedSeats = await Reservation.findAll({
+ where: {
+ timetable: timetable
+ }
+ })
+ res.json(reservedSeats)
+ } catch (error) {
+ res.status(500).send(error.message || "이미 예매되어있는 좌석을 찾는 중 오류발생")
+ }
+}
+const findReservation = async (req, res) => {
+ const { user } = req.body
+ try {
+ const reservation = await Reservation.findAll({
+ where: {
+ user: user
+ }
+ })
+ res.json(reservation)
+ } catch (error) {
+ res.status(500).send(error.message || "예매 내역들을 찾는 중 오류발생")
+ }
+}
+const findOneReservation = async (req, res) => {
+ const { userType, user } = req.body
+ try {
+ const reservation = await Reservation.findAll({
+ where: {
+ userType: userType,
+ user: user
+ },
+ })
+ // console.log(reservation)
+ res.json(reservation)
+ } catch (error) {
+ res.status(500).send(error.message || "예매 내역을 찾는 중 오류 발생")
+ }
+}
+const saveReservation = async (req, res) => {
+ const { movieId, selectedTheater, timetable, payment, user, userType, totalFee } = req.body
+ const rows = req.body.selectedSeats.map(el => el.split('-')[0])
+ const cols = req.body.selectedSeats.map(el => el.split('-')[1])
+ try {
+ for (let index = 0; index < rows.length; index++) {
+ const reservation = await Reservation.create({
+ user: user,
+ userType: userType,
+ movieId: movieId,
+ theater: selectedTheater,
+ row: rows[index],
+ col: cols[index],
+ timetable: timetable,
+ payment: payment,
+ totalFee: totalFee
+ })
+ }
+ const movie = await Movie.findOne({
+ where: {
+ movieId: movieId
+ }
+ })
+ movie.ticket_sales++
+ await movie.save();
+ res.json({ message: '200 OK' })
+ } catch (error) {
+ console.log(error)
+ res.status(500).send(error.message || "예매DB에 저장 실패")
+ }
+}
+
+export default {
+ findReservedSeats,
+ findReservation,
+ findOneReservation,
+ saveReservation
+}
\ No newline at end of file
diff --git a/server/controllers/theater.controller.js b/server/controllers/theater.controller.js
index dbee3dc39645fe8f3bba9456c697ccab9a646e7b..484fb09d9dbae6c5b2fd8e10ff4468ec6f4348e8 100644
--- a/server/controllers/theater.controller.js
+++ b/server/controllers/theater.controller.js
@@ -1,5 +1,18 @@
import { Theater, TheaterType } from "../db/index.js";
+const getTheaterInfo = async (req, res) => {
+ const { theaterName } = req.body
+ try {
+ const theaterInfo = await Theater.findOne({
+ where: { theaterName: String(theaterName) },
+ attributes: ['theaterName', 'rows', 'columns']
+ })
+ // console.log("theaterInfo====",theaterInfo)
+ return res.json(theaterInfo)
+ } catch (error){
+ console.log(error)
+ }
+}
const getAll = async (req, res) => {
try {
const findList = await Theater.findAll({ attributes: { exclude: ['createdAt', 'updatedAt'] }, include: [TheaterType], order: [['theaterName']] })
@@ -64,5 +77,6 @@ export default {
getOne,
getTypes,
submit,
- remove
-}
\ No newline at end of file
+ remove,
+ getTheaterInfo
+}
diff --git a/server/controllers/user.controller.js b/server/controllers/user.controller.js
index fa4cb6c21d1c4f193f19af3e4d7c465cd6fccdec..0781df4827f3938c53a8c2b748dad6f5cc27e4c5 100644
--- a/server/controllers/user.controller.js
+++ b/server/controllers/user.controller.js
@@ -1,14 +1,31 @@
import jwt from "jsonwebtoken";
import config from "../config/app.config.js";
-import { User, Role } from '../db/index.js';
-import Twilio from "twilio";
+import { User, Role, Guest, ConfirmNum } from '../db/index.js';
+import fs from "fs";
+import CryptoJS from "crypto-js";
+import validator from "validator";
+// 현재 유저 상태 결정
+const getUser = async (req, res) => {
+ try {
+ if (req.cookies.butterStudio) {
+ const token = req.cookies.butterStudio;
+ const decoded = jwt.verify(token, config.jwtSecret);
+ res.json(decoded);
+ } else {
+ res.json({ id: 0, role: "user" });
+ }
+ } catch (error) {
+ console.error(error);
+ return res.status(500).send("유저를 가져오지 못했습니다.");
+ }
+}
+// 로그인
const login = async (req, res) => {
try {
const { id, password } = req.body;
//사용자 존재 확인
const user = await User.scope("withPassword").findOne({ where: { userId: id } });
- console.log("user : ", user);
if (!user) {
return res.status(422).send(`사용자가 존재하지 않습니다`);
}
@@ -17,19 +34,13 @@ const login = async (req, res) => {
if (passwordMatch) {
// 3) 비밀번호가 맞으면 토큰 생성
const userRole = await user.getRole();
- // const userId = await user.getId();
- console.log("userRole1111 : ", userRole);
- // console.log("userId : ", userId);
-
const signData = {
id: user.id,
role: userRole.name,
};
- console.log("signData : ", signData);
const token = jwt.sign(signData, config.jwtSecret, {
expiresIn: config.jwtExpires,
});
- console.log(token);
// 4) 토큰을 쿠키에 저장
res.cookie(config.cookieName, token, {
maxAge: config.cookieMaxAge,
@@ -50,91 +61,421 @@ const login = async (req, res) => {
console.error(error);
return res.status(500).send("로그인 에러");
}
-
}
-
+// 로그아웃
const logout = async (req, res) => {
try {
- res.cookie(config.cookieName,"")
+ res.clearCookie(config.cookieName);
+ res.json({
+ id: 0,
+ role: "user",
+ })
+ res.send('successfully cookie cleared.')
} catch (error) {
console.error(error);
return res.status(500).send("로그인 에러");
}
}
-const compareId = async (req, res) => {
- const id = req.params.userId;
- const userid = await User.findOne({ where: { userId: id } });
- if (userid !== null) {
- return res.json(true);
- } else {
- return res.json(false);
+// 인증번호 발송
+const confirmMbnum = async (req, res) => {
+ try {
+
+ // 휴대폰 인증
+ const NCP_serviceID = process.env.NCP_serviceID;
+ const NCP_accessKey = process.env.NCP_accessKey;
+ const NCP_secretKey = process.env.NCP_secretKey;
+
+ const date = Date.now().toString();
+ const uri = NCP_serviceID;
+ const accessKey = NCP_accessKey;
+ const secretKey = NCP_secretKey;
+ 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);
+
+ 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);
+
+ const phoneNumber = req.params.phone;
+ console.log(phoneNumber);
+
+ //인증번호 생성
+ const verifyCode = Math.floor(Math.random() * (999999 - 100000)) + 100000;
+ console.log("verifyCode : ", verifyCode);
+ let today = new Date();
+ let time = String(today.getTime());
+ // 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']);
+ const confirm = await ConfirmNum.findOne({ where: { phone: phoneNumber } });
+ if (confirm) {
+ await confirm.destroy();
+ // 5분 유효시간 설정
+ await ConfirmNum.create({
+ confirmNum: String(verifyCode),
+ phone: phoneNumber,
+ startTime: time,
+ });
+ } else {
+ await ConfirmNum.create({
+ confirmNum: String(verifyCode),
+ phone: phoneNumber,
+ startTime: time,
+ }
+ );
+ }
+ res.json({ startTime: time, 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 confirmMbnum = async (req, res) => {
- const id = req.params.id;
- const token = req.params.token;
-
- const client = Twilio(id, token);
- // console.log(client);
- client.messages
- .create({
- to: '+8201086074580',
- from: '+14159428621',
- body: '[ButterStudio] 인증번호[1234]를 입력해주세요',
- })
- .then(message => console.log(message.sid))
- .catch(e => console.log(error));
- // console.log("id = ", id, "token = ", token);
- return res.json(true);
-}
+// 인증번호 확인
+const confirmNum = async (req, res) => {
+ try {
+ const { userMbnum, number, startTime } = req.body;
+ const confirm = await ConfirmNum.findOne({ where: { phone: userMbnum, startTime: startTime } });
+ let today = new Date();
+ let time = today.getTime();
+ const elapsedMSec = time - confirm.startTime;
+ const elapsedMin = String(elapsedMSec / 1000 / 60);
+ if (elapsedMin <= 5) {
+ if (number !== confirm.confirmNum) {
+ res.send("실패");
+ } else {
+ await confirm.destroy();
+ res.send("성공");
+ }
+ } else {
+ res.send("재전송")
+ }
+ } catch (error) {
+ console.error("error : ", error.message);
+ res.status(500).send("잘못된 접근입니다.");
+ }
+};
+
+//유효성 검사
+const validation = (errorMsg, data, minLength, maxLength, dataType) => {
+ if (validator.isLength(data, minLength, maxLength)) {
+ errorMsg[dataType] = false;
+ } else {
+ errorMsg[dataType] = true;
+ }
+ if (dataType === "userEmail") {
+ if (validator.isEmail(data, minLength, maxLength)) {
+ errorMsg[dataType] = false;
+ } else {
+ errorMsg[dataType] = true;
+ }
+
+ }
+};
+// 회원정보
const signup = async (req, res) => {
- const { userId, userEmail, userNickName, userBirthday, userPassword } = req.body;
- // 휴대폰 중복 확인
- const userMbnum = String(req.body.userMbnum);
+ const { userId, userName, userEmail, userNickName, userBirthday, userMbnum, userPassword } = req.body;
try {
+ let errorMsg = {
+ errorId: false,
+ errorName: false,
+ errorEmail: false,
+ errorBirthday: false,
+ errorNickName: false,
+ errorMbnum: false,
+ errorPassword: false,
+ };
+
+ //유효성 검사
+ validation(errorMsg, userId, 5, 10, "errorId");
+ validation(errorMsg, userName, 1, 10, "errorName");
+ validation(errorMsg, userEmail, 3, 20, "errorEmail");
+ validation(errorMsg, userBirthday, 6, 6, "errorBirthday");
+ validation(errorMsg, userNickName, 1, 10, "errorNickName");
+ validation(errorMsg, userMbnum, 11, 11, "errorMbnum");
+ validation(errorMsg, userPassword, 8, 11, "errorPassword");
+
+ let valid = !(Object.values(errorMsg).some((element) => (element)));
+ // db에서 데이터 중복검사
+ const id = await User.findOne({ where: { userId: userId } });
const mbnum = await User.findOne({ where: { phoneNumber: userMbnum } });
- if (mbnum) {
- return res.status(422).send(`이미 있는 휴대폰번호입니다.`);
+ const email = await User.findOne({ where: { email: userEmail } });
+ if (!valid) {
+ res.json(errorMsg);
+ } else {
+ if (id) {
+ return res.status(401).send(`이미 있는 아이디입니다.`);
+ } else if (email) {
+ return res.status(401).send(`이미 있는 이메일입니다.`);
+ } else if (mbnum) {
+ return res.status(401).send(`이미 있는 휴대폰번호입니다.`);
+ } else{
+ const role = await Role.findOne({ where: { name: "member" } })
+ await User.create({
+ userId: userId,
+ name: userName,
+ email: userEmail,
+ nickname: userNickName,
+ birth: userBirthday,
+ phoneNumber: userMbnum,
+ password: userPassword,
+ img: "",
+ roleId: role.id
+ });
+ res.json("성공");
+ }
}
- const role = await Role.findOne({ where: { name: "member" } })
- const newUser = await User.create({
- userId: userId,
- email: userEmail,
- nickname: userNickName,
- birth: userBirthday,
- phoneNumber: userMbnum,
- password: userPassword,
- roleId: role.id
- });
- res.json(newUser);
} catch (error) {
console.error(error.message);
res.status(500).send("회원가입 에러. 나중에 다시 시도 해주세요");
}
};
-const getNickName = async (req, res) => {
- console.log("여기여기");
- const id = req.params.id;
- console.log("id : ", id);
+const getMember = async (req, res) => {
try {
- const userNickName = await User.findOne({ where: { id: id }, attributes:["nickname"] });
- console.log("userNickName: ", userNickName);
- return res.json(userNickName.nickname)
+ const token = req.cookies.butterStudio;
+ 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 });
+ } else {
+ res.status(500).send("잘못된 접근입니다.");
+ }
} catch (error) {
- console.error("error : ",error.message);
- res.status(500).send("회원가입 에러. 나중에 다시 시도 해주세요");
+ console.error("error : ", error.message);
+ res.status(500).send("잘못된 접근입니다.");
}
}
+// 프로필 변경
+const uploadProfile = async (req, res) => {
+ try {
+ const image = req.file.filename;
+ const token = req.cookies.butterStudio;
+ const decoded = jwt.verify(token, config.jwtSecret);
+
+ if (decoded) {
+ const img = await User.findOne({ where: { id: decoded.id }, attributes: ["img"] });
+ 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"] });
+ res.json(success)
+ } else {
+ throw new Error("프로필 등록 실패")
+ }
+ }
+ } catch (error) {
+ console.error(error.message);
+ res.status(500).send("프로필 에러");
+ }
+}
+// 기본 비밀번호인지 확인
+const comparePw = async (req, res) => {
+ try {
+ //쿠키 안 토큰에서 id추출
+ const token = req.cookies.butterStudio;
+ const decoded = jwt.verify(token, config.jwtSecret);
+ //해당 id의 행 추출
+ const user = await User.scope("withPassword").findOne({ where: { id: decoded.id } });
+ //입력한 비번과 해당 행 비번을 비교
+ const passwordMatch = await user.comparePassword(req.params.pw);
+ //클라이언트로 동일여부를 전송
+ if (passwordMatch) {
+ return res.json(true)
+ } else {
+ return res.json(false)
+ }
+ } catch (error) {
+ console.error("error : ", error.message);
+ res.status(500).send("인증 에러");
+ }
+}
+// 회원정보 수정할 때 쓰는 함수
+const overlap = async (decoded, dataType, data) => {
+ try {
+ let overlap = await User.findOne({ where: { id: decoded.id } });
+ // 변경할 데이터가 자기자신이면 true
+ if (overlap[dataType] === data) {
+ return true
+ } else {
+ // 그렇지 않으면 다른 데이터들 중에서 중복되는지 검사
+ let overlap2 = await User.findOne({ attributes: [dataType] });
+ if (overlap2[dataType] === data) {
+ return false
+ } else {
+ return true
+ }
+ }
+ } catch (error) {
+ console.error(error.message);
+ }
+}
+// 회원정보 수정
+const modifyUser = async (req, res) => {
+ try {
+ const token = req.cookies.butterStudio;
+ const decoded = jwt.verify(token, config.jwtSecret);
+ const { userName, userEmail, userNickName, userMbnum, userPassword } = req.body;
+
+ let errorMsg = {
+ errorName: false,
+ errorEmail: false,
+ errorNickName: false,
+ errorMbnum: false,
+ errorPassword: false,
+ };
+
+ //유효성 검사
+ validation(errorMsg, userName, 1, 10, "errorName");
+ validation(errorMsg, userEmail, 3, 20, "errorEmail");
+ validation(errorMsg, userNickName, 1, 10, "errorNickName");
+ validation(errorMsg, userMbnum, 11, 11, "errorMbnum");
+ validation(errorMsg, userPassword, 8, 11, "errorPassword");
+
+ let valid = !(Object.values(errorMsg).some((element) => (element)));
+ const overlapEmail = await overlap(decoded, "email", userEmail);
+ const overlapMbnum = await overlap(decoded, "phoneNumber", userMbnum);
+ if (!valid) {
+ res.json(errorMsg);
+ } else {
+ if (overlapEmail && overlapMbnum) {
+ await User.update({
+ name: userName,
+ email: userEmail,
+ nickname: userNickName,
+ phoneNumber: userMbnum,
+ password: userPassword,
+ }, { where: { id: decoded.id }, individualHooks: true });
+ res.json("성공");
+ } else if (!overlapEmail && overlapMbnum) {
+ res.status(500).send("이미 있는 이메일입니다.");
+ } else if (overlapEmail && !overlapMbnum) {
+ res.status(500).send("이미 있는 핸드폰번호입니다.");
+ } else {
+ res.status(500).send("이미 있는 이메일, 핸드폰번호입니다.");
+ }
+ }
+ } catch (error) {
+ console.error(error.message);
+ res.status(500).send("수정 에러. 나중에 다시 시도 해주세요");
+ }
+};
+
+const getUserInfo = async (req, res) => {
+ const { id } = req.body
+ // console.log(id)
+ try {
+ const userInfo = await User.findOne({
+ where: { id: id },
+ attributes: ["id", "userId", "email", "nickname", "birth", "phoneNumber"]
+ })
+ // console.log(userInfo)
+ res.json(userInfo)
+ } catch (error) {
+ res.status(500).send("회원정보 불러오기 실패");
+ }
+}
+
+const saveGuestInfo = async (req, res) => {
+ const { name, email, birth, phoneNumber, password } = req.body
+ try {
+ const newGuest = await Guest.create({
+ name: name,
+ email: email,
+ birth: birth,
+ phoneNumber: phoneNumber,
+ password: password,
+ });
+ // console.log(newGuest)
+ res.clearCookie(config.cookieName);
+ const token = jwt.sign({id: newGuest.id, role: "user"}, config.jwtSecret, {
+ expiresIn: config.jwtExpires,
+ });
+ res.cookie(config.cookieName,token , {
+ maxAge: config.cookieMaxAge,
+ path: "/",
+ httpOnly: config.env === "production",
+ secure: config.env === "production",
+ })
+ res.json(newGuest);
+ } catch (error) {
+ res.status(500).send("비회원정보 등록 실패");
+ }
+}
+
+const getGuestInfo = async (req,res) => {
+ const {guestId} = req.params
+ // console.log(req.body)
+ try {
+ const guestInfo = await Guest.findOne({
+ where: {
+ id:guestId
+ }
+ })
+ // console.log("guestInfo====", guestInfo)
+ res.json(guestInfo)
+ } catch (error) {
+ res.status(500).send("비회원정보 불러오기 실패");
+ }
+}
export default {
+ getUser,
login,
logout,
- compareId,
confirmMbnum,
+ confirmNum,
signup,
- getNickName
+ comparePw,
+ modifyUser,
+ saveGuestInfo,
+ getMember,
+ uploadProfile,
+ getUserInfo,
+ getGuestInfo
}
diff --git a/server/db/index.js b/server/db/index.js
index 0c9b68b1d70519d7220510cfff7bcda5bb22104d..4435022d593065540939245b3f200d6388b8e60b 100644
--- a/server/db/index.js
+++ b/server/db/index.js
@@ -8,6 +8,8 @@ import TheaterTypeModel from "../models/theatertype.model.js";
import TicketFeeModel from "../models/ticketfee.model.js";
import TimeTableModel from '../models/timetable.model.js';
import ReservationModel from '../models/reservation.model.js';
+import GuestModel from '../models/guest.model.js'
+import ConfirmNumModel from '../models/confirmnum.model.js'
import dbConfig from "../config/db.config.js";
const sequelize = new Sequelize(
@@ -35,6 +37,8 @@ const TheaterType = TheaterTypeModel(sequelize)
const TicketFee = TicketFeeModel(sequelize)
const TimeTable = TimeTableModel(sequelize)
const Reservation = ReservationModel(sequelize)
+const Guest = GuestModel(sequelize)
+const ConfirmNum = ConfirmNumModel(sequelize)
User.belongsTo(Role);
Role.hasOne(User);
@@ -53,5 +57,7 @@ export {
TheaterType,
TicketFee,
TimeTable,
- Reservation
+ Reservation,
+ Guest,
+ ConfirmNum
}
\ No newline at end of file
diff --git a/server/index.js b/server/index.js
index d6c86f2939d9a683da5aa5b0b55aa4401705f55f..6880f508f229c5543b451e8ccb0434f522c50dd2 100644
--- a/server/index.js
+++ b/server/index.js
@@ -1,7 +1,7 @@
import dotenv from "dotenv";
-import { sequelize, User, Role } from "./db/index.js";
import app from "./app.js";
import appConfig from "./config/app.config.js";
+import { sequelize, User, Role } from "./db/index.js";
import { ROLE_NAME } from './models/role.model.js';
dotenv.config({
@@ -10,7 +10,7 @@ dotenv.config({
});
sequelize
- .sync({ force: true })
+ .sync({ force: false })
.then(async () => {
await Promise.all(
Object.keys(ROLE_NAME).map((name) => {
@@ -19,17 +19,19 @@ sequelize
);
const adminRole = await Role.findOne({ where: { name: "admin" } });
- // if (!adminRole) {
+ if (!adminRole) {
await User.create({
userId: "admin",
+ name: "관리자",
email: "han35799@naver.com",
nickname: "haha",
birth: "990926",
phoneNumber: "01086074580",
password: "admin!",
+ img: "970aaa79673a39331d45d4b55ca05d25",
roleId: adminRole?.id,
});
- // }
+ } else { }
app.listen(appConfig.port, () => {
console.log(`Server is running on port ${appConfig.port}`);
@@ -39,4 +41,4 @@ sequelize
console.log(err);
});
- export default {}
\ No newline at end of file
+export default {}
\ No newline at end of file
diff --git a/server/models/confirmnum.model.js b/server/models/confirmnum.model.js
new file mode 100644
index 0000000000000000000000000000000000000000..3f926e6f70ffde25825000cc7649dd3e4acdcc3d
--- /dev/null
+++ b/server/models/confirmnum.model.js
@@ -0,0 +1,33 @@
+import Sequelize from "sequelize";
+
+const { DataTypes } = Sequelize;
+
+const ConfirmNumModel = (sequelize) => {
+ const ConfirmNum = sequelize.define(
+ "confirmnum",
+ {
+ id: {
+ type: DataTypes.INTEGER,
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ confirmNum: {
+ type: DataTypes.STRING,
+ },
+ phone: {
+ type: DataTypes.STRING
+ },
+ startTime: {
+ type: DataTypes.STRING
+ },
+ },
+ {
+ timestamps: true,
+ freezeTableName: true,
+ tableName: "confirmnum"
+ }
+ );
+ return ConfirmNum;
+};
+
+export default ConfirmNumModel;
\ No newline at end of file
diff --git a/server/models/guest.model.js b/server/models/guest.model.js
new file mode 100644
index 0000000000000000000000000000000000000000..e48fb1254b85dde9d2c697adfd56ab2da5df661c
--- /dev/null
+++ b/server/models/guest.model.js
@@ -0,0 +1,40 @@
+import Sequelize from "sequelize";
+
+const { DataTypes } = Sequelize;
+
+const GuestModel = (sequelize) => {
+ const Guest = sequelize.define(
+ "guest",
+ {
+ id: {
+ type: DataTypes.INTEGER,
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ name: {
+ type: DataTypes.STRING,
+ },
+ email: {
+ type: DataTypes.STRING,
+ },
+ birth: {
+ type: DataTypes.STRING,
+ },
+ phoneNumber: {
+ type: DataTypes.STRING
+ },
+ password: {
+ type: DataTypes.STRING,
+ },
+ },
+ {
+ timestamps: true,
+ freezeTableName: true,
+ tableName: "guests",
+ }
+ );
+
+ return Guest
+};
+
+export default GuestModel
\ No newline at end of file
diff --git a/server/models/reservation.model.js b/server/models/reservation.model.js
index 562ce83398824a13ecebdf28efe617a91735d129..5db3008b1d00fdcaeae760dd4bb07f9938bbc14d 100644
--- a/server/models/reservation.model.js
+++ b/server/models/reservation.model.js
@@ -18,7 +18,7 @@ const ReservationModel = (sequelize) => {
type: DataTypes.INTEGER,
},
row: {
- type: DataTypes.STRING,
+ type: DataTypes.INTEGER,
},
col: {
type: DataTypes.INTEGER,
@@ -26,10 +26,16 @@ const ReservationModel = (sequelize) => {
timetable:{
type: DataTypes.INTEGER,
},
+ userType:{
+ type: DataTypes.STRING,
+ },
user:{
type: DataTypes.INTEGER,
},
payment:{
+ type: DataTypes.STRING,
+ },
+ totalFee:{
type: DataTypes.INTEGER,
}
},
diff --git a/server/models/theater.model.js b/server/models/theater.model.js
index bdb49082e853babf55f4dcf67a0c2f8200d8592c..9f77ea40edd381c701cd9117d37e59b80e340a6d 100644
--- a/server/models/theater.model.js
+++ b/server/models/theater.model.js
@@ -15,7 +15,7 @@ const TheaterModel = (sequelize) => {
type: DataTypes.STRING
},
rows: {
- type: DataTypes.STRING,
+ type: DataTypes.INTEGER,
},
columns: {
type: DataTypes.INTEGER,
diff --git a/server/models/user.model.js b/server/models/user.model.js
index a6ef2302a19bc9a21d84bebf25d2717e319e1b7b..ab097beb19f1269d3b0f9a5db2a45c9583cdc94c 100644
--- a/server/models/user.model.js
+++ b/server/models/user.model.js
@@ -14,23 +14,29 @@ const UserModel = (sequelize) => {
autoIncrement: true,
},
userId: {
- type: DataTypes.STRING,
+ type: DataTypes.STRING
+ },
+ name: {
+ type: DataTypes.STRING
},
email: {
- type: DataTypes.STRING,
+ type: DataTypes.STRING
},
nickname: {
- type: DataTypes.STRING,
+ type: DataTypes.STRING
},
birth: {
- type: DataTypes.STRING,
+ type: DataTypes.STRING
},
phoneNumber: {
type: DataTypes.STRING
},
password: {
- type: DataTypes.STRING,
+ type: DataTypes.STRING
},
+ img: {
+ type: DataTypes.STRING
+ }
},
{
timestamps: true,
diff --git a/server/routes/index.js b/server/routes/index.js
index 658d2bba48e7d9a1b190b09426f388e1ca7e809b..17b64bb75d2a5a8af45b3bc7adef8833a8946bad 100644
--- a/server/routes/index.js
+++ b/server/routes/index.js
@@ -6,6 +6,7 @@ import timetableRouter from "./timetable.route.js";
import cinemaRouter from "./cinema.route.js";
import kakaopayRouter from "./kakaopay.route.js";
import emailRouter from './email.route.js'
+import reservationRouter from './reservation.route.js'
const router = express.Router();
@@ -15,6 +16,7 @@ router.use('/kakaopay',kakaopayRouter)
router.use('/email',emailRouter)
router.use('/info', cinemaRouter)
router.use('/theater', theaterRouter)
+router.use('/reservation', reservationRouter)
router.use('/timetable', timetableRouter)
export default router;
\ No newline at end of file
diff --git a/server/routes/movie.route.js b/server/routes/movie.route.js
index 57f0da770b8bc87fa65c234cf9028cbba5bf07d4..5746285b9b89807be6c4e4e6796db1db655cec9d 100644
--- a/server/routes/movie.route.js
+++ b/server/routes/movie.route.js
@@ -7,12 +7,9 @@ router
.route("/")
.get(movieCtrl.getListfromDB)
-router
- .route('/showmovies/:category')
- .get(movieCtrl.getMovieById)
router
- .route('/movielist')
+ .route('/movielist/:category')
.get(movieCtrl.getMovieList)
router
@@ -38,6 +35,5 @@ router
.post(movieCtrl.create)
.delete(movieCtrl.remove)
-router.param('category', movieCtrl.getMovieByCategory)
export default router;
\ No newline at end of file
diff --git a/server/routes/reservation.route.js b/server/routes/reservation.route.js
new file mode 100644
index 0000000000000000000000000000000000000000..1ca833bfbfbea0c9110a20553af4a724452d84cc
--- /dev/null
+++ b/server/routes/reservation.route.js
@@ -0,0 +1,17 @@
+import express from "express";
+import ReservationCtrl from "../controllers/reservation.controller.js";
+
+const router = express.Router();
+
+
+router.route('/findreservation')
+ .post(ReservationCtrl.findReservedSeats)
+ .get(ReservationCtrl.findReservation)
+
+router.route('/findonereservation')
+ .post(ReservationCtrl.findOneReservation)
+
+router.route('/save')
+ .post(ReservationCtrl.saveReservation)
+
+export default router;
\ No newline at end of file
diff --git a/server/routes/theater.route.js b/server/routes/theater.route.js
index f52282f86b81f3ee834f81ababde330b00003038..9f11cb1eae0eb788dbf6ff6c01ac086acbe57030 100644
--- a/server/routes/theater.route.js
+++ b/server/routes/theater.route.js
@@ -3,6 +3,9 @@ import theaterCtrl from "../controllers/theater.controller.js";
const router = express.Router();
+router.route("/getInfo")
+ .post(theaterCtrl.getTheaterInfo)
+
router
.route("/")
.get(theaterCtrl.getAll)
@@ -17,4 +20,4 @@ router
.get(theaterCtrl.getOne)
.delete(theaterCtrl.remove)
-export default router;
\ No newline at end of file
+export default router;
diff --git a/server/routes/user.route.js b/server/routes/user.route.js
index 6dc9ef321c5abe2ac7af6bfac543669fc5d10ac0..1ce9e8a3c9830330c798857d770a6ecd4df6b41f 100644
--- a/server/routes/user.route.js
+++ b/server/routes/user.route.js
@@ -1,8 +1,17 @@
import express from "express";
+import multer from "multer";
import userCtrl from "../controllers/user.controller.js";
const router = express.Router();
+const upload = multer({
+ dest: "upload/"
+})
+
+router
+ .route("/user")
+ .get(userCtrl.getUser)
+
router
.route("/login")
.post(userCtrl.login)
@@ -16,15 +25,46 @@ router
.post(userCtrl.signup)
router
- .route("/:userId")
- .get(userCtrl.compareId)
+ .route("/profile")
+ .post(
+ upload.single("image"),
+ userCtrl.uploadProfile
+ )
+
+router
+ .route("/modify")
+ .post(userCtrl.modifyUser)
+
+router
+ .route("/member")
+ .get(userCtrl.getMember)
+
+router
+ .route("/num")
+ .post(userCtrl.confirmNum)
router
- .route("/:id/:token")
- .get(userCtrl.confirmMbnum)
+ .route("/pw/:pw")
+ .get(userCtrl.comparePw)
router
- .route("/:iddd")
- .get(userCtrl.getNickName)
+ .route("/phone/:phone")
+ .post(userCtrl.confirmMbnum)
+
+router
+ .route('/getuserinfo')
+ .post(userCtrl.getUserInfo)
+
+router
+ .route('/guest/save')
+ .post(userCtrl.saveGuestInfo)
+
+router
+ .route('/guestinfo/:guestId')
+ .get(userCtrl.getGuestInfo)
+
+router
+ .route("/:userId")
+ .get(userCtrl.compareId)
export default router;
\ No newline at end of file