"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.disallowSoftDelete = exports.disallowDelete = exports.disallowUpdate = exports.disallowCreate = exports.canAdmin = exports.canCreateNew = exports.canSoftDelete = exports.canUnrelate = exports.canRelate = exports.canList = exports.canDelete = exports.canUpdate = exports.canRead = exports.canCreate = exports.getPermissions = exports.mergeActionGroup = void 0;

var _immutable = _interopRequireDefault(require("immutable"));

var _get = _interopRequireDefault(require("lodash/get"));

var _set = _interopRequireDefault(require("lodash/set"));

var _configHelpers = require("./configHelpers");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const mergeActionGroup = (perms, path, actionGroup) => {
  const existingActionGroup = (0, _get.default)(perms, path);
  let mergedActionGroup;

  if (existingActionGroup) {
    const existingActionCodes = new Set(existingActionGroup.split(''));
    const actionCodes = new Set(actionGroup.split(''));
    mergedActionGroup = ['C', 'R', 'U', 'D', 'L'].reduce((merged, actionCode) => existingActionCodes.has(actionCode) || actionCodes.has(actionCode) ? "".concat(merged).concat(actionCode) : merged, '');
  } else {
    mergedActionGroup = actionGroup;
  }

  (0, _set.default)(perms, path, mergedActionGroup);
  return mergedActionGroup;
};

exports.mergeActionGroup = mergeActionGroup;

const getPermissions = (config, accountPermsData) => {
  const perms = {};
  let accountPerms = (0, _get.default)(accountPermsData, ['ns2:account_permission', 'permission']);

  if (accountPerms) {
    if (!Array.isArray(accountPerms)) {
      accountPerms = [accountPerms];
    }

    let canAdmin = false;
    let canCreateNew = false;
    accountPerms.forEach(permission => {
      const {
        actionGroup,
        resourceName
      } = permission;
      const resourceNameParts = resourceName.split('/');
      let servicePath;
      let transitionName;

      if (resourceNameParts.length === 1) {
        servicePath = resourceNameParts[0];
      } else if (resourceNameParts.length === 2) {
        servicePath = resourceName;
      } else if (resourceNameParts.length === 5 && resourceNameParts[3] === 'workflow') {
        servicePath = resourceNameParts[1];
        transitionName = resourceNameParts[4];
      }

      if (servicePath) {
        const recordTypeConfig = (0, _configHelpers.getRecordTypeConfigByServicePath)(config, servicePath);

        if (recordTypeConfig) {
          const {
            name
          } = recordTypeConfig;

          if (transitionName) {
            mergeActionGroup(perms, [name, 'transition', transitionName], actionGroup);
          } else {
            const mergedActionGroup = mergeActionGroup(perms, [name, 'data'], actionGroup);
            const serviceType = (0, _get.default)(recordTypeConfig, ['serviceConfig', 'serviceType']); // Track if any object, authority, or procedure record can be created. This is used to
            // determine if the Create New navigation item should be shown.

            if (mergedActionGroup.indexOf('C') >= 0 && (serviceType === 'object' || serviceType === 'authority' || serviceType === 'procedure')) {
              canCreateNew = true;
            } // Track if any vocabulary or security record can be created or updated. This is used
            // to determine if the Admin navigation item should be shown.


            if (mergedActionGroup.indexOf('L') >= 0 && (serviceType === 'security' || name === 'vocabulary')) {
              canAdmin = true;
            }
          }
        }
      }
    });
    perms.canCreateNew = canCreateNew;
    perms.canAdmin = canAdmin;
  }

  return _immutable.default.fromJS(perms);
};

exports.getPermissions = getPermissions;

const can = (recordType, permissions, actionCode) => {
  if (!permissions) {
    return false;
  }

  const actions = permissions.getIn([recordType, 'data']);
  return !!actions && actions.indexOf(actionCode) >= 0;
};

const canTransition = (recordType, permissions, transitionName) => {
  if (!permissions) {
    return false;
  }

  const actions = permissions.getIn([recordType, 'transition', transitionName]); // A transition from the UI is always an update (PUT).

  return !!actions && actions.indexOf('U') >= 0;
};

const canCreate = (recordType, permissions) => can(recordType, permissions, 'C');

exports.canCreate = canCreate;

const canRead = (recordType, permissions) => can(recordType, permissions, 'R');

exports.canRead = canRead;

const canUpdate = (recordType, permissions) => can(recordType, permissions, 'U');

exports.canUpdate = canUpdate;

const canDelete = (recordType, permissions) => can(recordType, permissions, 'D');

exports.canDelete = canDelete;

const canList = (recordType, permissions) => can(recordType, permissions, 'L'); // In order to create a relation, the UI requires that permissions of some level (by default,
// update) exist on the member records. (This is not enforced in the services layer.)


exports.canList = canList;

const canRelate = (recordType, permissions, config) => {
  if (!canCreate('relation', permissions)) {
    return false;
  }

  const relationMemberPerm = config && config.relationMemberPerm || 'U';
  return can(recordType, permissions, relationMemberPerm);
};

exports.canRelate = canRelate;

const canUnrelate = (recordType, permissions, config) => {
  if (!canDelete('relation', permissions)) {
    return false;
  }

  const relationMemberPerm = config && config.relationMemberPerm || 'U';
  return can(recordType, permissions, relationMemberPerm);
};

exports.canUnrelate = canUnrelate;

const canSoftDelete = (recordType, permissions) => canTransition(recordType, permissions, 'delete');

exports.canSoftDelete = canSoftDelete;

const canCreateNew = permissions => permissions && !!permissions.get('canCreateNew');

exports.canCreateNew = canCreateNew;

const canAdmin = permissions => permissions && !!permissions.get('canAdmin');

exports.canAdmin = canAdmin;

const disallow = (recordType, permissions, actionCode) => {
  if (can(recordType, permissions, actionCode)) {
    const dataPerms = permissions.getIn([recordType, 'data']);
    return permissions.setIn([recordType, 'data'], dataPerms.replace(actionCode, ''));
  }

  return permissions;
};

const disallowTransition = (recordType, permissions, transitionName) => {
  if (canTransition(recordType, permissions, transitionName)) {
    const transitionPerms = permissions.getIn([recordType, 'transition', transitionName]);
    return permissions.setIn([recordType, 'transition', transitionName], transitionPerms.replace('U', ''));
  }

  return permissions;
};

const disallowCreate = (recordType, permissions) => disallow(recordType, permissions, 'C');

exports.disallowCreate = disallowCreate;

const disallowUpdate = (recordType, permissions) => disallow(recordType, permissions, 'U');

exports.disallowUpdate = disallowUpdate;

const disallowDelete = (recordType, permissions) => disallow(recordType, permissions, 'D');

exports.disallowDelete = disallowDelete;

const disallowSoftDelete = (recordType, permissions) => disallowTransition(recordType, permissions, 'delete');

exports.disallowSoftDelete = disallowSoftDelete;