Name

global.TopicPermissionUtilSNC

Description

No description available

Script

var TopicPermissionUtilSNC = Class.create();
TopicPermissionUtilSNC.prototype = {
  initialize: function() {
      this.TOPIC_MANAGER = 'topic_manager';
      this.TOPIC_CONTRIBUTOR = 'topic_contributor';
  },

  /**
   * This function build an object from User-criteria string with key as User criteria and value as boolean flag.
   * @param {string} criteriaString, comma-separated User criteria.
   * @returns {Object} criteriaCache, Object with each User-criteria as key.
   */
  buildCacheFromCriteriaString : function(criteriaString) {
      var criteriaCache = {};
      if (!criteriaString || criteriaString.length == 0)
          return criteriaCache;
      var criteriaList = criteriaString.split(",");
      criteriaList.forEach(function(criteria) {
          criteriaCache[criteria] = true;
      });

      return criteriaCache;
  },

  /**
   * This function build a list of removed User-criteria and added User-criteria from previous topic record and current topic-record.
   * @param {Object} previousCriteriaCache, User-criteria object from previous topic-record.
   * @param {Object} currentCriteriaCache, User-criteria object from current topic-record.
   * @returns {Object} removeAddCriteriaList, Removed and added User-criteria from current topic record compared to previous topic record.
   */
  buildRemoveAndAddCriteriaFromCache : function(previousCriteriaCache, currentCriteriaCache) {
      var removedCriteriaList = [];
      var addedCriteriaList = [];

      for (criteria in previousCriteriaCache) {
          if (!(criteria in currentCriteriaCache)) {
              removedCriteriaList.push(criteria);
          }
      }

      for (criteria in currentCriteriaCache) {
          addedCriteriaList.push(criteria);
      }

      return {
          removed: removedCriteriaList,
          added: addedCriteriaList
      };
  },

  isValidRemoveScenarioTopicPermission : function(topicGlideRecord, topicCriteriaRemoveList) {
      if (this.isValidRemoveScenario(topicGlideRecord, topicCriteriaRemoveList)) {

      }
  },

  getParentTopicManagerAndContributor: function(parentTopicSysId) {
      var result = {};
      if (parentTopicSysId) {
          var gr = new GlideRecord('topic');
          gr.addQuery('sys_id', parentTopicSysId);
          gr.query();
          if (gr.next()) {
              result[this.TOPIC_MANAGER] = gr[this.TOPIC_MANAGER].toString();
              result[this.TOPIC_CONTRIBUTOR] = gr[this.TOPIC_CONTRIBUTOR].toString();
          }
      }
      return result;
  },

  /**
   * This function will validate the delete scenario of User-criteria from a topic.
   * @param {Object} topicGlideRecord, current topic glide record.
   * @param {Object} topicCriteriaRemoveList, Removed list of user-criteria from current topic.
   * @param {String} applyOnField, field to be checked (topic_manager / topic_contributor).
   * @returns {Boolean} result, true - if validation successful.
   */
  isValidRemoveScenario : function(topicGlideRecord, topicCriteriaRemoveList, applyOnField) {
      var result = true;
      applyOnField = applyOnField || this.TOPIC_MANAGER;
      if (topicGlideRecord && topicCriteriaRemoveList && topicCriteriaRemoveList.length > 0) {
          var parentTopic = topicGlideRecord.parent_topic.toString();
          if (parentTopic && parentTopic.length > 0) {
              var gr = new GlideRecord('topic');
              gr.addQuery('sys_id', parentTopic);
              gr.query();
              if (gr.next()) {
                  var criteriaString = gr[applyOnField].toString();
                  var parentCriteriaCache = this.buildCacheFromCriteriaString(criteriaString);
                  for (var i = 0; i < topicCriteriaRemoveList.length; ++i) {
                      var criteria = topicCriteriaRemoveList[i];
                      if (criteria in parentCriteriaCache) {
                          return false;
                      }
                  }
              }
          }
      }
      return result;
  },

  /**
   * This function cascade the final User-criteria to be applied to all its child topics, the cascade operation is additive.
   * @param {Object} currentTopicGr, Current topic glide record.
   * @param {String} userCriteriaString, User-criteria string separated by comma.
   * @param {String} userCriteriaRemoveString, Removed User-criteria string from current topic.
   * @param {String} applyOnField, field to be checked (topic_manager / topic_contributor).
   */
  addUserCriteriaInChildTopics : function(currentTopicGr, userCriteriaString, userCriteriaRemoveString, applyOnField) {
      var queue = [];
      applyOnField = applyOnField || this.TOPIC_MANAGER;
      queue.push(currentTopicGr.getUniqueValue());
      while (queue.length > 0) {
          var levelTopicSysIds = queue.join(',');
          queue = [];
          var gr = new GlideRecord('topic');
          gr.addQuery('parent_topic', 'IN', levelTopicSysIds);
          gr.query();
          while (gr.next()) {
              var childSysId = gr.getUniqueValue();
              var childUserCriteriaString = gr[applyOnField];
              var childUserCriteriaCache = this.buildCacheFromCriteriaString(childUserCriteriaString);
              var toApplyUserCriteriaCache = this.buildCacheFromCriteriaString(userCriteriaString);
              var removedUserCriteriaCache = this.buildCacheFromCriteriaString(userCriteriaRemoveString);
              var mergeList = this._unionParentAndChildCriteriaWithOverride(childUserCriteriaCache, toApplyUserCriteriaCache, removedUserCriteriaCache);
              gr[applyOnField] = mergeList.join(",");
              // Prevent this update to trigger Business Rule calls
              gr.setWorkflow(false);
              gr.update();
              queue.push(childSysId);
          }
      }
  },

  /**
   * This function cascade the final User-criteria to be applied to all its child topics, the cascade operation is overriding.
   * @param {Object} currentTopicGr, Current topic glide record.
   * @param {String} applyOnField, field to be checked (topic_manager / topic_contributor).
   */
  overrideUserCriteriaInChildTopics : function(currentTopicGr, applyOnField) {
      var queue = [];
      applyOnField = applyOnField || this.TOPIC_MANAGER;
      queue.push(currentTopicGr.getUniqueValue());
      var toBeAppliedUserCriteriaString = currentTopicGr[applyOnField];
      var toBeUpdatedChildTopics = [];
      while (queue.length > 0) {
          var levelTopicSysIds = queue.join(',');
          queue = [];
          var gr = new GlideRecord('topic');
          gr.addQuery('parent_topic', 'IN', levelTopicSysIds);
          gr.query();
          while (gr.next()) {
              var childSysId = gr.getUniqueValue();
              toBeUpdatedChildTopics.push(childSysId);
              queue.push(childSysId);
          }
      }
      if (toBeUpdatedChildTopics.length > 0) {
          var childrenGr = new GlideRecord('topic');
          var childrenSysIds = toBeUpdatedChildTopics.join(',');
          childrenGr.addQuery('sys_id', 'IN', childrenSysIds);
          childrenGr.query();
          while (childrenGr.next()) {
              childrenGr[applyOnField] = toBeAppliedUserCriteriaString;
              childrenGr.setWorkflow(false);
              childrenGr.update();
          }
      }
  },

  /**
   * This function will cascade the Topic manager field to all its child topic.
   * @param {Object} current, Current topic glide record.
   * @param {Object} previous, Previous topic glide record.
   */
  applyCascadeForTopicManager: function(current, previous) {
      this._extractAndPreProcess(current, previous, this.TOPIC_MANAGER);
  },

  /**
   * This function will cascade the Topic contributor field to all its child topic.
   * @param {Object} current, Current topic glide record.
   * @param {Object} previous, Previous topic glide record.
   */
  applyCascadeForTopicContributor: function(current, previous) {
      this._extractAndPreProcess(current, previous, this.TOPIC_CONTRIBUTOR);
  },

  /**
   * This function does the orchestration for cacade operation triggered from business rule.
   * It encapsulate the common operation for topic manager and topic contributor.
   * @param {Object} current, Current topic glide record.
   * @param {Object} previous, Previous topic glide record.
   * @param {String} applyOnField, field to be checked (topic_manager / topic_contributor).
   */
  _extractAndPreProcess: function(current, previous, applyOnField) {
      var previousUserCriteriaString = previous[applyOnField].toString();
      if (current.isNewRecord()) {
          var parentRecord = current.parent_topic.getRefRecord();
          if (parentRecord && parentRecord[applyOnField]) {
              previousUserCriteriaString = parentRecord[applyOnField].toString();
          }
      }
      var currentUserCriteriaString = current[applyOnField].toString();
      var previousUserCriteriaCache = this.buildCacheFromCriteriaString(previousUserCriteriaString);
      var currentUserCriteriaCache = this.buildCacheFromCriteriaString(currentUserCriteriaString);
      var addAndRemoveList = this.buildRemoveAndAddCriteriaFromCache(previousUserCriteriaCache, currentUserCriteriaCache);
      var toRemoveUserCriteriaString = addAndRemoveList.removed.join(",");
      if (addAndRemoveList.removed && addAndRemoveList.removed.length > 0) {
          if (this.isValidRemoveScenario(current, addAndRemoveList.removed, applyOnField)) {
              var userCriteriaToAdd = addAndRemoveList.added.join(",");
              this.addUserCriteriaInChildTopics(current, userCriteriaToAdd, toRemoveUserCriteriaString, applyOnField);
          } else {
              current.setAbortAction(true);
              gs.addErrorMessage(gs.getMessage("Can't remove the inherited user criteria from the child."));
          }
      } else if (addAndRemoveList.added && addAndRemoveList.added.length > 0) {
          var userCriteriaToAdd = addAndRemoveList.added.join(",");
          if (userCriteriaToAdd && userCriteriaToAdd.length > 0) {
              this.addUserCriteriaInChildTopics(current, userCriteriaToAdd, toRemoveUserCriteriaString, applyOnField);
          }
      }
  },
  
  /**
   * This function will return if a logged-in user is a topic manager or a topic contributor for the topic.
   * @param {String} topicSysId, Current topic SYS_ID.
   * @returns {Boolean} true, if the logged-in user is a topic manager or topic contributor for current topic.
   */
  isTopicManagerOrContributor: function(topicSysId) {
  	return this.isTopicManager(topicSysId) || this.isTopicContributor(topicSysId);
  },

  /**
   * This function will return if a logged-in user is a topic manager for the topic.
   * @param {String} topicSysId, Current topic SYS_ID.
   * @returns {Boolean} true, if the logged-in user is topic manager for current topic.
   */
  isTopicManager: function(topicSysId) {
      return this._userCriteriaMatch(topicSysId, this.TOPIC_MANAGER);
  },

  /**
   * This function will return if a logged-in user is a topic manager for any topic.
   * @returns {Boolean} true, if the logged-in user is topic manager for any topic.
   */
  isAnyTopicManager: function() {
      return this._hasAnyPermission(this.TOPIC_MANAGER);
  },

  isAnyTopicContributor: function() {
      return this._hasAnyPermission(this.TOPIC_CONTRIBUTOR);
  },

  canViewTaxonomy :function(taxonomy){
      var critIds = [];
      var gr = new GlideRecord("taxonomy");
      gr.get(taxonomy);
      critIds.push(gr.getValue('managers'));
      if(sn_uc.UserCriteriaLoader.userMatches(gs.getUserID(), critIds))
          return true;
      
      var userCriteriaList = [];
      var criteriaMap = {};
      
      var taxonomyUtil = new TaxonomyUtil();
      var grc = taxonomyUtil.getTaxonomyTopics(taxonomy,false);
      var encodedQuery = this.TOPIC_MANAGER+'ISNOTEMPTY';

      grc.addEncodedQuery(encodedQuery);
      grc.query();
      while (grc.next()) {
          var criteria = [];
          var contributorString = grc.getValue(this.TOPIC_MANAGER).toString();
          if (contributorString) {
              criteria = contributorString.split(",");
          }
          for (var i = 0; i < criteria.length; ++i) {
              var currCriteria = criteria[i];
              if (!(currCriteria in criteriaMap)) {
                  criteriaMap[currCriteria] = true;
              }
          }
      }
      var grc2 = taxonomyUtil.getTaxonomyTopics(taxonomy,false);
      var encodedQuery2 = this.TOPIC_CONTRIBUTOR+'ISNOTEMPTY';

      grc2.addEncodedQuery(encodedQuery2);
      grc2.query();
      while (grc2.next()) {
          var criteria2 = [];
          var contributorString2 = grc2.getValue(this.TOPIC_CONTRIBUTOR).toString();
          if (contributorString2) {
              criteria2 = contributorString2.split(",");
          }
          for (var i2 = 0; i2 < criteria2.length; ++i2) {
              var currCriteria2 = criteria2[i2];
              if (!(currCriteria2 in criteriaMap)) {
                  criteriaMap[currCriteria2] = true;
              }
          }
      }
      
      for (cmc in criteriaMap) {
          userCriteriaList.push(cmc);
      }
      
      if(sn_uc.UserCriteriaLoader.userMatches(gs.getUserID(), userCriteriaList))
          return true;
  },
  
  _hasAnyPermission: function(applyOnField) {
      applyOnField = applyOnField || this.TOPIC_MANAGER;
      var taxonomyUtil = new TaxonomyUtil();
      var isTaxonomyManager = taxonomyUtil.isTaxonomyManager();
      if (isTaxonomyManager) {
          return true;
      }
      var userCriteriaList = [];
      var criteriaMap = {};
      var gr = new GlideRecord("topic");
      gr.addNotNullQuery(applyOnField);
      gr.query();
      while (gr.next()) {
          var criteria = [];
          var criteriaString = gr.getValue(applyOnField).toString();
          if (criteriaString) {
              criteria = criteriaString.split(",");
          }
          for (var i = 0; i < criteria.length; ++i) {
              var currCriteria = criteria[i];
              if (!(currCriteria in criteriaMap)) {
                  criteriaMap[currCriteria] = true;
              }
          }
      }

      for (currCriteria in criteriaMap) {
          userCriteriaList.push(currCriteria);
      }
      return sn_uc.UserCriteriaLoader.userMatches(gs.getUserID(), userCriteriaList);
  },

  /**
   * This function will return if a logged-in user is a topic contributor for the topic.
   * @param {String} topicSysId, Current topic SYS_ID.
   * @returns {Boolean} true, if the logged-in user is topic contributor for current topic.
   */
  isTopicContributor: function(topicSysId) {
      return this._userCriteriaMatch(topicSysId, this.TOPIC_CONTRIBUTOR);
  },

  /**
   * This function does the check for User-criteria match with logged-in user.
   * @param {String} topicSysId, current topic SYS_ID.
   * @param {String} applyOnField, field to be checked (topic_manager / topic_contributor).
   * @returns {Boolean} true, if the logged-in user matches the user-criteria for applied-field (topic_manager / topic_contributor).
   */
  _userCriteriaMatch: function(topicSysId, applyOnField) {
      if (topicSysId && topicSysId.length > 0) {
          applyOnField = applyOnField || this.TOPIC_MANAGER;
          var critIds = [];
          var gr = new GlideRecord("topic");
          gr.addQuery('sys_id', topicSysId);
          gr.query();
          while (gr.next()) {
              var userCriteriaString = gr.getValue(applyOnField) || "";
              gs.info(userCriteriaString);
              critIds = userCriteriaString.split(",");
          }
          return sn_uc.UserCriteriaLoader.userMatches(gs.getUserID(), critIds);
      }
      return false;
  },

  /**
   * This function merge the child topic User-criteria with new added User-criteria in parent.
   * @param {Object} childCache, Object with all User-criteria in current topic.
   * @param {Object} parentCache, Object with all User-criteria in parent topic.
   * @param {Object} removeCache, Object with all User-criteria removed from previous topic.
   * @returns {Object} result, merged result with override action in child-topic.
   */
  _unionParentAndChildCriteriaWithOverride : function(childCache, parentCache, removeCache) {
      var result = [];
      for (criteriaToBeRemoved in removeCache) {
          if (criteriaToBeRemoved in childCache) {
              delete childCache[criteriaToBeRemoved];
          }
      }
      for (criteriaToBeAdded in parentCache) {
          if (!(criteriaToBeAdded in childCache)) {
              childCache[criteriaToBeAdded] = true;
          }
      }
      for (criteria in childCache) {
          result.push(criteria);
      }
      return result;
  },

  type: 'TopicPermissionUtilSNC'
};

Sys ID

4f51fc29772101108b71a0e89e5a9912

Offical Documentation

Official Docs: