Hi, so I made a ToDo app with React, Express, MongoDB and Node and need to allow each user that signs up to have only their todo items show for them.
I have searched as much as possible but can’t come to find a solution to this and please need assistance with this. I know I need to call the JWT token from localstorage and assign it to the task created but how I have no idea as I am at wits end and can’t find a solution to this.
Here is my code in the backend
My todo Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create the Scema to be used for the database
const todoSchema = new Schema({
userId: {type: mongoose.Schema.Types.ObjectId, ref: 'user'},
task: { type: String, required: true, trim: true }
});
const ToDo = mongoose.model('ToDO', todoSchema)
module.exports = ToDo;
My user Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create the user Schema
const userSchema = new Schema ({
name: {
type: String,
required: true,
},
email: {
type: String,
require: true
},
password: {
type: String,
require: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model('users', userSchema);
My todo API
const router = require('express').Router();
let ToDo = require('../../models/todo.models');
// Route for the home page, find the todos and render the json file
router.route('/').get((req, res) => {
ToDo.find()
.then(todos => res.json(todos))
.catch(err => res.status(400).json('Error: ' + err));
});
// Method to add a new todo item to the list, declared all the fields
router.route('/add').post((req, res) => {
const task = req.body.task;
console.log(req.body)
const newToDo = new ToDo({
task
});
// Once a new item is added, save it
newToDo.save()
.then(() => res.json('todo added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
// Find a todo by the ID generated by mongoDB
router.route('/:id').get((req, res) => {
ToDo.findById(req.params.id)
.then(todo => res.json(todo))
.catch(err => res.status(400).json('Error: ' + err));
});
// Delete a todo by ID from the database
router.route('/:id').delete((req, res) => {
ToDo.findByIdAndDelete(req.params.id)
.then(() => res.json('todo deleted.'))
.catch(err => res.status(400).json('Error: ' + err));
});
// Update an item with the specific ID
router.route('/update/:id').post((req, res) => {
ToDo.findById(req.params.id)
.then(todo => {
todo.task = req.body.task;
todo.save()
.then(() => res.json('todo updated!'))
.catch(err => res.status(400).json('Error: ' + err));
})
.catch(err => res.status(400).json('Error: ' + err));
});
module.exports = router;
My user API
const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const keys = require("../../config/keys");
// Load input validation
const validateRegisterInput = require("../../validation/register");
const validateLoginInput = require("../../validation/login");
// Load User model
const User = require("../../models/users.model");
// @route POST api/users/register
// @desc Register user
// @access Public
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(user => {
if (user) {
return res.status(400).json({ email: "Email already exists" });
} else {
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
// Hash password before saving in database
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));
});
});
}
});
});
// @route POST api/users/login
// @desc Login user and return JWT token
// @access Public
router.post("/login", (req, res) => {
// Form validation
const { errors, isValid } = validateLoginInput(req.body);
// Check validation
if (!isValid) {
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
// Find user by email
User.findOne({ email }).then(user => {
// Check if user exists
if (!user) {
return res.status(404).json({ emailnotfound: "Email not found" });
}
// Check password
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
// User matched
// Create JWT Payload
const payload = {
id: user.id,
name: user.name
};
// Sign token
jwt.sign(
payload,
keys.secretOrKey,
{
expiresIn: 31556926 // 1 year in seconds
},
(err, token) => {
res.json({
success: true,
token: "Bearer " + token
});
}
);
} else {
return res
.status(400)
.json({ passwordincorrect: "Password incorrect" });
}
});
});
});
module.exports = router;
My login validation
const Validator = require("validator");
const isEmpty = require("is-empty");
module.exports = function validateLoginInput(data) {
let errors = {};
// Convert empty fields to an empty string so we can use validator functions
data.email = !isEmpty(data.email) ? data.email : "";
data.password = !isEmpty(data.password) ? data.password : "";
// Email checks
if (Validator.isEmpty(data.email)) {
errors.email = "Email field is required";
} else if (!Validator.isEmail(data.email)) {
errors.email = "Email is invalid";
}
// Password checks
if (Validator.isEmpty(data.password)) {
errors.password = "Password field is required";
}
return {
errors,
isValid: isEmpty(errors)
};
};
My register validation
const Validator = require("validator");
const isEmpty = require("is-empty");
module.exports = function validateRegisterInput(data) {
let errors = {};
// Convert empty fields to an empty string so we can use validator functions
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 : "";
// Name checks
if (Validator.isEmpty(data.name)) {
errors.name = "Name field is required";
}
// Email checks
if (Validator.isEmpty(data.email)) {
errors.email = "Email field is required";
} else if (!Validator.isEmail(data.email)) {
errors.email = "Email is invalid";
}
// Password checks
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 = "Passwords must match";
}
return {
errors,
isValid: isEmpty(errors)
};
};
And lastly my server
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const passport = require('passport')
const users = require('./routes/api/users');
const todoRouter = require('./routes/api/todos');
const cors = require('cors');
const app = express();
app.use(cors());
// Body parser middleware
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
// DB Config
const db = require('./config/keys').mongoURI;
// Connection to mongoDB
mongoose.connect(db, { useNewUrlParser: true, useUnifiedTopology: true }
)
.then(() => console.log("MongoDB server up and running..."))
.catch(err => console.log(err));
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
app.use("/api/users", users);
app.use('/api/todos', todoRouter);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server connected on the following port: ${port}`))
So if you can help out with this and guide me on how to do this I will appreciate it