Mongoose how to prevent user already with username to change username
I have an auth system where the user can signup
c username
/ password
or facebook signin
c provider
/providerId
I want to prevent the username from being changed, but if they use facebook
, I allow them to install username
once. Is it possible to implement it in the model user
?
Here is my current implementation.
//username check unique
UserSchema.pre('save', true, function(next, done) {
var self = this //in case inside a callback
//sns provider, OK not to have username
if (self.provider && self.provider !== 'local' && !self.username) {
done()
return next()
}
//not modified
if (! self.isModified('username')) {
done()
return next()
}
mongoose.model('User').findOne({username: self.username}, function(err, user) {
if (err) {
done(err)
} else if (user) {
//todo: put msg in validation.js
self.invalidate('username', 'username must be unique')
done(helper.getValidationError('username must be unique'))
} else {
done()
}
})
return next()
})
//username check is valid username
UserSchema.pre('save', true, function(next, done) {
var self = this
if (self.provider && self.provider !== 'local' && !self.username) {
done()
return next()
}
//username is required for local strategy
var msg = helper.validation.user.username(self.username)
if (msg) {
self.invalidate('username', msg)
done(helper.getValidationError(msg))
}
else {
done()
}
return next()
})
Assistant confirmation is defined as:
exports.user = {
username: function(input) {
if (!input)
return 'username is required' //Note: required only for Local Strategy
var min = 3
var max = 10
if (input.length < min)
return 'username min of length is ' + min
if (input.length > max)
return 'username max of length is ' + max
return null
}
}
source to share
You can check if the original username is empty. All checks are given in the model. You don't need to change anything in the controller or router.
UserSchema.post('init', function() {
this.original = this.toObject()
})
UserSchema.pre('save', true, function(next, done) {
var self = this
if (! self.isModified('username')) {
done()
return next()
}
//To prevent Facebook user to delete username (and recreate a different one) with !self.original.username
if (self.provider && self.provider !== 'local' && !self.username && !self.original.username) {
done()
return next()
}
//prevent change of username
if (self.original.username) {
self.invalidate('username', 'cannot modify username')
done(helper.getValidationError('cannot modify username'))
}
mongoose.model('User').findOne({username: self.username}, function(err, user) {
if (err) {
done(err)
} else if (user) {
self.invalidate('username', 'username must be unique')
done(helper.getValidationError('username must be unique'))
} else {
done()
}
})
return next()
})
source to share