Guest User

Untitled

a guest
Feb 23rd, 2018
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.42 KB | None | 0 0
  1. 'use strict';
  2. const express = require('express');
  3. const bodyParser = require('body-parser');
  4.  
  5. const {User} = require('./models');
  6.  
  7. const router = express.Router();
  8.  
  9. const jsonParser = bodyParser.json();
  10.  
  11. // Post to register a new user
  12. router.post('/', jsonParser, (req, res) => {
  13. const requiredFields = ['username', 'password'];
  14. const missingField = requiredFields.find(field => !(field in req.body));
  15.  
  16. if (missingField) {
  17. return res.status(422).json({
  18. code: 422,
  19. reason: 'ValidationError',
  20. message: 'Missing field',
  21. location: missingField
  22. });
  23. }
  24.  
  25. const stringFields = ['username', 'password', 'firstName', 'lastName'];
  26. const nonStringField = stringFields.find(
  27. field => field in req.body && typeof req.body[field] !== 'string'
  28. );
  29.  
  30. if (nonStringField) {
  31. return res.status(422).json({
  32. code: 422,
  33. reason: 'ValidationError',
  34. message: 'Incorrect field type: expected string',
  35. location: nonStringField
  36. });
  37. }
  38.  
  39. // If the username and password aren't trimmed we give an error. Users might
  40. // expect that these will work without trimming (i.e. they want the password
  41. // "foobar ", including the space at the end). We need to reject such values
  42. // explicitly so the users know what's happening, rather than silently
  43. // trimming them and expecting the user to understand.
  44. // We'll silently trim the other fields, because they aren't credentials used
  45. // to log in, so it's less of a problem.
  46. const explicityTrimmedFields = ['username', 'password'];
  47. const nonTrimmedField = explicityTrimmedFields.find(
  48. field => req.body[field].trim() !== req.body[field]
  49. );
  50.  
  51. if (nonTrimmedField) {
  52. return res.status(422).json({
  53. code: 422,
  54. reason: 'ValidationError',
  55. message: 'Cannot start or end with whitespace',
  56. location: nonTrimmedField
  57. });
  58. }
  59.  
  60. const sizedFields = {
  61. username: {
  62. min: 1
  63. },
  64. password: {
  65. min: 10,
  66. // bcrypt truncates after 72 characters, so let's not give the illusion
  67. // of security by storing extra (unused) info
  68. max: 72
  69. }
  70. };
  71. const tooSmallField = Object.keys(sizedFields).find(
  72. field =>
  73. 'min' in sizedFields[field] &&
  74. req.body[field].trim().length < sizedFields[field].min
  75. );
  76. const tooLargeField = Object.keys(sizedFields).find(
  77. field =>
  78. 'max' in sizedFields[field] &&
  79. req.body[field].trim().length > sizedFields[field].max
  80. );
  81.  
  82. if (tooSmallField || tooLargeField) {
  83. return res.status(422).json({
  84. code: 422,
  85. reason: 'ValidationError',
  86. message: tooSmallField
  87. ? `Must be at least ${sizedFields[tooSmallField]
  88. .min} characters long`
  89. : `Must be at most ${sizedFields[tooLargeField]
  90. .max} characters long`,
  91. location: tooSmallField || tooLargeField
  92. });
  93. }
  94.  
  95. let {username, password, firstName = '', lastName = ''} = req.body;
  96. // Username and password come in pre-trimmed, otherwise we throw an error
  97. // before this
  98. firstName = firstName.trim();
  99. lastName = lastName.trim();
  100.  
  101. return User.find({username})
  102. .count()
  103. .then(count => {
  104. if (count > 0) {
  105. // There is an existing user with the same username
  106. return Promise.reject({
  107. code: 422,
  108. reason: 'ValidationError',
  109. message: 'Username already taken',
  110. location: 'username'
  111. });
  112. }
  113. // If there is no existing user, hash the password
  114. return User.hashPassword(password);
  115. })
  116. .then(hash => {
  117. return User.create({
  118. username,
  119. password: hash,
  120. firstName,
  121. lastName
  122. });
  123. })
  124. .then(user => {
  125. return res.status(201).json(user.serialize());
  126. })
  127. .catch(err => {
  128. // Forward validation errors on to the client, otherwise give a 500
  129. // error because something unexpected has happened
  130. if (err.reason === 'ValidationError') {
  131. return res.status(err.code).json(err);
  132. }
  133. res.status(500).json({code: 500, message: 'Internal server error'});
  134. });
  135. });
  136.  
  137. // Never expose all your users like below in a prod application
  138. // we're just doing this so we have a quick way to see
  139. // if we're creating users. keep in mind, you can also
  140. // verify this in the Mongo shell.
  141. router.get('/', (req, res) => {
  142. return User.find()
  143. .then(users => res.json(users.map(user => user.serialize())))
  144. .catch(err => res.status(500).json({message: 'Internal server error'}));
  145. });
  146.  
  147. module.exports = {router};
Add Comment
Please, Sign In to add comment