UNPKG

72.4 kBJavaScriptView Raw
1/* eslint-env mocha */
2'use strict';
3
4var request = require('supertest');
5var assert = require('assert');
6var _ = require('lodash');
7var async = require('async');
8var chance = new (require('chance'))();
9var docker = process.env.DOCKER;
10var customer = process.env.CUSTOMER;
11let EventEmitter = require('events');
12
13module.exports = function(app, template, hook) {
14 template.hooks.addEmitter(new EventEmitter());
15
16 describe('Authentication', function() {
17 it('Should be able to register an administrator', function(done) {
18 request(app)
19 .post(hook.alter('url', '/form/' + template.forms.adminRegister._id + '/submission', template))
20 .send({
21 data: {
22 'email': template.users.admin.data.email,
23 'password': template.users.admin.data.password
24 }
25 })
26 .expect(200)
27 .expect('Content-Type', /json/)
28 .end(function(err, res) {
29 if (err) {
30 return done(err);
31 }
32
33 var response = res.body;
34 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
35 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
36 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
37 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
38 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
39 assert.equal(response.data.email, template.users.admin.data.email);
40 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
41 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
42 assert.equal(response.form, template.resources.admin._id);
43 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
44 assert(response.hasOwnProperty('owner'), 'The response should contain the resource `owner`.');
45 assert.notEqual(response.owner, null);
46 assert.equal(response.owner, response._id);
47 assert.equal(response.roles.length, 1);
48 assert.equal(response.roles[0].toString(), template.roles.administrator._id.toString());
49
50 // Update our testProject.owners data.
51 var tempPassword = template.users.admin.data.password;
52 template.users.admin = response;
53 template.users.admin.data.password = tempPassword;
54
55 // Store the JWT for future API calls.
56 template.users.admin.token = res.headers['x-jwt-token'];
57
58 done();
59 });
60 });
61
62 it('Register another administrator', function(done) {
63 request(app)
64 .post(hook.alter('url', '/form/' + template.forms.adminRegister._id + '/submission', template))
65 .send({
66 data: {
67 'email': template.users.admin2.data.email,
68 'password': template.users.admin2.data.password
69 }
70 })
71 .expect(200)
72 .expect('Content-Type', /json/)
73 .end(function(err, res) {
74 if (err) {
75 return done(err);
76 }
77
78 var response = res.body;
79 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
80 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
81 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
82 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
83 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
84 assert.equal(response.data.email, template.users.admin2.data.email);
85 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
86 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
87 assert.equal(response.form, template.resources.admin._id);
88 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
89 assert(response.hasOwnProperty('owner'), 'The response should contain the resource `owner`.');
90 assert.notEqual(response.owner, null);
91 assert.equal(response.owner, response._id);
92 assert.equal(response.roles.length, 1);
93 assert.equal(response.roles[0].toString(), template.roles.administrator._id.toString());
94
95 // Update our testProject.owners data.
96 var tempPassword = template.users.admin2.data.password;
97 template.users.admin2 = response;
98 template.users.admin2.data.password = tempPassword;
99
100 // Store the JWT for future API calls.
101 template.users.admin2.token = res.headers['x-jwt-token'];
102
103 done();
104 });
105 });
106
107 it('A Form.io User should be able to login as administrator', function(done) {
108 request(app)
109 .post(hook.alter('url', '/form/' + template.forms.adminLogin._id + '/submission', template))
110 .send({
111 data: {
112 'email': template.users.admin.data.email,
113 'password': template.users.admin.data.password
114 }
115 })
116 .expect('Content-Type', /json/)
117 .expect(200)
118 .end(function(err, res) {
119 if (err) {
120 return done(err);
121 }
122
123 var response = res.body;
124 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
125 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
126 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
127 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
128 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
129 assert.equal(response.data.email, template.users.admin.data.email);
130 assert(!response.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
131 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
132 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
133 assert.equal(response.form, template.resources.admin._id);
134 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
135
136 // Update our template.users.admins data.
137 var tempPassword = template.users.admin.data.password;
138 template.users.admin = response;
139 template.users.admin.data.password = tempPassword;
140
141 // Store the JWT for future API calls.
142 template.users.admin.token = res.headers['x-jwt-token'];
143 done();
144 });
145 });
146
147 it('A Form.io User should not be able to login without credentials', function(done) {
148 request(app)
149 .post(hook.alter('url', '/form/' + template.forms.adminLogin._id + '/submission', template))
150 .send({})
151 .expect(401)
152 .end(function(err, res) {
153 if (err) {
154 return done(err);
155 }
156
157 assert.equal(!res.headers['x-jwt-token'], true);
158 done();
159 });
160 });
161
162 it('A Form.io User should not be able to login with empty credentials', function(done) {
163 request(app)
164 .post(hook.alter('url', '/form/' + template.forms.adminLogin._id + '/submission', template))
165 .send({
166 data: {
167 username: '',
168 password: ''
169 }
170 })
171 .expect(401)
172 .end(function(err, res) {
173 if (err) {
174 return done(err);
175 }
176
177 assert.equal(!res.headers['x-jwt-token'], true);
178 done();
179 });
180 });
181
182 it('A Form.io User should be able to login using an Alias', function(done) {
183 request(app)
184 .post(hook.alter('url', '/' + template.forms.adminLogin.path, template))
185 .send({
186 data: {
187 'email': template.users.admin.data.email,
188 'password': template.users.admin.data.password
189 }
190 })
191 .expect('Content-Type', /json/)
192 .expect(200)
193 .end(function(err, res) {
194 if (err) {
195 return done(err);
196 }
197
198 var response = res.body;
199 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
200 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
201 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
202 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
203 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
204 assert.equal(response.data.email, template.users.admin.data.email);
205 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
206 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
207 assert.equal(response.form, template.resources.admin._id);
208 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
209
210 // Update our template.users.admins data.
211 var tempPassword = template.users.admin.data.password;
212 template.users.admin = response;
213 template.users.admin.data.password = tempPassword;
214
215 // Store the JWT for future API calls.
216 template.users.admin.token = res.headers['x-jwt-token'];
217
218 done();
219 });
220 });
221
222 it('A Form.io User should not be able to login without credentials using an Alias', function(done) {
223 request(app)
224 .post(hook.alter('url', '/' + template.forms.adminLogin.path, template))
225 .send({})
226 .expect(401)
227 .end(function(err, res) {
228 if (err) {
229 return done(err);
230 }
231
232 assert.equal(!res.headers['x-jwt-token'], true);
233 done();
234 });
235 });
236
237 it('Should be able to register an authenticated user', function(done) {
238 template.hooks.reset();
239 request(app)
240 .post(hook.alter('url', '/form/' + template.forms.userRegister._id + '/submission', template))
241 .send({
242 data: {
243 'email': template.users.user1.data.email,
244 'password': template.users.user1.data.password
245 }
246 })
247 .expect(200)
248 .expect('Content-Type', /json/)
249 .end(function(err, res) {
250 if (err) {
251 return done(err);
252 }
253
254 var response = res.body;
255 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
256 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
257 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
258 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
259 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
260 assert.equal(response.data.email, template.users.user1.data.email);
261 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
262 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
263 assert.equal(response.form, template.resources.user._id);
264 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
265 assert(response.hasOwnProperty('owner'), 'The response should contain the resource `owner`.');
266 assert.notEqual(response.owner, null);
267 assert.equal(response.owner, response._id);
268 assert.equal(response.roles.length, 1);
269 assert.equal(response.roles[0].toString(), template.roles.authenticated._id.toString());
270
271 // Update our testProject.owners data.
272 var tempPassword = template.users.user1.data.password;
273 template.users.user1 = response;
274 template.users.user1.data.password = tempPassword;
275
276 // Store the JWT for future API calls.
277 template.users.user1.token = res.headers['x-jwt-token'];
278
279 done();
280 });
281 });
282
283 if (!docker) {
284 it('Should have sent an email to the user with an auth token', function (done) {
285 var email = template.hooks.getLastEmail();
286 new Promise((resolve, reject) => {
287 if (email && Object.keys(email) > 0) {
288 return resolve(email);
289 }
290
291 let events = template.hooks.getEmitter();
292 if (events) {
293 events.once('newMail', (email) => {
294 return resolve(email);
295 });
296 }
297 })
298 .then(email => {
299 assert.equal(email.from, 'no-reply@form.io');
300 assert.equal(email.to, template.users.user1.data.email);
301 assert.equal(email.subject, 'New user ' + template.users.user1._id.toString() + ' created');
302 assert.equal(email.html, 'Email: ' + template.users.user1.data.email);
303 done();
304 })
305 .catch(done)
306 });
307 }
308
309 it('Should be able to validate a request with the validate param.', function(done) {
310 request(app)
311 .post(hook.alter('url', '/form/' + template.forms.userRegister._id + '/submission?dryrun=1', template))
312 .send({
313 data: {
314 'email': template.users.user2.data.email,
315 'password': template.users.user2.data.password
316 }
317 })
318 .expect(200)
319 .expect('Content-Type', /json/)
320 .end(done);
321 });
322
323 it('Should be able to register another authenticated user.', function(done) {
324 request(app)
325 .post(hook.alter('url', '/form/' + template.forms.userRegister._id + '/submission', template))
326 .send({
327 data: {
328 'email': template.users.user2.data.email,
329 'password': template.users.user2.data.password
330 }
331 })
332 .expect(200)
333 .expect('Content-Type', /json/)
334 .end(function(err, res) {
335 if (err) {
336 return done(err);
337 }
338
339 var response = res.body;
340 assert(response.hasOwnProperty('owner'), 'The response should contain the resource `owner`.');
341 assert.notEqual(response.owner, null);
342 assert.equal(response.owner, response._id);
343
344 // Update our testProject.owners data.
345 var tempPassword = template.users.user2.data.password;
346 template.users.user2 = response;
347 template.users.user2.data.password = tempPassword;
348
349 // Store the JWT for future API calls.
350 template.users.user2.token = res.headers['x-jwt-token'];
351
352 done();
353 });
354 });
355
356 it('Should be able to register a user with special characters in their email address.', function(done) {
357 request(app)
358 .post(hook.alter('url', '/form/' + template.forms.userRegister._id + '/submission', template))
359 .send({
360 data: {
361 'email': 'test+user@example.com',
362 'password': template.users.user2.data.password
363 }
364 })
365 .expect(200)
366 .expect('Content-Type', /json/)
367 .end(function(err, res) {
368 if (err) {
369 return done(err);
370 }
371 done();
372 });
373 });
374
375 // Perform a login.
376 var login = function(done) {
377 request(app)
378 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
379 .send({
380 data: {
381 'email': template.users.user1.data.email,
382 'password': template.users.user1.data.password
383 }
384 })
385 .expect('Content-Type', /json/)
386 .expect(200)
387 .end(function(err, res) {
388 if (err) {
389 return done(err);
390 }
391
392 var response = res.body;
393 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
394 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
395 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
396 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
397 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
398 assert.equal(response.data.email, template.users.user1.data.email);
399 assert(!response.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
400 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
401 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
402 assert.equal(response.form, template.resources.user._id);
403 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
404
405 // Update our template.users.admins data.
406 var tempPassword = template.users.user1.data.password;
407 template.users.user1 = response;
408 template.users.user1.data.password = tempPassword;
409
410 // Store the JWT for future API calls.
411 template.users.user1.token = res.headers['x-jwt-token'];
412 done();
413 });
414 };
415
416 it('A Form.io User should be able to login as an authenticated user', login);
417
418 it('A Form.io User should not be able to login with bad password', function(done) {
419 request(app)
420 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
421 .send({
422 data: {
423 'email': template.users.user1.data.email,
424 'password': 'badpassword!!!'
425 }
426 })
427 .expect(401)
428 .end(function(err, res) {
429 if (err) {
430 return done(err);
431 }
432
433 assert.equal(!res.headers['x-jwt-token'], true);
434 done();
435 });
436 });
437
438 var lastAttempt = 0;
439 it('A Form.io User should get locked out if they keep trying a bad password', function(done) {
440 var count = 0;
441 async.whilst(
442 function(next) { return next(null, count < 4); },
443 function(next) {
444 count++;
445 lastAttempt = (new Date()).getTime();
446 request(app)
447 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
448 .send({
449 data: {
450 'email': template.users.user1.data.email,
451 'password': 'badpassword' + count + '!'
452 }
453 })
454 .expect(401)
455 .end(function(err, res) {
456 if (err) {
457 return next(err);
458 }
459
460 assert.equal(res.text, count < 4 ? 'User or password was incorrect' : 'Maximum Login attempts. Please wait 4 seconds before trying again.');
461 assert.equal(!res.headers['x-jwt-token'], true);
462 next();
463 });
464 },
465 function(err) {
466 if (err) {
467 return done(err);
468 }
469 done();
470 }
471 );
472 });
473
474 it('Verify that the Form.io user is locked out for 1 seconds even with right password.', function(done) {
475 request(app)
476 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
477 .send({
478 data: {
479 'email': template.users.user1.data.email,
480 'password': template.users.user1.data.password
481 }
482 })
483 .expect(401)
484 .end(function(err, res) {
485 if (err) {
486 return done(err);
487 }
488
489 assert.equal(res.text.indexOf('You must wait'), 0);
490 assert.equal(!res.headers['x-jwt-token'], true);
491 done();
492 });
493 });
494
495 it('Verify that we can login again after waiting.', function(done) {
496 setTimeout(function() {
497 login(done);
498 }, 4500);
499 });
500
501 it('Attempt 4 bad logins to attempt good login after window.', function(done) {
502 var count = 0;
503 async.whilst(
504 function(next) { return next(null, count < 4); },
505 function(next) {
506 count++;
507 lastAttempt = (new Date()).getTime();
508 request(app)
509 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
510 .send({
511 data: {
512 'email': template.users.user1.data.email,
513 'password': 'badpassword' + count + '!'
514 }
515 })
516 .expect(401)
517 .end(function(err, res) {
518 if (err) {
519 return next(err);
520 }
521
522 assert.equal(res.text, 'User or password was incorrect');
523 assert.equal(!res.headers['x-jwt-token'], true);
524 next();
525 });
526 },
527 function(err) {
528 if (err) {
529 return done(err);
530 }
531 done();
532 }
533 );
534 });
535
536 it('A user should be able to login as an authenticated user', function(done) {
537 request(app)
538 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
539 .send({
540 data: {
541 'email': template.users.user2.data.email,
542 'password': template.users.user2.data.password
543 }
544 })
545 .expect('Content-Type', /json/)
546 .expect(200)
547 .end(function(err, res) {
548 if (err) {
549 return done(err);
550 }
551 template.users.user2.token = res.headers['x-jwt-token'];
552 done();
553 });
554 });
555
556 it('A user should be able to login using a case insensitive email', function(done) {
557 request(app)
558 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
559 .send({
560 data: {
561 'email': template.users.user2.data.email.toUpperCase(),
562 'password': template.users.user2.data.password
563 }
564 })
565 .expect('Content-Type', /json/)
566 .expect(200)
567 .end(function(err, res) {
568 if (err) {
569 return done(err);
570 }
571 template.users.user2.token = res.headers['x-jwt-token'];
572 done();
573 });
574 });
575
576 it('A user should be able to reset their password', function(done) {
577 request(app)
578 .put(hook.alter('url', '/form/' + template.resources.user._id + '/submission/' + template.users.user2._id, template))
579 .set('x-jwt-token', template.users.user2.token)
580 .send({
581 data: {
582 'email': template.users.user2.data.email,
583 'password': 'temppass'
584 }
585 })
586 .expect('Content-Type', /json/)
587 .expect(200)
588 .end(function(err, res) {
589 if (err) {
590 return done(err);
591 }
592 template.users.user2.token = res.headers['x-jwt-token'];
593 done();
594 });
595 });
596
597 it('A user should be able to login with new password', function(done) {
598 request(app)
599 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
600 .send({
601 data: {
602 'email': template.users.user2.data.email,
603 'password': 'temppass'
604 }
605 })
606 .expect('Content-Type', /json/)
607 .expect(200)
608 .end(function(err, res) {
609 if (err) {
610 return done(err);
611 }
612 template.users.user2.token = res.headers['x-jwt-token'];
613 done();
614 });
615 });
616
617 it('A user should be able to set their password back to normal', function(done) {
618 request(app)
619 .put(hook.alter('url', '/form/' + template.resources.user._id + '/submission/' + template.users.user2._id, template))
620 .set('x-jwt-token', template.users.user2.token)
621 .send({
622 data: {
623 'email': template.users.user2.data.email,
624 'password': template.users.user2.data.password
625 }
626 })
627 .expect('Content-Type', /json/)
628 .expect(200)
629 .end(function(err, res) {
630 if (err) {
631 return done(err);
632 }
633 template.users.user2.token = res.headers['x-jwt-token'];
634 done();
635 });
636 });
637
638 it('An Anonymous user should not be able to access the /current endpoint', function(done) {
639 request(app)
640 .get(hook.alter('url', '/current', template))
641 .expect(401)
642 .end(done);
643 });
644
645 it('An administrator should be able to see the current User', function(done) {
646 request(app)
647 .get(hook.alter('url', '/current', template))
648 .set('x-jwt-token', template.users.admin.token)
649 .expect(200)
650 .end(function(err, res) {
651 if (err) {
652 return done(err);
653 }
654
655 var response = res.body;
656 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
657 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
658 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
659 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
660 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
661 assert.equal(response.data.email, template.users.admin.data.email);
662 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
663 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
664 assert.equal(response.form, template.resources.admin._id);
665 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
666
667 // Update our template.users.admins data.
668 var tempPassword = template.users.admin.data.password;
669 template.users.admin = response;
670 template.users.admin.data.password = tempPassword;
671
672 // Store the JWT for future API calls.
673 template.users.admin.token = res.headers['x-jwt-token'];
674
675 done();
676 });
677 });
678
679 it('A user should be able to see the current User', function(done) {
680 request(app)
681 .get(hook.alter('url', '/current', template))
682 .set('x-jwt-token', template.users.user1.token)
683 .expect(200)
684 .end(function(err, res) {
685 if (err) {
686 return done(err);
687 }
688
689 var response = res.body;
690 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
691 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
692 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
693 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
694 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
695 assert.equal(response.data.email, template.users.user1.data.email);
696 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
697 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
698 assert.equal(response.form, template.resources.user._id);
699 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
700
701 // Update our template.users.admins data.
702 var tempPassword = template.users.user1.data.password;
703 template.users.user1 = response;
704 template.users.user1.data.password = tempPassword;
705
706 // Store the JWT for future API calls.
707 template.users.user1.token = res.headers['x-jwt-token'];
708
709 done();
710 });
711 });
712
713 it('An Authenticated and Registered User should be able to logout', function(done) {
714 var oldToken = null;
715 request(app)
716 .get(hook.alter('url', '/logout', template))
717 .set('x-jwt-token', template.users.user1.token)
718 .expect(200)
719 .end(function(err, res) {
720 if (err) {
721 return done(err);
722 }
723
724 // Confirm that the token was sent and empty.
725 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
726 assert.equal(res.headers['x-jwt-token'], '');
727 done();
728 });
729 });
730
731 it('Attempt 5th bad login request, but after the accepted window.', function(done) {
732 setTimeout(function() {
733 request(app)
734 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
735 .send({
736 data: {
737 'email': template.users.user1.data.email,
738 'password': 'badpassword!'
739 }
740 })
741 .expect(401)
742 .end(function(err, res) {
743 if (err) {
744 return done(err);
745 }
746
747 assert.equal(res.text, 'User or password was incorrect');
748 assert.equal(!res.headers['x-jwt-token'], true);
749 done();
750 });
751 }, 4500);
752 });
753
754 var oldToken = null;
755 it('An Authenticated and Registered User should be able to login again', function(done) {
756 oldToken = template.users.user1.token;
757 request(app)
758 .post(hook.alter('url', '/' + template.forms.userLogin.path, template))
759 .send({
760 data: {
761 'email': template.users.user1.data.email,
762 'password': template.users.user1.data.password
763 }
764 })
765 .expect('Content-Type', /json/)
766 .expect(200)
767 .end(function(err, res) {
768 if (err) {
769 return done(err);
770 }
771
772 var response = res.body;
773 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
774 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
775 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
776 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
777 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
778 assert.equal(response.data.email, template.users.user1.data.email);
779 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
780 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
781 assert.equal(response.form, template.resources.user._id);
782 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
783
784 // Confirm the new token is different than the last.
785 assert.notEqual(
786 res.headers.hasOwnProperty('x-jwt-token'),
787 oldToken,
788 'The `x-jwt-token` recieved from re-logging in should be different than previously.'
789 );
790
791 // Update our testProject.owners data.
792 var tempPassword = template.users.user1.data.password;
793 template.users.user1 = response;
794 template.users.user1.data.password = tempPassword;
795
796 // Store the JWT for future API calls.
797 template.users.user1.token = res.headers['x-jwt-token'];
798
799 done();
800 });
801 });
802
803 it('A User who has re-logged in for a User-Created Project should be able to view the current User', function(done) {
804 request(app)
805 .get('/current')
806 .set('x-jwt-token', template.users.user1.token)
807 .expect(200)
808 .end(function(err, res) {
809 if (err) {
810 return done(err);
811 }
812
813 var response = res.body;
814 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
815 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
816 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
817 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
818 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
819 assert.equal(response.data.email, template.users.user1.data.email);
820 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
821 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
822 assert.equal(response.form, template.resources.user._id);
823 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
824
825 // Update our template.users.user1 data.
826 var tempPassword = template.users.user1.data.password;
827 template.users.user1 = response;
828 template.users.user1.data.password = tempPassword;
829
830 // Store the JWT for future API calls.
831 template.users.user1.token = res.headers['x-jwt-token'];
832
833 done();
834 });
835 });
836 });
837
838 if (!customer) {
839 describe('Get Temporary Tokens', function() {
840 it('A User should not be able to get a temporary token without providing their current one.', function(done) {
841 request(app)
842 .get(hook.alter('url', '/token', template))
843 .expect(400)
844 .expect('No authentication token provided.')
845 .end(done);
846 });
847
848 it('A User should not be able to get a temporary token by providing a bad existing token.', function(done) {
849 request(app)
850 .get(hook.alter('url', '/token', template))
851 .set('x-jwt-token', 'badtoken' + template.users.user1.token.substr(8))
852 .expect(400)
853 .expect('Bad Token')
854 .end(done);
855 });
856
857 it('A User should not be able to get a temporary token with an expire time set to beyond main token.', function(done) {
858 request(app)
859 .get(hook.alter('url', '/token', template))
860 .set('x-jwt-token', template.users.user1.token)
861 .set('x-expire', '1000000000000000')
862 .expect(400)
863 .expect('Cannot generate extended expiring temp token.')
864 .end(done);
865 });
866
867 var tempToken = null;
868 it('Should allow them to create a default temp token with default expiration.', function(done) {
869 request(app)
870 .get(hook.alter('url', '/token', template))
871 .set('x-jwt-token', template.users.user1.token)
872 .expect(200)
873 .end((err, res) => {
874 if (err) {
875 return done(err);
876 }
877
878 tempToken = res.body.token;
879 assert(tempToken.length > 10, 'Temporary token was not created');
880 done();
881 });
882 });
883
884 it('Should allow you to authenticate with the temporary token.', function(done) {
885 request(app)
886 .get(hook.alter('url', '/current', template))
887 .set('x-jwt-token', tempToken)
888 .expect(200)
889 .end((err, res) => {
890 if (err) {
891 return done(err);
892 }
893
894 assert.equal(res.body.data.email, template.users.user1.data.email);
895 assert.equal(res.body._id, template.users.user1._id);
896 done();
897 });
898 });
899
900 it('Should not allow you to get a new temp token using the old temp token.', function(done) {
901 request(app)
902 .get(hook.alter('url', '/token', template))
903 .set('x-jwt-token', tempToken)
904 .expect(400)
905 .expect('Cannot issue a temporary token using another temporary token.')
906 .end(done);
907 });
908
909 it('Should allow you to get a token with a different expire time.', function(done) {
910 request(app)
911 .get(hook.alter('url', '/token', template))
912 .set('x-jwt-token', template.users.user1.token)
913 .set('x-expire', 2)
914 .expect(200)
915 .end((err, res) => {
916 if (err) {
917 return done(err);
918 }
919
920 tempToken = res.body.token;
921 assert(tempToken.length > 10, 'Temporary token was not created');
922 done();
923 });
924 });
925
926 it('Should allow you to use that token within the expiration', function(done) {
927 request(app)
928 .get(hook.alter('url', '/current', template))
929 .set('x-jwt-token', tempToken)
930 .expect(200)
931 .end((err, res) => {
932 if (err) {
933 return done(err);
934 }
935
936 assert.equal(res.body.data.email, template.users.user1.data.email);
937 assert.equal(res.body._id, template.users.user1._id);
938 done();
939 });
940 });
941
942 it('Should not allow you to use the token beyond the expiration', function(done) {
943 setTimeout(function() {
944 request(app)
945 .get(hook.alter('url', '/current', template))
946 .set('x-jwt-token', tempToken)
947 .expect(440)
948 .expect('Token Expired')
949 .end(done);
950 }, 2000);
951 });
952
953 var allowedToken = '';
954 it('Should allow you to get a token for a specific path', function(done) {
955 request(app)
956 .get(hook.alter('url', '/token', template))
957 .set('x-jwt-token', template.users.user1.token)
958 .set('x-allow', 'GET:/form/[0-9a-z]+')
959 .expect(200)
960 .end((err, res) => {
961 if (err) {
962 return done(err);
963 }
964 allowedToken = res.body.token;
965 assert(!!allowedToken, 'No allowed token generated');
966 return done();
967 });
968 });
969
970 it('Should not allow you to navigate to certain paths', function(done) {
971 request(app)
972 .get(hook.alter('url', '/current', template))
973 .set('x-jwt-token', allowedToken)
974 .expect(401)
975 .end(done);
976 });
977
978 it('Should not allow you to perform methods on accepted paths', function(done) {
979 request(app)
980 .post(hook.alter('url', '/form/' + template.resources.user._id, template))
981 .set('x-jwt-token', allowedToken)
982 .expect(401)
983 .end(done);
984 });
985
986 it('Should allow you to see the path and method specified in the token', function(done) {
987 request(app)
988 .get(hook.alter('url', '/form/' + template.resources.user._id, template))
989 .set('x-jwt-token', allowedToken)
990 .expect(200)
991 .end(function(err, res) {
992 if (err) {
993 return done(err);
994 }
995 assert.equal(res.body._id, template.resources.user._id);
996 done();
997 });
998 });
999
1000 it('Should allow generation of tokens with more than one allowed paths.', function(done) {
1001 request(app)
1002 .get(hook.alter('url', '/token', template))
1003 .set('x-jwt-token', template.users.user1.token)
1004 .set('x-allow', 'GET:/form/[0-9a-z]+,GET:/current')
1005 .expect(200)
1006 .end((err, res) => {
1007 if (err) {
1008 return done(err);
1009 }
1010 allowedToken = res.body.token;
1011 assert(!!allowedToken, 'No allowed token generated');
1012 return done();
1013 });
1014 });
1015
1016 it('Should not allow you get a different token', function(done) {
1017 request(app)
1018 .get(hook.alter('url', '/token', template))
1019 .set('x-jwt-token', allowedToken)
1020 .expect(400)
1021 .end(done);
1022 });
1023
1024 it('Should not allow you to perform methods on accepted paths', function(done) {
1025 request(app)
1026 .post(hook.alter('url', '/form/' + template.resources.user._id, template))
1027 .set('x-jwt-token', allowedToken)
1028 .expect(401)
1029 .end(done);
1030 });
1031
1032 it('Should allow you to see the path and method specified in the token', function(done) {
1033 request(app)
1034 .get(hook.alter('url', '/form/' + template.resources.user._id, template))
1035 .set('x-jwt-token', allowedToken)
1036 .expect(200)
1037 .end(function(err, res) {
1038 if (err) {
1039 return done(err);
1040 }
1041 assert.equal(res.body._id, template.resources.user._id);
1042 done();
1043 });
1044 });
1045
1046 it('Should allow you to see the path and method specified in the token', function(done) {
1047 request(app)
1048 .get(hook.alter('url', '/current', template))
1049 .set('x-jwt-token', allowedToken)
1050 .expect(200)
1051 .end(function(err, res) {
1052 if (err) {
1053 return done(err);
1054 }
1055 assert.equal(res.body._id, template.users.user1._id);
1056 done();
1057 });
1058 });
1059 });
1060 }
1061
1062 /**
1063 * partially authentication tests
1064 * partially permissions tests
1065 * partially submissions tests
1066 */
1067 describe('Self Access Permissions', function() {
1068 var dummy = {
1069 data: {
1070 email: chance.email(),
1071 password: chance.word({length: 10})
1072 }
1073 };
1074 var oldAccess = null;
1075 before('Store the old user resource permissions', function(done) {
1076 request(app)
1077 .get(hook.alter('url', '/form/' + template.resources.user._id, template))
1078 .set('x-jwt-token', template.users.admin.token)
1079 .expect(200)
1080 .expect('Content-Type', /json/)
1081 .end(function(err, res) {
1082 if (err) {
1083 return done(err);
1084 }
1085
1086 var response = res.body;
1087 oldAccess = {
1088 access: response.access,
1089 submissionAccess: response.submissionAccess
1090 };
1091
1092 // Store the JWT for future API calls.
1093 template.users.admin.token = res.headers['x-jwt-token'];
1094
1095 done();
1096 });
1097 });
1098
1099 after('Restore the old user resource permissions', function(done) {
1100 request(app)
1101 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1102 .set('x-jwt-token', template.users.admin.token)
1103 .send(oldAccess)
1104 .expect(200)
1105 .expect('Content-Type', /json/)
1106 .end(function(err, res) {
1107 if (err) {
1108 return done(err);
1109 }
1110
1111 var response = res.body;
1112 template.resources.user = response;
1113
1114 // Store the JWT for future API calls.
1115 template.users.admin.token = res.headers['x-jwt-token'];
1116
1117 done();
1118 });
1119 });
1120
1121 it('Update the user resource to have no submissionAccess', function(done) {
1122 request(app)
1123 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1124 .set('x-jwt-token', template.users.admin.token)
1125 .send({
1126 submissionAccess: []
1127 })
1128 .expect(200)
1129 .expect('Content-Type', /json/)
1130 .end(function(err, res) {
1131 if (err) {
1132 return done(err);
1133 }
1134
1135 var response = res.body;
1136 assert.equal(response.submissionAccess.length, 0);
1137 template.resources.user = response;
1138
1139 // Store the JWT for future API calls.
1140 template.users.admin.token = res.headers['x-jwt-token'];
1141
1142 done();
1143 });
1144 });
1145
1146 it('The resource owner can make a user account without permissions', function(done) {
1147 request(app)
1148 .post(hook.alter('url', '/form/' + template.resources.user._id + '/submission', template))
1149 .set('x-jwt-token', template.users.admin.token)
1150 .send(dummy)
1151 .expect(201)
1152 .expect('Content-Type', /json/)
1153 .end(function(err, res) {
1154 if (err) {
1155 return done(err);
1156 }
1157
1158 var response = res.body;
1159 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
1160 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
1161 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
1162 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
1163 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
1164 assert.equal(response.data.email, dummy.data.email);
1165 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
1166 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
1167 assert.equal(response.form, template.resources.user._id);
1168 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
1169 assert(response.hasOwnProperty('owner'), 'The response should contain the resource `owner`.');
1170 assert.equal(response.owner, template.users.admin._id);
1171 assert.equal(response.roles.length, 1);
1172 assert.equal(response.roles[0].toString(), template.roles.authenticated._id.toString());
1173
1174 // Update our testProject.owners data.
1175 var tempPassword = dummy.data.password;
1176 dummy = response;
1177 dummy.data.password = tempPassword;
1178
1179 // Store the JWT for future API calls.
1180 dummy.token = res.headers['x-jwt-token'];
1181
1182 done();
1183 });
1184 });
1185
1186 it('An anonymous user should not be able to create a user account without permissions', function(done) {
1187 request(app)
1188 .post(hook.alter('url', '/form/' + template.resources.user._id + '/submission', template))
1189 .send({
1190 data: {
1191 email: chance.email(),
1192 password: chance.word({length: 10})
1193 }
1194 })
1195 .expect(401)
1196 .end(done);
1197 });
1198
1199 // FA-923
1200 it('An anonymous user should be able to access the resource form without submissionAccess permissions', function(done) {
1201 request(app)
1202 .get(hook.alter('url', '/' + template.resources.user.path, template))
1203 .expect(200)
1204 .end(done);
1205 });
1206
1207 it('A user (created by an admin) can login to their account', function(done) {
1208 request(app)
1209 .post(hook.alter('url', '/form/' + template.forms.userLogin._id + '/submission', template))
1210 .send({
1211 data: {
1212 'email': dummy.data.email,
1213 'password': dummy.data.password
1214 }
1215 })
1216 .expect('Content-Type', /json/)
1217 .expect(200)
1218 .end(function(err, res) {
1219 if (err) {
1220 return done(err);
1221 }
1222
1223 var response = res.body;
1224 assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.');
1225 assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.');
1226 assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.');
1227 assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.');
1228 assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.');
1229 assert.equal(response.data.email, dummy.data.email);
1230 assert(!response.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
1231 assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.');
1232 assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.');
1233 assert.equal(response.form, template.resources.user._id);
1234 assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.');
1235
1236 // Update our dummys data.
1237 var tempPassword = dummy.data.password;
1238 dummy = response;
1239 dummy.data.password = tempPassword;
1240
1241 // Store the JWT for future API calls.
1242 dummy.token = res.headers['x-jwt-token'];
1243 done();
1244 });
1245 });
1246
1247 // FA-923
1248 it('A user without read submissionAccess permissions and no self access, can still read the resource form', function(done) {
1249 request(app)
1250 .get(hook.alter('url', '/' + template.resources.user.path, template))
1251 .set('x-jwt-token', dummy.token)
1252 .expect(200)
1253 .end(done);
1254 });
1255
1256 it('A user without read permissions, should not be able to read their submission', function(done) {
1257 request(app)
1258 .get(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1259 .set('x-jwt-token', dummy.token)
1260 .expect(401)
1261 .end(done);
1262 });
1263
1264 it('A user without read permissions, should not be able to read their submission, via index', function(done) {
1265 request(app)
1266 .get(hook.alter('url', '/' + template.resources.user.path + '/submission', template))
1267 .set('x-jwt-token', dummy.token)
1268 .expect(401)
1269 .end(done);
1270 });
1271
1272 it('A user without update permissions, should not be able to update their submission', function(done) {
1273 request(app)
1274 .put(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1275 .set('x-jwt-token', dummy.token)
1276 .send({
1277 data: {
1278 email: chance.email()
1279 }
1280 })
1281 .expect(401)
1282 .end(done);
1283 });
1284
1285 it('A user without delete permissions, should not be able to delete their submission', function(done) {
1286 request(app)
1287 .delete(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1288 .set('x-jwt-token', dummy.token)
1289 .expect(401)
1290 .end(done);
1291 });
1292
1293 it('Update the user resource to have read_own access', function(done) {
1294 request(app)
1295 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1296 .set('x-jwt-token', template.users.admin.token)
1297 .send({
1298 submissionAccess: [
1299 {
1300 type: 'read_own',
1301 roles: [template.roles.authenticated._id]
1302 }
1303 ]
1304 })
1305 .expect(200)
1306 .expect('Content-Type', /json/)
1307 .end(function(err, res) {
1308 if (err) {
1309 return done(err);
1310 }
1311
1312 var response = res.body;
1313 assert.equal(response.submissionAccess.length, 1);
1314 assert.equal(response.submissionAccess[0].type, 'read_own');
1315 template.resources.user = response;
1316
1317 // Store the JWT for future API calls.
1318 template.users.admin.token = res.headers['x-jwt-token'];
1319
1320 done();
1321 });
1322 });
1323
1324 // FA-923
1325 it('A user with read submissionAccess permissions and no self access, can still read the resource form', function(done) {
1326 request(app)
1327 .get(hook.alter('url', '/' + template.resources.user.path, template))
1328 .set('x-jwt-token', dummy.token)
1329 .expect(200)
1330 .end(done);
1331 });
1332
1333 it('A user without read permissions (not the owner), should not be able to read their submission', function(done) {
1334 request(app)
1335 .get(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1336 .set('x-jwt-token', dummy.token)
1337 .expect(401)
1338 .end(done);
1339 });
1340
1341 it('A user without read permissions (not the owner), should not be able to read their submission, via index', function(done) {
1342 request(app)
1343 .get(hook.alter('url', '/' + template.resources.user.path + '/submission', template))
1344 .set('x-jwt-token', dummy.token)
1345 .expect(200)
1346 .end(function(err, res) {
1347 if (err) {
1348 return done(err);
1349 }
1350
1351 var response = res.body;
1352 assert(response instanceof Array);
1353 assert.equal(response.length, 0);
1354
1355 // Store the JWT for future API calls.
1356 dummy.token = res.headers['x-jwt-token'];
1357
1358 done();
1359 });
1360 });
1361
1362 it('A user without update permissions (not the owner), should not be able to update their submission', function(done) {
1363 request(app)
1364 .put(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1365 .set('x-jwt-token', dummy.token)
1366 .send({
1367 data: {
1368 email: chance.email()
1369 }
1370 })
1371 .expect(401)
1372 .end(done);
1373 });
1374
1375 it('A user without delete permissions (not the owner), should not be able to delete their submission', function(done) {
1376 request(app)
1377 .delete(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1378 .set('x-jwt-token', dummy.token)
1379 .expect(401)
1380 .end(done);
1381 });
1382
1383 it('Update the user resource to have update_own access', function(done) {
1384 request(app)
1385 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1386 .set('x-jwt-token', template.users.admin.token)
1387 .send({
1388 submissionAccess: [
1389 {
1390 type: 'update_own',
1391 roles: [template.roles.authenticated._id]
1392 }
1393 ]
1394 })
1395 .expect(200)
1396 .expect('Content-Type', /json/)
1397 .end(function(err, res) {
1398 if (err) {
1399 return done(err);
1400 }
1401
1402 var response = res.body;
1403 assert.equal(response.submissionAccess.length, 1);
1404 assert.equal(response.submissionAccess[0].type, 'update_own');
1405 template.resources.user = response;
1406
1407 // Store the JWT for future API calls.
1408 template.users.admin.token = res.headers['x-jwt-token'];
1409
1410 done();
1411 });
1412 });
1413
1414 // FA-923
1415 it('A user with update submissionAccess permissions and no self access, can still read the resource form', function(done) {
1416 request(app)
1417 .get(hook.alter('url', '/' + template.resources.user.path, template))
1418 .set('x-jwt-token', dummy.token)
1419 .expect(200)
1420 .end(done);
1421 });
1422
1423 it('A user without read permissions (not the owner), should not be able to read their submission', function(done) {
1424 request(app)
1425 .get(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1426 .set('x-jwt-token', dummy.token)
1427 .expect(401)
1428 .end(done);
1429 });
1430
1431 it('A user without read permissions (not the owner), should not be able to read their submission, via index', function(done) {
1432 request(app)
1433 .get(hook.alter('url', '/' + template.resources.user.path + '/submission', template))
1434 .set('x-jwt-token', dummy.token)
1435 .expect(401)
1436 .end(done);
1437 });
1438
1439 it('A user without update permissions (not the owner), should not be able to update their submission', function(done) {
1440 request(app)
1441 .put(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1442 .set('x-jwt-token', dummy.token)
1443 .send({
1444 data: {
1445 email: chance.email()
1446 }
1447 })
1448 .expect(401)
1449 .end(done);
1450 });
1451
1452 it('A user without delete permissions (not the owner), should not be able to delete their submission', function(done) {
1453 request(app)
1454 .delete(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1455 .set('x-jwt-token', dummy.token)
1456 .expect(401)
1457 .end(done);
1458 });
1459
1460 it('Update the user resource to have delete_own access', function(done) {
1461 request(app)
1462 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1463 .set('x-jwt-token', template.users.admin.token)
1464 .send({
1465 submissionAccess: [
1466 {
1467 type: 'delete_own',
1468 roles: [template.roles.authenticated._id]
1469 }
1470 ]
1471 })
1472 .expect(200)
1473 .expect('Content-Type', /json/)
1474 .end(function(err, res) {
1475 if (err) {
1476 return done(err);
1477 }
1478
1479 var response = res.body;
1480 assert.equal(response.submissionAccess.length, 1);
1481 assert.equal(response.submissionAccess[0].type, 'delete_own');
1482 template.resources.user = response;
1483
1484 // Store the JWT for future API calls.
1485 template.users.admin.token = res.headers['x-jwt-token'];
1486
1487 done();
1488 });
1489 });
1490
1491 // FA-923
1492 it('A user with delete submissionAccess permissions and no self access, can still read the resource form', function(done) {
1493 request(app)
1494 .get(hook.alter('url', '/' + template.resources.user.path, template))
1495 .set('x-jwt-token', dummy.token)
1496 .expect(200)
1497 .end(done);
1498 });
1499
1500 it('A user without read permissions (not the owner), should not be able to read their submission', function(done) {
1501 request(app)
1502 .get(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1503 .set('x-jwt-token', dummy.token)
1504 .expect(401)
1505 .end(done);
1506 });
1507
1508 it('A user without read permissions (not the owner), should not be able to read their submission, via index', function(done) {
1509 request(app)
1510 .get(hook.alter('url', '/' + template.resources.user.path + '/submission', template))
1511 .set('x-jwt-token', dummy.token)
1512 .expect(401)
1513 .end(done);
1514 });
1515
1516 it('A user without update permissions (not the owner), should not be able to update their submission', function(done) {
1517 request(app)
1518 .put(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1519 .set('x-jwt-token', dummy.token)
1520 .send({
1521 data: {
1522 email: chance.email()
1523 }
1524 })
1525 .expect(401)
1526 .end(done);
1527 });
1528
1529 it('A user without delete permissions (not the owner), should not be able to delete their submission', function(done) {
1530 request(app)
1531 .delete(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1532 .set('x-jwt-token', dummy.token)
1533 .expect(401)
1534 .end(done);
1535 });
1536
1537 it('Update the user resource to have only self access', function(done) {
1538 request(app)
1539 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1540 .set('x-jwt-token', template.users.admin.token)
1541 .send({
1542 submissionAccess: [
1543 {
1544 type: 'self'
1545 }
1546 ]
1547 })
1548 .expect(200)
1549 .expect('Content-Type', /json/)
1550 .end(function(err, res) {
1551 if (err) {
1552 return done(err);
1553 }
1554
1555 var response = res.body;
1556 assert.equal(response.submissionAccess.length, 1);
1557 assert.equal(response.submissionAccess[0].type, 'self');
1558 assert(response.submissionAccess[0].roles instanceof Array);
1559 assert.deepEqual(response.submissionAccess[0].roles, []);
1560 template.resources.user = response;
1561
1562 // Store the JWT for future API calls.
1563 template.users.admin.token = res.headers['x-jwt-token'];
1564
1565 done();
1566 });
1567 });
1568
1569 // FA-923
1570 it('A user with no submissionAccess permissions and self access, can still read the resource form', function(done) {
1571 request(app)
1572 .get(hook.alter('url', '/' + template.resources.user.path, template))
1573 .set('x-jwt-token', dummy.token)
1574 .expect(200)
1575 .end(done);
1576 });
1577
1578 it('A user without read permissions, but self access (not the owner), should not be able to read their submission', function(done) {
1579 request(app)
1580 .get(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1581 .set('x-jwt-token', dummy.token)
1582 .expect(401)
1583 .end(done);
1584 });
1585
1586 it('A user without read permissions, but self access (not the owner), should not be able to read their submission, via index', function(done) {
1587 request(app)
1588 .get(hook.alter('url', '/' + template.resources.user.path + '/submission', template))
1589 .set('x-jwt-token', dummy.token)
1590 .expect(401)
1591 .end(done);
1592 });
1593
1594 it('A user without update permissions, but self access (not the owner), should not be able to update their submission', function(done) {
1595 request(app)
1596 .put(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1597 .set('x-jwt-token', dummy.token)
1598 .send({
1599 data: {
1600 email: chance.email()
1601 }
1602 })
1603 .expect(401)
1604 .end(done);
1605 });
1606
1607 it('A user without delete permissions, but self access (not the owner), should not be able to delete their submission', function(done) {
1608 request(app)
1609 .delete(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1610 .set('x-jwt-token', dummy.token)
1611 .expect(401)
1612 .end(done);
1613 });
1614
1615 it('Update the user resource to have read_own and self access', function(done) {
1616 request(app)
1617 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1618 .set('x-jwt-token', template.users.admin.token)
1619 .send({
1620 submissionAccess: [
1621 {
1622 type: 'read_own',
1623 roles: [template.roles.authenticated._id]
1624 },
1625 {
1626 type: 'self'
1627 }
1628 ]
1629 })
1630 .expect(200)
1631 .expect('Content-Type', /json/)
1632 .end(function(err, res) {
1633 if (err) {
1634 return done(err);
1635 }
1636
1637 var response = res.body;
1638 var types = _.map(response.submissionAccess, 'type');
1639 assert.equal(response.submissionAccess.length, 2);
1640 assert(types.indexOf('read_own') !== -1);
1641 assert(types.indexOf('self') !== -1);
1642 template.resources.user = response;
1643
1644 // Store the JWT for future API calls.
1645 template.users.admin.token = res.headers['x-jwt-token'];
1646
1647 done();
1648 });
1649 });
1650
1651 // FA-923
1652 it('A user with read submissionAccess permissions and self access, can still read the resource form', function(done) {
1653 request(app)
1654 .get(hook.alter('url', '/' + template.resources.user.path, template))
1655 .set('x-jwt-token', dummy.token)
1656 .expect(200)
1657 .end(done);
1658 });
1659
1660 it('A user with read_own and self access, not the owner, should be able to read their submission', function(done) {
1661 request(app)
1662 .get(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1663 .set('x-jwt-token', dummy.token)
1664 .expect(200)
1665 .end(done);
1666 });
1667
1668 it('A user with read_own and self access, not the owner, should be able to read their submission, via index', function(done) {
1669 request(app)
1670 .get(hook.alter('url', '/' + template.resources.user.path + '/submission', template))
1671 .set('x-jwt-token', dummy.token)
1672 .expect(200)
1673 .end(function(err, res) {
1674 if (err) {
1675 return done(err);
1676 }
1677
1678 var response = res.body;
1679 assert(response instanceof Array);
1680 assert.equal(response.length, 1);
1681 assert.equal(response[0]._id, dummy._id);
1682
1683 // Store the JWT for future API calls.
1684 dummy.token = res.headers['x-jwt-token'];
1685
1686 done();
1687 });
1688 });
1689
1690 it('A user with read_own and self access, not the owner, should not be able to update their submission', function(done) {
1691 request(app)
1692 .put(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1693 .set('x-jwt-token', dummy.token)
1694 .send({
1695 data: {
1696 email: chance.email()
1697 }
1698 })
1699 .expect(401)
1700 .end(done);
1701 });
1702
1703 it('A user with read_own and self access, not the owner, should not be able to delete their submission', function(done) {
1704 request(app)
1705 .delete(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1706 .set('x-jwt-token', dummy.token)
1707 .expect(401)
1708 .end(done);
1709 });
1710
1711 it('Update the user resource to have update_own and self access', function(done) {
1712 request(app)
1713 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1714 .set('x-jwt-token', template.users.admin.token)
1715 .send({
1716 submissionAccess: [
1717 {
1718 type: 'update_own',
1719 roles: [template.roles.authenticated._id]
1720 },
1721 {
1722 type: 'self'
1723 }
1724 ]
1725 })
1726 .expect(200)
1727 .expect('Content-Type', /json/)
1728 .end(function(err, res) {
1729 if (err) {
1730 return done(err);
1731 }
1732
1733 var response = res.body;
1734 var types = _.map(response.submissionAccess, 'type');
1735 assert.equal(response.submissionAccess.length, 2);
1736 assert(types.indexOf('update_own') !== -1);
1737 assert(types.indexOf('self') !== -1);
1738 template.resources.user = response;
1739
1740 // Store the JWT for future API calls.
1741 template.users.admin.token = res.headers['x-jwt-token'];
1742
1743 done();
1744 });
1745 });
1746
1747 // FA-923
1748 it('A user with update submissionAccess permissions and self access, can still read the resource form', function(done) {
1749 request(app)
1750 .get(hook.alter('url', '/' + template.resources.user.path, template))
1751 .set('x-jwt-token', dummy.token)
1752 .expect(200)
1753 .end(done);
1754 });
1755
1756 it('A user with update_own and self access, not the owner, should not be able to read their submission', function(done) {
1757 request(app)
1758 .get(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1759 .set('x-jwt-token', dummy.token)
1760 .expect(401)
1761 .end(done);
1762 });
1763
1764 it('A user with update_own and self access, not the owner, should not be able to read their submission, via index', function(done) {
1765 request(app)
1766 .get(hook.alter('url', '/' + template.resources.user.path + '/submission', template))
1767 .set('x-jwt-token', dummy.token)
1768 .expect(401)
1769 .end(done);
1770 });
1771
1772 it('A user with update_own and self access, not the owner, should be able to update their submission', function(done) {
1773 request(app)
1774 .put(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1775 .set('x-jwt-token', dummy.token)
1776 .send({
1777 data: {
1778 email: chance.email()
1779 }
1780 })
1781 .expect(200)
1782 .end(done);
1783 });
1784
1785 it('A user with update_own and self access, not the owner, should not be able to delete their submission', function(done) {
1786 request(app)
1787 .delete(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1788 .set('x-jwt-token', dummy.token)
1789 .expect(401)
1790 .end(done);
1791 });
1792
1793 it('Update the user resource to have delete_own and self access', function(done) {
1794 request(app)
1795 .put(hook.alter('url', '/form/' + template.resources.user._id, template))
1796 .set('x-jwt-token', template.users.admin.token)
1797 .send({
1798 submissionAccess: [
1799 {
1800 type: 'delete_own',
1801 roles: [template.roles.authenticated._id]
1802 },
1803 {
1804 type: 'self'
1805 }
1806 ]
1807 })
1808 .expect(200)
1809 .expect('Content-Type', /json/)
1810 .end(function(err, res) {
1811 if (err) {
1812 return done(err);
1813 }
1814
1815 var response = res.body;
1816 var types = _.map(response.submissionAccess, 'type');
1817 assert.equal(response.submissionAccess.length, 2);
1818 assert(types.indexOf('delete_own') !== -1);
1819 assert(types.indexOf('self') !== -1);
1820 template.resources.user = response;
1821
1822 // Store the JWT for future API calls.
1823 template.users.admin.token = res.headers['x-jwt-token'];
1824
1825 done();
1826 });
1827 });
1828
1829 // FA-923
1830 it('A user with delete submissionAccess permissions and self access, can still read the resource form', function(done) {
1831 request(app)
1832 .get(hook.alter('url', '/' + template.resources.user.path, template))
1833 .set('x-jwt-token', dummy.token)
1834 .expect(200)
1835 .end(done);
1836 });
1837
1838 it('A user with delete_own and self access, not the owner, should not be able to read their submission', function(done) {
1839 request(app)
1840 .get(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1841 .set('x-jwt-token', dummy.token)
1842 .expect(401)
1843 .end(done);
1844 });
1845
1846 it('A user with delete_own and self access, not the owner, should not be able to read their submission, via index', function(done) {
1847 request(app)
1848 .get(hook.alter('url', '/' + template.resources.user.path + '/submission', template))
1849 .set('x-jwt-token', dummy.token)
1850 .expect(401)
1851 .end(done);
1852 });
1853
1854 it('A user with delete_own and self access, not the owner, should not be able to update their submission', function(done) {
1855 request(app)
1856 .put(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1857 .set('x-jwt-token', dummy.token)
1858 .send({
1859 data: {
1860 email: chance.email()
1861 }
1862 })
1863 .expect(401)
1864 .end(done);
1865 });
1866
1867 it('A user with delete_own and self access, not the owner, should be able to delete their submission', function(done) {
1868 request(app)
1869 .delete(hook.alter('url', '/' + template.resources.user.path + '/submission/' + dummy._id, template))
1870 .set('x-jwt-token', dummy.token)
1871 .expect(200)
1872 .end(done);
1873 });
1874 });
1875
1876 describe('Template Permissions', function() {
1877 it('An Anonymous user should not be able to export a project', function(done) {
1878 request(app)
1879 .get(hook.alter('url', '/export', template))
1880 .expect(401)
1881 .expect('Content-Type', /text/)
1882 .end((err, res) => {
1883 if (err) {
1884 return done(err);
1885 }
1886
1887 let response = res.text;
1888 assert.equal(response, 'Unauthorized');
1889 done();
1890 });
1891 });
1892
1893 it('An Admin user should be able to export a project', function(done) {
1894 request(app)
1895 .get(hook.alter('url', '/export', template))
1896 .set('x-jwt-token', template.users.admin.token)
1897 .expect(200)
1898 .expect('Content-Type', /json/)
1899 .end((err, res) => {
1900 if (err) {
1901 return done(err);
1902 }
1903
1904 let response = res.body;
1905 assert.deepEqual(
1906 _.difference(
1907 ['title', 'version', 'description', 'name', 'roles', 'forms', 'actions', 'resources'],
1908 Object.keys(response)
1909 ),
1910 []
1911 );
1912 return done();
1913 });
1914 });
1915 });
1916};