Your IP : 216.73.216.220


Current Path : /home/deltalab/PMS/partner-manager-backend/services/
Upload File :
Current File : //home/deltalab/PMS/partner-manager-backend/services/indaco-module.js

// dependencies
const { partnerModel } = require('../models/mongoose/partner');
const { userModel } = require('../models/mongoose/user');

/**
 * Check if the specified indaco module is part of the partner's subscription plan
 * 
 * @param {string} partnerId the id of the partner to check
 * @param {string} moduleCode the indaco module code to check
 * @returns a promise that will resolve in a boolean value: true if the module is active;
 *          otherwise, false
 */
async function isAccessibleModuleActiveAsync(partnerId, moduleCode) {

  const partner = await partnerModel.findById(partnerId).populate({
    path: 'subscriptionPlanId',
    populate: {
      path: 'indacoModulesIds'
    }
  }).lean();

  return !!partner.subscriptionPlanId.indacoModulesIds.find(im => im.code === moduleCode);
}

/**
 * Check if the specified user has active the specified feature for the specified service
 * 
 * @param {*} userId the user id to search for
 * @param {*} moduleCode the indaco module code to check
 * @param {*} featureCode the accessible feature code to check
 */
async function isModuleAccessibleFeatureEnabled(userId, moduleCode, featureCode) {
  const user = await userModel.findById(userId).lean();

  return !!user.userModuleAccessibleFeatures.find(f => f[0] === moduleCode && f[1] === featureCode);
}

/**
 * Filters authenticated resolvers for only a specific indaco module activated on related partner; 
 * use it in conjunction with the authentication required function (auth service)
 * cause it depends on its decoded token information and authentication check.
 * 
 * @param {*} resolvers 
 * @returns 
 */
function partnerIndacoModuleRequired(resolvers, moduleCode) {
  Object.keys(resolvers).forEach((k) => {
    resolvers[k] = resolvers[k].wrapResolve(next => async (rp) => {
      const user = await userModel.findById(rp.decoded.userId).lean();

      if (!user.partnerId) {
        throw new Error('User without a partner!');
      }

      if (!(await isAccessibleModuleActiveAsync(user.partnerId, moduleCode))) {
        throw new Error('Unauthorized');
      }

      return next(rp);
    })
  });

  return resolvers;
}

/**
 * Filters authenticated resolvers for only a specific indaco module accessible feature activated on the user; 
 * use it in conjunction with the authentication required function (auth service)
 * cause it depends on its decoded token information and authentication check.
 * 
 * @param {*} resolvers 
 * @returns 
 */
function partnerIndacoAccessibleFeatureRequired(resolvers, moduleCode, featureCode) {
  Object.keys(resolvers).forEach((k) => {
    resolvers[k] = resolvers[k].wrapResolve(next => async (rp) => {
      if (!(await isModuleAccessibleFeatureEnabled(rp.decoded.userId.toString(), moduleCode, featureCode))) {
        throw new Error('Unauthorized');
      }

      return next(rp);
    })
  });

  return resolvers;
}

// EXPORTS ===========================
module.exports = {
  isAccessibleModuleActiveAsync,
  isModuleAccessibleFeatureEnabled,
  partnerIndacoModuleRequired,
  partnerIndacoAccessibleFeatureRequired
};