In router/user.js for routing:
router.post('/register', auth.optional, (req, res, next) => {
const {
body: { user }
} = req
// validation code skipped for brevity
const finalUser = new User(user)
finalUser.setPassword(user.password)
// to save the user in Mongo DB
return finalUser.save().then(() => res.json({ user: finalUser.toAuthJSON() }))
})
Post request sent with a body of:
{
"user":{
"email":"leon@idiot.com",
"password": "123abc"
}
}
In model/User.js for database schema:
const UserSchema = new Schema({
email: String,
hash: String,
salt: String
})
// Please note: this is a regular/normal function definition
UserSchema.methods.setPassword = function (password) {
// this references the UserSchema created
this.salt = crypto.randomBytes(16).toString('hex')
console.log(`salt: ${this.salt}`)
this.hash = crypto
.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512')
.toString('hex')
console.log(`hash: ${this.hash}`)
}
Everything works fine now. The log output as:
salt: e7e3151de63fc8a90e3621de4db0f72e
hash: 19dd9fdbc78d0baf20513b3086976208ab0f9eee6d68f3c71c72cd123a06459653c24c11148db03772606c40ba4846e2f9c6d4f1014d329f01d22805fc988f6164fc13d4157394b118d921b9cbd742ab510e4d2fd4ed214a0d523262ae2b2f80f6344fbd948e8c858f95ed9706952db90d415312156a994c65c42921afc8c3e5b1b24a923219445eec8ed62de313ab3d78dc93b715689a552b6449870c5bfcc3bec80c4438b1895cab41f92ef681344ac8578de476a82aa798730cf3a6ef86973a4364a8712c6b3d53ce67ffffd7569b9ade5db09ad95490354c6f7194fdd9d8f8a1cb7ccddf59e701198a1beee59a2dd6afb90ae50e26ea480e9a6d607e4b37857a02016ee4d692d468dd9a67499547eb03fc6cfa676686f7990c2251c9516459288c55584138aed56a5df6c4692f7ef6925e8f3d6f6a0c780c4d80580447f2b1258bea799a8c7eb9da878ab70a94c4227ec03d18d56b2722c315d0e2b2681d81d78d4213288f7305cbbfa377c3b2eb75e0f0b093e6067b14adce4a01f0a7bde8515350a1c987739c12574ec4c49008510e2e7e5534f9b76d15b1af68e43ef54e6b8a1bea859aafd23d6b6bc61d5b1965004cd6dd933545cf755f3e6dfc8f230f37a79a8bc006b9b14465b1b08d60cb45ef3b6a1b73f5afac90bdc58d5ec15c7596dc7e8d503f8dfbd6a3289cf997da2031389c7f3d165e34b29178f3daf76d
3
But it does not work with such a definition:
UserSchema.methods.setPassword = password => {
// what this reference is undefined, so are ones below
this.salt = crypto.randomBytes(16).toString('hex')
console.log(`salt: ${this.salt}`)
this.hash = crypto
.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512')
.toString('hex')
console.log(`hash: ${this.hash}`)
}
The error is:
{
"errors": {
"message": "Cannot set property 'salt' of undefined",
"error": {}
}
}
which means what this referenced is undefined.
What I find online is that fat arrow functions explicitly prevent binding of this, and it's a problem of scopes, that this in fat arrow functions has a scope of its immediate object. But I cannot say that I understand it very well.
1. In this case, what is the scope of this in fat arrow functions?
2. What is the scope, of this, in normal function definitions?
3. How to access the object, in this case: UserSchema, properties (forgive me for less proper words) in fat arrow functions as one does in normal function definitions?
These posts are quite helpful:
Are 'Arrow Functions' and 'Functions' equivalent / exchangeable?
How does the “this” keyword work?
But I am still expecting answers to my specific questions in particular cases, before figuring them out.