Advertisement
Guest User

Untitled

a guest
Apr 7th, 2020
379
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * What's wrong here and how can this be improved?
  3.  */
  4.  
  5.  // Basically a lot of the code inside `updateUserPassword` can be moved out of the function body into other smaller functions.
  6.  // This would make the code easier to understand and it would enable a potentially better unit test coverage (unit test many small functions rather than one big function alone)
  7.  
  8. async function updateUserPassword(data, ctx) {
  9.   const user = await getUser({ userId: data.userId }, ctx);
  10.  
  11.   // the following 2 lines would be more efficient if placed outside the function
  12.   const userRoles = config.get("userRoles");
  13.   const allowedClientRoles = config.get("allowedClientRoles");
  14.  
  15.   const sameTenants = utils.compareClientTenantIdWithUserTenantId(
  16.     data.tenantId,
  17.     ctx
  18.   );
  19.  
  20.   // logTenantError can be moved outside of this function with a parametrized `ctx`, like `const logTenantError = (ctx) => { ... }
  21.   // 403 and "access_denied" are better stored in application constants rather than used as literal values
  22.   const logTenantError = () => {
  23.     const message = "Access denied";
  24.     log.request(message, ctx, ERROR);
  25.     throw error.create(message, 403, "access_denied");
  26.   };
  27.  
  28.   // can be moved out with parametrized `sameTenants`
  29.   const checkTenant = () =>
  30.     fp.cond([
  31.       [fp.isEqual(true), fp.noop],
  32.       [fp.isEqual(false), logTenantError]
  33.     ])(sameTenants);
  34.  
  35.   // can be moved out ...
  36.   const checkUserPermission = () =>
  37.     fp.cond([
  38.       [fp.isEqual(true), fp.noop],
  39.       [fp.isEqual(false), checkTenant]
  40.     ])(userRoles.includes(user.role));
  41.  
  42.   // same here
  43.   const logClientError = () => {
  44.     const message = "Access denied";
  45.     log.request(message, ctx, ERROR);
  46.     throw error.create(message, 403, "access_denied");
  47.   };
  48.  
  49.   fp.cond([
  50.     [fp.isEqual(true), checkUserPermission],
  51.     [fp.isEqual(false), logClientError]
  52.   ])(allowedClientRoles.includes(await getClientRole(ctx)));
  53.  
  54.   const queryResult = await db.query(
  55.     `FOR user IN users FILTER password == @password AND userId == @userId and tenantId == @tenantId`,
  56.     {
  57.       tenantId: data.tenantId,
  58.       userId: data.userId,
  59.       password: decrypt(data.password)
  60.     }
  61.   );
  62.  
  63.   if (!queryResult.hasNext()) {
  64.     throw error.create("User not found", 404, "user_not_found");
  65.   }
  66.  
  67.   // `rev` is an unused param in both following logger functions
  68.   const logErrorRevokeTokens = (rev, message, context) => {
  69.     log.request(message, context, ERROR);
  70.   };
  71.  
  72.   const logSuccessRevokeTokens = (rev, message, context) =>{
  73.     log.request(message, context, INFO);
  74.   };
  75.  
  76.   const { tenantId, userId } = data;
  77.   const { revoked, message } = await utils.revokeTokensOfUser(
  78.     tenantId,
  79.     userId,
  80.     ctx
  81.   );
  82.  
  83.   // This will probably always branch on TRUE, because fp.cond evaluates each parameter (revoked, message and ctx) for each predicate.
  84.   // Even if `revoked` is `false`, `message` and/or `ctx` are very likely to always evaluate to a "truthy" value when coerced into booleans.
  85.   fp.cond([
  86.     [fp.isEqual(true), logSuccessRevokeTokens],
  87.     [fp.isEqual(false), logErrorRevokeTokens]
  88.   ])(revoked, message, ctx);
  89.  
  90.   return;
  91. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement