Guest User

Untitled

a guest
Nov 8th, 2018
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.86 KB | None | 0 0
  1. // Easier to follow. Equally easy to test -- and with one fewer function in need of testing.
  2.  
  3. import { userInfo } from "os";
  4.  
  5. const Promise = require("bluebird");
  6. const { hashStringAsync } = Promise.promisifyAll(require("./lib/crypto"));
  7. const { logEventAsync } = Promise.promisifyAll(require("./lib/log"));
  8. const { openAsync } = Promise.promisifyAll(require("./lib/db"));
  9. const { TimeoutError, ValidationError, NotFoundError } = require("./errors");
  10.  
  11. const _openHandle = openAsync(); // FYI: Promises include memoization (caching) built into same API
  12.  
  13. module.exports = { auth };
  14.  
  15. /* auth is our main function */
  16. async function auth({
  17. username,
  18. password,
  19. _onTimeoutError = errorHandler,
  20. _onNotFoundError = errorHandler,
  21. _onValidationError = errorHandler,
  22. }) {
  23. try {
  24. // No more reusing "password" as "hashed password".
  25. // Still starting the hash ASAP and not waiting for it.
  26. const hashedPasswordPromise = hashStringAsync(password);
  27. authValidate({ username, password });
  28. const { users, admin } = await getModels();
  29. const user = await users.findOneAsync({
  30. username,
  31. // I would have renamed "password" here; bad form to have a field named
  32. // password that's expecting a hash.
  33. password: await hashedPasswordPromise, // Deferred await to when we need it.
  34. });
  35.  
  36. // Inventing a side tributary: If a user is an admin, then grab their admin
  37. // permissions.
  38. if (user.admin) {
  39. const admin = await admin.findOneAsync({ id: user.id });
  40. user.adminPermissions = admin.permissions;
  41. }
  42. await userFound(user);
  43. return userInfo;
  44. } catch (e) {
  45. // Left this in because Bluebird's extension for matching errors is cute.
  46. // It's super easy to forget the `await` here - it changes how functions work in pretty substantial, yet non-obvious ways.
  47. // if the custom handlers (_onTimeoutError) fail to output the error info, they wouldn't be able re-throw errors to be caught higher up
  48. await Promise.reject(e) // I agree, it is pretty cute :)
  49. .catch(TimeoutError, _onTimeoutError)
  50. .catch(NotFoundError, _onNotFoundError)
  51. .catch(ValidationError, _onValidationError)
  52. .catch(errorHandler);
  53. }
  54. }
  55.  
  56. function authValidate({ username, password }) {
  57. if (!username || username.length < 4) {
  58. throw new ValidationError("Invalid username. Required, 4 char minimum.");
  59. }
  60. if (!password || password.length < 4) {
  61. throw new ValidationError("Invalid password. Required, 4 char minimum.");
  62. }
  63. }
  64.  
  65. function userFound(results) {
  66. if (results) return;
  67. throw new NotFoundError("No users matched. Login failed");
  68. }
  69.  
  70. function getModels() {
  71. return _openHandle.then(({ models }) => models);
  72. }
  73.  
  74. function errorHandler(err) {
  75. console.error("Failed auth!", err);
  76. }
Add Comment
Please, Sign In to add comment