FullstackAcademy / boilermaker

Code scaffold for projects

Home Page:https://www.youtube.com/watch?v=7bLSuTHH4Ag&list=PLx0iOsdUOUmn7D5XL4mRUftn8hvAJGs8H

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Change `get ()` password/salt obfuscation to use `defaultScope`

glebec opened this issue · comments

password: {
type: Sequelize.STRING,
// Making `.password` act like a func hides it when serializing to JSON.
// This is a hack to get around Sequelize's lack of a "private" option.
get() {
return () => this.getDataValue('password')
}

The password and salt fields define getters. Those getters return functions instead of values. This was done to demonstrate a (hacky) way to prevent certain fields from being leaked to the front-end. This works because res.json-ing an instance JSON stringifies the object, and functions are skipped when serializing to JSON.

A much more semantic solution is to define a defaultScope which uses either an attributes whitelist, or alternatively a blacklist (attributes: { exclude: ['password', 'salt'] }. The downside to this solution is that defaultScope is disabled when opting into custom scopes; the solution is to manually compose the custom scope with defaultScope. This requires the developer to know about the issue and remember to do the composition.

The more semantic solution is thus easier to omit by accident. A mitigating measure would be to add a comment explicitly warning students to always include defaultScope when opting into using custom scopes on a query.

Even though the get trick works in more circumstances, it is still ultimately a trick, and difficult to predict all the possible edge cases. It makes assumptions about what will be done with instances in order to send them to the front end. Conversely, the use of a defaultScope and attributes indicates precisely what is intended, and is therefore less confusing. It also stops the fields from being included closer to the source, that is, at the db query level – potentially preventing leakage of private fields in currently-unforeseen circumstances.


EDIT: ah, now I remember why I did it this way. You still need to fetch the password and salt fields in order to verify user credentials. So omitting by default won't work – unless the login route does a fetch for the user with an explicit scope that includes the password and salt. Given that, I am not sure if I want to bother, as this feels like it would add complexity.

I'm going to close this issue. I started making a branch which explicitly omits the password and salt fields, but that makes actually updating or checking the user credentials much messier, with async methods & async hooks that are more brittle and mesh much more laboriously.