NodeJS Express password reset in MVC - node.js

I am trying to set up a password-reset route inside my node application, which is suppose to send an email to the user with a password reset link.
The issue that I am having is that I keep receiving the error TypeError: cannot read property json of undefined. To my understanding this means that I am not passing the email correctly to my server side code.
I am having troubles locating the exact place of my bug. I've followed this example, however I've changed it to a more of a MVC architecture. Meaning that I've split the Node code into a service and a controller.
Here is my ReactJS code:
class PasswordResetComponent extends Component {
constructor(props){
super(props);
this.state = {
email:'',
showError:false,
messageFromServer:''
}
}
handleChange = name => event => {
this.setState({
[name]: event.target.value
});
}
sendEmail = e => {
e.preventDefault();
if(this.state.email == ' '){
this.setState({
showError: false,
messageFromServer:' ',
});
}else{
(async () => {
const rawResponse = await fetch(process.env.REACT_APP_SERVER_URI + '/user/password-reset', {
method: 'POST',
body: this.state.email
});
const response = await rawResponse.json();
console.log(response)
})();
}
}
render(){
console.log(this.state.email)
const {email, messageFromServer, showError, showNullError} = this.state;
return(
<div className="container-fluid no-gutters page-login">
<div className="row">
<div className="login-wrapper">
<form onSubmit={this.sendEmail} method="POST">
<div className="form-row">
<div className="form-group col-md-12">
<input type="email" name="email" className="form-control" value={email} onChange={this.handleChange('email')} placeholder="Email" required/>
</div>
</div>
<button type="submit" className="btn btn-primary btn-lg btn-block">Send Confirmation</button>
</form>
<Link to="/login"><button className="mt-4 btn btn-info">Back to Login</button></Link>
</div>
</div>
</div>
);
}
}
Inside my React code, I manage to successfully print out the value of this.state.email meaning that it should be passing fine. I also receive a 200 status on the request.
Here is my Service for password reset:
exports.passwordResetService = async function(email,res, req){
try{
User.findOne({
email: email
}).then(user => {
if( user == null){
res.json('email not in db');
}else{
const token = crypto.randomBytes(20).toString('hex');
console.log(token);
user.update({
resetPasswordToken: token,
resetPasswordExpires: Date.now() + 360000,
});
const transporter = nodemailer.createTransport({
service: 'gmx',
host: 'mail.gmx.com',
port: 587,
secure: true,
auth: {
user: `${process.env.EMAIL_ADDRESS}`,
pass: `${process.env.EMAIL_PASSWORD}`,
},
});
const mailOptions = {
from:'testaccount9909#gmx.com',
to: `${user.email}`,
subject: `Password Reset Email Broh'`,
text:
`Please click the following link to reset your account's password:`+
`http://localhost:3003/reset/${token}\n\n`+
`If you simply ignore the link, your password will remain unchanged!`
}
console.log('sending email...');
transporter.sendMail(mailOptions, function(err, response){
if(err){
console.error('there was an error: ', err);
} else {
console.log('here is the resposne:', response);
res.status(200).json('recovery email sent');
}
})
}
}).catch(error =>
console.log(error)
);
}catch(e){
throw Error("And Error occured while resetting the password");
}
}
Here is my Controller for password reset:
exports.passwordReset = async function(req, res, next){
try{
let passwordResetValue = await UserService.passwordResetService(req.body.email);
return res.status(200).json({status:200, data: passwordResetValue, error:"false", message:"Password reset email has been sent!"})
}catch(e){
console.log(e, "Wopsie wopsie email reset error!");
res.status(400);
}
};
The Place where I am getting the error is inside the Service, more specifically:
if( user == null){
res.json('email not in db');
}
Why am I not passing the user email to the NodeJS service?

The reason you're getting cannot read property json of undefined is because res is not available to passwordResetService since you've not passed it from the route callback and since it's not a middleware
Since all that you're doing with passwordResetService is do some validation and send email you can make few changes to your code like:
// Since you want to send the some success message, you can make a promise wrapper
// to return a promise which you can later await to get status or failure
function mailSender(mailOptions) {
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, function(err, response){
if(err){
// could just reject(err) instead
reject('there was an error: ', err);
} else {
console.log('here is the resposne:', response);
resolve('recovery email sent');
}
});
});
}
exports.passwordResetService = async function(email){
let mailStatus;
try{
const user = User.findOne({ email });
if (user === null) {
return ({ message: "email not in db" });
}
const token = crypto.randomBytes(20).toString('hex');
console.log(token);
user.update({
resetPasswordToken: token,
resetPasswordExpires: Date.now() + 360000,
});
const transporter = nodemailer.createTransport({
service: 'gmx',
host: 'mail.gmx.com',
port: 587,
secure: true,
auth: {
user: `${process.env.EMAIL_ADDRESS}`,
pass: `${process.env.EMAIL_PASSWORD}`,
},
});
const mailOptions = {
from:'testaccount9909#gmx.com',
to: `${user.email}`,
subject: `Password Reset Email Broh'`,
text:
`Please click the following link to reset your account's password:`+
`http://localhost:3003/reset/${token}\n\n`+
`If you simply ignore the link, your password will remain unchanged!`
}
console.log('sending email...');
// wait for promise to resolve, if promise is rejected, catch block will catch the error
mailStatus = await mailSender(mailOptions);
} catch(e) {
throw Error("And Error occured while resetting the password");
}
return mailStatus;
}

Related

How to display the error in .ejs template

So I converted the .hbs template to .ejs template and try to see the difference. I thought converting would be same, but it turns out it doesn't.
My code is working. I can register a user, but no error shows up. The error display is the main problem in my code.
Error-looping of .ejs
This is the .HBS version of Error
{{#if message}}
<h4 class="alert alert-danger mt-4">{{message}}</h4>
{{/if}}
This is the .EJS version of Error
//SignUp.js / SignIn.js
<% if (error) { %>
<h4 class="alert alert-danger mt-4">{{message}}</h4>
<% } %>
Another version of Error in .EJS
<% if (hasErrors) {%>
<div class="alert alert-danger">
<% messages.forEach(function(message){ %>
<p><%= message %></p>
<% });%>
</div>
<% }%>
This is the Controllers folder - auth.js
exports.signin = async (req, res) => {
try {
const {email, password} = req.body;
if(!email || !password) {
return res.status(400).render('shop/signin', {
message: 'Please provide an email and/or password'
});
}
con.query('SELECT * FROM users WHERE email = ?', [email], async (error, results) => {
console.log(results);
if(!results || !(await bcrypt.compare(password, results[0].password))) {
res.status(401).render('shop/signin', {
message: 'Email or Password is incorrect'
});
}
else {
const id = results[0].id;
const token = jwt.sign({ id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRES_IN
});
console.log("The token is: " + token);
const cookieOptions = {
expires: new Date(
Date.now() = process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000
),
httpOnly: true
}
res.cookie('jwt', token, cookieOptions);
res.status(200).redirect("shop/profile");
}
});
}
catch(error) {
console.log(error);
}
}
exports.signup = (req, res) => {
console.log(req.body);
const {name, email, password, passwordConfirm} = req.body;
con.query('SELECT email FROM users WHERE email = ?', [email], async (error, results) => {
if(error) {
console.log(error);
}
if(results.length > 0) {
return res.render('shop/signup', {
message: 'That email is already in use!'
});
}
else if(password !== passwordConfirm) {
return res.render('shop/signup', {
message: 'Passwords do not match!'
});
}
let hashedPassword = await bcrypt.hash(password, 8);
console.log(hashedPassword);
con.query('INSERT INTO users SET ?', {name: name, email: email, password: hashedPassword}, (error, results) => {
if(error) {
console.log(error);
}
else {
console.log(results);
return res.render('shop/signup', {
message: 'User Registered!'
});
}
});
});
}
This is the Routes folder - user.js
router.post('/signup', authController.signup);
router.post('/signin', authController.signin);
module.exports = router;
Lord
You can solve this job in two ways.
1-Local Message
return res.send("<script> alert('Error Message'); window.location = 'shop/signin'; </script>")
2- If you don't want to use local messages Use 'flash' and 'session' packages

React JS: Rendering Blank page instead of rendering the component in route

In React JS App there is forgot password functionality, on entering email end users get password reset link if the user's email exists in DB. When user clicks the link inside email it gets redirect and load blank screen. I can't figure out the problem, I had checked all routes and looks like perfect.
This is ResetPassword Component where user can enter set his new password.
const ResetPassword = (props) => {
const userId = props.match.params.id
const [password,setPassword] = useState({
password: '', confirmPassword: ''
})
const baseUrl = process.env.REACT_APP_baseUrl
const changePassUrl = `${baseUrl}/user/reset/${userId}`
const history = useHistory()
const resetPassword = async e => {
e.preventDefault()
const options = {
method: 'PATCH',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(password)
}
await fetch(changePassUrl, options)
.then(response => response.json())
.then(user => {
console.log('Success:', user);
if(user.status===true){
toast.success('Password changed Successfully. Login with New Password',{position: 'top-center', autoClose: 8000})
history.push('/login')
}
else if(user.status === false){
toast.error('Please try again!',{position: 'top-center', autoClose: 8000})
}
})
.catch((error) => {
console.error('Error:', error);
});
}
App.js route of above component.
<Route exact path='/reset/:id' component={ResetPassword}/>
Node API that sends the reset link via NodeMailer.
module.exports.resetUserPassword = (req, res) => {
User.findOne({email: req.body.email},
(err, users) => {
if (err) {
res.status(500).json({
status: false,
message: 'some error occured in Finding User.',
error: err,
});
}
if (users) {
const url = process.env.Url
var transporter = nodemailer.createTransport({
host: process.env.mailHost,
port: 587,
auth: {
user: process.env.mailUser,
pass: process.env.mailPass
}
});
var mailOptions = {
from: process.env.mailUser,
to: users.email,
subject: 'Password Reset Link',
html: `
<div style='color: #000'>
<h2>Hello ${users.fullName},</h2>
<h3>A request has been received to change the password for your Jobs#MyCityMyStore Account.</h3>
<h3>Click here to reset your password</h3>
<p>If you did not initiate this request, Please contact us immediately at </p><a href='#'>support#support.com</a><br/>
<p>Thank you.</p>
<p>support#support Team</p>
</div>`
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
res.status(200).json({ status: true, email: users.email });
}else{
res.status(200).json({status: false, data: 'User not found '+users})
}
}
);
};

Getting "Please enter all fields error" no matter what is entered in register, using react-redux and jwt

I am using react-redux, axios, and JWT to create a registration system to a simple web app I built. No matter what is entered, I get a "Please enter all fields error". I have programmed other errors, and even when all input is valid I get the same one. I do not see any compilation error either in dev tools or in my terminal. This is my first try at authentication/registration.
This is my registerModal:
class RegisterModal extends Component{
state = {
Modal: false,
name: '',
email: '',
password:'',
msg: null
}
static propTypes ={
isAuthenticated: PropTypes.bool,
error: PropTypes.object.isRequired,
register: PropTypes.func.isRequired,
clearErrors: PropTypes.func.isRequired
}
componentDidUpdate(prevProps){
const {error} = this.props;
if(error !== prevProps.error){
//reg error
if(error.id === 'REGISTER_FAIL'){
this.setState({msg: error.msg.msg})
}else{
this.setState({msg: null});
}
}
}
toggle = () =>{
this.props.clearErrors();
this.setState({
Modal: !this.state.Modal
});
}
onChange = (e)=>{
this.setState(
{[e.target.name]: e.target.value}
);
}
onSubmit = e =>{
e.preventDefault();
const{name, email, password} = this.state;
//create user object
const newUser = {
name,
email,
password
};
this.props.register(newUser);
}
render(){
return(
<div>
<NavLink onClick = {this.toggle} href ="#" color = "danger">
Register
</NavLink>
<Modal
isOpen={this.state.Modal}
toggle={this.toggle} >
<ModalHeader toggle={this.toggle}>Register</ModalHeader>
<ModalBody>
{this.state.msg ? <Alert color = "danger">{this.state. msg}</Alert>: null}
<Form onSubmit = {this.onSubmit}>
<FormGroup>
<Label for ="name">Name</Label>
<Input
type = "text"
name= "name"
id = "name"
placeholder="Name"
onChange = {this.onChange}>
</Input>
</FormGroup>
<FormGroup>
<Label for ="Email">Email </Label>
<Input
type = "email"
name= "email"
id = 'email'
placeholder="Enter email"
onChange = {this.onChange}>
</Input>
</FormGroup>
<FormGroup>
<Label for ="Password">Password</Label>
<Input
type = "password"
name= "password"
id = "password"
placeholder="Password"
onChange = {this.onChange}>
</Input>
</FormGroup>
<Button
color="success"
style={{marginTop:'2rem'}}
block>
Register</Button>
</Form>
</ModalBody>
</Modal>
</div>
);
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.auth.isAuthenticated,
error: state.error
});
export default connect(
mapStateToProps,
{register, clearErrors})(RegisterModal);
This is in my auth.js file in routes folder:
//POST api/auth
//#desc Auth user
router.post('/', (req, res)=> {
const { email, password } = req.body;
//validation
if(!email || !password){
return res.status(400).json({msg: 'Please enter all fields'});
}
//Check for existing user
User.findOne({email})
.then(user =>{
if(!user) return res.status(400).json({msg: 'User does not exists'})
//Validate password
bcrypt.compare(password, user.password)
.then(isMatch =>{
if(!isMatch) return res.status(400).json({ msg: 'Invalid credentials'});
jwt.sign(
{id: user.id},
config.get('jwtSecret'),
{expiresIn: 3600},
(err, token) => {
if(err) throw err;
res.json({
token,
user: {
id: user.id,
name: user.name,
email: user.email
}
});
}
)
})
});
});
authActions.js:
//check tokens and register user
export const loadUser = () => (dispatch, getState) => {
//user loading
dispatch({type: USER_LOADING});
axios.get('/api/auth/user', tokenConfig(getState))
.then(res => dispatch({
type: USER_LOADED,
payload: res.data
}))
.catch(err => {
dispatch(returnErrors(err.response.data, err.response.status));
dispatch({
type: AUTH_ERROR
});
});
}
export const register = ({name, email, password}) => dispatch =>{
//headers
const config = {
header: {
'Content-Type': 'application/json'
}
}
//request body
const body = JSON.stringify({name, email, password});
axios.post('/api/users', body, config)
.then(res => dispatch({
type: REGISTER_SUCCESS,
payload:res.data
}))
.catch(err=>{
dispatch(returnErrors(err.response.data, err.response.status, 'REGISTER_FAIL'));
dispatch({
type: REGISTER_FAIL
})
})
}
//setup config /header and token
export const tokenConfig = getState => {
//get token from local storage
const token = getState().auth.token;
//headers
const config = {
headers: {
"Content-type": "application/json"
}
}
//if token add to headers
if(token){
config.headers['x-auth-token'] = token;}
return config;
}
Please let me know if I should add anything.
Assuming your registration route handles the request correctly, changing "header" to "headers" in the config you are passing into the axios.post() of your register action should solve it.

The authentication is working properly but whenever I typed the wrong email address, my server is getting crashed

The server is keep getting crashed whenever i typed the wrong email address, i understood the problem, but can anyone tell me how to solve this.
Problem:Here the authentication is done for password only, if the password is wrong it is giving me the right error which is "Incorrect email or address", but not give this one when i try with wrong email address.
so i need the authentication for the email address also from my understanding this much i summarized.
Logins.js(API)
var oracledb = require('oracledb');
var bcrypt = require('bcrypt');
var jwt = require('jsonwebtoken');
var config = require(__dirname + '../../config.js');
import { Redirect } from 'react-router'
// var redirect = require("express-redirect");
// var express = require("express");
//var passport = require('passport');
//var LocalStrategy = require('passport-local').Strategy;
//var history = require('history');
//import post from './users';
//var cors = require('cors');
// var history = require('browser-history');
// var app = express();
// redirect(app);
// const targetBaseUrl = '/Signup';
function post(req, res, next) {
console.log('oye')
oracledb.getConnection(
config.database,
function(err, connection){
if (err) {
console.log('haha')
return next(err);
// console.log(err);
}
console.log('fuha')
connection.execute(
'select id as "id", ' +
' email as "email", ' +
' password as "password", ' +
' role as "role" ' +
'from jsao_users ' +
'where email = :email',
{
email: req.body.email.toLowerCase()
},
{
outFormat: oracledb.OBJECT
},
function(err, results){
var user;
console.log('huo')
console.log(err)
//console.log(results)
console.log(results.rows[0])
``````````````````````````````````````````````````````````````````````
if (results.rows[0] === undefined) {
console.log('hiiiiiii')
return <Redirect to='/Signup' />
// app.redirect(targetBaseUrl);
// history.push("/Main");
}
``````````````````````````````````````````````````````````````````
// else {connection.release(function(err) {
// console.log('hy')
// if (err) {
// console.log('joker')
// console.error(err.message);
// }
// });
// return next(err);
// // console.log(err);
// }
user = results.rows[0];
//debugger;
console.log(user)
bcrypt.compare(req.body.password,user.password, function(err, pwMatch) {
var payload;
if (err) {
console.log('wrong');
return next(err);
}
/*if (result == true) {
//res.redirect('http://localhost:3000/Main');
//res.end();
}
else {
res.send('Incorrect password');
//res.redirect('/Signin');
//res.end();
}
/*if(req.body.password != user.password){
res.json({success: false, message: 'passwords do not match'});
}*/
/*if(req.body.password == user.password) {
this.props.history.push("/Main");
}*/
if(pwMatch) {
//this.props.history.push("/Main");
console.log("password matched");
}
else {
res.status(401).send({message: 'Invalid email or password.'});
return;
}
payload = {
sub: user.email,
role: user.role
};
res.status(200).json({
user: user,
token: jwt.sign(payload, config.jwtSecretKey, {expiresIn: "60m" }),
});
});
//res.status(404).end();
connection.release(function(err) {
if (err) {
console.error(err.message);
}
});
});
}
);
}
module.exports.post = post;
Signin.js (Front-end)
import React, { Component } from "react";
import { Button, FormGroup, FormControl, ControlLabel } from "react-bootstrap";
import axios from 'axios';
import "./Signin.css";
class Signin extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: ""
};
}
validateForm() {
return this.state.email.length > 0 && this.state.password.length > 0;
}
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
}
```````````````````````````````````````````````````````````````
handleSubmit = event => {
event.preventDefault();
const user = {
email: this.state.email,
password : this.state.password
};
// API CALL
axios.post(`http://localhost:4000/api/logins`, user)
.then(res => {
console.log(res);
console.log(res.data);
//console.log("successful");
})
//this.props.history.push("/Main");
}
`````````````````````````````````````````````````````````````````````
render() {
return (
<div className="Login">
<form onSubmit={this.handleSubmit}>
<FormGroup controlId="email" bsSize="large">
<ControlLabel>Email</ControlLabel>
<FormControl
autoFocus
type="email"
value={this.state.email}
onChange={this.handleChange}
/>
</FormGroup>
<FormGroup controlId="password" bsSize="large">
<ControlLabel>Password</ControlLabel>
<FormControl
value={this.state.password}
onChange={this.handleChange}
type="password"
/>
</FormGroup>
<Button
block
bsSize="large"
disabled={!this.validateForm()}
type="submit"
>
Login
</Button>
</form>
</div>
);
}
}
export default Signin;
The expected result for the wrong email address is "Invalid email or password"
But instead getting this error:
C:\Users\anura\Desktop\reactApp\eclaims\src\Backend\routes\logins.js:49
bcrypt.compare(req.body.password,user.password, function(err, pwMatch) {
^
TypeError: Cannot read property 'password' of undefined
at C:\Users\anura\Desktop\reactApp\eclaims\src\Backend\routes\logins.js:49:59
at fetchRowsCb (C:\Users\anura\Desktop\reactApp\eclaims\src\Backend\node_modules\oracledb\lib\connection.js:109:7)
[nodemon] app crashed - waiting for file changes before starting...
The app crashed because you didn't throw exception and return immediately when getting user not found err, because the email is invalid, user variable is null, you cannot read property password of null or undefined
if (err) {
connection.release(function(err) {
if (err) {
console.error(err.message);
}
});
// MUST RETURN HERE !!!
//return next(err);
console.log(err);
}
user = results.rows[0];
// user IS NULL HERE, CANNOT READ PROPERTY OF NULL OR UNDERFINED
//debugger;
bcrypt.compare(req.body.password,user.password, function(err, pwMatch) {
In your callback check for empty values when no entry in db found.
function(err, results){
var user;
...
// put check for empty value if no entries found
if (results.length === 0) {
res.status(401).send({message: 'Invalid email or password.'});
} else {
// rest of your code
user = results.rows[0];
//debugger;
bcrypt.compare(req.body.password,user.password, function(err, pwMatch) {
var payload;
}
...
}
}

How can redirct a user to specific url based on his role in this react-redux code

I have node.js backend that has a login/signup and couple of urls that are accessed by their respective role. For example I have tested this url http://localhost:5000/api/deleteuser:user_id and this url is only accessed by a user that has role "ADMIN" and other routes with the same access control
in my react-redux application I managed to create login/register that uses jwt however after the user login with his username and password the system only direct him to the dashboard. i want to check the user role when the user attempt to login so that if he was admin then the system directs him to the admin page or if he is a teacher also to the teacher's page and so on.
at the moment i am struggling to figure how can I solve this problem.
i tried to used CASL for react but i just could not understand it so can you help me with this please
thanks in advance
I have tried to use CASL https://www.npmjs.com/package/#casl/react but I just could not understand it.
export const userSignin = (userData, history) => {
return dispatch => {
axios.post('/api/signin', userData)
.then(res => {
//success message
toastr.success('Welcome')
//redirect to dashboard
//save token to location storage
const { token } = res.data;
localStorage.setItem('jwtToken', token);
//set token to auth header
setAuthToken(token);
//decode token
const jwtDecoded = jwtDecode(token);
if(res.data.role === 'admin'){
history.push('/admin');
}else{
history.push('/dashboard');
}
//set current user
dispatch(setCurrentUser(jwtDecoded));
})
.catch(error => dispatch({
type: GET_ERRORS,
payload: error.response.data
}))
}
}
class Signin extends React.Component {
state = {
username: '',
password: '',
usernameError: '',
passwordError: '',
errors: {}
}
handleUsername = (e) => {
this.setState({ username: e.target.value }, () => { this.validateUsername() });
}
handlePassword = (e) => {
this.setState({ password: e.target.value }, () => { this.validatePassword() });
}
validateUsername = () => {
const { username } = this.state;
let usernameError;
if (username === '') {
usernameError = 'Username is required';
}
this.setState({ usernameError });
return !usernameError;
}
validatePassword = () => {
const { password } = this.state;
let passwordError;
if (password === '') {
passwordError = 'Password is required';
}
this.setState({ passwordError });
return !passwordError;
}
handleSubmit = (e) => {
e.preventDefault();
const validUsername = this.validateUsername();
const validPassword = this.validatePassword();
if (validUsername && validPassword) {
const userData = {
username: this.state.username,
password: this.state.password
}
this.props.userSignin(userData, this.props.history);
}
}
componentDidMount() {
if (this.props.auth.isAuthenticated) {
// const role = this.props.role;
// if (role === "Admin") {
// this.props.history.push('/admin');
// } else {
// this.props.history.push('/dashboard');
// }
this.props.history.push('/dashboard');
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.auth.isAuthenticated === true) {
this.props.history.push('/dashboard');
}
if (nextProps.errors) {
this.setState({ errors: nextProps.errors })
}
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-sm-4 col-sm-offset-4">
{
this.state.errors.success === false ? <p className="text-danger text-center">{this.state.errors.message}</p> : null
}
</div>
<div className="col-sm-4 col-sm-offset-4">
<h3 className='text-center'>Login</h3>
<form onSubmit={this.handleSubmit}>
<div className={classnames('form-group', { 'has-error': this.state.usernameError })}>
<input
type="text"
className="form-control"
value={this.state.username}
onChange={this.handleUsername}
placeholder="Username"
/>
<span className="help-block">{this.state.usernameError}</span>
</div>
<div className={classnames('form-group', { 'has-error': this.state.passwordError })}>
<input
type="password"
className="form-control"
value={this.state.password}
onChange={this.handlePassword}
placeholder="Password"
/>
<span className="help-block">{this.state.passwordError}</span>
</div>
<button className="btn btn-success btn-sm">Login</button>
</form>
</div>
</div>
</div>
);
}
}
Signin.propTypes = {
auth: PropTypes.object.isRequired,
userSignin: PropTypes.func.isRequired
}
const mapStateToProps = (state) => {
return {
auth: state.auth,
errors: state.errors
}
}
export default connect(mapStateToProps, { userSignin })(withRouter(Signin));
exports.signin = (req, res) => {
User.findOne({ username: req.body.username }, function (err, user) {
if (err) throw err;
if (!user) {
res.status(401).json({ success: false, message: 'Auth failed,User not found' });
} else if (user) {
var validPassword = user.comparePassword(req.body.password);
if (!validPassword) {
res.status(401).json({ success: false, message: 'Auth failed,wrong password' });
} else {
var token = jwt.sign({
id: user._id,
username: user.username,
email: user.email,
password: user.password,
profileImage: user.profileImage,
created_at: user.created_at
}, config.secret, { expiresIn: '1h' });
res.status(200).json({ success: true, message: 'Authenticated', token: 'Bearer ' + token });
}
}
});
}
at the moment this only direct the user to dashboard, i think i am missing something here
In the last line of exports.signin you need to include the role in the object you're sending back. for example you're sending this:
res.status(200).json({ success: true, message: 'Authenticated', token: 'Bearer ' + token })
but it needs to be something like this:
res.status(200).json({ success: true, message: 'Authenticated', role: 'admin', token: 'Bearer ' + token })
Then in React, make sure you're accessing the correct element in that if statement to push to the proper route.

Resources