Completed
Pull Request — master (#40)
by
unknown
02:53
created

src/cli/users/utils.js   C

Complexity

Total Complexity 59
Complexity/F 2.81

Size

Lines of Code 215
Function Count 21

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 0
wmc 59
nc 1
mnd 3
bc 52
fnc 21
dl 0
loc 215
rs 5.2857
bpm 2.4761
cpm 2.8095
noi 4
c 2
b 0
f 0

15 Functions

Rating   Name   Duplication   Size   Complexity  
A utils.js ➔ findSync 0 10 3
A utils.js ➔ findByEmail 0 10 3
B utils.js ➔ decodeUser 0 12 5
A utils.js ➔ findByUsername 0 10 3
A utils.js ➔ getAll 0 3 1
A utils.js ➔ getRole 0 10 1
A utils.js ➔ findByResetPasswordToken 0 10 3
B utils.js ➔ checkSameEmail 0 21 5
A utils.js ➔ isValid 0 8 3
C utils.js ➔ commonPassword 0 45 8
A utils.js ➔ getTokenFromCookies 0 6 1
A utils.js ➔ encryptPassword 0 4 1
A utils.js ➔ getUserRoutes 0 11 1
A utils.js ➔ isUserAllowedOnRoute 0 19 4
A utils.js ➔ find 0 10 3

How to fix   Complexity   

Complexity

Complex classes like src/cli/users/utils.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import owasp from 'owasp-password-strength-test'
2
import bcrypt from 'bcrypt-nodejs'
3
import Cookies from 'cookies'
4
import jwt from 'jwt-simple'
5
6
import {
7
  User
8
  ,config
9
  ,coreUtils
10
} from '../../cli'
11
12
export function checkSameEmail(data) {
13
  var emailAlreadyUsed = false
14
  var bdd = User.manager.instance.get()
15
  for (var i = 0, len = bdd.length; i < len; i++) {
16
    var user = bdd[i]
17
    if (user.email === data.email && parseInt(user.id) !== parseInt(data.id)) {
18
      emailAlreadyUsed = true
19
    }
20
  }
21
22
  if (emailAlreadyUsed === true) {
23
    return {
24
      success:0,
25
      message: 'Email adress already exist'
26
    }
27
  }else {
28
    return {
29
      success:1
30
    }
31
  }
32
}
33
34
export function getRole(data) {
35
  var roles = config.users.roles
36
  Array.prototype.forEach.call(roles, (role) => {
37
    if(role.name === data.role) {
38
      data.role = role
39
    }
40
  })
41
42
  return data
43
}
44
45
export function commonPassword(data) {
46
  var owaspConfig = config.users.owasp
47
  owasp.config(owaspConfig)
48
  var sameAsUser = (typeof owaspConfig.sameAsUser !== 'undefined' && owaspConfig.sameAsUser !== null) ? owaspConfig.sameAsUser : true
49
  var mostCommon = (typeof owaspConfig.mostCommon !== 'undefined' && owaspConfig.mostCommon !== null) ? owaspConfig.mostCommon : true
50
  var mostCommonPassword = config.users.mostCommonPassword
51
  owasp.tests.required.push(function(password) {
52
    if (mostCommon && coreUtils.array.contains(mostCommonPassword, password.toLowerCase())) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if mostCommon && coreUtils....password.toLowerCase()) is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
53
      return 'the password used is too common.'
54
    }
55
  })
56
57
  var currentUserName = data.username
58
  owasp.tests.required.push(function(password) {
59
    var username = currentUserName
60
    var shouldTest = sameAsUser
61
62
    if(shouldTest) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if shouldTest is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
63
      if (password.toLowerCase() === username.toLowerCase()) {
64
        return 'username and password must be different.'
65
      }
66
      if (password.toLowerCase() === username.toLowerCase().split('').reverse().join('')) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if password.toLowerCase() =...("").reverse().join("") is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
67
        return 'username and password must be different, not just inverted.'
68
      }
69
    }
70
  })
71
72
  var res = owasp.test(data.password)
73
74
  if(typeof res.errors !== 'undefined' && res.errors !== null
75
      && res.errors.length > 0) {
76
    var message = ''
77
    Array.prototype.forEach.call(res.errors, (error) => {
78
      message += error + '<br />'
79
    })
80
    return {
81
      success:0,
82
      message: message
83
    }
84
  }else {
85
    return {
86
      success:1
87
    }
88
  }
89
}
90
91
export function encryptPassword(numb, password) {
92
  var salt = bcrypt.genSaltSync(numb)
93
  return bcrypt.hashSync(password, salt)
94
}
95
96
export function getUserRoutes(workflow) {
97
  var routes = config.users.routes
98
  var userRoles = []
99
  Array.prototype.forEach.call(Object.keys(routes), (role) => {
100
    if(role === workflow) {
101
      userRoles = routes[role]
102
    }
103
  })
104
105
  return userRoles
106
}
107
108
109
export function findSync(id) {
110
  var bdd = User.manager.instance.get()
111
  for (var i = 0, len = bdd.length; i < len; i++) {
112
    var user = bdd[i]
113
    if (parseInt(user.id) === parseInt(id)) {
114
      return user
115
    }
116
  }
117
  return null
118
}
119
120
export function find(id, done) {
121
  var bdd = User.manager.instance.get()
122
  for (var i = 0, len = bdd.length; i < len; i++) {
123
    var user = bdd[i]
124
    if (parseInt(user.id) === parseInt(id)) {
125
      return done(null, user)
126
    }
127
  }
128
  return done(null, null)
129
}
130
131
export function findByUsername(username, done) {
132
  var bdd = User.manager.instance.get()
133
  for (var i = 0, len = bdd.length; i < len; i++) {
134
    var user = bdd[i]
135
    if (user.username === username) {
136
      return done(null, user)
137
    }
138
  }
139
  return done(null, null)
140
}
141
142
export function findByEmail(email, done) {
143
  var bdd = User.manager.instance.get()
144
  for (var i = 0, len = bdd.length; i < len; i++) {
145
    var user = bdd[i]
146
    if (user.email === email) {
147
      return done(null, user)
148
    }
149
  }
150
  return done(null, null)
151
}
152
153
export function findByResetPasswordToken(resetPasswordToken, done) {
154
  var bdd = User.manager.instance.get()
155
  for (var i = 0, len = bdd.length; i < len; i++) {
156
    var user = bdd[i]
157
    if (user.resetPasswordToken === resetPasswordToken) {
158
      return done(null, user)
159
    }
160
  }
161
  return done(null, null)
162
}
163
164
export function isValid(user, password) {
165
  if(user.actif === 1) {
166
    if(bcrypt.compareSync(password, user.password)) {
167
      return true
168
    }
169
  }
170
  return false
171
}
172
173
export function decodeUser(req, res) {
174
  var decoded = {}
175
  var token = User.utils.getTokenFromCookies(req, res)
176
  if(typeof token !== 'undefined' && token !== null && token !== '') {
177
    try {
178
      var secret = config.users.secret
179
      decoded = jwt.decode(token, secret)
180
    } catch (err) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
181
  }
182
183
  return decoded
184
}
185
186
export function getTokenFromCookies(req, res) {
187
  var cookies = new Cookies(req, res, {
188
    secure: config.cookie.secure
189
  })
190
  return cookies.get('x-access-token')
191
}
192
193
export function isUserAllowedOnRoute(user, currentRoute) {
194
  var isAllowed = true
195
196
  if (user != null) {
197
    var routes = config.users.routes
198
    if(typeof routes[user.role.workflow] !== 'undefined' && routes[user.role.workflow] !== null) {
199
      Array.prototype.forEach.call(routes[user.role.workflow], (route) => {
200
        var reg = new RegExp(route)
201
        if(reg.test(currentRoute)) {
202
          isAllowed = false
203
        }
204
      })
205
    }
206
  }else {
207
    isAllowed = false
208
  }
209
210
  return isAllowed
211
}
212
213
export function getAll() {
214
  return User.manager.instance.get()
215
}