0

I am working on api with node.js, express and mongodb i have a route DELETE HTTP:localhost:5000/api/users/usernames/ which I send json object that contains usernames

I am using Insomnia to make requests.

server.js

require('dotenv').config();
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const errorHandler = require('./_helpers/error-handler');



const app = express();

const port = process.env.PORT || 5000;


app.use(cors());
app.use(express.json());


const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true});
const connection = mongoose.connection;
connection.once('open', () => {
    console.log("MongoDB database connection established successfully");
});

// routers
app.use('/api/users', require('./routes/api/users/users.controller'));

app.use(errorHandler);

app.listen(port, () => {
    console.log(`Server is running on port ${port}`);
});

user.model.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Roles = require('../_helpers/roles');

const User = new Schema({
    username: { type: String, unique: true, required: true },
    hash: { type: String, required: true },
    firstName: { type: String, required: true },
    lastName: { type: String, required: true },
    role: { type: String, enum: Object.keys(Roles), required: true },
    createdDate: { type: Date, default: new Date() }
});

User.set('toJSON', {
    virtuals: true,
    versionKey: false,
    transform: function (doc, ret) {
        delete ret._id;
        delete ret.hash;
    }
});

module.exports = mongoose.model('User', User);

this is my userController js file

router.delete('/usernames', authorize(Roles.Admin), _deleteByUsername);

function _deleteByUsername(req, res, next) {
    userService.deleteByUsername(req.body)
        .then(() => res.status(200).json({"message": "User(s) successfully deleted!"}))
        .catch(err => next(err));
}

this is my userService js file

function _deleteByUsername(usernames) {
    Object.values(usernames).forEach(async (username) => {
        await User.findOneAndDelete({username})
    });
}

when I make a DELETE HTTP://localhost:5000/api/users/usernames with this json object

{
    "0": "testUser1",
    "1": "testUser2
}

It seems it doesn't even pass req.body in _deleteByUsername Here is the error I got

CastError: Cast to ObjectId failed for value "usernames" at path "_id" for model "User"
    at model.Query.exec (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\query.js:4358:21)
    at model.Query.Query.then (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\query.js:4450:15)
    at processTicksAndRejections (internal/process/task_queues.js:93:5) {
  messageFormat: undefined,
  stringValue: '"usernames"',
  kind: 'ObjectId',
  value: 'usernames',
  path: '_id',
  reason: Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
      at new ObjectID (D:\web-development-servers\order-management-system\back-end\node_modules\bson\lib\bson\objectid.js:59:11)
      at castObjectId (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\cast\objectid.js:25:12)
      at ObjectId.cast (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\schema\objectid.js:279:12)
      at ObjectId.SchemaType.applySetters (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\schematype.js:1110:12)
      at ObjectId.SchemaType._castForQuery (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\schematype.js:1545:15)
      at ObjectId.SchemaType.castForQuery (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\schematype.js:1535:15)
      at ObjectId.SchemaType.castForQueryWrapper (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\schematype.js:1512:20)
      at cast (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\cast.js:331:32)
      at model.Query.Query.cast (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\query.js:4759:12)
      at castQuery (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\query.js:4559:18)
      at model.Query.Query._findAndModify (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\query.js:3458:23)
      at model.Query.<anonymous> (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\query.js:3421:8)
      at model.Query._wrappedThunk [as _findOneAndRemove] (D:\web-development-servers\order-management-system\back-end\node_modules\mongoose\lib\helpers\query\wrapThunk.js:16:8)
      at D:\web-development-servers\order-management-system\back-end\node_modules\kareem\index.js:370:33
      at processTicksAndRejections (internal/process/task_queues.js:75:11)
}

I don't know what am I doing wrong. I expect request body to be json object so I can use Object.values() but the thing is I think it doesn't even invoke _deleteByUsername

AK-35
  • 559
  • 2
  • 9
  • 24
  • Do you have any Express middleware that reads and parses the body? Express does not read the body on its own. Can you show the client-side code that sends the DELETE request? – jfriend00 Dec 28 '20 at 09:01
  • Also, you are not supposed to use a body with a DELETE request. The URL itself is supposed to identify the resource that the DELETE verb applies to. Many clients cannot even send a body with a DELETE and many servers will ignore a body sent with a DELETE. So, I think you probably should rework how this request is selecting what resource to apply the DELETE operation to. Have a read here [Is an entity body allowed for a delete request](https://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request) for further discussion. – jfriend00 Dec 28 '20 at 09:04
  • 2
    You did not answer or respond to most of my comments. I can't help you further unless you do. – jfriend00 Dec 28 '20 at 09:14
  • @jifriend it is in my server.js `app.use(express.json())`; – AK-35 Dec 28 '20 at 09:41
  • And, what about the comment that many client or server environments do not support sending a body with a DELETE? And, that in a REST design, the identifier for what you are deleting should be in the URL, not in the body? And, where's the client code that is sending the request? – jfriend00 Dec 28 '20 at 14:50
  • The error comes from mongodb, you are not using correct _id, mongodb cannot cast id that you provided to mongodb _id – Nodir Nasirov Dec 28 '20 at 15:04
  • @jfriend00 I am using Insomnia to make a request. And if that's the case then I am using DELETE wrong. I am new to this stuff. I would appreciate any suggestions. – AK-35 Dec 28 '20 at 21:17
  • @NodirNasirov I am not trying to use _id but somehow mongodb thinks I am trying to provide _id – AK-35 Dec 28 '20 at 21:18
  • What is up with argument here? ‘_deleteByUsername(usernameasdasdasds)‘ change it to ‘usernames’ – Nodir Nasirov Dec 29 '20 at 01:53

0 Answers0