openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
1,143 lines (1,142 loc) • 42.3 kB
HTML
<html lang="en">
<head>
<title>Code coverage report for src/api/users.coffee</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>
<a href="../../index.html">All files</a> / <a href="index.html">src/api</a> users.coffee
</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">20.98% </span>
<span class="quiet">Statements</span>
<span class='fraction'>30/143</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/21</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/16</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">21.13% </span>
<span class="quiet">Lines</span>
<span class='fraction'>30/142</span>
</div>
</div>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet">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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360</td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">User = require('../model/users').User
Q = require 'q'
logger = require 'winston'
authorisation = require './authorisation'
moment = require 'moment'
randtoken = require 'rand-token'
contact = require '../contact'
config = require "../config/config"
config.newUserExpiry = config.get('newUserExpiry')
config.userPasswordResetExpiry = config.get('userPasswordResetExpiry')
config.alerts = config.get('alerts')
utils = require "../utils"
atna = require 'atna-audit'
os = require 'os'
auditing = require '../auditing'
himSourceID = config.get('auditing').auditEvents.auditSourceID
###
# Get authentication details
###
exports.authenticate = <span class="fstat-no" title="function not covered" >(</span>email) ->
<span class="cstat-no" title="statement not covered" > email = u</span>nescape email
try
<span class="cstat-no" title="statement not covered" > user = y</span>ield User.findOne(email: email).exec()
<span class="cstat-no" title="statement not covered" > if not user</span>
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 404, "Could not find user by email #{email}", 'info'</span>
# Audit unknown user requested
<span class="cstat-no" title="statement not covered" > audit = a</span>tna.userLoginAudit atna.OUTCOME_SERIOUS_FAILURE, himSourceID, os.hostname(), email
<span class="cstat-no" title="statement not covered" > audit = a</span>tna.wrapInSyslog audit
auditing.sendAuditEvent audit, <span class="fstat-no" title="function not covered" ></span>-> logger.debug 'Processed internal audit'
else
this.body =
salt: user.passwordSalt
ts: new Date()
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Error during authentication #{e}", 'error'
#################################
### Reset password Functions ###
#################################
passwordResetPlainMessageTemplate = <span class="fstat-no" title="function not covered" >(</span>firstname, setPasswordLink) -> """
<---------- Existing User - Reset Password ---------->
Hi #{firstname},
A request has been made to reset your password on the OpenHIM instance running on #{config.alerts.himInstance}
Follow the below link to reset your password and log into OpenHIM Console
#{setPasswordLink}
<---------- Existing User - Reset Password ---------->
"""
passwordResetHtmlMessageTemplate = <span class="fstat-no" title="function not covered" >(</span>firstname, setPasswordLink) -> """
<h1>Reset OpenHIM Password</h1>
<p>Hi #{firstname},<br/><br/>A request has been made to reset your password on the OpenHIM instance running on #{config.alerts.himInstance}</p>
<p>Follow the below link to set your password and log into OpenHIM Console</p>
<p>#{setPasswordLink}</p>
"""
exports.generateRandomToken = <span class="fstat-no" title="function not covered" ></span>() ->
<span class="cstat-no" title="statement not covered" > return r</span>andtoken.generate 32
###
# update user token/expiry and send new password email
###
exports.userPasswordResetRequest = <span class="fstat-no" title="function not covered" >(</span>email) ->
<span class="cstat-no" title="statement not covered" > email = u</span>nescape email
if email is 'root@openhim.org'
<span class="cstat-no" title="statement not covered" > this.body = "</span>Cannot request password reset for 'root@openhim.org'"
<span class="cstat-no" title="statement not covered" > this.status = 4</span>03
<span class="cstat-no" title="statement not covered" > return</span>
# Generate the new user token here
# set expiry date = true
<span class="cstat-no" title="statement not covered" > token = e</span>xports.generateRandomToken()
<span class="cstat-no" title="statement not covered" > duration = config.userPasswordResetExpiry.d</span>uration
<span class="cstat-no" title="statement not covered" > durationType = config.userPasswordResetExpiry.d</span>urationType
<span class="cstat-no" title="statement not covered" > expiry = m</span>oment().add(duration, durationType).utc().format()
updateUserTokenExpiry =
token: token
tokenType: 'existingUser'
expiry: expiry
try
<span class="cstat-no" title="statement not covered" > user = y</span>ield User.findOneAndUpdate(email: email, updateUserTokenExpiry).exec()
if not user
<span class="cstat-no" title="statement not covered" > this.body = "Tried to request password reset for invalid email address: #{e</span>mail}"
<span class="cstat-no" title="statement not covered" > this.status = 4</span>04
<span class="cstat-no" title="statement not covered" > logger.info "Tried to request password reset for invalid email address: #{email}"</span>
<span class="cstat-no" title="statement not covered" > return</span>
<span class="cstat-no" title="statement not covered" > consoleURL = config.alerts.c</span>onsoleURL
<span class="cstat-no" title="statement not covered" > setPasswordLink = "#{consoleURL}/#/set-password/#{t</span>oken}"
# Send email to user to reset password
<span class="cstat-no" title="statement not covered" > plainMessage = p</span>asswordResetPlainMessageTemplate user.firstname, setPasswordLink
<span class="cstat-no" title="statement not covered" > htmlMessage = p</span>asswordResetHtmlMessageTemplate user.firstname, setPasswordLink
<span class="cstat-no" title="statement not covered" > sendEmail = Q</span>.denodeify contact.contactUser
<span class="cstat-no" title="statement not covered" > sendEmailError = y</span>ield sendEmail 'email', email, 'OpenHIM Console Password Reset', plainMessage, htmlMessage
if sendEmailError
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 500, "Could not send email to user via the API #{e}", 'error'</span>
<span class="cstat-no" title="statement not covered" > logger.info 'The email has been sent to the user'</span>
<span class="cstat-no" title="statement not covered" > this.body = "</span>Successfully set user token/expiry for password reset."
<span class="cstat-no" title="statement not covered" > this.status = 2</span>01
logger.info "User updated token/expiry for password reset #{email}"
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Could not update user with email #{email} via the API #{e}", 'error'
#######################################
### New User Set Password Functions ###
#######################################
# get the new user details
exports.getUserByToken = <span class="fstat-no" title="function not covered" >(</span>token) ->
<span class="cstat-no" title="statement not covered" > token = u</span>nescape token
try
projectionRestriction = "email": 1, "firstname": 1, "surname": 1, "msisdn": 1, "token": 1, "tokenType": 1, "locked": 1, "expiry": 1, "_id": 0
<span class="cstat-no" title="statement not covered" > result = y</span>ield User.findOne(token: token, projectionRestriction).exec()
<span class="cstat-no" title="statement not covered" > if not result</span>
<span class="cstat-no" title="statement not covered" > this.body = "User with token #{token} </span>could not be found."
this.status = 404
else
# if expiry date has past
<span class="cstat-no" title="statement not covered" > if moment(result.expiry).isBefore(moment())</span>
# user- set password - expired
<span class="cstat-no" title="statement not covered" > this.body = "Token #{token} </span>has expired"
this.status = 410
else
this.body = result
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Could not find user with token #{token} via the API #{e}", 'error'
# update the password/details for the new user
exports.updateUserByToken = <span class="fstat-no" title="function not covered" >(</span>token) ->
<span class="cstat-no" title="statement not covered" > token = u</span>nescape token
<span class="cstat-no" title="statement not covered" > userData = this.request.b</span>ody
try
# first try get new user details to check expiry date
<span class="cstat-no" title="statement not covered" > userDataExpiry = y</span>ield User.findOne(token: token).exec()
<span class="cstat-no" title="statement not covered" > if not userDataExpiry</span>
<span class="cstat-no" title="statement not covered" > this.body = "User with token #{token} </span>could not be found."
<span class="cstat-no" title="statement not covered" > this.status = 4</span>04
<span class="cstat-no" title="statement not covered" > return</span>
else
# if expiry date has past
<span class="cstat-no" title="statement not covered" > if moment(userDataExpiry.expiry).isBefore(moment())</span>
# new user- set password - expired
<span class="cstat-no" title="statement not covered" > this.body = "User with token #{token} </span>has expired to set their password."
<span class="cstat-no" title="statement not covered" > this.status = 4</span>10
<span class="cstat-no" title="statement not covered" > return</span>
catch <span class="cstat-no" title="statement not covered" >e</span>
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 500, "Could not find user with token #{token} via the API #{e}", 'error'</span>
<span class="cstat-no" title="statement not covered" > return</span>
# check to make sure 'msisdn' isnt 'undefined' when saving
i</span></span>f userData.msisdn then <span class="cstat-no" title="statement not covered" >msisdn = userData.msisdn else <span class="cstat-no" title="statement not covered" >msisdn = null
# construct user object to prevent other properties from being updated
userUpdateObj =
token: null
tokenType: null
expiry: null
passwordAlgorithm: userData.passwordAlgorithm
passwordSalt: userData.passwordSalt
passwordHash: userData.passwordHash
if userDataExpiry.tokenType is 'newUser'
<span class="cstat-no" title="statement not covered" > userUpdateObj.firstname = userData.f</span>irstname
<span class="cstat-no" title="statement not covered" > userUpdateObj.surname = userData.s</span>urname
<span class="cstat-no" title="statement not covered" > userUpdateObj.locked = f</span>alse
<span class="cstat-no" title="statement not covered" > userUpdateObj.msisdn = msisdn</span>
try
<span class="cstat-no" title="statement not covered" > yield User.findOneAndUpdate(token: token, userUpdateObj).exec()</span>
<span class="cstat-no" title="statement not covered" > this.body = "</span>Successfully set new user password."
logger.info "User updated by token #{token}"
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Could not update user with token #{token} via the API #{e}", 'error'
#######################################
### New User Set Password Functions ###
#######################################
plainMessageTemplate = <span class="fstat-no" title="function not covered" >(</span>firstname, setPasswordLink) -> """
<---------- New User - Set Password ---------->
Hi #{firstname},
A profile has been created for you on the OpenHIM instance running on #{config.alerts.himInstance}
Follow the below link to set your password and log into OpenHIM Console
#{setPasswordLink}
<---------- New User - Set Password ---------->
"""
htmlMessageTemplate = <span class="fstat-no" title="function not covered" >(</span>firstname, setPasswordLink) -> """
<h1>New OpenHIM Profile</h1>
<p>Hi #{firstname},<br/><br/>A profile has been created for you on the OpenHIM instance running on #{config.alerts.himInstance}</p>
<p>Follow the below link to set your password and log into OpenHIM Console</p>
<p>#{setPasswordLink}</p>
"""
###
# Adds a user
###
exports.addUser = <span class="fstat-no" title="function not covered" ></span>->
# Test if the user is authorised
if not authorisation.inGroup 'admin', this.authenticated
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to addUser denied.", 'info'</span>
<span class="cstat-no" title="statement not covered" > return</span>
<span class="cstat-no" title="statement not covered" > userData = this.request.b</span>ody
# Generate the new user token here
# set locked = true
# set expiry date = true
<span class="cstat-no" title="statement not covered" > token = r</span>andtoken.generate 32
<span class="cstat-no" title="statement not covered" > userData.token = t</span>oken
<span class="cstat-no" title="statement not covered" > userData.tokenType = '</span>newUser'
<span class="cstat-no" title="statement not covered" > userData.locked = t</span>rue
<span class="cstat-no" title="statement not covered" > duration = config.newUserExpiry.d</span>uration
<span class="cstat-no" title="statement not covered" > durationType = config.newUserExpiry.d</span>urationType
<span class="cstat-no" title="statement not covered" > userData.expiry = m</span>oment().add(duration, durationType).utc().format()
<span class="cstat-no" title="statement not covered" > consoleURL = config.alerts.c</span>onsoleURL
<span class="cstat-no" title="statement not covered" > setPasswordLink = "#{consoleURL}/#/set-password/#{t</span>oken}"
try
<span class="cstat-no" title="statement not covered" > user = new U</span>ser userData
<span class="cstat-no" title="statement not covered" > result = y</span>ield Q.ninvoke user, 'save'
# Send email to new user to set password
<span class="cstat-no" title="statement not covered" > plainMessage = p</span>lainMessageTemplate userData.firstname, setPasswordLink
<span class="cstat-no" title="statement not covered" > htmlMessage = h</span>tmlMessageTemplate userData.firstname, setPasswordLink
<span class="cstat-no" title="statement not covered" > contact.contactUser 'email', userData.email, 'OpenHIM Console Profile', plainMessage, htmlMessage, <span class="fstat-no" title="function not covered" >(</span>err) -></span>
if err
logger.error "The email could not be sent to the user via the API #{err}"
else
logger.info 'The email has been sent to the new user'
<span class="cstat-no" title="statement not covered" > this.body = '</span>User successfully created'
<span class="cstat-no" title="statement not covered" > this.status = 2</span>01
logger.info "User #{this.authenticated.email} created user #{userData.email}"
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Could not add user via the API #{e}", 'error'
###
# Retrieves the details of a specific user
###
exports.getUser = <span class="fstat-no" title="function not covered" >(</span>email) ->
<span class="cstat-no" title="statement not covered" > email = u</span>nescape email
# Test if the user is authorised, allow a user to fetch their own details
if not authorisation.inGroup('admin', this.authenticated) and this.authenticated.email isnt email
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to getUser denied.", 'info'</span>
<span class="cstat-no" title="statement not covered" > return</span>
try
<span class="cstat-no" title="statement not covered" > result = y</span>ield User.findOne(email: email).exec()
<span class="cstat-no" title="statement not covered" > if not result</span>
<span class="cstat-no" title="statement not covered" > this.body = "User with email #{email} </span>could not be found."
this.status = 404
else
this.body = result
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Could not get user via the API #{e}", 'error'
exports.updateUser = <span class="fstat-no" title="function not covered" >(</span>email) ->
<span class="cstat-no" title="statement not covered" > email = u</span>nescape email
# Test if the user is authorised, allow a user to update their own details
if not authorisation.inGroup('admin', this.authenticated) and this.authenticated.email isnt email
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to updateUser denied.", 'info'</span>
<span class="cstat-no" title="statement not covered" > return</span>
<span class="cstat-no" title="statement not covered" > userData = this.request.b</span>ody
# reset token/locked/expiry when user is updated and password supplied
if userData.passwordAlgorithm and userData.passwordHash and userData.passwordSalt
<span class="cstat-no" title="statement not covered" > userData.token = n</span>ull
<span class="cstat-no" title="statement not covered" > userData.tokenType = n</span>ull
<span class="cstat-no" title="statement not covered" > userData.locked = f</span>alse
<span class="cstat-no" title="statement not covered" > userData.expiry = null</span>
# Don't allow a non-admin user to change their groups
i</span>f this.authenticated.email is email and not authorisation.inGroup 'admin', this.authenticated then <span class="cstat-no" title="statement not covered" >delete userData.groups
#Ignore _id if it exists (update is by email)
i</span>f userData._id then <span class="cstat-no" title="statement not covered" >delete userData._id
try
<span class="cstat-no" title="statement not covered" > yield User.findOneAndUpdate(email: email, userData).exec()</span>
<span class="cstat-no" title="statement not covered" > this.body = "</span>Successfully updated user."
logger.info "User #{this.authenticated.email} updated user #{userData.email}"
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Could not update user #{email} via the API #{e}", 'error'
exports.removeUser = <span class="fstat-no" title="function not covered" >(</span>email) ->
# Test if the user is authorised
if not authorisation.inGroup 'admin', this.authenticated
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to removeUser denied.", 'info'</span>
<span class="cstat-no" title="statement not covered" > return</span>
<span class="cstat-no" title="statement not covered" > email = u</span>nescape email
# Test if the user is root@openhim.org
if email is 'root@openhim.org'
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 403, "User root@openhim.org is OpenHIM root, User cannot be deleted through the API", 'info'</span>
<span class="cstat-no" title="statement not covered" > return</span>
try
<span class="cstat-no" title="statement not covered" > yield User.findOneAndRemove(email: email).exec()</span>
<span class="cstat-no" title="statement not covered" > this.body = "Successfully removed user with email #{e</span>mail}"
logger.info "User #{this.authenticated.email} removed user #{email}"
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Could not remove user #{email} via the API #{e}", 'error'
exports.getUsers = <span class="fstat-no" title="function not covered" ></span>->
# Test if the user is authorised
if not authorisation.inGroup 'admin', this.authenticated
<span class="cstat-no" title="statement not covered" > utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to getUsers denied.", 'info'</span>
<span class="cstat-no" title="statement not covered" > return</span>
try
this.body = yield User.find().exec()
catch <span class="cstat-no" title="statement not covered" >e</span>
utils.logAndSetResponse this, 500, "Could not fetch all users via the API #{e}", 'error'
</pre></td></tr>
</table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage
generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Oct 10 2016 13:39:22 GMT+0200 (SAST)
</div>
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="../../sorter.js"></script>
</body>
</html>