All files populate-or-restrict.js

50% Statements 24/48
44.74% Branches 17/38
25% Functions 2/8
51.06% Lines 24/47
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 1041x         1x         6x 6x 6x   6x     5x       5x         5x         5x       5x   5x 2x 2x 2x       5x 1x   4x       4x 4x       4x 4x               1x 1x                                                                          
import errors from 'feathers-errors';
 
/**
 * Populate the current user associated with the JWT
 */
const defaults = {
  userEndpoint: '/users',
  idField: '_id'
};
 
export default function (options = {}) {
  return function (hook) {
    let id;
 
    options = Object.assign({}, defaults, hook.app.get('auth'), options);
 
    // If it's an after hook grab the id from the result
    Iif (hook.type !== 'before') {
      throw new Error(`The 'populateOrRestrict' hook should only be used as a 'before' hook.`);
    }
 
    Iif (hook.method !== 'find' && hook.method !== 'get') {
      throw new Error(`'populateOrRestrict' should only be used in a find or get hook.`);
    }
 
    // If it was an internal call then skip this hook
    Iif (!hook.params.provider) {
      return hook;
    }
 
    // If we don't have a payload we have to always use find instead of get because we must not return id queries that are unrestricted and we don't want the developer to have to add after hooks.
    let query = Object.assign({}, hook.params.query, options.restrict);
 
    // Set provider as undefined so we avoid an infinite loop if this hook is
    // set on the resource we are requesting.
    const params = Object.assign({}, hook.params, { provider: undefined });
 
    if (hook.id !== null && hook.id !== undefined) {
      const id = {};
      id[options.idField] = hook.id;
      query = Object.assign(query, id);
    }
 
    // Check to see if we have an id from a decoded JWT
    if (hook.params.payload) {
      id = hook.params.payload[options.idField];
    } else {
      Iif (hook.result) {
        return hook;
      }
 
      return this.find({ query }, params).then(results => {
        Iif (hook.method === 'get' && Array.isArray(results) && results.length === 1) {
          hook.result = results[0];
          return hook;
        } else {
          hook.result = results;
          return hook;
        }
      }).catch(() => {
        throw new errors.NotFound(`No record found`);
      });
    }
 
    // If we didn't find an id then just pass through
    Eif (id === undefined) {
      return Promise.resolve(hook);
    }
 
    return new Promise(function (resolve) {
      hook.app.service(options.userEndpoint).get(id, {}).then(user => {
        // attach the user to the hook for use in other hooks or services
        hook.params.user = user;
 
        // If it's an after hook attach the user to the response
        if (hook.result) {
          hook.result.data = Object.assign({}, user = !user.toJSON ? user : user.toJSON());
 
          // remove the id field from the root, it already exists inside the user object
          delete hook.result[options.idField];
        }
 
        return resolve(hook);
      }).catch(() => {
        if (hook.result) {
          return hook;
        }
 
        return this.find({ query }, params).then(results => {
          if (hook.method === 'get' && Array.isArray(results) && results.length === 1) {
            hook.result = results[0];
            return hook;
          } else {
            hook.result = results;
            return hook;
          }
        }).catch(() => {
          throw new errors.NotFound(`No record found`);
        });
      });
    });
  };
}