정승호

로그인 페이지 제작

This diff is collapsed. Click to expand it.
...@@ -6,9 +6,17 @@ ...@@ -6,9 +6,17 @@
6 "@testing-library/jest-dom": "^4.2.4", 6 "@testing-library/jest-dom": "^4.2.4",
7 "@testing-library/react": "^9.5.0", 7 "@testing-library/react": "^9.5.0",
8 "@testing-library/user-event": "^7.2.1", 8 "@testing-library/user-event": "^7.2.1",
9 + "antd": "^4.3.4",
10 + "axios": "^0.19.2",
11 + "http-proxy-middleware": "^1.0.4",
9 "react": "^16.13.1", 12 "react": "^16.13.1",
10 "react-dom": "^16.13.1", 13 "react-dom": "^16.13.1",
11 - "react-scripts": "3.4.1" 14 + "react-redux": "^7.2.0",
15 + "react-router-dom": "^5.2.0",
16 + "react-scripts": "3.4.1",
17 + "redux": "^4.0.5",
18 + "redux-promise": "^0.6.0",
19 + "redux-thunk": "^2.3.0"
12 }, 20 },
13 "scripts": { 21 "scripts": {
14 "start": "react-scripts start", 22 "start": "react-scripts start",
......
1 -import React from 'react'; 1 +import React from "react";
2 -import logo from './logo.svg'; 2 +import {
3 -import './App.css'; 3 + BrowserRouter as Router,
4 + Switch,
5 + Route,
6 + Link
7 +} from "react-router-dom";
4 8
9 +import LandingPage from './components/views/LandingPage/LandingPage';
10 +import LoginPage from './components/views/LoginPage/LoginPage';
11 +import RegisterPage from './components/views/RegisterPage/RegisterPage';
5 function App() { 12 function App() {
6 return ( 13 return (
7 - <div className="App"> 14 + <Router>
8 - <header className="App-header"> 15 + <div>
9 - <img src={logo} className="App-logo" alt="logo" /> 16 +
10 - <p> 17 +
11 - Edit <code>src/App.js</code> and save to reload. 18 + {/*
12 - </p> 19 + A <Switch> looks through all its children <Route>
13 - <a 20 + elements and renders the first one whose path
14 - className="App-link" 21 + matches the current URL. Use a <Switch> any time
15 - href="https://reactjs.org" 22 + you have multiple routes, but you want only one
16 - target="_blank" 23 + of them to render at a time
17 - rel="noopener noreferrer" 24 + */}
18 - > 25 + <Switch>
19 - Learn React 26 + <Route exact path="/" component={LandingPage}/>
20 - </a> 27 +
21 - </header> 28 + <Route exact path="/login" component={LoginPage}/>
22 - </div> 29 +
30 + <Route exact path="/register" component = {RegisterPage} />
31 +
32 + </Switch>
33 + </div>
34 + </Router>
23 ); 35 );
24 } 36 }
25 37
26 -export default App; 38 +export default App
39 +
40 +
......
1 +export const LOGIN_USER = "login_user";
...\ No newline at end of file ...\ No newline at end of file
1 +import axios from 'axios';
2 +
3 +import {
4 + LOGIN_USER
5 +} from './types';
6 +
7 +export function loginUser(dataTosubmit){
8 + const request = axios.post('/api/users/login', dataTosubmit)
9 + .then(response => response.data)
10 +
11 + return {
12 + type: LOGIN_USER,
13 + payload: request
14 + }
15 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import {combineReducers} from 'redux';
2 +import user from './user_reducer';
3 +
4 +const rootReducer = combineReducers({
5 + user
6 +})
7 +
8 +export default rootReducer
...\ No newline at end of file ...\ No newline at end of file
1 +import {
2 + LOGIN_USER
3 +} from '../_actions/types';
4 +
5 +export default function (state={}, action){
6 + switch (action.type) {
7 + case LOGIN_USER:
8 + return { ...state, loginSuccess: action.payload}
9 + break;
10 +
11 + default:
12 + return state;
13 + }
14 +}
...\ No newline at end of file ...\ No newline at end of file
1 -import React from 'react' 1 +import React, {useEffect} from 'react'
2 +import axios from 'axios';
2 3
3 -function LandingPage(){ 4 +function LandingPage() {
4 - return( 5 + useEffect(() => {
5 - <div> 6 + axios.get('/api/hello')
7 + .then(response => {console.log(response)})
8 + }, [])
6 9
7 - </div>
8 10
11 + return (
12 + <div style = {{
13 + display: 'flex', justifyContent: 'center', alignItems: 'center'
14 + , width: '100%', height: '100vh'
15 + }}>
16 + <h2> 시작 페이지 </h2>
17 + </div>
9 ) 18 )
10 } 19 }
11 20
12 -export default LandingPage
...\ No newline at end of file ...\ No newline at end of file
21 +export default LandingPage
......
1 -import React from 'react' 1 +import React,{useState} from 'react'
2 +import Axios from 'axios'
3 +import { useDispatch} from 'react-redux';
4 +import {loginUser} from '../../../_actions/user_actions';
2 5
3 function LoginPage(){ 6 function LoginPage(){
7 + const dispatch = useDispatch();
8 + const [Email, setEmail] = useState("")
9 + const [PassWord, setPassWord] = useState("")
10 +
11 + const onEmailHandler = (event) => {
12 + setEmail(event.currentTarget.value)
13 + }
14 +
15 + const onPassWordHandler = (event) => {
16 + setPassWord(event.currentTarget.value)
17 + }
18 +
19 + const onSubmitHandler = (event) => {
20 + event.preventDefault();
21 +
22 +
23 + let body = {
24 + email: Email,
25 + password: PassWord
26 + }
27 +
28 + dispatch(loginUser(body))
29 +
30 +
31 + }
32 +
4 return ( 33 return (
5 - <div> 34 + <div style = {{
6 - LoginPage 35 + display: 'flex', justifyContent: 'center', alignItems: 'center'
7 - </div> 36 + , width: '100%', height: '100vh'
37 + }}>
38 + <form style = {{display :'flex', flexDirection: 'column'}}
39 + onSubmit= {onSubmitHandler}
40 + >
41 + <label>Email</label>
42 + <input type = "email" value = {Email} onChange={onEmailHandler} />
43 + <label>PassWord</label>
44 + <input type = "password" value= {PassWord} onChange = {onPassWordHandler} />
45 + <br />
46 + <button type = "submit">
47 + Login
48 + </button>
49 +
50 + </form>
51 + </div>
8 ) 52 )
9 53
10 } 54 }
......
...@@ -3,12 +3,30 @@ import ReactDOM from 'react-dom'; ...@@ -3,12 +3,30 @@ import ReactDOM from 'react-dom';
3 import './index.css'; 3 import './index.css';
4 import App from './App'; 4 import App from './App';
5 import * as serviceWorker from './serviceWorker'; 5 import * as serviceWorker from './serviceWorker';
6 +import {Provider} from 'react-redux';
7 +import 'antd/dist/antd.css';
8 +import { applyMiddleware, createStore} from 'redux';
9 +import promiseMiddleware from 'redux-promise';
10 +import ReduxThunk from 'redux-thunk';
11 +import Reducer from './_reducers/index';
6 12
13 +const creatStoreWithMiddleware = applyMiddleware(promiseMiddleware,ReduxThunk)(createStore)
7 ReactDOM.render( 14 ReactDOM.render(
8 - <React.StrictMode> 15 + <Provider
9 - <App /> 16 + store={creatStoreWithMiddleware(Reducer,
10 - </React.StrictMode>, 17 + window.__REDUX_DEVTOOLS_EXTENTION__&&
11 - document.getElementById('root') 18 + window.__REDUX_DEVTOOLS_EXTENTION__()
19 +
20 + )}
21 + >
22 + <App />
23 + </Provider>
24 +
25 +
26 +
27 + ,document.getElementById('root')
28 +
29 +
12 ); 30 );
13 31
14 // If you want your app to work offline and load faster, you can change 32 // If you want your app to work offline and load faster, you can change
......
1 +const {createProxyMiddleware} = require('http-proxy-middleware');
2 +module.exports = function(app){
3 + app.use(
4 + createProxyMiddleware('/api',{
5 + target : 'http://localhost:5000/',
6 + changeOrigin: true
7 + })
8 + )
9 +};
This diff is collapsed. Click to expand it.
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
5 "main": "index.js", 5 "main": "index.js",
6 "scripts": { 6 "scripts": {
7 "start": "node index.js", 7 "start": "node index.js",
8 - "backend": "nodemon index.js", 8 + "backend": "nodemon server/index.js",
9 - "test": "echo \"Error: no test specified\" && exit 1" 9 + "test": "echo \"Error: no test specified\" && exit 1",
10 + "dev": "concurrently \"npm run backend \" \"npm run start --prefix client\""
10 }, 11 },
11 "repository": { 12 "repository": {
12 "type": "git", 13 "type": "git",
...@@ -17,6 +18,7 @@ ...@@ -17,6 +18,7 @@
17 "dependencies": { 18 "dependencies": {
18 "bcrypt": "^4.0.1", 19 "bcrypt": "^4.0.1",
19 "body-parser": "^1.19.0", 20 "body-parser": "^1.19.0",
21 + "concurrently": "^5.2.0",
20 "cookie-parser": "^1.4.5", 22 "cookie-parser": "^1.4.5",
21 "express": "^4.17.1", 23 "express": "^4.17.1",
22 "jsonwebtoken": "^8.5.1", 24 "jsonwebtoken": "^8.5.1",
......
...@@ -22,7 +22,7 @@ mongoose.connect(config.mongoURI,{ ...@@ -22,7 +22,7 @@ mongoose.connect(config.mongoURI,{
22 22
23 23
24 24
25 -app.get('/', (req,res) => res.send('Hello world!! 오늘도 지식이 쌓였당!!')) 25 +app.get('/api/hello', (req,res) => res.send('Hello world!! 오늘도 지식이 쌓였당!!'))
26 26
27 app.post('/api/users/register', (req, res) => { 27 app.post('/api/users/register', (req, res) => {
28 // 회원 가입시 필요한 정보들을 client에서 가져오면 28 // 회원 가입시 필요한 정보들을 client에서 가져오면
......
...@@ -23,4 +23,4 @@ let auth = (req,res,next) => { ...@@ -23,4 +23,4 @@ let auth = (req,res,next) => {
23 23
24 } 24 }
25 25
26 -module.exports = {auth};
...\ No newline at end of file ...\ No newline at end of file
26 +module.exports = {auth}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -2,6 +2,7 @@ const mongoose = require('mongoose'); ...@@ -2,6 +2,7 @@ const mongoose = require('mongoose');
2 const bcrypt = require('bcrypt'); 2 const bcrypt = require('bcrypt');
3 const saltRounds = 10; 3 const saltRounds = 10;
4 const jwt = require('jsonwebtoken'); 4 const jwt = require('jsonwebtoken');
5 +
5 const userSchema = mongoose.Schema({ 6 const userSchema = mongoose.Schema({
6 name : { 7 name : {
7 type : String, 8 type : String,
...@@ -71,16 +72,23 @@ userSchema.methods.generateToken = function(cb){ ...@@ -71,16 +72,23 @@ userSchema.methods.generateToken = function(cb){
71 if(err) return cb(err) 72 if(err) return cb(err)
72 cb(null, user) 73 cb(null, user)
73 }) 74 })
74 -
75 -
76 -
77 -
78 } 75 }
79 76
77 +userSchema.statics.findByToken = function(token, cb){
78 + var user = this;
79 + // 토큰을 복호화한다.
80 +
81 + jwt.verify(token,'secretToken', function(err, decoded){
82 + // 유저 아이디를 이용해서 유저를 찾고
83 + // 클라이언트에서 가져온 토큰과 데이터베이스에 보관된 토큰이
84 + //일치하는지 확인
85 + user.findOne({"_id": decoded, "token" : token}, function(err, user){
86 + if(err) return cb(err);
87 + cb(null, user)
88 + })
89 + })
90 +}
80 91
81 const User = mongoose.model('Users', userSchema) 92 const User = mongoose.model('Users', userSchema)
82 93
83 - 94 +module.exports = {User}
84 -
85 -module.exports = {User}
86 -
...\ No newline at end of file ...\ No newline at end of file
......