-
Notifications
You must be signed in to change notification settings - Fork 28
/
index.js
72 lines (57 loc) · 2.17 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
const bcrypt = require('bcrypt')
const RECOMMENDED_ROUNDS = 12
const BCRYPT_HASH_REGEX = /^\$2[ayb]\$[0-9]{2}\$[A-Za-z0-9./]{53}$/
// Plugin that provides automatic bcrypt hashing for passwords on Objection.js models.
const objectionPassword = (options) => {
// Provide good defaults for the options if possible.
options = {
allowEmptyPassword: false,
passwordField: 'password',
rounds: RECOMMENDED_ROUNDS,
...options
}
// Return the mixin.
// If the plugin doesn't take options, the mixin can be exported directly. The factory function is not needed.
return (Model) => {
return class extends Model {
async $beforeInsert (...args) {
await super.$beforeInsert(...args)
return await this.generateHash()
}
async $beforeUpdate (queryOptions, ...args) {
await super.$beforeUpdate(queryOptions, ...args)
if (queryOptions.patch && this[options.passwordField] === undefined) {
return
}
return await this.generateHash()
}
// Compares a password to a bcrypt hash, returns whether or not the password was verified.
async verifyPassword (password) {
return await bcrypt.compare(password, this[options.passwordField])
}
/* Sets the password field to a bcrypt hash of the password.
* Only does so if the password is not already a bcrypt hash. */
async generateHash () {
const password = this[options.passwordField]
if (password) {
if (this.constructor.isBcryptHash(password)) {
throw new Error('bcrypt tried to hash another bcrypt hash')
}
const hash = await bcrypt.hash(password, options.rounds)
this[options.passwordField] = hash
return hash
}
// Throw an error if empty passwords are not allowed.
if (!options.allowEmptyPassword) {
throw new Error('password must not be empty')
}
}
/* Detect rehashing to avoid undesired effects.
* Returns true if the string seems to be a bcrypt hash. */
static isBcryptHash (str) {
return BCRYPT_HASH_REGEX.test(str)
}
}
}
}
module.exports = objectionPassword