Automattic / Automattic/mongoose
Make update validators fail if `upsert` is set and `required` path isn't in `$set` or `$setOnInsert`
- Dominant language
- JavaScript
- Stars
- 27.5k
- Forks
- 4k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 35
Description
**Do you want to request a *feature* or report a *bug*?**
Bug
**What is the current behavior?**
`findOneAndUpdate` doesn't run the `required` validations, neither with the third parameter of the method or with the pre hook.
**If the current behavior is a bug, please provide the steps to reproduce.**
1. The model: `model/section.js`
```javascript
const Section = new Schema({
_id: {type: String},
name: {type: String, required: true, unique: true},
title: {type: String, required: true, unique: true}
}, {collection: 'sections', timestamps: true});
Section.pre('findOneAndUpdate', function (next) {
// workaround that works..
// const {title, name} = this.getUpdate();
// if (!isString(name)) {
// throw new Error('cannot save a Section with undefined name');
// }
// if (!isString(title)) {
// throw new Error('cannot save a Section with undefined title');
// }
this.options.upsert = true;
this.options.runValidators = true;
this.setDefaultsOnInsert = true;
next();
});
module.exports = mongoose.model('Section', Section);
```
2. The service: `service/section.js`
```javascript
const {Section} = require('../model');
const {isNil, isString, assign} = require('lodash');
class SectionService {
static save(section) {
if (isNil(section)) {
throw new Error('undefined Section');
}
return Section.findOneAndUpdate(
{_id: section.name},
assign(section, {_id: section.name})
).lean().exec();
}
}
```
3. Try to save a document:
```javascript
SectionService.save({name: 'name', custom: 'custom'});
```
4. Then the document it's saved without the `custom` field.
**What is the expected behavior?**
Should throw an error for being with a `title` field as`required`.
**Please mention your node.js, mongoose and MongoDB version.**
`5.2.16`
Contributor guide
Research direction
Reproduce the behavior using model/section.js and service/section.js, focusing on findOneAndUpdate with upsert and runValidators enabled. Trace the update-validation entry point and verify that an upsert missing the required title in both $set and $setOnInsert raises a required-field error instead of saving the document.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, mongodb
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100