I've been trying to work on a movie app using the MERN stack. After having a few issues regarding the backend of one the features, I went back through my code and realised it doesnt seem that the jwt is being recieved after login. I have no issues with the signup and login other that it seemingly not obtaining the jwt
Heres the authJwt file
const jwt = require("jsonwebtoken");
const config = require("../config/auth.config.js");
const db = require("../models");
const User = db.user;
const Role = db.role;
verifyToken = (req, res, next) => {
let token = req.headers["x-access-token"];
if (!token) {
return res.status(403).send({ message: "No token provided!" });
}
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
return res.status(401).send({ message: "Unauthorized!" });
}
req.userId = decoded.id;
next();
});
};
isAdmin = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
Role.find(
{
_id: { $in: user.roles }
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "admin") {
next();
return;
}
}
res.status(403).send({ message: "Require Admin Role!" });
return;
}
);
});
};
isModerator = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
Role.find(
{
_id: { $in: user.roles }
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "moderator") {
next();
return;
}
}
res.status(403).send({ message: "Require Moderator Role!" });
return;
}
);
});
};
const authJwt = {
verifyToken,
isAdmin,
isModerator
};
module.exports = authJwt;
Heres the user routes file. When I go to http://localhost:8081//api/test/user after logging in, it displays the message "No token provided!"
const { authJwt } = require("../middlewares");
const controller = require("../controllers/user.controller");
module.exports = function(app) {
app.use(function(req, res, next) {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
app.get("/api/test/all", controller.allAccess);
app.get("/api/test/user", [authJwt.verifyToken], controller.userBoard);
app.get(
"/api/test/mod",
[authJwt.verifyToken, authJwt.isModerator],
controller.moderatorBoard
);
app.get(
"/api/test/admin",
[authJwt.verifyToken, authJwt.isAdmin],
controller.adminBoard
);
};
Here's my server.js file
const express = require("express");
const cors = require("cors");
const dbConfig = require("./app/config/db.config");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
const db = require("./app/models");
const Role = db.role;
db.mongoose
.connect(`mongodb+srv://tami00:MEUxClWqUNbLz359#cluster0.gmvao.mongodb.net/test?retryWrites=true&w=majority`, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("Successfully connect to MongoDB.");
initial();
})
.catch(err => {
console.error("Connection error", err);
process.exit();
});
// simple route
app.use('/api/favourite', require('./app/routes/favourite.routes'));
// routes
// require(".app/routes/favourite.routes")(app);
require("./app/routes/auth.routes")(app);
require("./app/routes/user.routes")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
function initial() {
Role.estimatedDocumentCount((err, count) => {
if (!err && count === 0) {
new Role({
name: "user"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'user' to roles collection");
});
new Role({
name: "creator"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'creator' to roles collection");
});
new Role({
name: "watcher"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'watcher' to roles collection");
});
}
});
}
FRONTEND
AuthService
import axios from "axios";
const API_URL = "http://localhost:8080/api/auth/";
class AuthService {
login(username, password) {
return axios
.post(API_URL + "signin", {
username,
password
})
.then(response => {
if (response.data.accessToken) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
});
}
logout() {
localStorage.removeItem("user");
}
register(username, email, password) {
return axios.post(API_URL + "signup", {
username,
email,
password
});
}
getCurrentUser() {
return JSON.parse(localStorage.getItem('user'));;
}
}
export default new AuthService();
Auth Header
export default function authHeader() {
const user = JSON.parse(localStorage.getItem('user'));
if (user && user.accessToken) {
// return { Authorization: 'Bearer ' + user.accessToken }; // for Spring Boot back-end
return { 'x-access-token': user.accessToken }; // for Node.js Express back-end
} else {
return {};
}
}
Login Component
import React, { Component } from "react";
import Form from "react-validation/build/form";
import Input from "react-validation/build/input";
import CheckButton from "react-validation/build/button";
import AuthService from "../services/auth.service";
const required = value => {
if (!value) {
return (
<div className="alert alert-danger" role="alert">
This field is required!
</div>
);
}
};
export default class Login extends Component {
constructor(props) {
super(props);
this.handleLogin = this.handleLogin.bind(this);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangePassword = this.onChangePassword.bind(this);
this.state = {
username: "",
password: "",
loading: false,
message: ""
};
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onChangePassword(e) {
this.setState({
password: e.target.value
});
}
handleLogin(e) {
e.preventDefault();
this.setState({
message: "",
loading: true
});
this.form.validateAll();
if (this.checkBtn.context._errors.length === 0) {
AuthService.login(this.state.username, this.state.password).then(
() => {
this.props.history.push("/profile");
window.location.reload();
},
error => {
const resMessage =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
this.setState({
loading: false,
message: resMessage
});
}
);
} else {
this.setState({
loading: false
});
}
}
render() {
return (
<div className="col-md-12">
<div className="card card-container">
<img
src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"
alt="profile-img"
className="profile-img-card"
/>
<Form
onSubmit={this.handleLogin}
ref={c => {
this.form = c;
}}
>
<div className="form-group">
<label htmlFor="username">Username</label>
<Input
type="text"
className="form-control"
name="username"
value={this.state.username}
onChange={this.onChangeUsername}
validations={[required]}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<Input
type="password"
className="form-control"
name="password"
value={this.state.password}
onChange={this.onChangePassword}
validations={[required]}
/>
</div>
<div className="form-group">
<button
className="btn btn-primary btn-block"
disabled={this.state.loading}
>
{this.state.loading && (
<span className="spinner-border spinner-border-sm"></span>
)}
<span>Login</span>
</button>
</div>
{this.state.message && (
<div className="form-group">
<div className="alert alert-danger" role="alert">
{this.state.message}
</div>
</div>
)}
<CheckButton
style={{ display: "none" }}
ref={c => {
this.checkBtn = c;
}}
/>
</Form>
</div>
</div>
);
}
}
Related
I've created a route called login and another one function(middleware), if the authentication is good, this can be redirected to the delete route but unfortunately, my jwt token is not recognizable.
I want to know why, the problem must be in this part of api :
Api
function parseArticle (req, res, next) {
let token = req.headers['x-access-token'] || req.headers['authorization'];
if (!!token && token.startsWith('Bearer ')) {
token = token.slice(7, token.length);
}
if (token) {
jwt.verify(token, 'RANDOM_TOKEN_SECRET', (err, decoded) => {
if (err) {
return res.status(401).json('token_not_valid');
} else {
req.decoded = decoded;
const expiresIn = 24 * 60 * 60;
const newToken = jwt.sign({
user : decoded.user
},
'RANDOM_TOKEN_SECRET',
{
expiresIn: expiresIn
});
next();
}
});
} else {
return res.status(401).json('token_required');
}
}
router.route('/article/:articleId')
.get(parseArticle, (req, res) => {
db.query("SELECT * FROM articles WHERE id_article = (?)", [req.articleId], function (err,result) { if (err) throw err;
console.log(result);
res.json(result)
})
})
.put(parseArticle, (req, res) => {
const name = req.body.name
const description = req.body.description
const image = req.body.image
const price = parseInt(req.body.price)
req.article.name = name
req.article.description = description
req.article.image = image
req.article.price = price
res.send()
})
.delete(parseArticle, (req, res) => {
db.query("DELETE FROM articles WHERE id_article = (?)", [req.articleId], function (err,result) { if (err) throw err;
console.log(result);})
res.json({message: "Propre"})})
router.post('/login', (req, res) => {
function runQuery(sqlQuery, args){
return new Promise(function (resolve, reject) {
db.query(sqlQuery, args, function(error, results, fields) {
if (error) reject(error);
else resolve(results);
});
});
}
runQuery("SELECT * from users where email = ? ", [req.body.email]).then(user => {
if (user.length === 0) {
return res.status(401).json({ error: 'Utilisateur non trouvé !',
success : 0});
}
bcrypt.compare(req.body.password, user[0].password)
.then(valid => {
if (!valid) {
return res.status(401).json({ error: 'Mot de passe incorrect !',
success : 0});
}
const userId = user[0].id_user;
const token = jwt.sign({ userId: user[0].id_user },
'RANDOM_TOKEN_SECRET',
{ expiresIn: '24h' });
res.header("Authorization","Bearer " + token)
return res.status(200).json({success : 1})
})
.catch(error => res.status(500).json({ error }));
})
.catch(error => res.status(500).json({ error }));
});
Login.vue
<template>
<form #submit.prevent="checkData">
<input type="text" name="email" v-model="login.email" placeholder="Entrez votre adresse-mail"/>
<input type="text" name="password" v-model="login.password" placeholder="Entrez votre mot de passe"/>
<button type="submit"> Connexion </button>
</form>
</template>
<script>
module.exports = {
name: "Login",
data () {
return {
login : {
email: "",
password: "",
},
}
},
methods : {
async checkData() {
let user = {email : this.login.email, password : this.login.password}
try {
const response = await axios.post('/api/login', user)
console.log(response.data.success)
if(response.data.success === 1){
await this.$router.push({name: 'home'})
}
if(response.data.success === 0){
this.error = "Connexion Échouée"
}
}
catch(err) {console.error("network error",err)}
}
}
}
</script>
<style scoped>
button {
padding: 10px;
}
</style>
Thanks for you help,
Have a nice week-end
You return the token to the client in the Authorization header:
res.header("Authorization","Bearer " + token)
This is a non-standard use of this header, it will not automatically be sent back in the next request. At the least, you would need extra code on the client to receive this header and store the token, for example, in the session storage.
It's probably easier to store the token in a session cookie, which will be handled automatically by the client:
res.cookie("token", token, {httpOnly: true})
Also consider the secure option for the cookie. You must also extend your server-side code to find the token in the cookie:
let token = req.headers['x-access-token'] || req.headers['authorization']
|| req.cookies.token;
I'm using mern to set up a social media of sorts. I'm trying to do if a post is favourited then it should be true if not false. However the result for favourited is always false regardless of if the post is in the users likes in the DB.
If the post has been favourited the button is meant to be set to show the word removed, that way the user knows they've favourited it. If its not favourited(false) it should show add. However, if the user favourites a post and likes it then refreshes the page instead of showing remove it shows add and if the user adds it again it then adds the same movie to the DB.
favourite routes
const express = require('express');
const router = express.Router();
const { authJwt } = require("../middlewares");
const Favourite = require("../models/favourite.model");
router.use(function(req, res, next) {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
router.post("/favouriteNumber", [authJwt.verifyToken], (req, res) => {
Favourite.find({"movieId": req.body.movieId})
.exec((err, favourite) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, favouriteNumber: favourite.length})
})
})
router.post("/favourited", [authJwt.verifyToken], (req, res) => {
Favourite.find({"movieId": req.body.movieId, "userFrom": req.body.userFrom})
.exec((err, favourite) => {
if(err) return res.status(400).send(err)
let result = false;
if(favourite.length !== 0) {
result = true
}
res.status(200).json({success: true, favourited: result});
})
})
router.post("/addToFavourite", [authJwt.verifyToken], (req, res) => {
const favourite = new Favourite(req.body)
favourite.save((err, doc) => {
if(err) return res.json({success: false, err})
return res.status(200).json({success: true, doc})
})
})
router.post("/removeFavorite", [authJwt.verifyToken], (req, res) => {
Favourite.findOneAndDelete({movieId: req.body.movieId, userFrom: req.body.userFrom})
.exec((err, doc) => {
if(err) return res.json({success: false, err})
return res.status(200).json({success: true, doc})
})
})
router.post("/getFavourites", [authJwt.verifyToken], (req, res) => {
Favourite.find({ userFrom: req.body.data })
.populate('userFrom')
.exec((err, films) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, films})
})
})
module.exports = router;
favourite component
import Axios from 'axios';
import React, { useEffect, useState } from 'react'
import styled from "styled-components";
import authService from '../../services/auth.service';
import authHeader from '../../services/auth-header';
const FavouriteButton = styled.button`
height: 30px;
width: 40px;
`;
function FavouriteComp(props) {
const currentUser = authService.getCurrentUser();
const [favourited, setFavourited] = useState(false);
const variable = {
userFrom: currentUser.id,
movieId: props.movieInfo?.id,
movieTitle: props.movieInfo?.title,
movieImg: props.movieInfo?.poster_path
}
const onClickFavourite = () => {
//if user already likes the film - remove it
if(favourited) {
Axios.post('http://localhost:8080/api/favourite/removeFavorite', variable, { headers: authHeader() })
.then(response =>{
if(response.data.success){
setFavourited(!favourited)
console.log("Removed from favourites")
}else {
alert('Failed to remove');
}
})
//if not - add to favourites
}else {
Axios.post('http://localhost:8080/api/favourite/addToFavourite', variable, { headers: authHeader() })
.then(response =>{
if(response.data.success){
setFavourited(!favourited)
console.log("Added to favourites")
}else {
alert('Failed to add');
}
})
}
}
useEffect(() => {
Axios.post('http://localhost:8080/api/favourite/favourited', variable, { headers: authHeader() })
.then(response =>{
if(response.data.success){
// setFavourited(response.data.favourited)
// console.log(response.data)
}else {
alert('Failed to get info');
}
})
}, [])
return (
<div>
<FavouriteButton onClick={onClickFavourite}>{!favourited ? "add" : "remove"}</FavouriteButton>
</div>
)
}
export default FavouriteComp
So I am trying to redirect after I am deleting the page, it get's deleted from the database but it doesn't redirect me to my homepage. It worked fine when I was using json-server locally, but when I started using Mongoose it wasn't working properly and wasn't redirecting.
The code inside .then isn't working, I tried console.log inside the .then but it didn't log
I am using mongoose as my database
Here is my entire component:
import { useParams } from "react-router-dom";
import useFetch from "../useFetch";
import { useHistory } from "react-router-dom";
import moment from "moment";
import profile_image from "../images/picture.jpg";
const BlogDetails = () => {
let blogDate = moment().format('D MMM YYYY');
const { id } = useParams();
const { data: blog, isPending, errorMsg } = useFetch("http://localhost:5000/postsdata/" + id);
const history = useHistory()
const handleDelete = () => {
fetch('http://localhost:5000/postsdata/' + blog._id, { method: 'DELETE' })
.then(() => {
history.push('/');
})
.catch((err) => console.log(err))
}
return (
<div className="blog-details">
<div className="top-profile">
<div className="top-profile-picture">
<img src={profile_image} alt="profile-pic-top" />
</div>
<div className="top-profile-name">
<p>Vishwajeet Deshmukh</p>
</div>
</div>
{isPending && <div>Loading...</div>}
{errorMsg && <div>{errorMsg}</div>}
{blog && (
<article className="blog-main-content" >
<div className="main-content-header">
<div className="content-title-date">
<h2 className="blogdetails-title">{blog.title}</h2>
<p className="blogdetails-date">{blogDate}</p>
</div>
<div className="content-image">
<img src={blog.imgsrc} alt="" />
</div>
</div>
<div className="blogdetails-body"><p>{`${blog.postBody}`}</p></div>
<button className="blogdetails-delete" onClick={handleDelete}>Delete Me</button>
</article>
)}
</div>
);
};
export default BlogDetails;
Here is my router.js which handles my delete
const express = require('express');
const router = express.Router();
const { Posts } = require("./models");
//<----------------------------------- CRUD OPERATIONS ------------------------------------------>
router.get("/", () => {
console.log("Server Connected");
})
//<---------------------------- Get Posts from Database ---------------------------->
router.get("/postsdata", (req, res) => {
Posts.find((err, data) => {
if (err) {
res.status(500).send(err);
} else {
res.status(201).send(data);
}
return null;
})
})
//<------------- Get Specific Posts from Database --------------->
router.get("/postsdata/:_id", (req, res) => {
const id = req.params._id;
Posts.findById(id, (err, data) => {
if (err) {
res.status(500).send(err);
throw new Error(err)
} else {
res.status(201).send(data);
}
return data;
})
})
//<---------------------------- Post On the Posts Database ---------------------------->
router.post("/postsdata", (req, res) => {
const db = req.body;
Posts.create(db, err => {
if (!err) {
console.log("Posted on Server");
} else {
throw new Error(err)
}
return null
})
})
//<---------------------------- Delete Posts from Database ---------------------------->
router.delete("/postsdata/:id", (req, res) => {
const id = req.params._id
Posts.deleteOne(id, (err, data) => {
if (err) {
console.log(err);
throw new Error(err)
} else {
console.log(data);
}
return null
})
})
module.exports = router;
after deleting the postdata, send a response from the API.
router.delete("/postsdata/:id", (req, res) => {
const id = req.params._id
Posts.deleteOne(id, (err, data) => {
if (err) {
console.log(err);
throw new Error(err)
} else {
return res.status(200).json({status: 'success'}); // try with this
}
return null
})
})
Hello try it with async/await sayntax
const handleDelete = async () => {
await fetch('http://localhost:5000/postsdata/' + blog._id, { method: 'DELETE' });
history.push('/');
}
y'all, I'm trying to create a signup and login local-Strategy with passport and have been seeing a PROXY ERROR:. I thought I was returning all possible endings for the functions but maybe I'm missing something? I'm new to development and am going crazy haha... Any help is much appreciated, also let me know if I missed adding pertinent code. (I did not add the return block from the react component, I assumed it unnecessary). I am importing my strategies through a strategy index.js (also did not include).
SignupStratagy.js / local strategy
const Strategy = require("passport-local").Strategy;
const User = require("../models/User");
// for password encryption;
const bcrypt = require("bcrypt");
const saltRounds = 10;
const SignupStrategy = new Strategy({ passReqToCallback: true }, function (
req,
username,
password,
done
) {
// console.log(username, password);
const encryptedPass = bcrypt.hashSync(password, saltRounds);
// console.log("encryptedPassword", encryptedPass);
const phone = req.body.phone;
const email = req.body.email;
const street = req.body.street;
const city = req.body.city;
const state = req.body.state;
const zip = req.body.zip;
const isAdmin = req.body.isAdmin;
User.findOne({ username: username }, (err, user) => {
// console.log("SignupStrategy.js / req:", req.body);
if (err) {
return done(err, user);
}
if (user) {
return done("User Name is already taken:", user);
}
})
// .lean()
// .exec();
// console.log("SignupStrategy.js / encrypted password:", encryptedPass);
let newUser = {
username,
password: encryptedPass,
phone,
email,
street,
city,
state,
zip,
isAdmin,
};
User.create(newUser, (error, newUser) => {
if (error) {
return done(error, null);
}
// delete the user password before it is sent back to the front-end;
newUser.password = undefined;
delete newUser.password;
return done(null, newUser);
});
});
module.exports = SignupStrategy;
apiRoute.js / route for signup
const router = require("express").Router();
const db = require("../models");
const passport = require("../config");
// const isAuthenticated = require("../config/middleware/isAuthenticated");
// USER SIGN-UP ROUTE
router.post("/api/signup", function (req, res, next) {
// console.log(req.body);
passport.authenticate("local-signup", (error, user) => {
// console.log("apiRoutes.js / error:", error, "apiRoutes.js / user:", user)
if (error)
return res.status(500).json({
message: error,
});
else {
return res.status(200).json(user);
}
})(req, res, next);
});
Signup / react component
import React, { useState } from "react";
import axios from "axios";
import { Redirect, Link } from "react-router-dom";
import chip from "../../images/chipper/chipperOne.png";
import "./style.css";
function Signup() {
const [signupState, setSignupState] = useState({
username: "",
password: "",
phone: "",
email: "",
street: "",
city: "",
state: "",
zip: "",
key: "",
redirect: false,
adminRedirect: false,
isAdmin: false,
});
const onChange = (e) => {
// console.log("working")
// console.log(typeof e.target.type)
if (e.target.type === "checkbox") {
if (signupState.isAdmin === false) {
setSignupState({
...signupState,
isAdmin: true,
})
} else {
setSignupState({
...signupState,
isAdmin: false,
});
}
} else {
setSignupState({
...signupState,
[e.target.name]: e.target.value,
});
}
};
const onSubmit = async (e) => {
e.preventDefault();
if (signupState.isAdmin === true) {
const response = await axios.post("/api/admin-sign-up", {
key: signupState.key,
});
console.log(response.status);
if (response.status === 500) {
console.log(response);
return;
}
if (response.status === 200) {
console.log(response.status);
setSignupState({
...signupState,
adminRedirect: true,
});
}
}
// console.log(`onSubmit ${signupState}`);
axios.post("/api/signup", {
username: signupState.username,
password: signupState.password,
phone: signupState.phone,
email: signupState.email,
street: signupState.street,
city: signupState.city,
state: signupState.state,
zip: signupState.zip,
isAdmin: signupState.isAdmin,
})
.then((res) => {
console.log(res);
if (res.data) {
console.log(`Sign-in Successful`);
setSignupState({
...signupState,
redirect: true,
});
}
})
.catch((err) => {
if (err) console.log(`Sign-Up server error ${err}`);
});
};
ERROR:
Proxy error: Could not proxy request /api/signup from localhost:3000 to http://localhost:3001.
[1] See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
Im currently trying to send a message from my server side and display it in my react front end.
I have tried everything to display the message I use with res.send() but the react fails to receive it can anyone help me point out what I am doing wrong here?
Sample of the front end:
import React, {Component} from 'react';
import axios from 'axios';
import Tabs from 'react-bootstrap/Tabs';
import Tab from 'react-bootstrap/Tab';
export default class CreateFile extends Component {
constructor(props) {
super(props);
this.onChangeFileDescription = this.onChangeFileDescription.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
file_description: '',
};
this.handleSelect = this.handleSelect.bind(this);
axios
.get("http://localhost:4000/api/isloggedin")
.then(res => {
if (!res.data) {
return this.setState({isloggedin: false});
}
});
}
onChangeFileDescription(e) {
this.setState({
file_description: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
console.log(`Form submitted:`);
console.log(`File Description: ${this.state.file_description}`);
const newFile = {
file_description: this.state.file_description,
}
axios.post('http://localhost:4000/files/add', newFile)
.then(res => console.log(res.data));
this.setState({
file_description: '',
})
}
render() {
return this.state.isloggedin ? (
<div style={{marginTop: 20}}>
<h3>Upload a New File</h3>
<Tabs
id="controlled-tab-example"
activeKey={this.state.key}
onSelect={key => this.setState({key})}
>
<Tab eventKey="audio" title="Audio">
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>File Description: </label>
<input type="text"
className="form-control"
value={this.state.file_description}
onChange={this.onChangeFileDescription}
/>
</div>
</Tabs>
</div>
) : (
<h3>Please login</h3>
);
}
}
This is the server side:
Im checking if the submitted form is empty and if it is sending a error back asking users to fill the required field.
const express = require('express');
const bodyParser = require('body-parser');
const fileRoutes = express.Router();
const File = require("../models/fileHandler");
module.exports = function(app) {
app.use(bodyParser.json());
fileRoutes.route('/').get(function (req, res) {
File.find(function (err, files) {
if (err) {
console.log(err);
} else {
res.json(files);
}
});
});
fileRoutes.route('/:id').get(function (req, res) {
let id = req.params.id;
File.findById(id, function (err, file) {
res.json(file);
});
});
fileRoutes.route('/add').post(function (req, res) {
console.log(req.body.file_description);
if (req.body.file_description === ""){
console.log("its empty!");
var result = {"data" :"hello everybody !"}
res.status(200).json({'description': 'description is needed'});
return res.send(result);
}
let file = new File(req.body);
file.save()
.then(file => {
res.status(200).json({'file': 'file added successfully'});
})
.catch(err => {
res.status(400).send('adding new file failed');
});
});
fileRoutes.route('/update/:id').post(function (req, res) {
File.findById(req.params.id, function (err, file) {
if (!file)
res.status(404).send('data is not found');
else
file.file_description = req.body.file_description;
file.file_size = req.body.file_size;
file.file_duration = req.body.file_duration;
file.file_artist = req.body.file_artist;
file.file_bitrate = req.body.file_bitrate;
file.file_codec = req.body.file_codec;
file.file_audioChannels = req.body.file_audioChannels;
file.file_dimensions = req.body.file_dimensions;
file.file_tag = req.body.file_tag;
file.file_colorProfile = req.body.file_colorProfile;
file.file_extension = req.body.file_extension;
file.file_employeeResponsible = req.body.file_employeeResponsible;
file.file_editActive = req.body.file_editActive;
file.file_completed = req.body.file_completed;
file.save().then(file => {
res.json('File updated');
})
.catch(err => {
res.status(400).send("Update not possible");
});
});
});
app.use('/files', fileRoutes);
};
Ok after some digging I managed to solve this issue.
I thought i posted here in case anyone had a similar problem.
So what I did was to check everything with express validator and if there was any problem to send it to the react front end.
And in react front end if the there is any problem received regarding that specific field it will display it on top of the input field.
hope this helps.
{this.state.errors &&
this.state.errors.file_description && <p>{this.state.errors.file_description.msg}
And the complete snippet of the react front end.
import React, {Component} from 'react';
import axios from 'axios';
import Tabs from 'react-bootstrap/Tabs';
import Tab from 'react-bootstrap/Tab';
export default class CreateFile extends Component {
constructor(props) {
super(props);
this.onChangeFileDescription = this.onChangeFileDescription.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
file_description: ''
};
this.handleSelect = this.handleSelect.bind(this);
axios
.get("http://localhost:4000/api/isloggedin")
.then(res => {
if (!res.data) {
return this.setState({isloggedin: false});
}
});
}
onChangeFileDescription(e) {
this.setState({
file_description: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
console.log(`Form submitted:`);
console.log(`File Description: ${this.state.file_description}`);
const newFile = {
file_description: this.state.file_description
}
axios.post('http://localhost:4000/files/add', newFile)
.then(result => {
if (result.data.errors) {
return this.setState(result.data);
}
return this.setState({
userdata: result.data,
errors: null,
success: true
});
});
this.setState({
file_description: ''
})
}
render() {
return this.state.isloggedin ? (
<div style={{marginTop: 20}}>
<h3>Upload a New File</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>File Description: </label>
<input type="text"
className="form-control"
value={this.state.file_description}
onChange={this.onChangeFileDescription}/>
{this.state.errors &&
this.state.errors.file_description && <p>{this.state.errors.file_description.msg}</p>}
</div>
<label className="form-check-label">Yes</label>
</div>
</div>
<div className="form-group">
<input type="submit" value="Upload File" className="btn btn-primary"/>
</div>
</form>
</Tab>
</Tabs>
</div>
) : (
<h3>Please login</h3>
);
}
}
for the backend I have also tweaked it so if there is any problem it will post that back to the react front end validating with Express validator and using the normal route and post methods.
const express = require('express');
var { check, validationResult } = require("express-validator/check");
const bodyParser = require('body-parser');
const fileRoutes = express.Router();
const File = require("../models/fileHandler");
module.exports = function(app) {
const fileValidation = [
check("file_description")
.not()
.isEmpty()
.withMessage("Description required"),
];
app.use(bodyParser.json());
fileRoutes.route('/').get(function (req, res) {
File.find(function (err, files) {
if (err) {
console.log(err);
} else {
res.json(files);
}
});
});
fileRoutes.route('/:id').get(function (req, res) {
let id = req.params.id;
File.findById(id, function (err, file) {
res.json(file);
});
});
fileRoutes.route('/add').post(fileValidation, function (req, res) {
var errors = validationResult(req);
if (!errors.isEmpty()) {
return res.send({ errors: errors.mapped() });
}else{
console.log("its empty!");
let file = new File(req.body);
file.save()
.then(file => {
res.status(200).json({'file': 'file added successfully'});
})
.catch(err => res.send(err));
}
});
fileRoutes.route('/update/:id').post(function (req, res) {
File.findById(req.params.id, function (err, file) {
if (!file)
res.status(404).send('data is not found');
else
file.file_description = req.body.file_description;
file.save().then(file => {
res.json('File updated');
})
.catch(err => {
res.status(400).send("Update not possible");
});
});
});
app.use('/files', fileRoutes);
};