All files / node-activedirectory/lib/services service.getUsersForGroups.js

0% Statements 0/60
0% Branches 0/42
0% Functions 0/17
0% Lines 0/55

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129                                                                                                                                                                                                                                                                 
var _                                   = require('underscore');
const log                               = require('./internal/service.log');
const joinAttributes                    = require('./internal/service.joinAttributes');
 
const chunkItem                         = require('./getUsersForGroup/service.usersforgroup.chunkItem');
 
const defaultPageSize                   = 1000; // The maximum number of results that AD will return in a single call. Default=1000
const defaultAttributes                 = require('../configs/config.defaultAttributes');
const limitpromises                       = require('limitpromises');
 
/**
 * For the specified group, retrieve all of the users that belong to the group.
 *
 * @public
 * @param {Object} [opts] Optional LDAP query string parameters to execute. { scope: '', filter: '', attributes: [ '', '', ... ], sizeLimit: 0, timelimit: 0 }
 * @param {String} groupName The name of the group to retrieve membership from.
 * @param {Function} callback The callback to execute when completed. callback(err: {Object}, users: {Array[User]})
 */
async function getUsersForGroups(opts, groupNames, callback) {
 
    let groups = [];
    let groupsCall = limitpromises(GroupName =>{
        return new Promise((resolve, reject) => {
            self.findGroup(_.defaults({}, _.omit(opts || {}, 'attributes'), {
                attributes: joinAttributes((opts || {}).attributes || defaultAttributes.group, ['member'])
            }), groupName).then((group) => {
                // If no Group has been found
                if(!group) resolve([]);
                
                groups.push(getMembersOfTypeGroup(group.member));
            });
        })
    } )
    var self = this;
    return new Promise((resolve, reject) => {
        if (typeof (groupName) === 'function') {
            callback = groupName;
            groupName = opts;
            opts = undefined;
        }
        log.trace('getUsersForGroup(%j,%s)', opts, groupName);
    
        let result = [];
    
        self.findGroup(_.defaults({}, _.omit(opts || {}, 'attributes'), {
            attributes: joinAttributes((opts || {}).attributes || defaultAttributes.group, ['member'])
        }), groupName).then(async function (group) {
            // Group not found
            if (!group) {
                if (callback) callback(null, group);
                resolve(group);
                return;
            }
            // If only one result found, encapsulate result into array.
            if (typeof (group.member) === 'string') {
                group.member = [group.member];
            }
 
            /**
             * Breaks the large array into chucks of the specified size.
             * @param {Array} arr The array to break into chunks
             * @param {Number} chunkSize The size of each chunk.
             * @returns {Array} The resulting array containing each chunk
             */
            function chunk(arr, chunkSize) {
                var result = [];
                for (var index = 0, length = arr.length; index < length; index += chunkSize) {
                    result.push(arr.slice(index, index + chunkSize));
                }
                return (result);
            }
 
            // We need to break this into the default size queries so
            // we can have them running concurrently.
            var chunks = chunk(group.member || [], defaultPageSize);
            if (chunks.length > 1) {
                log.debug('Splitting %d member(s) of "%s" into %d parallel chunks',
                    (group.member || []).length, groupName, chunks.length);
            }
 
            // Chunks represent the cn for each user;
            // We use the limitpromises Function which will limit the number of promises running at the same time.
            // This is necessary to avoid that the socket of the AD is in use and thus cannot be accessed
            if(!chunks || chunks.length === 0) return resolve([]);
            let allChunks = limitpromises(Chunk => {
                return new Promise((resolve, reject) => {
                    chunkItem(Chunk, opts, self).then(members => {
                        resolve(result.concat(members));
                    }, err => {
                        if(callback){
                            callback(err);
                        }
                        return reject(err);                      
                    });
                });
            }, chunks, 10000, "chunks");
            
 
            // Wait for all the chunks to be ready then send the result back;
            await Promise.all(allChunks.map(Chunk => {
                return Chunk.promiseFunc
            })).then(data => {
                if(callback){
                    if(data.length === 0){
                        callback(null, []);
                    } else {
                        callback(null, data[0]);
                    }                        
                }
                return data.length === 0 ? resolve([]) : resolve(data[0]);
            }, err => {
                return reject(err);
            });
        }, err => {
            
            if (callback) callback(err);
            return reject(err);
        
        });
    });
    
};
 
// Takes an array of group members and returns all the ones that are groups
function getMembersOfTypeGroup(Members){
    return Members.filter(Member => {return Member.indexOf("OU=Group") !== -1});
}
 
module.exports = getUsersForGroups;