I have a Mongoose "User" schema, and one of the fields needs to be read-only. (the "accounts" field can be updated externally, so I don't want updates to the User to overwrite the changes.)
var UserSchema = new Schema({
firstName: {
type: String,
trim: true,
default: '',
validate: [validateLocalStrategyProperty, 'Please fill in your first name']
},
lastName: {
type: String,
trim: true,
default: '',
validate: [validateLocalStrategyProperty, 'Please fill in your last name']
},
displayName: {
type: String,
trim: true
},
email: {
type: String,
trim: true,
default: '',
validate: [validateLocalStrategyProperty, 'Please fill in your email'],
match: [/.+\@.+\..+/, 'Please fill a valid email address']
},
username: {
type: String,
unique: 'Username already exists',
required: 'Please fill in a username',
trim: true
},
password: {
type: String,
},
accounts: [{
account_hash: {type: String},
account_name: {type: String}
}],
updated: {
type: Date
},
created: {
type: Date,
default: Date.now
}
}
I've seen answers recommending making the field virtual, but on save, the field gets removed from Mongo. Is there an easy way to make specific fields in a Mongoose schema read-only?
With the latest version of Mongoose, you can set 'immutable' as a property on the the field that you want to be immutable. You can read more here Mongoose immutable.
So you can do something like
const schema = new Schema({
name: { type: String, immutable: true },
age: Number
});
const Model = mongoose.model('Test', schema);
await Model.create({ name: 'test' });
const doc = await Model.findOne();
doc.isNew; // false
doc.name = 'new name';
doc.name; // 'test', because `name` is immutable
The downside to this is that your users will not get an error message that lets them know that the field they're trying to update or have updated is read only
It seems to me your best bet is the pre
middleware for save/update
.
You can check if the fields you do not want changed are being changed with isModified
and simply throw error about your fields being read only from there:
someSchema.pre('save', function(next) {
if(this.isModified('someField')) {
throw 'someField is read only!'
}
else {
next();
}
});
For update you should be getting the updates via this.getUpdate()
and look in there for your fields.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With