add login hook to frontend

This commit is contained in:
Sorrel Bri 2020-01-18 00:18:51 -08:00 committed by sorrelbri
parent 18d351d698
commit a9a10c1adb
8 changed files with 93 additions and 22 deletions

View file

@ -1,13 +1,77 @@
import React, { useState } from 'react';
import './Login.scss';
import authServices from '../../services/authServices';
import FormError from '../FormError/FormError';
const Login = (props) => {
const [username, setUsername] = 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 (
<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>
<input

View file

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

View file

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

View file

@ -7,7 +7,7 @@ export const authReducer = (state: state, action: action):state => {
return loginReducer(state, action);
case 'SIGNUP':
return signupReducer(state, action);
return loginReducer(state, action);
case 'LOGOUT':
return state;
@ -18,13 +18,6 @@ export const authReducer = (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;
return {...state, user: newUser };
}

View file

@ -9,8 +9,19 @@ headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
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) => {

View file

@ -16,7 +16,8 @@ describe('signupService', () => {
});
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;
if (!savedUser) {
return res.status(401).json({err: 'bad credentials'});
return res.status(401).send({errors: 'bad credentials'});
}
const hashedPassword = savedUser.password;
const passwordMatch = await compareHash(user.password, hashedPassword);
if (!passwordMatch) {
return res.status(401).json({err: 'bad credentials'});
return res.status(401).send({errors: 'bad credentials'});
}
const authorizedUser = {...savedUser};
delete authorizedUser.password;
signToken(res, authorizedUser);
res.send('ok').status(200);
res.send({...authorizedUser}).status(200);
}
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) => {
if (err) done(err);
res.should.status(401);
res.body.err.should.equal('bad credentials');
res.body.errors.should.equal('bad credentials');
done();
});
})
@ -32,7 +32,7 @@ const authSignupSpec = (chai, knex, server) => {
.end((err, res) => {
if (err) done(err);
res.should.status(401);
res.body.err.should.equal('bad credentials');
res.body.errors.should.equal('bad credentials');
done();
})
})