add login hook to frontend

This commit is contained in:
Sorrel Bri 2020-01-18 00:18:51 -08:00
parent 22b6dc443a
commit 015b1a63b8
8 changed files with 93 additions and 22 deletions

View file

@ -1,13 +1,77 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import './Login.scss'; import './Login.scss';
import authServices from '../../services/authServices';
import FormError from '../FormError/FormError';
const Login = (props) => { const Login = (props) => {
const [username, setUsername] = useState(''); const [username, setUsername] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const minimumPasswordLength = 8;
const errorDispatchAction = {
type: 'ERR',
message: 'AUTH_ERROR'
}
const validateLoginForm = next => {
if (password.length < minimumPasswordLength) {
return props.dispatch({
...errorDispatchAction,
body: { authError: 'This password is invalid'}
})
}
if (!/^[\w\d_.-]+$/.test(username)) {
return props.dispatch({
...errorDispatchAction,
body: { authError: "This username is invalid"}
})
}
next();
}
const postLoginForm = async () => {
const loginResponse = await authServices.loginService({
username,
password
})
const parsedResponse = JSON.parse(loginResponse);
if (parsedResponse.errors) {
const authError = parsedResponse.errors
return props.dispatch({
...errorDispatchAction,
body: { authError }
})
}
return props.dispatch({
type: 'AUTH',
message: 'LOGIN',
body: parsedResponse
})
}
const handleSubmit = e => {
e.preventDefault();
validateLoginForm(postLoginForm);
}
const formError = errors => {
if(!errors) return <></>;
if (errors.auth) {
return <FormError error={errors.auth}/>
}
}
return ( return (
<div className="Login" data-testid="Login"> <div className="Login" data-testid="Login">
<form data-testid="Login__form"> {formError(props.state.errors)}
<form
data-testid="Login__form"
onSubmit={e => handleSubmit(e)}
>
<label htmlFor="username-input">Username:</label> <label htmlFor="username-input">Username:</label>
<input <input

View file

@ -1,9 +1,11 @@
import React from 'react'; import React from 'react';
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import Login from './Login'; import Login from './Login';
import { initState } from '../../reducers/init/stateReducer.init';
test('renders Login without crashing', () => { test('renders Login without crashing', () => {
const { getByTestId } = render(<Login />); const state = initState();
const { getByTestId } = render(<Login state={state}/>);
const LoginDiv = getByTestId('Login'); const LoginDiv = getByTestId('Login');
expect(LoginDiv).toBeInTheDocument(); expect(LoginDiv).toBeInTheDocument();
}); });

View file

@ -70,7 +70,7 @@ const Signup = (props) => {
}) })
} }
const handleSubmit = async e => { const handleSubmit = e => {
e.preventDefault(); e.preventDefault();
validateSignupForm(postSignupForm); validateSignupForm(postSignupForm);
} }

View file

@ -7,7 +7,7 @@ export const authReducer = (state: state, action: action):state => {
return loginReducer(state, action); return loginReducer(state, action);
case 'SIGNUP': case 'SIGNUP':
return signupReducer(state, action); return loginReducer(state, action);
case 'LOGOUT': case 'LOGOUT':
return state; return state;
@ -18,13 +18,6 @@ export const authReducer = (state: state, action: action):state => {
} }
function loginReducer(state: state, action: action): state { function loginReducer(state: state, action: action): state {
const userCredentials = action.body;
return state;
}
function signupReducer(state: state, action: action): state {
const newUser = action.body; const newUser = action.body;
return {...state, user: newUser }; return {...state, user: newUser };
} }

View file

@ -9,8 +9,19 @@ headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json'); headers.append('Accept', 'application/json');
headers.append('Sec-Fetch-Site', 'cross-site') headers.append('Sec-Fetch-Site', 'cross-site')
const loginService = () => { const loginService = async(formData) => {
const response = await fetch(loginEndpoint, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(formData),
headers: headers
})
.then(res => {
return res.text();
}).catch(err => {
return err;
});
return response;
} }
const signupService = async (formData) => { const signupService = async (formData) => {
@ -20,7 +31,7 @@ const signupService = async (formData) => {
body: JSON.stringify(formData), body: JSON.stringify(formData),
headers: headers headers: headers
}) })
.then(res => { .then(res => {
return res.text(); return res.text();
}).catch(err => { }).catch(err => {
return err; return err;

View file

@ -16,7 +16,8 @@ describe('signupService', () => {
}); });
describe('loginService', () => { describe('loginService', () => {
it('', () => { it('login is successful', async () => {
// const response = await loginService(newUserFormData);
// console.log(response);
}); });
}); });

View file

@ -45,25 +45,25 @@ const login = async (req, res, next) => {
const savedUser = queryResults[0] || null; const savedUser = queryResults[0] || null;
if (!savedUser) { if (!savedUser) {
return res.status(401).json({err: 'bad credentials'}); return res.status(401).send({errors: 'bad credentials'});
} }
const hashedPassword = savedUser.password; const hashedPassword = savedUser.password;
const passwordMatch = await compareHash(user.password, hashedPassword); const passwordMatch = await compareHash(user.password, hashedPassword);
if (!passwordMatch) { if (!passwordMatch) {
return res.status(401).json({err: 'bad credentials'}); return res.status(401).send({errors: 'bad credentials'});
} }
const authorizedUser = {...savedUser}; const authorizedUser = {...savedUser};
delete authorizedUser.password; delete authorizedUser.password;
signToken(res, authorizedUser); signToken(res, authorizedUser);
res.send('ok').status(200); res.send({...authorizedUser}).status(200);
} }
catch (err) { catch (err) {
res.status(500).json(err); res.status(500).send({errors: err});
} }
} }

View file

@ -19,7 +19,7 @@ const authSignupSpec = (chai, knex, server) => {
.end((err, res) => { .end((err, res) => {
if (err) done(err); if (err) done(err);
res.should.status(401); res.should.status(401);
res.body.err.should.equal('bad credentials'); res.body.errors.should.equal('bad credentials');
done(); done();
}); });
}) })
@ -32,7 +32,7 @@ const authSignupSpec = (chai, knex, server) => {
.end((err, res) => { .end((err, res) => {
if (err) done(err); if (err) done(err);
res.should.status(401); res.should.status(401);
res.body.err.should.equal('bad credentials'); res.body.errors.should.equal('bad credentials');
done(); done();
}) })
}) })