I have a Sign Up modal in my React Bootstrap App to allow registration for new users. I set an onChange event for each attributes to be stored in the database and user should be saved to database if the button Sign Up is clicked, triggering the onClick button. The problem is, the user won't be saved to Mongodb at all. I'm certain the problem is within the SignUpModal code since I did try passing it via node.js on index.js and it worked. The codes are below:
SignUpModal.js (client side)
const [userEmail, setEmail] = useState("");
const [userPassword, setPassword] = useState("");
const [userFullName, setFullName] = useState("");
const [userType, setType] = useState("");
//add user to database
const addUser = () => {
Axios.post("/addUser", {
userEmail: userEmail,
userPassword: userPassword,
userFullName: userFullName,
userType: userType,
});
};
return(
<Modal
{...props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Sign Up Form
</Modal.Title>
</Modal.Header>
<Form>
<Modal.Body>
<Form.Group className="mb-3" controlId="userEmail">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" placeholder="Enter your email here"
onChange = {(event) => {
setEmail(event.target.value);
}}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="userPassword">
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Enter your password here"
onChange = {(event) => {
setPassword(event.target.value);
}}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="userFullName">
<Form.Label>Full Name</Form.Label>
<Form.Control type="text" placeholder="Enter full name here"
onChange = {(event) => {
setFullName(event.target.value);
}}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formType">
<Form.Label>I am a... (Tick one of the options below):</Form.Label>
{['radio'].map((type) => (
<div key={`inline-${type}`} className="mb-3">
<Form.Check
inline
label="Client"
name="group1"
type={type}
id={`inline-${type}-1`}
onChange = {(event) => {
setType(event.target.value);
}}
/>
<Form.Check
inline
label="Service provider"
name="group1"
type={type}
id={`inline-${type}-2`}
onChange = {(event) => {
setType(event.target.value);
}}
/>
</div>
))}
</Form.Group>
</Modal.Body>
<Modal.Footer>
<Button onClick={props.onHide}>Close</Button>
<Button variant="primary" type="submit" onClick= {addUser}>
Sign Up!
</Button>
</Modal.Footer>
</Form>
</Modal>
)
}
index.js (server side)
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const UserModel = require("./models/User");
const cors = require("cors");
app.use(express.json());
app.use(cors());
mongoose.connect("mongodb+srv://tryweb:password1234#cluster5.c58gv.mongodb.net/user?retryWrites=true&w=majority",
{
useNewUrlParser: true,
});
app.post("/addUser", async(req, res) => {
const user = new UserModel(
{ userEmail: req.body.userEmail,
userPassword: req.body.userPassword,
userFullName: req.body.userFullName,
userType: req.body.userType
}
);
try{
await user.save();
}
catch(err){
console.log(err);
}
});
app.listen(3000, () => {
console.log("Server running in port 3000...");
});
I have tried changing the URL to http://localhost:3000/addUser and it still does not work. Anyone knows what I am doing wrong?
This looks good, but you might be hitting an error with the data or within the browser. Try logging the data as it comes into the request with console.log(req.body).
Try this:
Assuming that your ./models/User looks something like this:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
let User = new Schema(
{
userEmail: {
type: String
},
userPassword: {
type: String
},
userFullName: {
type: String
},
userType: {
type: String
}
},
{ collection: "Users" }
);
module.exports = mongoose.model("User", User);
And the code:
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const UserModel = require("./models/User");
const cors = require("cors");
app.use(express.json());
app.use(cors());
const mongooseConnectionString = "mongodb+srv://tryweb:password1234#cluster5.c58gv.mongodb.net/user?retryWrites=true&w=majority";
const mongooseConnection = mongoose.connect(mongooseConnectionString,
{
useNewUrlParser: true,
});
// Let us know we established connection
mongooseConnection.once("open", function() {
console.log("MongoDB database connection established successfully");
});
app.post("/addUser", async(req, res) => {
const user = new UserModel(req.body);
try{
await user.save();
response.send(user);
}
catch(err){
console.log(err);
response.status(500).send(error);
}
});
app.listen(3000, () => {
console.log("Server running in port 3000...");
});
Related
I want to make a login page. But the problem is that even though the data I entered is wrong, it redirects to the page. how can i fix this?
I only have email and password information in my table
const client = require('../../db')
const express = require('express');
const app = express();
const cors = require("cors");
app.use(cors());
app.use(express.json()); //req.body
app.listen(2121, ()=>{
console.log("Sever is now listening at port 5000");
})
client.connect();
app.post("/login", async (req, res) => {
try {
const { email, password } = req.body;
const user = await client.query(
`SELECT * FROM users WHERE email=$1 AND password=$2`,
[email, password]
);
if (user.rows.length === 0) {
res.send("Kullanıcı adı veya şifre yanlış");
} else {
res.send("Kullanıcı adı veya şifre doğru");// Eşleşen kullanıcı bilgileri varsa diğer sayfaya yönlendir
}
} catch (err) {
console.error(err.message);
}
});
this is my database code.when i run my database query in postman it works correctly
import React, { useState } from 'react'
import Navbar from '../../common/Navbar/Navbar';
const User = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [user, setUser] = useState([]);
const [error, setError] = useState('');
const onSubmitForm = async e => {
e.preventDefault();
try {
const response = await fetch(`http://localhost:2120/login`,{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
if (response.ok) {
window.location.replace(`/AdminPage.js`);
} else {
setError('Invalid email or password');
}
} catch (err) {
console.error(error);
setError('An error occurred. Please try again later.');
}
};
return (
<>
<Navbar/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.4.1/dist/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"></link>
<div className="container text-center">
<h1 className="my-5">Search for the Dormitory You Want</h1>
<form className="d-flex" onSubmit={onSubmitForm}>
<input
type="text"
name="name"
placeholder="Enter email ..."
className="form-control"
value={email}
onChange={e => setEmail(e.target.value)}
/>
<input
type="text"
name="name"
placeholder="Enter password ..."
className="form-control"
value={password}
onChange={e => setPassword(e.target.value)}
/>
<button className="btn btn-success">Submit</button>
</form>
</div>
</>
)
}
export default User
this is my login page code.
The issue is related backend side since when you are sending the wrong login and password, you are still responding as a 200 ok. By default the HTTP status code sent in a response from an Express application is 200 (OK). Instead of that, you can just throw an error message with 404 status. In addition, if there is another issue that is not related correction of credentials you may to response 500 status code as an internal error. I have added inside catch.
app.post("/login", async (req, res) => {
try {
const { email, password } = req.body;
const user = await client.query(
`SELECT * FROM users WHERE email=$1 AND password=$2`,
[email, password]
);
if (user.rows.length === 0) {
res.status(404).send("Kullanıcı adı veya şifre yanlış");
} else {
res.send("Kullanıcı adı veya şifre doğru");// Eşleşen kullanıcı bilgileri varsa diğer sayfaya yönlendir
}
} catch (err) {
response
.status(500)
.json({ message: "Error in invocation of API: /login" })
}
});
I am devloping a webapp with nodejs and reactjs with redux. I am trying to make a request to register a new user but i am getting a bad request.
This is the error i am getting:
POST http://localhost:5000/api/users 400 bad request
This is my users route:
const express = require('express');
const config = require('config');
const router = express.Router();
const gravatar = require('gravatar');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { check , validationResult } = require('express-validator/');
const User = require('../../models/User');
//#route POST api/users
//#desc Register user
//#access public
router.post('/', [
check('name', 'Name is required')
.not()
.isEmpty(),
check('email', 'Plese include a valid email').isEmail(),
check('password', 'Please enter a password with 6 or more characters').isLength({min:6})
],
async (req, res)=> {
const errors = validationResult(req);
if(!errors.isEmpty()){
return res.status(400).json({ errors:errors.array()}); //400 is for bad requests
}
const { name, email, password } = req.body;
try{
//See if user exists
let user = await User.findOne({ email });
if(user){
return res.status(400).json({ errors: [{ msg:'User already exists' }] });
}
//Get users gravatar
const avatar = gravatar.url(email,{
s:'200',
r:'pg',
d:'mm'
})
user = new User({
name,
email,
avatar,
password
});
//Encrypt password
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
//Return jsonwebtoken -> this for users to be logged in right after registration
const payload = {
user:{
id: user.id
}
}
jwt.sign(
payload,
config.get('jwtSecret'),
{expiresIn: 360000}, //change to 3600 for production
(err, token)=>{
if(err) throw err;
res.json({ token });
}
)
}catch(err){
console.error('err.message');
res.status(500).send('Server Error');
}
});
module.exports = router;
The route is not the problem i think because if i register manually a user via postman it works.
This is my register.js component:
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { Link, Navigate } from 'react-router-dom';
import { setAlert } from '../../actions/alert';
import { register } from '../../actions/auth';
import PropTypes from 'prop-types';
const Register = ({ setAlert, register }) => {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
password2: ''
});
const { name, email, password, password2 } = formData;
const onChange = (e) =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = async (e) => {
e.preventDefault();
if (password !== password2) {
setAlert('Passwords do not match', 'danger');
} else {
register({ name, email, password });
console.log('SUCCESS')
}
};
return (
<section className="container">
<h1 className="large text-primary">Sign Up</h1>
<p className="lead">
<i className="fas fa-user" /> Create Your Account
</p>
<form className="form" onSubmit={onSubmit}>
<div className="form-group">
<input
type="text"
placeholder="Name"
name="name"
value={name}
onChange={onChange}
/>
</div>
<div className="form-group">
<input
type="email"
placeholder="Email Address"
name="email"
value={email}
onChange={onChange}
/>
<small className="form-text">
This site uses Gravatar so if you want a profile image, use a
Gravatar email
</small>
</div>
<div className="form-group">
<input
type="password"
placeholder="Password"
name="password"
value={password}
onChange={onChange}
/>
</div>
<div className="form-group">
<input
type="password"
placeholder="Confirm Password"
name="password2"
value={password2}
onChange={onChange}
/>
</div>
<input type="submit" className="btn btn-primary" value="Register" />
</form>
<p className="my-1">
Already have an account? <Link to="/login">Sign In</Link>
</p>
</section>
);
};
Register.propTypes = {
setAlert: PropTypes.func.isRequired,
register: PropTypes.func.isRequired
};
export default connect( null, { setAlert , register })(Register);
and this is one of my actions auth.js where i request my api
import axios from "axios";
import { setAlert } from './alert'
import {
REGISTER_SUCCESS,
REGISTER_FAIL
} from './types'
//Register user
export const register = ( { name, email, password } ) => async dispatch => {
const config = {
headers: {
'Content-type': 'application/json'
}
}
const body = JSON.stringify({ name , email, password });
try {
const res = await axios.post('http://localhost:5000/api/users', body, config);
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
});
} catch (error) {
const errors = error.response.data.errors;
if(errors){
errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
}
dispatch({
type:REGISTER_FAIL
});
}
}
I am pretty sure this might be an axios error on how i am trying to perform a request or a redux mistake.
My app works fine, if i don´t enter or enter invalid data to my registration form all my validation alerts show up. The issue is when i submit the form and try to send the data to register the new user.
I am trying to store data from an option, but I'm not sure where I went wrong in the schema or the react code. Is there another I could perhaps do it?
When I run it I get this error.
POST http://localhost:8080/api/user 500 (Internal Server Error)
Here is my model
model.js
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');
const joi = require('joi');
const { optional } = require('joi');
const userSchema = new mongoose.Schema({
firstName:{type: String, required: true},
lastName:{type: String, required: true},
email:{type: String, required: true},
password:{type: String, required: true},
status:{type: String, enum: ['active', 'inactive'],required : true },
});
userSchema.methods.generateAuthToken = function(){
const token = jwt.sign({_id:this._id}, process.env.JWTPRIVATEKEY)
return token
}
const User = mongoose.model("user", userSchema);
const validate = (data) => {
const schema = joi.object({
firstName:joi.string().required().label("First Name"),
lastName:joi.string().required().label("Last Name"),
email: joi.string().email().required().label("Email"),
password: joi.string().required().label("password"),
status:joi.string().enum['active', 'inactive'].required().label(" ")
});
return schema.validate(data)
}
module.exports = {User, validate}
When I run it I get "error creating user"
routes user.js
const router =require("express").Router();
const {User, validate} = require('../models/user')
const bcrypt = require("bcrypt");
router.post("/", async(req, res) => {
try{
const {error} = validate(req.body)
if(error)
return res.status(400).send({message: error.details[0].message})
const user = await User.findOne({ email:req.body.email})
if (user)
return res.status(409).send({message: "duplicate email"})
const salt = await bcrypt.genSalt(Number(process.env.SALT))
const hashPassword = await bcrypt.hash(req.body.password, salt);
await new User({...req.body, password: hashPassword}).save();
res.status(201).send({message: "User created succesfully"})
}catch(error){
console.log(error.details)
res.status(500).send({message: "Error creating user"})
}
})
module.exports = router;
here are my react.js files, I believe my error should lie here but I maybe be mistaken.
index.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { Link, useNavigate } from "react-router-dom";
import styles from "./styles.module.css";
const Signup = () => {
const [data, setData] = useState({
firstName: "",
lastName: "",
email: "",
password: "",
status: "",
});
const [error, setError] = useState("");
const navigate = useNavigate();
const handleChange = ({ currentTarget: input }) => {
setData({ ...data, [input.name]: input.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
try {
const url = "http://localhost:8080/api/user";
const { data: res } = await axios.post(url, data);
navigate("/login");
console.log(res.message);
} catch (error) {
if (
error.response &&
error.response.status >= 400 &&
error.response.status <= 500
) {
setError(error.response.data.message);
}
}
};
return (
<div className={styles.signup_container}>
<div className={styles.signup_form_container}>
<div className={styles.left}>
<h1>Welcome Back</h1>
<Link to="/login">
<button type="button" className={styles.white_btn}>
Sign in
</button>
</Link>
</div>
<div className={styles.right}>
<form className={styles.form_container} onSubmit={handleSubmit}>
<h1>Create Account</h1>
<input
type="text"
placeholder="First Name"
name="firstName"
onChange={handleChange}
value={data.firstName}
required
className={styles.input}
/>
<input
type="text"
placeholder="Last Name"
name="lastName"
onChange={handleChange}
value={data.lastName}
required
className={styles.input}
/>
<input
type="email"
placeholder="Email"
name="email"
onChange={handleChange}
value={data.email}
required
className={styles.input}
/>
<input
type="password"
placeholder="Password"
name="password"
onChange={handleChange}
value={data.password}
required
className={styles.input}
/>
<select name ="status">
<option value="1">active</option>
<option value="2">inactive</option>
</select>
{error && <div className={styles.error_msg}>{error}</div>}
<button type="submit" className={styles.green_btn}>
Sign Up
</button>
</form>
</div>
</div>
</div>
);
};
export default Signup;
Hi, I'm new to this react and koa. Is this code correct? I'm trying to create react and koa projects from scratch. I have a react project. I would like to create a downloadable windows exe. I can do it with a node server using Zeit pkg but I don't know how to do that (or something similar) with react.
I have tried Zeit pkg. Not seeing many other options.
Backend
server.js
require('dotenv').config();
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const cors = require('#koa/cors');
const { dbConnect } = require('./utills/dbConnect.js');
const app = new Koa();
app.use(cors());
app.use(bodyParser());
//routers
const userRouter = require('./routes/user.router.js');
app.use(userRouter.routes())
.use(userRouter.allowedMethods());
const vehicleRouter = require('./routes/vehicle.router.js');
app.use(vehicleRouter.routes())
.use(userRouter.allowedMethods());
app.listen(8080, () => {
dbConnect();
console.log("Application running on port 8080");
});
//Installed packages
// #koa/cors
// #koa/router
// dotenv
// jsonwebtoken
// koa
// koa-bodyparser
// mongoose
// nodemon
model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
id: {type:String, required:true},
name: {type:String, required:true},
email: {type:String, required:true},
password:{type:String, required:true}
});
const User = mongoose.model("User", userSchema);
module.exports = User;
Controller
const jwt = require('jsonwebtoken');
const User = require("../models/user.model");
const getAllUsers = async (ctx)=>{
await User.find().then((users)=>{
ctx.body = users;
}).catch((err)=>{
console.log(err);
})
}
const addUser = async (ctx)=>{
const {id, name, email, password} = ctx.request.body;
const newUser = new User({id, name, email, password});
const user = await User.create(newUser);
if(user){
ctx.body = user;
ctx.set('Content-Type', 'application.json');
ctx.status = 201;
} else {
ctx.body = {status:"error occured"}
ctx.set('Content-Type', 'application.json');
}
}
const updateUser = async (ctx)=>{
const uid = ctx.params.id;
const {id, name, email, password} = ctx.request.body;
const updateUser = {id, name, email, password}
await User.findByIdAndUpdate(uid, updateUser).then(()=>{
ctx.body = {status:"User Updated"};
}).catch((err)=>{
console.log(err);
ctx.body = {status:"Error occured"}
})
}
const deleteUser = async (ctx)=>{
const uid = ctx.params.id;
await User.findByIdAndDelete(uid).then(()=>{
ctx.body = {status:"User Deleted"};
}).catch((err)=>{
console.log(err);
ctx.body = {status:"Error occured"}
})
}
const login = async (ctx)=>{
const {email, password} = ctx.request.body;
const user = await User.findOne({email});
console.log(user)
if(user && (password == user.password)){
const token = jwt.sign(
{
_id: user._id,
name: user.name,
email: user.email,
password: user.password
},
'SecretKey123'
)
return ctx.body = {token:token}
} else {
return ctx.body = {status:'Login Failed'}
}
}
const auth = async (req, res)=>{
const token = req.headers['x-access-token']
try {
const decoded = jwt.verify(token, 'secret123')
const _id = decoded._id
const user = await User.findById(_id);
return res.json({ status: 'ok', name: user.name, role: user.role, id: user._id, subRole: user.subRole, uid:user.id, user:user })
} catch (error) {
console.log(error)
res.json({ status: 'error', error: 'invalid token' })
}
}
module.exports = {addUser, updateUser, deleteUser, getAllUsers, login, auth}
Router
const Router = require('#koa/router');
const { addUser, getAllUsers, updateUser, deleteUser, login, auth } = require('../controller/user.controller');
const userRouter = new Router({
prefix: '/users'
});
userRouter.get('/',getAllUsers);
userRouter.post('/add',addUser);
userRouter.put('/update/:id', updateUser);
userRouter.delete('/delete', deleteUser);
userRouter.post('/login', login);
userRouter.post('auth', auth)
module.exports = userRouter;
DB Connect
const mongoose = require('mongoose');
const dbConnect = () => {
const dbConStr = process.env.MONGODB_URL;
mongoose.connect(dbConStr, (connection)=>{
console.log("MongoDB Connection Success");
})
}
module.exports = {dbConnect}
Frontend
App.js
import logo from './logo.svg';
import './App.css';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import {BrowserRouter as Router, Routes, Route} from 'react-router-dom'
import HeaderComponent from './components/HeaderComponent';
import Register from './pages/Register';
import Users from './pages/Users';
import Login from './pages/Login';
function App() {
return (
div className='container'>
HeaderComponent/>
Router>
Routes>
Route exact path="/" element={Users/>}/>
Route exact path="/register" element={Register/>}/>
Route exact path="/login" element={Login/>}/>
/Routes>
/Router>
/div>
);
}
export default App;
Login.jsx
import axios from "axios";
import React,{useEffect, useState} from "react";
function Login() {
//User Details
const[email, setEmail] = useState('');
const[password, setPassword] = useState('');
function loginUserHandler(e) {
e.preventDefault();
const user = { email, password }
axios.post('http://localhost:8080/users/login', user).then((res)=>{
if(res.data.token){
sessionStorage.setItem("isLogged", true);
window.location="/";
} else {
window.location.reload(false)
alert("login failed")
}
}).catch((err)=>{
console.log(err);
})
}
return (
div>
h2 className="text-center mt-3">Login/h2>
div>
form style={{width:"50%", margin:"auto"}}>
div className="form-group">
label>Email : /label>
input type="email" className="form-control" onChange={(e)=>setEmail(e.target.value)} />
/div>
div className="form-group">
label>Password : /label>
input type="password" className="form-control" onChange={(e)=>setPassword(e.target.value)} />
/div>
div className="text-center mt-2">
button className="btn btn-primary" onClick={loginUserHandler}>Login/button>
/div>
/form>
/div>
/div>
);
}
export default Login;
Register.jsx
import axios from "axios";
import React,{useEffect, useState} from "react";
function Register() {
//User Details
const[name, setName] = useState('');
const[email, setEmail] = useState('');
const[id, setId] = useState('');
const[password, setPassword] = useState('');
function registerUserHandler(e) {
e.preventDefault();
const user = {name, email, password, id}
axios.post('http://localhost:8080/users/add', user).then(()=>{
alert('User added');
}).catch((err)=>{
console.log(err);
})
}
return (
div>
h2 className="text-center mt-3">Register/h2>
div>
form style={{width:"50%", margin:"auto"}}>
div className="form-group">
label>Name : /label>
input type="text" className="form-control" onChange={(e)=>setName(e.target.value)} />
/div>
div className="form-group">
label>Email : /label>
input type="email" className="form-control" onChange={(e)=>setEmail(e.target.value)} />
/div>
div className="form-group">
label>ID : /label>
input type="text" className="form-control" onChange={(e)=>setId(e.target.value)} />
/div>
div className="form-group">
label>Password : /label>
input type="password" className="form-control" onChange={(e)=>setPassword(e.target.value)} />
/div>
div className="text-center mt-2">
button className="btn btn-primary" onClick={registerUserHandler}>Register/button>
/div>
/form>
/div>
/div>
);
}
export default Register;
I am making a MERN application with register and login functionality. When i try to submit the form in the browser the console shows me a 400 bad request. The functionality works on the backend and returns a 200 ok status but not on the front-end.
this is a picture of the error in the browser.
here is my code below
validation
const Validator = require("validator");
const isEmpty = require("is-empty");
module.exports = function validateRegisterInput(data) {
let errors = {};
data.name = !isEmpty(data.name) ? data.name : "";
data.email = !isEmpty(data.email) ? data.email: "";
data.password = !isEmpty(data.password) ? data.password: "";
data.password2 = !isEmpty(data.password2) ? data.password2: "";
if(Validator.isEmpty(data.name)) {
errors.name = "Name field is Required";
}
if(Validator.isEmpty(data.email)) {
errors.email = "Email field is Required";
} else if(!Validator.isEmail(data.email)) {
errors.email = "Email is invalid"
}
if (Validator.isEmpty(data.password)) {
errors.password = "Password field is required";
}
if (Validator.isEmpty(data.password2)) {
errors.password2 = "Confirm password field is required";
}
if(!Validator.isLength(data.password, {min: 6, max: 30})){
errors: password = "Password must be at least 6 characters";
}
if(!Validator.equals(data.password, data.password2)){
errors.password2 = "Password must match"
}
return {
errors,
isValid: isEmpty(errors)
};
};
controller
const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const jwt = require ("jsonwebtoken");
const keys = require("../../config/key");
const validateRegisterInput = require("../../validation/register");
const validateLoginInput = require("../../validation/login");
const User = require("../../models/User");
router.post("/register", (req, res) => {
//FORM VALIDATION
const {errors, isValid } = validateRegisterInput(req.body)
//CHECK VALIDATION
if(!isValid) {
return res.status(400).json(errors)
}
User.findOne({ email: req.body.email }).then( returnedUser => {
if(returnedUser) {
return res.status(400).json({email: "Email already exists"});
}
});
// saving user with request information to database
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password,
});
bcrypt.genSalt(10, (err, salt)=>{
bcrypt.hash(newUser.password, salt, (err, hash)=>{
if(err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => res.json(user))
.catch(err => console.log(err));
});
});
});
router.post("/login", (req, res)=>{
const {errors, isValid} = validateLoginInput(req.body)
if(!isValid){
return res.status(400).json(errors)
}
const email = req.body.email;
const password = req.body.password
User.findOne({ email: email }).then(user =>{
if(!user){
return res.status(404).json({ emailNotFound: "Email not found"});
}
bcrypt.compare(password, user.password).then(isMatch => {
if(isMatch){
const payload = { id: user.id, name: user.name };
jwt.sign(payload,
keys.secretOrKey,
{expiresIn: 31556926},
(err, token) => {
res.json({ success: true, token: "Bearer " + token });
});
} else {
return res.status(400)
.json({passwordincorrect: "password incorrect"})
}
})
})
});
module.exports = router;
Action
import axios from "axios";
import setAuthToken from "../utils/setAuthToken";
import jwt_decode from "jwt-decode";
import {
GET_ERRORS,
SET_CURRENT_USER,
USER_LOADING
} from "./types";
// Register User
export const registerUser = (userData, history) => dispatch => {
axios.post("/api/users/register", userData)
.then(res => history.push("/login")) // re-direct to login on successful register
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Login - get user token
export const loginUser = userData => dispatch => {
axios
.post("/api/users/login", userData)
.then(res => {
// Save to localStorage
// Set token to localStorage
const { token } = res.data;
localStorage.setItem("jwtToken", token);
// Set token to Auth header
setAuthToken(token);
// Decode token to get user data
const decoded = jwt_decode(token);
// Set current user
dispatch(setCurrentUser(decoded));
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Set logged in user
export const setCurrentUser = decoded => {
return {
type: SET_CURRENT_USER,
payload: decoded
};
};
// User loading
export const setUserLoading = () => {
return {
type: USER_LOADING
};
};
// Log user out
export const logoutUser = () => dispatch => {
// Remove token from local storage
localStorage.removeItem("jwtToken");
// Remove auth header for future requests
setAuthToken(false);
// Set current user to empty object {} which will set isAuthenticated to false
dispatch(setCurrentUser({}));
};
component
import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { registerUser } from "../../actions/authActions";
import classnames from "classnames";
class Register extends Component {
constructor() {
super();
this.state = {
name: "",
email: "",
password: "",
password2: "",
errors: {},
};
}
componentDidMount() {
// If logged in and user navigates to Register page, should redirect them to dashboard
if (this.props.auth.isAuthenticated) {
this.props.history.push("/dashboard");
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({
errors: nextProps.errors,
});
}
}
onChange = (e) => {
this.setState({ [e.target.id]: e.target.value });
};
onSubmit = (e) => {
e.preventDefault();
const newUser = {
name: this.state.name,
email: this.state.email,
password: this.state.password,
password2: this.state.password2,
};
console.log(newUser);
this.props.registerUser(newUser, this.props.history);
};
render() {
const { errors } = this.state;
return (
<div className="container">
<div className="row">
<div className="col s8 offset-s2">
<Link to="/" className="btn-flat waves-effect">
<i className="material-icons left">keyboard_backspace</i> Back to
home
</Link>
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<h4>
<b>Register</b> below
</h4>
<p className="grey-text text-darken-1">
Already have an account? <Link to="/login">Log in</Link>
</p>
</div>
<form noValidate onSubmit={this.onSubmit}>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.name}
error={errors.name}
id="name"
type="text"
className={classnames("", {
invalid: errors.name
})}
/>
<label htmlFor="name">Name</label>
<span className="red-text">{errors.name}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.email}
error={errors.email}
id="email"
type="email"
className={classnames("", {
invalid: errors.email
})}
/>
<label htmlFor="email">Email</label>
<span className="red-text">{errors.email}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.password}
error={errors.password}
id="password"
type="password"
className={classnames("", {
invalid: errors.password
})}
/>
<label htmlFor="password">Password</label>
<span className="red-text">{errors.password}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.password2}
error={errors.password2}
id="password2"
type="password"
className={classnames("", {
invalid: errors.password2
})}
/>
<label htmlFor="password2">Confirm Password</label>
<span className="red-text">{errors.password2}</span>
</div>
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<button
style={{
width: "150px",
borderRadius: "3px",
letterSpacing: "1.5px",
marginTop: "1rem",
}}
type="submit"
className="btn btn-large waves-effect waves-light hoverable blue accent-3"
>
Sign up
</button>
</div>
</form>
</div>
</div>
</div>
);
}
}
Register.propTypes = {
registerUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
auth: state.auth,
errors: state.errors,
});
export default connect(mapStateToProps, { registerUser })(withRouter(Register));
Here is the root server
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const app = express();
const users = require("./controllers/api/users")
app.use(
bodyParser.urlencoded({
extended: false
})
);
//DATA BASE CONFIGURATION
const dbkeys = require("./config/key").mongoURI;
mongoose.connect(
dbkeys,
{useNewUrlParser: true} )
.then(()=> console.log("database connection successful"))
.catch(err => console.log(err))
app.use(passport.initialize());
require("./config/passport")(passport);
app.use("/api/users", users);
const port = 5000;
app.listen( port, () => console.log("server us up and running on port 5000!"))
Axios sends the data as JSON (application/json). You're currently only using the body parser for urlencoded, which refers to application/x-www-form-urlencoded which is the data format which <form>s use by default.
You need to also use bodyParser.json():
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());