I have 3 routes in my code , for Users, for Products and For Orders.
I use jwt and generate tokens for users, and I want to assign orders to token Owners.
Here's my Order Model :
var mongoose = require('mongoose');
var orderSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId ,
product: {type: mongoose.Schema.Types.ObjectId, ref: 'Product'},
quantity: {type: Number , default: 1},
user_name: String
});
module.exports = mongoose.model('Order', orderSchema);
And here's my middleware to check Authenticate (It's imported as checkAuth) :
module.exports = (req,res,next) => {
try {
var decoded = jwt.verify(req.headers.token, secretjwt);
req.userData = decoded;
next();
} catch (error) {
return res.status(401).json({
'error': 'Auth Failed',
'details': error.message
});
}
Here's my post api for adding orders, What Should I write as user_name to assign it to the user (I don't want to get username as a body parameter)?
router.post('/newOrder', checkAuth, (req,res,next) => {
var order = new Order({
quantity: req.body.quantity,
product: req.body.productId,
user_name: // WHAT SHOULD IT BE?
});
order.save()
.then(result => {
res.status(200).json(result);
})
.catch(err => {
res.json(200);
});
});
Thanks in advance!
Instead of
req.userData = decoded
put
req.body.userData = decoded
And put user_name: req.body.userData in following snip
router.post('/newOrder', checkAuth, (req,res,next) => {
var order = new Order({
quantity: req.body.quantity,
product: req.body.productId,
user_name: // WHAT SHOULD IT BE?
});
order.save()
.then(result => {
res.status(200).json(result);
})
.catch(err => {
res.json(200);
});
});
Related
when I use this code to try and update the user it appears as a server error. Im using JWT and mongodb but am unsure if im pulling the token or the id to update the users information. Below my controller code is attached and my schema.
const updateUser = async (req, res) => {
try {
const user = await User.findByIdAndUpdate(req.user.id)
if(!user) return res.status(400).send({ error: 'User not found'})
Object.assign(user, req.body);
user.save()
res.send({ data: user})
} catch (error) {
res.status(500).send({error: 'Server Error'})
}
}
const mongoose = require('mongoose');
let userSchema = new mongoose.Schema({
name: { type: String, required: true},
email: { type: String, required: true, unique: true},
password: { type: String, required: true},
date: { type: Date, default: Date.now}
})
module.exports = mongoose.model('user', userSchema)
Updated update function but i appear to have an error
const updateUser = async (req, res) => {
try {
const updatedUser = await User.findByIdAndUpdate(req.params.id,req.body)
if(!updatedUser) return res.status(400).send('User cannot be updated!')
res.json(updatedUser)
} catch (error) {
res.status(500).send({error: 'Server Error'})
}
}
Try this :
//update user by id
exports.updateUser = async (req, res) => {
try {
const updatedUser = await
<--req.params.id is the user.id and req.body contains the requested fields to update -->
User.findByIdAndUpdate(req.params.id,req.body)
res.json(updatedUser);
}
catch (err) {
console.log(err);
res.status(500).json({ message: 'Internal server error' });
}
}
I have this collection Cart (cart schema) to delete and it is referenced with 2 other schemes, Meal and Customer (owner user, its schema is: User Schema).
How can I delete the cart by passing as req.params.id the user's id from the HTTP request?
Cart Schema
const mongoose = require('mongoose');
const idValidator = require('mongoose-id-validator');
const Schema = mongoose.Schema;
const cartItemSchema = new Schema ({
quantity: { type: Number, required: true },
itemId: { type: mongoose.Types.ObjectId, required: true, ref: 'Meal' }
});
const cartSchema = new Schema ({
cartItems : [
cartItemSchema
],
customer: { type: mongoose.Types.ObjectId, required: true, ref: 'User'}
});
cartSchema.plugin(idValidator);
module.exports = mongoose.model('Cart', cartSchema);
I created a function to delete the document, but it doesn't work, it returns the message: 'Deleted cart.', but isn't true, the document remains in collection.
const deleteCartByUserId = async (req, res, next) => {
const userId = req.params.uid;
let cart;
try {
cart = await Cart.find({ customer: userId });
} catch(err) {
const error = new HttpError('Something went wrong, could not delete cart.', 500);
return next(error);
}
if(!cart) {
const error = new HttpError('Could not find cart for this user id.', 404);
return next(error);
}
try {
Cart.deleteOne({ customer: userId });
} catch(err) {
console.log(err);
const error = new HttpError('Something went wrong, could not delete cart.', 500);
return next(error);
}
res.status(200).json({ message: 'Deleted cart.' });
};
So the porblem was that you missed an await before delete one function call.
Also I've changed some of youre code to make it cleaner:
const functionHandler = fn =>
(req, res, next) =>
Promise
.resolve(fn(req, res, next))
.catch(next);
const deleteCartByUserId = functionHandler(async (req, res) => {
const { params: { uid: userId } } = req;
const cart = await Cart.findOneAndDelete({ customer: userId })
if(!cart) {
throw new HttpError('Could not find cart for this user id.', 404);
}
res.status(200).json({ message: 'Deleted cart.' });
});
In your error handler middleware you can check for error type and if it's not HttpError use internal server error.
I am a beginner in Node Js /Express and am currently trying to design a simple chess forum. I am having great difficulty creating the CRUD functions for the different entities. The 3 entities are: User, Message and Colour.
Their relationship to each other is User.OneToMany(Message) and Colour.OneToMany(Message).I use Mongoose.
user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var user = new Schema({
name: {
type: String
},
email: {
type: String
},
password: {
type: String
}
});
const UserDB= mongoose.model('user', user);
module.exports = UserDB;
message.js
const mongoose = require('mongoose');
const Schema= mongoose.Schema;
var message = new Schema({
titel: {
type: String
},
message: {
type: String
},
user: {
type: Schema.Types.ObjectId,
required: true,
ref: 'User'
},
color: {
type: Schema.Types.ObjectId,
required: true,
ref: 'color'
}
});
const MessageDB= mongoose.model('message', message);
module.exports=MessageDB
color.js
const mongoose = require('mongoose');
const Schema= mongoose.Schema;
var color = new Schema({
color: {
type: String
}
});
const ColorDB=mongoose.model('Color', color);
module.exports=ColorDB
I have implemented all the CRUD functions for the user.
controller.js
var UserDB = require('../model/user');
//CRUD for User
//(c)reate new User
exports.create=(req,res)=>{
//validate
if(!req.body){
res.status(400).send({message:'Empty'});
return;
}
//hash password
//const hashedPassword= bcrypt.hashSync(req.body.password,salt)
//
//new user
const user = new UserDB({
name: req.body.name,
email: req.body.email,
password: req.body.password
})
//save database
user
.save(user)
.then(data => {
res.redirect('/signup')
})
.catch(err =>{
res.status(500).send({
message: err.message || "Mars Attacks !"
})
});
}
//(r)ead User
exports.find=(req,res)=>{
//find by email (login)
if (req.query.email){
const email=req.query.email;
const password=req.query.password;
UserDB.findOne({email: email, password:password})
.then(data=>{
if(!data){
res.status(404).send({message: 'Not found user with email' +email})
} else {
res.redirect('/forum')
}
})
.catch(err=>{
res.status(500).send({message: 'Error reading user with email' +email})
})
}
//find by id
if(req.query.id){
const id=req.query.id;
UserDB.findById(id)
.then(data=>{
if(!data){
res.status(404).send({message: 'Not found user with id' +id})
} else{
res.send(data)
}
})
.catch(err=>{
res.status(500).send({message: 'Error reading user with id' +id })
})
}else{
UserDB.find()
.then(user =>{
res.send(user)
})
.catch(err =>{
res.status(500).send({
message: err.message || 'Ack! Ack!' })
})
}
}
//(u)pdate User
exports.update=(req,res)=>{
if(!req.body){
return res
.status(400)
.send({message: 'Data to update can not be empty.'})
}
const id= req.params.id;
UserDB.findByIdAndUpdate(id,req.body,{useFindAndModify: false})
.then(data=>{
if(!data){
res.status(404).send({message: `Cannot Update user with ${id}`})
}else{
res.send(data)
}
})
.catch(err=>{
res.status(500).send({message: 'Laserbeam !'})
})
}
//(d)elete User
exports.delete=(req,res)=>{
const id = req.params.id;
UserDB.findByIdAndDelete(id)
.then(data=> {
if(!data){
res.status(404).send({message: `Cannot Delete ${id}`})
}else{
res.send({
message: 'Gone!'
})
}
})
.catch(err=>{
res.status(500).send({
message:'Ack ! Could not delete User with id=' + id
});
});
}
My router looks like this:
router.js
const express = require('express');
const route = express.Router();
const controller = require ('../controller/controller');
//API
route.post('/api/users',controller.create);
route.get('/api/users',controller.find);
route.put('/api/users/:id',controller.update);
route.delete('/api/users/:id',controller.delete);
module.exports=route;
I tried to transfer the concept of the controller to the other 2 entities (message,colour). Unfortunately in vain. What are the crud functions for the other two entities ?
first you need to save the user ID as a session or via token. I would suggest look into passport.js for more information on this one.
After you have set the session.. you can access the userID in req.user.
You can now easily create a CRUD like this as an example - create only
// route
route.post('/api/message',messageController.create);
// create controller
// post data json
// {
// color:'color_ID'
// }
function create(req, res){
const message = {
titel:'this is a title',
message:'this is a message',
user: req.user,
color: req.body.color
};
await Message.create(message);
res.json({mesage:'Message Created'})
}
I am using mongoose and express to build an API for storing technology work tickets. I have a field in my Ticket model that references a User id and an array field in my User model that references all the Tickets (by ID) that are owned by that user.
When I create a new Ticket (using HTTP post method), I want my database to automatically add that ticket's id to the tickets field of its assigned user (like a SQL Join). However, I can't get it to work.
I've tried updating my user model inside the /tickets POST request in my router, but can't wrap my head around how to actually make it work.
Here is my code:
// Ticket Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Promise = require('bluebird');
const ObjectId = mongoose.Schema.Types.ObjectId;
const User = require('./user');
Promise.promisifyAll(mongoose);
const TicketSchema = new Schema({
open: {type: Date, required: true},
close: Date,
description: {type: String, required: true},
done: Boolean,
status: String,
repairType: {type: String, required: true},
ticketOwner: {type: ObjectId, ref: 'User', required: true}
});
const Ticket = mongoose.model('Ticket', TicketSchema, 'tickets');
module.exports = Ticket;
// User Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Promise = require('bluebird');
const ObjectId = mongoose.Schema.Types.ObjectId;
const Ticket = require('./ticket');
Promise.promisifyAll(mongoose);
const UserSchema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
email: {type: String, required: true},
tickets: [{type: ObjectId, ref: 'Ticket'}]
});
const User = mongoose.model('User', UserSchema, 'users');
module.exports = User;
// Tickets Route
const express = require('express');
const router = express.Router();
const Ticket = require('../models/ticket');
router.route('/')
// READ all tickets.
.get(function(req, res, next) {
Ticket.findAsync({})
.then(function(tickets) {
res.json(tickets);
})
.catch(next)
.error(console.error);
})
// CREATE new ticket.
.post(function(req, res, next) {
let ticket = new Ticket();
let prop;
for (prop in req.body) {
ticket[prop] = req.body[prop];
}
ticket.saveAsync()
.then(function(ticket) {
console.log('success');
res.json({'status': 'success', 'ticket': ticket});
})
.catch(function(e) {
console.log('fail');
res.json({'status': 'error', 'error': e});
})
.error(console.error);
});
router.route('/:id')
// READ a single Ticket by ID
.get(function(req, res, next) {
Ticket.findOne({_id: req.params.id}, {})
.populate('ticketOwner')
.exec(function (e, ticket) {
if (e) return console.error(e);
res.json(ticket);
})
})
// UPDATE a Ticket
.put(function(req, res, next) {
let ticket = {};
let prop;
for (prop in req.body) {
ticket[prop] = req.body[prop];
}
Ticket.updateAsync({_id: req.params.id}, ticket)
.then(function(updatedTicket) {
return res.json({'status': 'success', 'ticket': updatedTicket})
})
.catch(function(e) {
return res.status(400).json({'status': 'fail', 'error': e});
});
})
// DELETE a Ticket
.delete(function(req, res, next) {
Ticket.findByIdAndRemoveAsync(req.params.id)
.then(function(deletedTicket) {
res.json({'status': 'success', 'ticket': deletedTicket});
})
.catch(function(e) {
res.status(400).json({'status': 'fail', 'error': e})
});
});
module.exports = router;
// Users Route
const express = require('express');
const router = express.Router();
const User = require('../models/user');
router.route('/')
// READ all users.
.get(function(req, res, next) {
User.findAsync({})
.then(function(users) {
res.json(users);
})
.catch(next)
.error(console.error);
})
// CREATE new user.
.post(function(req, res, next) {
let user = new User();
let prop;
for (prop in req.body) {
user[prop] = req.body[prop];
}
user.saveAsync()
.then(function(user) {
console.log('success');
res.json({'status': 'success', 'user': user});
})
.catch(function(e) {
console.log('fail');
res.json({'status': 'error', 'error': e});
})
.error(console.error);
});
router.route('/:id')
// READ a single User by ID
.get(function(req, res, next) {
User.findOne({_id: req.params.id}, {})
.populate('tickets')
.exec(function (e, user) {
if (e) return console.error(e);
res.json(user);
})
})
// UPDATE a User
.put(function(req, res, next) {
let user = {};
let prop;
for (prop in req.body) {
user[prop] = req.body[prop];
}
User.updateAsync({_id: req.params.id}, user)
.then(function(updatedUser) {
return res.json({'status': 'success', 'user': updatedUser})
})
.catch(function(e) {
return res.status(400).json({'status': 'fail', 'error': e});
});
})
// DELETE a User
.delete(function(req, res, next) {
User.findByIdAndRemoveAsync(req.params.id)
.then(function(deletedUser) {
res.json({'status': 'success', 'user': deletedUser});
})
.catch(function(e) {
res.status(400).json({'status': 'fail', 'error': e})
});
});
module.exports = router;
I working on Mongoose and Express project where by I have 3 models: User, Album and Purchase. The purchase model references the user and album. I am creating a POST endpoint where by I can make a purchase and then retrieve the data as well as the user and album relations which should be populated with their data, but I am stuck.
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
// TODO: Define Schema
name: {
type: String,
required: true
}
})
var User = mongoose.model('User', userSchema)
var albumSchema = mongoose.Schema({
// TODO: Define Schema
title: {
type: String,
required: true
},
performer: {
type: String,
required: true
},
cost: {
type: Number,
required: true
}
})
var Album = mongoose.model('Album', albumSchema);
var puchaseSchema = mongoose.Schema({
// TODO: Define Schema
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Album'
},
album: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
})
var Purchase = mongoose.model('Purchase', puchaseSchema);
app.use(bodyParser.json());
app.listen(3000);
// TODO: GET /albums
app.get('/albums', (req,res) => {
Album.find()
.then((response) => {
res.json({data: response})
})
.catch(err => {
res.json({error: err})
})
})
// TODO: GET /albums/:id
app.get('/albums/:id', (req,res) => {
Album.findById(req.params.id)
.then(response => {
res.json({data: response})
.catch(err => {
res.json({Error: err})
})
})
})
// TODO: POST /albums
app.post('/albums', (req,res) => {
const newPost = Album({
title: req.body.title,
performer: req.body.performer,
cost: req.body.cost
})
newPost.save(err => {
if(err)
res.json({error: err})
})
.then(data => {
res.json({data: data})
})
})
// TODO: PUT /albums/:id
app.put('/albums/:id', (req,res) => {
Album.findByIdAndUpdate(req.params.id, req.body, {new: true},
(err, album) =>{
if(err) return res.status(500).send(err)
return res.json({data: album})
})
})
// TODO: DELETE /albums/:id
app.delete('/albums/:id', (req,res) => {
const id = req.params.id
Album.findById(id)
.then(docs => {
docs.remove()
res.status(204)
.json({data:docs})
})
})
// TODO: POST /purchases
app.post('/purchases', (req,res) => {
})```
This might help you. Look into mongoose's populate method.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.findById(purchase.id).populate('user').populate('album').then((purchaseData) => {
return res.json({purchaseData});
}).catch(e => {
console.log(e);
});
}).catch(e => {
console.log(e);
});
})
Here's an alternative for populating after saving the document.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.populate(purchase, [{path: 'user'}, {path: 'album'}], (err, data) => {
if(err) {
return res.json(e);
}
return res.json(data);
});
}).catch(e => {
console.log(e);
});
}
)
As mentioned here: https://mongoosejs.com/docs/api.html#model_Model.populate