diff --git a/.gitignore b/.gitignore index 600e365ec83f8384cb5c98d0379367a7909cd329..ce60c7eb72c08685664b73c5d0909f52631a1c88 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -**/node_modules \ No newline at end of file +**/node_modules +**/sessions \ No newline at end of file diff --git a/backend/app.js b/backend/app.js index ca50dd679097307abcc7f4450eaabd926742b5b7..81d1bf673f525aa03d1f2aed029205e276a53d41 100644 --- a/backend/app.js +++ b/backend/app.js @@ -5,6 +5,8 @@ var path = require("path"); var cookieParser = require("cookie-parser"); var bodyParser = require("body-parser"); var logger = require("morgan"); +var session = require("express-session"); +var FileStore = require("session-file-store")(session); var bookRouter = require("./routes/books"); var loginRouter = require("./routes/login"); @@ -20,6 +22,15 @@ var promise = mongoose.connect(mongoDB, { }); //mongoose.connect(mongoDB); +app.use( + session({ + secret: "!@#$MySESSION$#@!", + resave: false, + saveUninitialized: true, + store: new FileStore() + }) +); + app.use(require("connect-history-api-fallback")()); // view engine setup diff --git a/backend/package-lock.json b/backend/package-lock.json index cf69950ac9b849d615cd062aee366f332f18e8c1..3d3dca925cd7e58c54ad564f7e04b2abe0e7bcec 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -96,6 +96,11 @@ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, + "bagpipe": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz", + "integrity": "sha1-40HRZPyyTN8E6n4Ft2XsEMiupqE=" + }, "basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -397,6 +402,38 @@ } } }, + "express-session": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.0.tgz", + "integrity": "sha512-t4oX2z7uoSqATbMfsxWMbNjAL0T5zpvcJCk3Z9wnPPN7ibddhnmDZXHfEcoBMG2ojKXZoCyPMc5FbtK+G7SoDg==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.0", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + } + } + }, "finalhandler": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", @@ -421,11 +458,26 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + }, "graceful-readlink": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", @@ -458,6 +510,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -507,6 +564,14 @@ "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jstransformer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", @@ -842,6 +907,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -919,6 +989,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -982,6 +1057,18 @@ "send": "0.16.2" } }, + "session-file-store": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.3.1.tgz", + "integrity": "sha512-6W8N+ziXDoT3oNKqLP+38QMO1CELfWHhn7/G/T/Bj2BXLKnkJCCFqWIb9E50Rr3ENtzuxy3FT9KHy39+skBubg==", + "requires": { + "bagpipe": "^0.3.5", + "fs-extra": "^8.0.1", + "object-assign": "^4.1.1", + "retry": "^0.12.0", + "write-file-atomic": "1.3.1" + } + }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", @@ -997,6 +1084,11 @@ "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", @@ -1066,6 +1158,19 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "optional": true }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1105,6 +1210,16 @@ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" }, + "write-file-atomic": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.1.tgz", + "integrity": "sha1-fUW6MjFjKN0ex9kPYOvA2EW7dZo=", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", diff --git a/backend/package.json b/backend/package.json index 1526d6261651dddea071980de0afeba7c660619d..4d65a8a1889da3542e030cb682ded233098427e5 100644 --- a/backend/package.json +++ b/backend/package.json @@ -11,9 +11,11 @@ "cookie-parser": "~1.4.4", "debug": "~2.6.9", "express": "^4.16.4", + "express-session": "^1.17.0", "http-errors": "~1.6.3", "mongoose": "^5.7.12", "morgan": "~1.9.1", - "pug": "2.0.0-beta11" + "pug": "2.0.0-beta11", + "session-file-store": "^1.3.1" } } diff --git a/backend/routes/login.js b/backend/routes/login.js index 44a53a74ba2f267d1feb56fbb5d643be60404ea7..66a879e238c63e1acb3671d3c114a2dc89409bfb 100644 --- a/backend/routes/login.js +++ b/backend/routes/login.js @@ -21,16 +21,42 @@ router.post("/signUp", function(req, res, next) { }); router.post("/checkLogin", function(req, res, next) { - console.log("Hello"); + var sess = req.session; + User.findOne( { id: req.body.user.id, password: req.body.user.password }, function(err, user) { if (err) return res.status(500).json({ error: err }); // User가 없으면 error if (!user) return res.status(404).json({ error: "user not found" }); + sess.logined = true; + sess.userid = req.body.user.id; res.json(user); } ); }); +router.get("/logout", function(req, res) { + var sess = req.session; + if (sess.userid) { + req.session.destroy(function(err) { + if (err) { + console.log(err); + } else { + res.redirect("/"); // 수정해야 할 듯 + } + }); + } else { + res.redirect("/"); + } +}); + +router.get("/checkSession", function(req, res) { + var sess = req.session; + if (sess.userid) res.json(true); + else { + res.json(false); + } +}); + module.exports = router; diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 9746098f9d32fdc123646c58ae284bcc88f4d7d0..e983ef150174e37ca5359a730b95eb87682954d0 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -8,16 +8,30 @@ <div style="flex:1"> <div align="right"> - <Login /> + <div v-if="!checkLoggedIn"> + <Login /> + <SignUp /> + </div> + <div v-if="checkLoggedIn"> + <Logout /> + </div> </div> </div> <div class="md-toolbar-row"> <md-tabs class="md-primary" style="margin: auto; height: 30px"> <md-tab id="tab-home" md-label="Home" to="/"></md-tab> - <md-tab id="tab-dashBoard" md-label="Dashboard" to="/dashBoard"></md-tab> + <md-tab + id="tab-dashBoard" + md-label="Dashboard" + to="/dashBoard" + ></md-tab> <md-tab id="tab-profile" md-label="Profile" to="/profile"></md-tab> - <md-tab id="tab-list" md-label="전공서적보기" to="/BookSearchPage"></md-tab> + <md-tab + id="tab-list" + md-label="전공서적보기" + to="/BookSearchPage" + ></md-tab> </md-tabs> </div> </md-app-toolbar> @@ -34,43 +48,44 @@ import "vue-material/dist/theme/default.css"; Vue.use(VueMaterial); import Login from "./components/login/Login"; +import Logout from "./components/login/Logout"; +import SignUp from "./components/login/SignUp"; export default { name: "App", data() { return { - url: { - //bookIndex: "/api/books" - } + isLoggedIn: "false" }; }, components: { - Login + Login, + SignUp, + Logout }, - computed: { - // changeID() { - // this.id = `${this.id}`; - // }, - // changePWD() { - // this.pwd = `${this.pwd}`; - // }, - // logged_io() { - // if (!this.flag) return true; - // else return false; - // } + created() { + this.checkSession(); }, methods: { - // login: function() { - // if (this.id != "" && this.pwd != "") { - // alert(this.id + " login!!"); - // this.flag = !this.flag; - // this.id = ""; - // this.pwd = ""; - // } else alert("ID/PASSWORD를 입력하세요"); - // }, - // logout: function() { - // this.flag = !this.flag; - // } + checkSession() { + this.$http.get("/api/login/checkSession").then(function(response) { + //console.log(response.data); + if (response.data === true) { + return true; + } else { + return false; + } + }); + } + }, + computed: { + checkLoggedIn() { + console.log(this.checkSession()); + if (this.checkSession() === true) { + return true; + } + return false; + } } }; </script> diff --git a/frontend/src/components/login/Login.vue b/frontend/src/components/login/Login.vue index 993c237a3d41596ffd50b54bc850e8771e6a1e67..4ace51f26052827a18a4aeb1d810a42e4106d70e 100644 --- a/frontend/src/components/login/Login.vue +++ b/frontend/src/components/login/Login.vue @@ -1,24 +1,39 @@ <template> <div id="login"> - Login - <input v-model="user.id" placeholder="ID" /> - <input v-model="user.password" type="password" placeholder="password" /> - <button v-on:click="login">login</button> - <!-- <a v-bind:href="url.signUpUrl"> Sign up </a> --> - <router-link to="/login/signUp" tag="button">Sign Up</router-link> + <md-button class="md-primary" v-on:click="active = true">Login</md-button> + <md-dialog :md-active.sync="active" style="width: 500px; height: 1000px"> + <md-dialog-title>Login</md-dialog-title> + <md-field class="select"> + <label>ID</label> + <md-input v-model="user.id" /> + </md-field> + + <md-field class="select"> + <label>Password</label> + <md-input v-model="user.password" type="password" /> + </md-field> + + <md-button class="md-primary" v-on:click="login">Login</md-button> + <md-button class="md-primary" v-on:click="active = false" + >Close</md-button + > + </md-dialog> </div> </template> <script> +import Vue from "vue"; +import VueMaterial from "vue-material"; +import "vue-material/dist/vue-material.min.css"; +import "vue-material/dist/theme/default.css"; +Vue.use(VueMaterial); export default { data: function() { return { + active: false, user: { id: "", password: "" - }, - url: { - signUpUrl: "/login/signUp" } }; }, @@ -29,11 +44,12 @@ export default { .post("/api/login/checkLogin", { user: this.user }) - .then( response => { //로그인 성공 alert("success login"); + //this.$router.push("Logout"); + this.active = false; }, error => { // error 를 보여줌 @@ -47,3 +63,14 @@ export default { } }; </script> + +<style scoped> +.select { + margin: 15px; + display: inline-flex; + width: auto; +} +.md-dialog { + max-width: 768px; +} +</style> diff --git a/frontend/src/components/login/Logout.vue b/frontend/src/components/login/Logout.vue new file mode 100644 index 0000000000000000000000000000000000000000..a76e5d29636c1226790977494f8567d2724450ca --- /dev/null +++ b/frontend/src/components/login/Logout.vue @@ -0,0 +1,29 @@ +<template> + <div id="logout"> + <md-button class="md-primary" v-on:click="logout">Logout</md-button> + </div> +</template> + +<script> +import Vue from "vue"; +import VueMaterial from "vue-material"; +import "vue-material/dist/vue-material.min.css"; +import "vue-material/dist/theme/default.css"; +Vue.use(VueMaterial); + +export default { + data: function() { + return {}; + }, + methods: { + logout() { + console.log("Logout start"); + this.$http.get("/api/login/logout").then(response => { + if (response) { + //this.$router.push("home"); + } + }); + } + } +}; +</script> diff --git a/frontend/src/components/login/SignUp.vue b/frontend/src/components/login/SignUp.vue index 5d132f5fad97bca567810198a63a7146406d7762..a7118e3575df16c42d80ab83a3b81410576b072f 100644 --- a/frontend/src/components/login/SignUp.vue +++ b/frontend/src/components/login/SignUp.vue @@ -1,49 +1,46 @@ <template> - <div> - <md-card class="md-layout-item md-size-50 md-small-size-100"> - <md-card-header> - <div class="md-title">Sign Up</div> - </md-card-header> + <div id="logout"> + <md-button class="md-primary" v-on:click="active = true">Sign Up</md-button> + <md-dialog :md-active.sync="active" style="width:500px; height: 1000px"> + <md-dialog-title>Sign Up</md-dialog-title> + <md-field class="select"> + <label>Name</label> + <md-input name="name" v-model="user.name" /> + </md-field> - <md-card-content> - <md-field> - <label for="name">Name</label> - <md-input name="name" v-model="user.name" /> - </md-field> + <md-field class="select"> + <label for="id">ID</label> + <md-input name="id" v-model="user.id" /> + </md-field> - <md-field> - <label for="id">ID</label> - <md-input name="id" v-model="user.id" /> - </md-field> + <md-field :md-toggle-password="true" class="select"> + <label for="password">Password</label> + <md-input name="password" v-model="user.password" type="password" /> + </md-field> - <md-field :md-toggle-password="true"> - <label for="password">Password</label> - <md-input name="password" v-model="user.password" type="password" /> - </md-field> + <md-field class="select"> + <label for="email">Email</label> + <md-input name="email" v-model="user.email" /> + </md-field> - <md-field> - <label for="email">Email</label> - <md-input name="email" v-model="user.email" /> - </md-field> - </md-card-content> - - <md-card-actions> - <md-button class="md-raised md-primary" v-on:click="signUp" - >Sign Up</md-button - > - </md-card-actions> - </md-card> + <md-button class="md-raised md-primary" v-on:click="signUp" + >Sign Up</md-button + > + <md-button class="md-primary" v-on:click="active = false" + >Close</md-button + > + </md-dialog> </div> </template> <style> -.md-card { - margin: auto; +.select { + margin: 15px; + display: inline-flex; + width: auto; } - -.md-primary { - background-color: blue; - color: white; +.md-dialog { + max-width: 768px; } </style> @@ -55,15 +52,6 @@ import "vue-material/dist/vue-material.min.css"; import "vue-material/dist/theme/default.css"; Vue.use(VueMaterial); -// import {MdField, MdButton, MdCard, MdInput} from 'vue-material/dist/components' -// import 'vue-material/dist/vue-material.min.css' -// import 'vue-material/dist/theme/default.css' - -// Vue.use(MdField) -// Vue.use(MdButton) -// Vue.use(MdCard) -// Vue.use(MdInput) - export default { data: function() { return { @@ -74,7 +62,8 @@ export default { email: "", isLoggedIn: false }, - sending: false + sending: false, + active: false }; }, methods: { @@ -87,10 +76,11 @@ export default { .then(response => { if (response.data.result === 0) { alert("Error, please, try again"); + this.active = false; } if (response.data.result === 1) { alert("Success"); - this.$router.push("/"); // Home 페이지로 보내줌 + this.active = false; } }) .catch(function(error) { diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 4f644e990f12bb03059f859cdce26bd22d8d7dc6..c41d8636988d38ae0c2e2d05fd67ebd02889dfd2 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -6,6 +6,7 @@ import dashBoard from "@/components/dashBoard"; import profile from "@/components/profile"; import BookSearchPage from "@/components/BookSearchPage"; import Login from "@/components/login/Login"; +import Logout from "@/components/login/Logout"; import SignUp from "@/components/login/SignUp"; export default new Router({ @@ -37,7 +38,12 @@ export default new Router({ component: Login }, { - path: "/login/signUp", + path: "/logout", + name: "Logout", + component: Logout + }, + { + path: "/signUp", name: "SignUp", component: SignUp }