Handle and show login/signup errors
This commit is contained in:
parent
8ac687e454
commit
1ea6b0b75b
@ -30,6 +30,8 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
login(user) {
|
login(user) {
|
||||||
|
console.log("Logging in")
|
||||||
|
console.log(user)
|
||||||
this.setState({user: user});
|
this.setState({user: user});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
app/src/frontend/error-box.js
Normal file
20
app/src/frontend/error-box.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import React, { Fragment } from 'react';
|
||||||
|
|
||||||
|
const ErrorBox = (props) => (
|
||||||
|
<Fragment>
|
||||||
|
{
|
||||||
|
(props.msg)?
|
||||||
|
(
|
||||||
|
<div className="alert alert-danger" role="alert">
|
||||||
|
{
|
||||||
|
(typeof props.msg === 'string' || props.msg instanceof String)?
|
||||||
|
props.msg
|
||||||
|
: 'Unexpected error'
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default ErrorBox;
|
@ -1,13 +1,16 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Redirect, Link } from 'react-router-dom';
|
import { Redirect, Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import ErrorBox from './error-box';
|
||||||
|
|
||||||
class Login extends Component {
|
class Login extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
show_password: ''
|
show_password: '',
|
||||||
|
error: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
@ -26,7 +29,6 @@ class Login extends Component {
|
|||||||
|
|
||||||
handleSubmit(event) {
|
handleSubmit(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const login = this.props.login
|
|
||||||
fetch('/login', {
|
fetch('/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(this.state),
|
body: JSON.stringify(this.state),
|
||||||
@ -37,20 +39,19 @@ class Login extends Component {
|
|||||||
res => res.json()
|
res => res.json()
|
||||||
).then(function(res){
|
).then(function(res){
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
console.error(res.error); // tell user
|
this.setState({error: res.error})
|
||||||
} else {
|
} else {
|
||||||
console.log(res); // redirect back
|
this.setState({error: undefined})
|
||||||
fetch('/users/me').then(
|
fetch('/users/me').then(
|
||||||
(res) => res.json()
|
(res) => res.json()
|
||||||
).then(function(user){
|
).then(
|
||||||
console.log(user)
|
(user) => this.props.login(user)
|
||||||
login(user);
|
).catch(
|
||||||
}).catch(function(err){
|
(err) => this.setState({error: err})
|
||||||
console.error(err);
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}).catch(
|
}.bind(this)).catch(
|
||||||
err => console.error(err)
|
(err) => this.setState({error: err})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ class Login extends Component {
|
|||||||
<article>
|
<article>
|
||||||
<section className="main-col">
|
<section className="main-col">
|
||||||
<h1 className="h2">Log in</h1>
|
<h1 className="h2">Log in</h1>
|
||||||
|
<ErrorBox msg={this.state.error} />
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<label htmlFor="username">Username*</label>
|
<label htmlFor="username">Username*</label>
|
||||||
<input name="username" id="username"
|
<input name="username" id="username"
|
||||||
@ -80,18 +82,18 @@ class Login extends Component {
|
|||||||
|
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
<input id="show_password" name="show_password"
|
<input id="show_password" name="show_password"
|
||||||
className="position-static" type="checkbox"
|
className="form-check-input" type="checkbox"
|
||||||
checked={this.state.show_password}
|
checked={this.state.show_password}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="show_password">Show password?</label>
|
<label htmlFor="show_password" className="form-check-label">Show password?</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="buttons-container">
|
<div className="buttons-container">
|
||||||
<input type="submit" value="Log In" className="btn btn-primary" />
|
<input type="submit" value="Log In" className="btn btn-primary" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Would you like to create an account?
|
Would you like to create an account instead?
|
||||||
|
|
||||||
<div className="buttons-container">
|
<div className="buttons-container">
|
||||||
<Link to="sign-up.html" className="btn btn-outline-dark">Sign Up</Link>
|
<Link to="sign-up.html" className="btn btn-outline-dark">Sign Up</Link>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Redirect, Link } from 'react-router-dom';
|
import { Redirect, Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import ErrorBox from './error-box';
|
||||||
|
|
||||||
class SignUp extends Component {
|
class SignUp extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -10,7 +12,8 @@ class SignUp extends Component {
|
|||||||
confirm_email: '',
|
confirm_email: '',
|
||||||
password: '',
|
password: '',
|
||||||
show_password: '',
|
show_password: '',
|
||||||
confirm_conditions: false
|
confirm_conditions: false,
|
||||||
|
error: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
@ -39,17 +42,19 @@ class SignUp extends Component {
|
|||||||
res => res.json()
|
res => res.json()
|
||||||
).then(function(res){
|
).then(function(res){
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
console.error(res.error); // tell user
|
this.setState({error: res.error})
|
||||||
} else {
|
} else {
|
||||||
console.log(res); // redirect back
|
this.setState({error: undefined})
|
||||||
fetch('/users/me').then(function(user){
|
fetch('/users/me').then(
|
||||||
this.props.login(user);
|
(res) => res.json()
|
||||||
}).catch(function(err){
|
).then(
|
||||||
console.error(err);
|
(user) => this.props.login(user)
|
||||||
})
|
).catch(
|
||||||
|
(err) => this.setState({error: err})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}).catch(
|
}.bind(this)).catch(
|
||||||
err => console.error(err)
|
(err) => this.setState({error: err})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +69,7 @@ class SignUp extends Component {
|
|||||||
<p>
|
<p>
|
||||||
Create an account to start colouring in.
|
Create an account to start colouring in.
|
||||||
</p>
|
</p>
|
||||||
|
<ErrorBox msg={this.state.error} />
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<label htmlFor="username">Username*</label>
|
<label htmlFor="username">Username*</label>
|
||||||
<input name="username" id="username"
|
<input name="username" id="username"
|
||||||
@ -95,20 +101,22 @@ class SignUp extends Component {
|
|||||||
|
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
<input id="show_password" name="show_password"
|
<input id="show_password" name="show_password"
|
||||||
className="position-static" type="checkbox"
|
className="form-check-input" type="checkbox"
|
||||||
checked={this.state.show_password}
|
checked={this.state.show_password}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="show_password">Show password?</label>
|
<label className="form-check-label" htmlFor="show_password">
|
||||||
|
Show password?
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
<input id="confirm_conditions" name="confirm_conditions"
|
<input id="confirm_conditions" name="confirm_conditions"
|
||||||
className="position-static" type="checkbox"
|
className="form-check-input" type="checkbox"
|
||||||
checked={this.state.confirm_conditions}
|
checked={this.state.confirm_conditions}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
required />
|
required />
|
||||||
<label htmlFor="confirm_conditions">
|
<label className="form-check-label" htmlFor="confirm_conditions">
|
||||||
I confirm that I have read and agree to the <a
|
I confirm that I have read and agree to the <a
|
||||||
href="/privacy-policy">privacy policy</a> and <a
|
href="/privacy-policy">privacy policy</a> and <a
|
||||||
href="/user-agreement">contributor agreement</a>.
|
href="/user-agreement">contributor agreement</a>.
|
||||||
|
@ -12,8 +12,8 @@ input[type="email"] {
|
|||||||
input[type="number"] {
|
input[type="number"] {
|
||||||
padding-right: 0.25rem;
|
padding-right: 0.25rem;
|
||||||
}
|
}
|
||||||
.form-check {
|
.form-check-input {
|
||||||
padding-left: 0;
|
margin-top: 0.6rem;
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
margin: 0.5em 0 0;
|
margin: 0.5em 0 0;
|
||||||
|
@ -178,11 +178,13 @@ server.post('/users', function(req, res){
|
|||||||
const user = req.body;
|
const user = req.body;
|
||||||
if (req.session.user_id) {
|
if (req.session.user_id) {
|
||||||
res.send({error: 'Already signed in'});
|
res.send({error: 'Already signed in'});
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.email){
|
if (user.email){
|
||||||
if (user.email != user.confirm_email) {
|
if (user.email != user.confirm_email) {
|
||||||
res.send({error: "Email did not match confirmation."});
|
res.send({error: "Email did not match confirmation."});
|
||||||
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
user.email = null;
|
user.email = null;
|
||||||
@ -198,7 +200,7 @@ server.post('/users', function(req, res){
|
|||||||
}
|
}
|
||||||
}).catch(function(err){
|
}).catch(function(err){
|
||||||
console.error(err);
|
console.error(err);
|
||||||
res.send({error: 'Server error'})
|
res.send(err)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,6 +2,12 @@ import { query } from './db';
|
|||||||
|
|
||||||
|
|
||||||
function createUser(user) {
|
function createUser(user) {
|
||||||
|
if (!user.password || user.password.length < 8) {
|
||||||
|
return Promise.reject({error: 'Password must be at least 8 characters'})
|
||||||
|
}
|
||||||
|
if (user.password.length > 70) {
|
||||||
|
return Promise.reject({error: 'Password must be at most 70 characters'})
|
||||||
|
}
|
||||||
return query(
|
return query(
|
||||||
`INSERT
|
`INSERT
|
||||||
INTO users (
|
INTO users (
|
||||||
@ -52,14 +58,14 @@ function authUser(username, password) {
|
|||||||
]
|
]
|
||||||
).then(function(data){
|
).then(function(data){
|
||||||
const user = data.rows[0];
|
const user = data.rows[0];
|
||||||
if (user.auth_ok) {
|
if (user && user.auth_ok) {
|
||||||
return {user_id: user.user_id}
|
return {user_id: user.user_id}
|
||||||
} else {
|
} else {
|
||||||
return {error: 'Authentication failed'}
|
return {error: 'Username or password not recognised'}
|
||||||
}
|
}
|
||||||
}).catch(function(err){
|
}).catch(function(err){
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return {error: 'Database error'};
|
return {error: 'Username or password not recognised'};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user