Commit 2bfc9c64 authored by CHAERIN KIM's avatar CHAERIN KIM
Browse files

이걸 병합하세요

parent 693328cc
JWT_SECRET=jwtSecret
\ No newline at end of file
...@@ -3,16 +3,21 @@ const express = require('express'); ...@@ -3,16 +3,21 @@ const express = require('express');
const path = require('path'); const path = require('path');
const cookieParser = require('cookie-parser'); const cookieParser = require('cookie-parser');
const logger = require('morgan'); const logger = require('morgan');
require('dotenv').config();
const indexRouter = require('./routes/index'); const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users'); const usersRouter = require('./routes/users');
const loginRouter = require('./routes/login');
const connect = require('./schemas'); const connect = require('./schemas');
const app = express(); const app = express();
const port = 3030; const port = 3030;
require('dotenv').config();
connect(); connect();
app.listen(port, () => console.log(port));
// view engine setup // view engine setup
// app.set('views', path.join(__dirname, 'views')); // app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'pug'); // app.set('view engine', 'pug');
...@@ -25,9 +30,7 @@ app.use(express.static(path.join(__dirname, 'public'))); ...@@ -25,9 +30,7 @@ app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter); app.use('/', indexRouter);
app.use('/users', usersRouter); app.use('/users', usersRouter);
app.use('/login', loginRouter);
app.listen(port, () => console.log(port));
// catch 404 and forward to error handler // catch 404 and forward to error handler
app.use(function(req, res, next) { app.use(function(req, res, next) {
...@@ -42,7 +45,7 @@ app.use(function(err, req, res, next) { ...@@ -42,7 +45,7 @@ app.use(function(err, req, res, next) {
// render the error page // render the error page
res.status(err.status || 500); res.status(err.status || 500);
res.render('error'); // res.render('error');
}); });
module.exports = app; module.exports = app;
This diff is collapsed.
...@@ -7,9 +7,11 @@ ...@@ -7,9 +7,11 @@
"@testing-library/react": "^9.5.0", "@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1", "@testing-library/user-event": "^7.2.1",
"axios": "^0.20.0", "axios": "^0.20.0",
"bcrypt": "^5.0.0",
"bootstrap": "^4.5.2", "bootstrap": "^4.5.2",
"formik": "^2.1.5", "formik": "^2.1.5",
"jquery": "^3.5.1", "jquery": "^3.5.1",
"mongoose": "^5.10.6",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"react": "^16.13.1", "react": "^16.13.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
......
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom'; import { Link, Redirect } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
const Nav = styled.nav` const Nav = styled.nav`
...@@ -7,13 +7,23 @@ const Nav = styled.nav` ...@@ -7,13 +7,23 @@ const Nav = styled.nav`
` `
function Menu() { function Menu() {
const [state, setState] = useState()
if (state) return <Redirect to="/" />;
function logout() {
localStorage.removeItem('token');
alert("로그아웃 되었습니다.");
setState(true);
}
return ( return (
<Nav className="navbar sticky-top navbar-expand-md"> <Nav className="navbar sticky-top navbar-expand-md">
<Link to="/home" className="navbar-brand">대관 서비스</Link> <Link to="/home" className="navbar-brand">대관 서비스</Link>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar" aria-controls="collapsibleNavbar"> <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar" aria-controls="collapsibleNavbar">
<span className="navbar-toggler-icon"></span> <span className="navbar-toggler-icon"></span>
</button> </button>
<div className="collapse navbar-collapse" id="collapsibleNavbar"> <div className="collapse navbar-collapse justify-content-between" id="collapsibleNavbar">
<ul className="navbar-nav"> <ul className="navbar-nav">
<li className="nav-item"> <li className="nav-item">
<Link to="/home" className="nav-link">대관 현황</Link> <Link to="/home" className="nav-link">대관 현황</Link>
...@@ -27,8 +37,11 @@ function Menu() { ...@@ -27,8 +37,11 @@ function Menu() {
<li className="nav-item"> <li className="nav-item">
<Link to="/notice" className="nav-link">공지사항</Link> <Link to="/notice" className="nav-link">공지사항</Link>
</li> </li>
</ul> </ul>
<div>
<button onClick={logout} type="button">로그아웃</button>
<button><Link to="/signup">회원가입</Link></button>
</div>
</div> </div>
</Nav> </Nav>
) )
......
import React from 'react';
import { Redirect, Route } from "react-router-dom";
export const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
(localStorage.getItem("token") !==null) ? (
<Component {...props} />
) : (
<Redirect to={{
pathname: "/login",
state: {match: props.location}
}} />
)
}
/>
)
\ No newline at end of file
import React, { } from 'react';
function Home() {
return (
<div>
<h2>asdkj;alsdkj</h2>
</div>
)
}
export default Home
import React, { useState } from 'react';
import { Formik } from 'formik';
import * as Yup from 'yup';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
const Log = styled.div`
background-color: #981e1e;
`
const Logo = styled.div`
background-color: #E76A6A;
`
function Login() {
// const [state, setState]= useState(false);
// if (state) {
// return <Redirect to="/" />;
// }
return (
<div className="container-fluid">
<div className="row">
<Logo className="col-md-5 col-12">
<h2>고려대학교</h2>
<h4>대관 시스템</h4>
</Logo>
<Log className="col-md-7 col-12">
<Formik
initialValues={{ email: '', password: '' }}
validationSchema={Yup.object({
email: Yup.string()
.email('이메일형식이 유효하지 않습니다.')
.required('이메일을 입력해주세요.'),
password: Yup.string()
.required('비밀번호를 입력해주세요.')
.min(8, '8자 이상 입력해주세요.'),
})}
onSubmit={(values, { setSubmitting }) => {
// axios({
// method: 'post',
// url: '/login',
// data: values,
// }).then(res => {
// if (res.status === 404) return alert(res.data.error)
alert("로그인이 완료되었습니다!")
// localStorage.setItem('token', res.data.token);
// localStorage.setItem('id', res.data.users._id);
// setState(true);
// })
// .catch(err => {
// alert(err.error)
// });
setTimeout(() => {
setSubmitting(false);
}, 400); // finish the cycle in handler
}}
>
{({
errors,
touched,
handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur
isSubmitting,
}) => (
<div className="row justify-content-center align-items-center">
<form onSubmit={handleSubmit} className="col-sm-3">
<div className="form-group mb-4">
<input
className={(touched.email && errors.email ? 'form-control is-invalid' : "form-control")}
type="email"
name="email"
{...getFieldProps('email')}
placeholder="Input Email"
/>
{touched.email && errors.email ? (
<div className="invalid-feedback text-left">{errors.email}</div>
) : null}
</div>
<div className="form-group mb-4">
<input
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
type="password"
name="password"
{...getFieldProps('password')}
placeholder="Input Password"
/>
{touched.password && errors.password ? (
<div className="invalid-feedback text-left">{errors.password}</div>
) : null}
</div>
<button type="submit" className="btn btn-dark" disabled={isSubmitting}>
Login
</button>
<button>
<Link to="/Home">gha</Link></button>
<Link to="/signup">비밀번호를 잊으셨나요?</Link>
<div></div>
<Link to="/signup">회원이 아니신가요?</Link>
</form>
</div>
)}
</Formik>
</Log>
</div>
</div>
)
}
export default Login
...@@ -4,6 +4,7 @@ import { Link, Redirect } from 'react-router-dom'; ...@@ -4,6 +4,7 @@ import { Link, Redirect } from 'react-router-dom';
import { Formik } from 'formik'; import { Formik } from 'formik';
import * as Yup from 'yup'; import * as Yup from 'yup';
import axios from 'axios'; import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css';
const Log = styled.div` const Log = styled.div`
background-color: #981e1e; background-color: #981e1e;
...@@ -14,10 +15,10 @@ const Logo = styled.div` ...@@ -14,10 +15,10 @@ const Logo = styled.div`
function Login() { function Login() {
const [state, setState] = useState(false); const [state, setState]= useState(false);
if (state) { if (state) {
return <Redirect to="/" />; return <Redirect to="/home" />;
} }
return ( return (
<div className="container-fluid"> <div className="container-fluid">
...@@ -28,11 +29,10 @@ function Login() { ...@@ -28,11 +29,10 @@ function Login() {
</Logo> </Logo>
<Log className="col-md-7 col-12"> <Log className="col-md-7 col-12">
<Formik <Formik
initialValues={{ email: '', password: '' }} initialValues={{ id: '', password: '' }}
validationSchema={Yup.object({ validationSchema={Yup.object({
email: Yup.string() id: Yup.string()
.email('이메일형식이 유효하지 않습니다.') .required('학번을 입력해주세요.'),
.required('이메일을 입력해주세요.'),
password: Yup.string() password: Yup.string()
.required('비밀번호를 입력해주세요.') .required('비밀번호를 입력해주세요.')
.min(8, '8자 이상 입력해주세요.'), .min(8, '8자 이상 입력해주세요.'),
...@@ -70,14 +70,14 @@ function Login() { ...@@ -70,14 +70,14 @@ function Login() {
<form onSubmit={handleSubmit} className="col-sm-3"> <form onSubmit={handleSubmit} className="col-sm-3">
<div className="form-group mb-4"> <div className="form-group mb-4">
<input <input
className={(touched.email && errors.email ? 'form-control is-invalid' : "form-control")} className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")}
type="email" type="number"
name="email" name="id"
{...getFieldProps('email')} {...getFieldProps('id')}
placeholder="Input Email" placeholder="Input Student Id"
/> />
{touched.email && errors.email ? ( {touched.id && errors.id ? (
<div className="invalid-feedback text-left">{errors.email}</div> <div className="invalid-feedback text-left">{errors.id}</div>
) : null} ) : null}
</div> </div>
<div className="form-group mb-4"> <div className="form-group mb-4">
...@@ -96,6 +96,7 @@ function Login() { ...@@ -96,6 +96,7 @@ function Login() {
Login Login
</button> </button>
<button><Link to="/home"></Link></button> <button><Link to="/home"></Link></button>
<div></div>
<Link to="/signup">비밀번호를 잊으셨나요?</Link> <Link to="/signup">비밀번호를 잊으셨나요?</Link>
<div></div> <div></div>
<Link to="/signup">회원이 아니신가요?</Link> <Link to="/signup">회원이 아니신가요?</Link>
......
import React, { useState } from 'react';
import { Formik } from 'formik';
import * as Yup from 'yup';
import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css';
import { Link, Redirect } from 'react-router-dom';
function Signup() {
// const [state, setState] = useState(false);
// if (state) {
// return <Redirect to="/login" />;
// }
return (
<div className="d-flex flex-column justify-content-between vh-100">
<Formik
initialValues={{ name: '', email: '', password: '', password2: '', address: '', }}
validationSchema={Yup.object({
name: Yup.string()
.required('이름을 입력해주세요.'),
email: Yup.string()
.email('이메일형식이 유효하지 않습니다.')
.required('이메일을 입력해주세요.'),
password: Yup.string()
.required('비밀번호를 입력해주세요.')
.min(8, '8자 이상 입력해주세요.'),
password2: Yup.string()
.required('비밀번호를 다시 입력해주세요.')
.min(8, '8자 이상 입력해주세요.')
.oneOf([Yup.ref("password"), null], '비밀번호가 일치하지 않습니다.'),
address: Yup.string()
.required('주소를 입력해주세요.')
})}
onSubmit={(values, { setSubmitting }) => {
// axios({
// method: 'post',
// url: '/users',
// data: values,
// }).then(res => {
// if (res.status === 404) return alert(res.data.error)
alert("회원가입이 완료되었습니다!")
// setState(true);
// })
// .catch(err => {
// alert(err.error)
// });
setTimeout(() => {
setSubmitting(false);
}, 400); // finish the cycle in handler
}}
>
{({
errors,
touched,
handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur
isSubmitting,
}) => (
<div className="row justify-content-center align-items-center">
<form onSubmit={handleSubmit} className="col-sm-3">
<div className="form-group mb-4">
<input
className={(touched.name && errors.name ? 'form-control is-invalid' : "form-control")}
type="text"
name="name"
{...getFieldProps('name')}
placeholder="Input Name" />
{touched.name && errors.name ? (
<div className="invalid-feedback text-left">{errors.name}</div>
) : null}
</div>
<div className="form-group mb-4">
<input
className={(touched.email && errors.email ? 'form-control is-invalid' : "form-control")}
type="email"
name="email"
{...getFieldProps('email')}
placeholder="Input Email"
/>
{touched.email && errors.email ? (
<div className="invalid-feedback text-left">{errors.email}</div>
) : null}
</div>
<div className="form-group mb-4">
<input
className={(touched.address && errors.address ? 'form-control is-invalid' : "form-control")}
type="text"
name="address"
{...getFieldProps('address')}
placeholder="Input Address" />
{touched.address && errors.address ? (
<div className="invalid-feedback text-left">{errors.address}</div>
) : null}
</div>
<div className="form-group mb-4">
<input
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
type="password"
name="password"
{...getFieldProps('password')}
placeholder="Input Password"
/>
{touched.password && errors.password ? (
<div className="invalid-feedback text-left">{errors.password}</div>
) : null}
</div>
<div className="form-group mb-4">
<input
className={(touched.password2 && errors.password2 ? 'form-control is-invalid' : "form-control")}
type="password"
name="password2"
{...getFieldProps('password2')}
placeholder="Input Confirm Password"
/>
{touched.password2 && errors.password2 ? (
<div className="invalid-feedback text-left">{errors.password2}</div>
) : null}
</div>
<button type="submit" className="btn btn-dark" disabled={isSubmitting}>
Sign Up
</button>
<button>
<Link to="/">gha</Link></button>
</form>
</div>
)}
</Formik>
</div>
);
}
export default Signup;
...@@ -20,8 +20,7 @@ function Signup() { ...@@ -20,8 +20,7 @@ function Signup() {
name: Yup.string() name: Yup.string()
.required('이름을 입력해주세요.'), .required('이름을 입력해주세요.'),
id: Yup.string() id: Yup.string()
// .id('이메일형식이 유효하지 않습니다.') .required('학번을 입력해주세요.'),
.required('이메일을 입력해주세요.'),
password: Yup.string() password: Yup.string()
.required('비밀번호를 입력해주세요.') .required('비밀번호를 입력해주세요.')
.min(8, '8자 이상 입력해주세요.'), .min(8, '8자 이상 입력해주세요.'),
...@@ -29,11 +28,8 @@ function Signup() { ...@@ -29,11 +28,8 @@ function Signup() {
.required('비밀번호를 다시 입력해주세요.') .required('비밀번호를 다시 입력해주세요.')
.min(8, '8자 이상 입력해주세요.') .min(8, '8자 이상 입력해주세요.')
.oneOf([Yup.ref("password"), null], '비밀번호가 일치하지 않습니다.'), .oneOf([Yup.ref("password"), null], '비밀번호가 일치하지 않습니다.'),
// address: Yup.string()
// .required('주소를 입력해주세요.')
})} })}
onSubmit={(values, { setSubmitting }) => { onSubmit={(values, { setSubmitting }) => {
console.log(values);
axios({ axios({
method: 'post', method: 'post',
url: '/users', url: '/users',
...@@ -76,26 +72,15 @@ function Signup() { ...@@ -76,26 +72,15 @@ function Signup() {
<div className="form-group mb-4"> <div className="form-group mb-4">
<input <input
className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")} className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")}
type="text" type="number"
name="id" name="id"
{...getFieldProps('id')} {...getFieldProps('id')}
placeholder="Input id" placeholder="Input Student Id"
/> />
{touched.id && errors.id ? ( {touched.id && errors.id ? (
<div className="invalid-feedback text-left">{errors.id}</div> <div className="invalid-feedback text-left">{errors.id}</div>
) : null} ) : null}
</div> </div>
{/* <div className="form-group mb-4">
<input
className={(touched.address && errors.address ? 'form-control is-invalid' : "form-control")}
type="text"
name="address"
{...getFieldProps('address')}
placeholder="Input Address" />
{touched.address && errors.address ? (
<div className="invalid-feedback text-left">{errors.address}</div>
) : null}
</div> */}
<div className="form-group mb-4"> <div className="form-group mb-4">
<input <input
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")} className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
...@@ -123,8 +108,8 @@ function Signup() { ...@@ -123,8 +108,8 @@ function Signup() {
<button type="submit" className="btn btn-dark" disabled={isSubmitting}> <button type="submit" className="btn btn-dark" disabled={isSubmitting}>
Sign Up Sign Up
</button> </button>
<button><Link to="/">로그인</Link></button> <button><Link to="/login">로그인</Link></button>
<button><Link to="/home"></Link></button> <button><Link to="/"></Link></button>
</form> </form>
</div> </div>
)} )}
......
This diff is collapsed.
...@@ -10,11 +10,11 @@ ...@@ -10,11 +10,11 @@
"cookie-parser": "~1.4.4", "cookie-parser": "~1.4.4",
"debug": "~2.6.9", "debug": "~2.6.9",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"express": "^4.16.4", "express": "^4.17.1",
"http-errors": "^1.6.3", "http-errors": "^1.6.3",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"mongoose": "^5.10.5", "mongoose": "^5.10.6",
"morgan": "~1.9.1", "morgan": "~1.9.1",
"pug": "2.0.0-beta11" "pug": "^3.0.0"
} }
} }
const express = require('express');
const User = require('../schemas/user');
const bcrypt = require("bcrypt");
const jwt = require('jsonwebtoken');
const router = express.Router();
router.get('/', function (req, res, next) {
console.log('/login get request', req.body)
User.find({})
.then((signups) => {
res.json(signups);
})
.catch((err) => {
console.error(err);
next(err);
});
});
router.post('/', function (req, res, next) {
console.log('/login post request', req.body)
User.findOne({ id: req.body.id }, 'id password', function (err, users) {
if (err) return res.status(500).json({ error: err });
if (!users) {
return res.status(404).json({ error: '해당 아이디가 존재하지 않습니다.' });
}
bcrypt.compare(req.body.password, users.password, function (err, result) {
if (err) {
console.log(err)
return res.status(500).json({ error: err });
}
if (result) {
const token = jwt.sign({
id:users.id,
}, process.env.JWT_SECRET, {
expiresIn: '1m',
});
return res.status(201).json({
token,
users,
});
}
res.status(404).json({ error: '비밀번호를 다시 입력해주세요.' });
});
})
});
module.exports = router;
const jwt = require('jsonwebtoken');
exports.isLoggedIn = (req, res, next) => {
if (req.isAuthenticated()) {
next();
} else {
res.status(403).send('로그인 필요');
}
};
exports.isNotLoggedIn = (req, res, next) => {
if (!req.isAuthenticated()) {
next();
} else {
res.redirect('/');
}
};
exports.verifyToken = (req, res, next) => {
try {
req.decoded = jwt.verify(req.headers.authorization, process.env.JWT_SECRET);
console.log('decode', req.decoded)
return next();
} catch (error) {
if (error.name === 'TokenExpiredError') { // 유효기간 초과
return res.status(419).json({
code: 419,
error: '토큰이 만료되었습니다. 다시 로그인 해주세요.',
});
}
return res.status(401).json({
code: 401,
error: '유효하지 않은 토큰입니다. 다시 로그인 해주세요.',
});
}
};
var express = require('express'); const express = require('express');
var router = express.Router(); const User = require('../schemas/user');
const bcrypt = require("bcrypt");
const { verifyToken } = require('./middlewares');
/* GET users listing. */ const router = express.Router();
router.get('/', function(req, res, next) {
router.post('/', function (req, res, next) {
console.log('/users post req.body', req.body) console.log('/users post req.body', req.body)
User.findOne({ id: req.body.id }, function (err, users) { User.findOne({ id: req.body.id }, function (err, users) {
if (err) return res.status(500).json({ error: err }); if (err) return res.status(500).json({ error: err });
...@@ -28,5 +31,4 @@ router.get('/', function(req, res, next) { ...@@ -28,5 +31,4 @@ router.get('/', function(req, res, next) {
}); });
}) })
}); });
module.exports = router; module.exports = router;
...@@ -6,7 +6,7 @@ module.exports = () => { ...@@ -6,7 +6,7 @@ module.exports = () => {
mongoose.set('debug', true); mongoose.set('debug', true);
} }
mongoose.connect('mongodb://cherry:1q2w3e4r@localhost:27017/admin', { mongoose.connect('mongodb://cherry:1q2w3e4r@localhost:27017/admin', {
dbName: 'KU_Rental', dbName: 'ku_rental', useNewUrlParser: true, useUnifiedTopology: true,
}, (error) => { }, (error) => {
if (error) { if (error) {
console.log('몽고디비 연결 에러', error); console.log('몽고디비 연결 에러', error);
......
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