From b55409cb482a3602e3666c2272062b72986613b7 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Thu, 29 Aug 2019 13:20:43 +0100 Subject: [PATCH] feature #12: login functionality --- package.json | 1 + src/api/authApi copy.js | 12 ------------ src/api/authApi.js | 21 ++++++++++++++++++--- src/components/auth/LoginForm.js | 18 ------------------ src/components/auth/LoginPage.js | 18 +++++++++++------- src/redux/actions/actionTypes.js | 2 +- src/redux/actions/authActions.js | 26 +++++++++++++++++++++++--- src/redux/reducers/authReducer.js | 11 +++++++++++ src/redux/reducers/index.js | 2 ++ src/tools/apiServer.js | 18 +++++++++--------- src/tools/history.js | 3 +++ 11 files changed, 79 insertions(+), 53 deletions(-) delete mode 100644 src/api/authApi copy.js create mode 100644 src/redux/reducers/authReducer.js create mode 100644 src/tools/history.js diff --git a/package.json b/package.json index c014c84..ef645d6 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "express": "^4.17.1", "file-loader": "3.0.1", "fs-extra": "7.0.1", + "history": "^4.9.0", "html-webpack-plugin": "4.0.0-beta.5", "identity-obj-proxy": "3.0.0", "immer": "^2.1.5", diff --git a/src/api/authApi copy.js b/src/api/authApi copy.js deleted file mode 100644 index 2c1e7f3..0000000 --- a/src/api/authApi copy.js +++ /dev/null @@ -1,12 +0,0 @@ -import { handleResponse, handleError } from "./apiUtils"; -const baseUrl = process.env.REACT_APP_API_URL + "/api/auth/"; - -export function login(userName, password) { - const requestOptions = { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ userName, password }) - }; - - return fetch(requestOptions); -} diff --git a/src/api/authApi.js b/src/api/authApi.js index 2c1e7f3..4c7ee6a 100644 --- a/src/api/authApi.js +++ b/src/api/authApi.js @@ -1,12 +1,27 @@ import { handleResponse, handleError } from "./apiUtils"; const baseUrl = process.env.REACT_APP_API_URL + "/api/auth/"; -export function login(userName, password) { +function login(username, password) { const requestOptions = { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ userName, password }) + body: JSON.stringify({ username, password }) }; - return fetch(requestOptions); + return fetch(baseUrl + "/auth/login", requestOptions) + .then(handleResponse) + .then(token => { + localStorage.setItem("trelloid_token", JSON.stringify(token)); + return token; + }) + .catch(handleError); } + +function logout() { + localStorage.removeItem("user"); +} + +export const auth = { + login, + logout +}; diff --git a/src/components/auth/LoginForm.js b/src/components/auth/LoginForm.js index 62a4931..81aa83f 100644 --- a/src/components/auth/LoginForm.js +++ b/src/components/auth/LoginForm.js @@ -8,24 +8,6 @@ const LoginForm = ({ onChange, onSave, errors, user }) => (

Registration

{errors.summary &&

{errors.summary}

} - - - - { - toast.success("User saved"); - this.props.history.push("/users"); + this.props.history.push("/"); }) .catch(error => { this.setState({ @@ -61,7 +59,13 @@ class LoginPage extends Component { render() { return (
- +
); } diff --git a/src/redux/actions/actionTypes.js b/src/redux/actions/actionTypes.js index 87a0950..73df9b1 100644 --- a/src/redux/actions/actionTypes.js +++ b/src/redux/actions/actionTypes.js @@ -2,7 +2,7 @@ export const LOGIN_REQUEST = "LOGIN_REQUEST"; export const LOGIN_SUCCESS = "LOGIN_SUCCESS"; export const LOGIN_FAILURE = "LOGIN_FAILURE"; -export const LOGOUT = "LOGOUT"; +export const LOGOUT_SUCCESS = "LOGOUT_SUCCESS"; // Card actions. export const CREATE_CARD_SUCCESS = "CREATE_CARD_SUCCESS"; diff --git a/src/redux/actions/authActions.js b/src/redux/actions/authActions.js index b58fe28..a9639aa 100644 --- a/src/redux/actions/authActions.js +++ b/src/redux/actions/authActions.js @@ -1,4 +1,6 @@ import * as actionTypes from "./actionTypes"; +import { beginApiCall } from "./apiStatusActions"; +import * as authApi from "../../api/authApi"; export function loginFailure(user) { return { type: actionTypes.LOGIN_FAILURE, user: user }; @@ -12,10 +14,28 @@ export function loginSuccess(user) { return { type: actionTypes.LOGIN_SUCCESS, user: user }; } -export function logout(user) { - return { type: actionTypes.LOGOUT, user: user }; +export function logoutSuccess(user) { + return { type: actionTypes.LOGOUT_SUCCESS }; } export function login(user) { - return; + return function(dispatch) { + dispatch(beginApiCall()); + dispatch(loginRequest({ user })); + const { userName, password } = user; + return authApi + .login(userName, password) + .then(() => { + dispatch(loginSuccess(user)); + }) + .catch(err => { + dispatch(loginFailure(err)); + throw err; + }); + }; +} + +export function logout() { + localStorage.removeItem("trelloid_token"); + return logoutSuccess(); } diff --git a/src/redux/reducers/authReducer.js b/src/redux/reducers/authReducer.js new file mode 100644 index 0000000..3535e93 --- /dev/null +++ b/src/redux/reducers/authReducer.js @@ -0,0 +1,11 @@ +import * as actionTypes from "../actions/actionTypes"; +import initialState from "./initialState"; + +export default function authReducer(state = initialState.users, action) { + switch (action.type) { + case actionTypes.LOGIN_SUCCESS: + return action.user; + default: + return state; + } +} diff --git a/src/redux/reducers/index.js b/src/redux/reducers/index.js index e0c6ff5..2a89849 100644 --- a/src/redux/reducers/index.js +++ b/src/redux/reducers/index.js @@ -1,10 +1,12 @@ import { combineReducers } from "redux"; import apiCallsInProgress from "./apiStatusReducer"; +import auth from "./authReducer"; import cards from "./cardReducer"; import users from "./userReducer"; const rootReducer = combineReducers({ apiCallsInProgress, + auth, cards, users }); diff --git a/src/tools/apiServer.js b/src/tools/apiServer.js index b0dd7c6..ff091ef 100755 --- a/src/tools/apiServer.js +++ b/src/tools/apiServer.js @@ -39,14 +39,16 @@ server.post("/users/", function(req, res, next) { server.post("/auth/login", function(req, res, next) { const { userName, password } = req.body; - if (isAuthenticated(userName, password) === false) { + const user = isAuthenticated(userName, password); + if (user) { + const access_token = createToken({ userName, password }); + res.status(200).json({ access_token, user }); + } else { const status = 401; const message = "Incorrect email or password"; res.status(status).json({ status, message }); return; } - const access_token = createToken({ userName, password }); - res.status(200).json({ access_token }); }); router.db._.id = "_id"; @@ -105,11 +107,9 @@ function verifyToken(token) { } function isAuthenticated(userName, password) { - return ( - users.findIndex( - user => - user.userName === userName && - bcrypt.compareSync(password, user.password) - ) !== -1 + const user = users.filter( + user => + user.userName === userName && bcrypt.compareSync(password, user.password) ); + return user[0]; } diff --git a/src/tools/history.js b/src/tools/history.js new file mode 100644 index 0000000..7001cee --- /dev/null +++ b/src/tools/history.js @@ -0,0 +1,3 @@ +import { createBrowserHistory } from "history"; + +export const history = createBrowserHistory();