| Current Path : /proc/thread-self/root/home/deltalab/PMS/partner-manager-backend/services/ |
| Current File : //proc/thread-self/root/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
};