1
votes

I was trying to fetch my orders from my database for my logged In user but when I fetched it I am getting error from database, And Here is my code:-

// @desc   Get logged in user orders
// @route  GET /api/orders/myorders
// @access Private
const getMyOrders = asyncHandler(async (req, res) => {
    const orders = await Order.find({ user: req.user._id })
    res.json(orders);
})

Here is my route file:-

import express from 'express';
import { addOrderItems, getMyOrders, getOrderById, updateOrderToPaid } from '../controllers/orderController.js';
import { protect } from '../middleware/authMiddleware.js';

const router = express.Router();

router.route('/').post(protect, addOrderItems)
router.route('/:id').get(protect, getOrderById)
router.route('/:id/pay').put(protect, updateOrderToPaid)
router.route('/myorders').get(protect, getMyOrders)

export default router;

Here is my Order model file

import mongoose from 'mongoose';

const orderSchema = mongoose.Schema({
    user: {
        type: mongoose.Schema.Types.ObjectId,
        required: true,
        ref: 'User'
    },
    orderItems: [
        {
            name: { type: String, required: true },
            qty: { type: Number, required: true },
            image: { type: String, required: true },
            price: { type: Number, required: true },
            product: {
                type: mongoose.Schema.Types.ObjectId,
                required: true,
                ref: 'Product'
            }
        }
    ],
    shippingAddress: {
        address: { type: String, required: true },
        city: { type: String, required: true },
        postalCode: { type: String, required: true },
        country: { type: String, required: true }
    },
    paymentMethod: {
        type: String,
        required: true
    },
    paymentResult: {
        id: { type: String },
        status: { type: String },
        update_time: { type: String },
        email_address: { type: String }
    },
    taxPrice: {
        type: String,
        required: true,
        default: 0.0
    },
    shippingPrice: {
        type: String,
        required: true,
        default: 0.0
    },
    totalPrice: {
        type: String,
        required: true,
        default: 0.0
    },
    isPaid: {
        type: Boolean,
        required: true,
        default: false
    },
    paidAt: {
        type: Date
    },
    isDelivered: {
        type: Boolean,
        required: true,
        default: false
    },
    deliveredAt: {
        type: Date
    }
}, {
    timeStamps: true
})

const Order = mongoose.model('Order', orderSchema)

export default Order;

And I also upload my protect middleware where I add my protect route and from where i get the user

import jwt from 'jsonwebtoken';
import asyncHandler from 'express-async-handler';
import User from '../models/userModel.js';

const protect = asyncHandler(async (req, res, next) => {
    let token;

    if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
        try {
            token = req.headers.authorization.split(' ')[1]
            const decoded = jwt.verify(token, process.env.JWT_SECRET)

            req.user = await User.findById(decoded.id).select('-password')
            next()
        } catch (error) {
            console.log(error)
            res.status(401)
            throw new Error('Not authorized, token not found')
        }
    }

    if (!token) {
        res.status(401)
        throw new Error('Not authorized')
    }

})

export { protect }

And My error:-

{
    "message": "Cast to ObjectId failed for value \"myorders\" at path \"_id\" for model \"Order\"",
    "stack": "CastError: Cast to ObjectId failed for value \"myorders\" at path \"_id\" for model \"Order\"\n    at model.Query.exec (C:\\proShop\\node_modules\\mongoose\\lib\\query.js:4358:21)\n    at model.Query.Query.then (C:\\proShop\\node_modules\\mongoose\\lib\\query.js:4450:15)\n    at processTicksAndRejections (internal/process/task_queues.js:93:5)"
}

I uploaded my all files and code I anyone get knows the solution please tell me, please.

4

4 Answers

5
votes

I think the problem is because when you placed (/:id) above the (/myorder), then you input the URL with /.../myorders, Route will consider myorders as an id, and it is not a type of ObjectId

1
votes

So I came here looking for an explanation for that same error. Here my route list when I get it.

router.route('/').post(protect, addOrderItems)
router.route('/:id/pay').put(protect, updateOrderToPaid)
router.route('/:id').get(protect, getOrderById)
router.route('/myorders').get(protect, getMyOrders)

Just by changing the order, and placing my ('/myorders') above ('/:id') I avoid the error. so this list gives me the wanted results!

router.route('/').post(protect, addOrderItems)
router.route('/:id/pay').put(protect, updateOrderToPaid)
router.route('/myorders').get(protect, getMyOrders)
router.route('/:id').get(protect, getOrderById) 

I hope some one can explain why this makes a huge difference!

0
votes

Where is the id property coming from in the decoded jwt?

req.user = await User.findById(decoded.id).select('-password')

Since your schema doesn't define a property called id, the actual id inserted in the database will be defined under _id. So, if your encoded jwt is simply a user projection, you'd find have match with this small change:

req.user = await User.findById(decoded._id).select('-password')

Otherwise, you might still want to validate what the jwt actually contains. If there's a cast error, the issue certainly is that decoded.id is not an ObjectId.

0
votes

Place myorders route below the order create route. Keep the route with route parameter below regular routes.

router.route('/').post(protect, addOrderItems)
router.route('/myorders').get(protect, getMyOrders)

router.route('/:id/pay').put(protect, updateOrderToPaid)
router.route('/:id').get(protect, getOrderById)