zotoio/launchdarkly-nodeutils

View on GitHub
src/LaunchDarklyUtilsRoles.js

Summary

Maintainability
A
0 mins
Test Coverage
import { default as jsonPatch } from 'fast-json-patch';
import { default as fs } from 'fs';
import { default as path } from 'path';
import { default as globule } from 'globule';
import { default as _ } from 'lodash';

// Class representing Custom role functionality
export class LaunchDarklyUtilsRoles {
    /**
     * Custom role specific api functions attached as 'LaunchDarklyUtils.roles'
     * @constructor LaunchDarklyUtilsRoles
     * @param { Swagger } apiClient - generated launchdarkly apiClient
     * @param { Object } log - logger implementation, or 'console'
     * @param { LaunchDarklyUtils } ldUtils - primary utils class
     * @returns { LaunchDarklyUtilsRoles } custom flag api functions
     */
    constructor(apiClient, log, ldUtils) {
        this.log = log;
        this.apiClient = apiClient;
        this.ldUtils = ldUtils;
        if (!this.ldUtils) {
            throw {
                message: 'LaunchDarklyUtilsRoles constructor requires ldUtils parameter'
            };
        }
    }

    /**
     * Api group object key in LD api
     * @returns {string}
     */
    get API_GROUP() {
        return 'Custom roles';
    }

    /**
     * Get all custom roles in account
     * @returns {Promise}
     * @fulfil {Object} custom role list json
     * @reject {Error} object with message
     * @example ldutils getTeamMemberCustomRoles owner-sample-account@launchdarkly.com
     */
    async getCustomRoles() {
        try {
            return this.apiClient.apis[this.API_GROUP].getCustomRoles().then(response => {
                return response.body;
            });
        } catch (e) {
            throw {
                api: 'getCustomRoles',
                message: e.message,
                docs: 'https://apidocs.launchdarkly.com/tag/Custom-roles#operation/getCustomRoles'
            };
        }
    }

    /**
     * Get a single custom role by key
     * @param {string} customRoleKey - custom role key
     * @returns {Promise}
     * @fulfil {Object} custom role json
     * @reject {Error} object with message
     * @example ldutils getCustomRole my-role
     */
    async getCustomRole(customRoleKey) {
        try {
            return this.apiClient.apis[this.API_GROUP]
                .getCustomRole({ customRoleKey: customRoleKey })
                .then(response => {
                    return response.body;
                });
        } catch (e) {
            throw {
                api: 'getCustomRole',
                message: e.message,
                docs: 'https://apidocs.launchdarkly.com/tag/Custom-roles#operation/getCustomRoles'
            };
        }
    }

    /**
     * Get a single role by _id
     * @param {string} customRoleId - custom role _id
     * @returns {Promise}
     * @fulfil {Object} custom role json
     * @reject {Error} object with message
     * @example ldutils getCustomRoleById <id>
     */
    async getCustomRoleById(customRoleId) {
        return this.apiClient.apis[this.API_GROUP].getCustomRoles().then(roleList => {
            let roles = _.filter(roleList.body.items, { _id: customRoleId });

            if (roles.length !== 1) {
                throw {
                    api: 'getCustomRoles',
                    message: `role not found for _id ${customRoleId}`,
                    docs: 'https://apidocs.launchdarkly.com/tag/Custom-roles#operation/getCustomRoles'
                };
            }

            return this.getCustomRole(roles[0].key);
        });
    }

    /**
     * Create a new custom role
     * @param {string} customRoleKey - custom role key
     * @param {string} customRoleName - custom role name
     * @param {string} customRolePolicyArray - array of policy objects per https://docs.launchdarkly.com/docs/custom-roles
     * @param {string} customRoleDescription - user friendly description
     * @returns {Promise}
     * @fulfil {Object} custom role json
     * @reject {Error} object with message
     * @example ldutils createCustomRole my-role "My Role" [policyArrayJson] "some description"
     */
    async createCustomRole(customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription) {
        let customRole = {
            name: customRoleName,
            key: customRoleKey,
            description: customRoleDescription,
            policy: customRolePolicyArray
        };
        try {
            return this.apiClient.apis[this.API_GROUP]
                .postCustomRole({}, { requestBody: customRole })
                .then(response => {
                    return response.body;
                });
        } catch (e) {
            throw {
                api: 'postCustomRole',
                message: e.message,
                docs: 'https://apidocs.launchdarkly.com/tag/Custom-roles#operation/postCustomRole'
            };
        }
    }

    /**
     * Update an existing custom role
     * @param {string} customRoleKey - custom role key
     * @param {string} customRoleName - custom role name
     * @param {string} customRolePolicyArray - array of policy objects per https://docs.launchdarkly.com/docs/custom-roles
     * @param {string} customRoleDescription - user friendly description
     * @returns {Promise}
     * @fulfil {Object} updated custom role json
     * @reject {Error} object with message
     * @example ldutils updateCustomRole my-role "My Role" [policyArrayJson] "some description"
     */
    async updateCustomRole(customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription) {
        let updatedCustomRole = {
            name: customRoleName,
            key: customRoleKey,
            description: customRoleDescription,
            policy: customRolePolicyArray
        };

        let that = this;
        return this.getCustomRole(customRoleKey)

            .then(customRole => {
                let patchDelta = jsonPatch.compare(customRole, updatedCustomRole);
                that.log.debug(`customRoleDiff for '${customRoleKey}' ${JSON.stringify(patchDelta)}`);
                return patchDelta;
            })
            .then(patchDelta => {
                try {
                    return this.apiClient.apis[this.API_GROUP]
                        .patchCustomRole(
                            {
                                customRoleKey: customRoleKey
                            },
                            {
                                requestBody: patchDelta
                            }
                        )
                        .then(response => {
                            return response.body;
                        });
                } catch (e) {
                    throw {
                        api: 'patchCustomRole',
                        message: e.message,
                        docs: 'https://apidocs.launchdarkly.com/tag/Custom-roles#operation/patchCustomRole'
                    };
                }
            });
    }

    /**
     * Check for existence of role by key; update if exists, otherwise create new role
     * @param {string} customRoleKey - custom role key
     * @param {string} customRoleName - custom role name
     * @param {string} customRolePolicyArray - array of policy objects per https://docs.launchdarkly.com/docs/custom-roles
     * @param {string} customRoleDescription - user friendly description
     * @returns {Promise}
     * @fulfil {Object} updated/created custom role json
     * @reject {Error} object with message
     * @example ldutils upsertCustomRole my-role "My Role" [policyArrayJson] "some description"
     */
    async upsertCustomRole(customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription) {
        let that = this;
        return this.getCustomRole(customRoleKey)

            .then(() => {
                that.log.debug(`Role '${customRoleKey}' Found, Updating...`);
                return this.updateCustomRole(
                    customRoleKey,
                    customRoleName,
                    customRolePolicyArray,
                    customRoleDescription
                );
            })

            .catch(() => {
                that.log.debug(`Role '${customRoleKey}' Not Found, Creating...`);
                return this.createCustomRole(
                    customRoleKey,
                    customRoleName,
                    customRolePolicyArray,
                    customRoleDescription
                );
            });
    }

    /**
     * Load a file of custom role json, and update/create roles based on this
     * @param {string} roleBulkLoadFile - path to json file (eg. exampleRoleBulkLoad.json)
     * @returns {Promise}
     * @fulfil {Object} array of updated/created role json
     * @reject {Error} object with message
     * @example ldutils bulkUpsertCustomRoles ./my-roles.json
     */
    async bulkUpsertCustomRoles(roleBulkLoadFile) {
        let filePath = path.resolve(roleBulkLoadFile);
        let roles = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
        let that = this;

        this.log.debug(`Bulk Upserting Roles from File: ${filePath}`);

        return roles.reduce((acc, role) => {
            return acc.then(results => {
                return that.upsertCustomRole(role.key, role.name, role.policy, role.description).then(data => {
                    results.push(data);
                    return results;
                });
            });
        }, Promise.resolve([]));
    }

    /**
     * Create/update custom roles based on a folder of multiple json files
     * @param {string} roleFolder - path to folder containing json
     * @returns {Promise}
     * @fulfil {Object} array of updated/created role json
     * @reject {Error} object with message
     * @example ldutils bulkUpsertCustomRoleFolder ./my-roles-dir-containing json
     */
    async bulkUpsertCustomRoleFolder(roleFolder) {
        let folderPath = path.normalize(path.resolve(roleFolder));
        let globMatch = folderPath + '/*.json';
        this.log.debug(`Looking for Files with Pattern '${globMatch}'`);
        let fileArray = globule.find(globMatch);
        let promises = [];
        let that = this;
        fileArray.forEach(async file => {
            that.log.debug(`Found File '${file}'. Calling 'bulkUpsertCustomRoles'`);
            promises.push(that.bulkUpsertCustomRoles(file));
        });
        // resolve all and flatten into single result array
        return Promise.all(promises).then(results => {
            return Promise.resolve([].concat.apply([], results));
        });
    }
}