Name

global.ResponsibilityAccessConfigCacheUtilSNC

Description

No description available

Script

var ResponsibilityAccessConfigCacheUtilSNC = Class.create();
ResponsibilityAccessConfigCacheUtilSNC.prototype = {
  initialize: function() {
      this.context = {};
  },




  /**************************     METHODS FOR FETCHING RESPONSIBILITY ACCESS CONFIGURATIONS     **************************/

  /*
   * Returns
   * true: if there is a valid Responsibility access config record present in the table for [appliesToRelationship, accessLevel, accessibleEntity]
   * false: otherwise
   * 
   */
  hasAccessConfigRecord: function(appliesToRelationship, accessLevel, accessibleEntity) {
      if (gs.nil(appliesToRelationship) || gs.nil(accessibleEntity)) {
          return false;
      }

      // If accessLevel is not passed, default it to READ
      accessLevel = accessLevel || global.CSMRelationshipConstants.ACCESS.READ;

      var appliesToRelationshipObject = this.getAppliesToRelationshipFromCache(appliesToRelationship);
      if (!gs.nil(appliesToRelationshipObject) && !gs.nil(appliesToRelationshipObject[accessLevel]) && !gs.nil(appliesToRelationshipObject[accessLevel][accessibleEntity]))
          return true;

      return false;
  },

  /*
   * Returns list of responsibility sys_id's after filtering based on the passed parameters
   * 
   */
  getResponsibilitiesFromCache: function(appliesToRelationship, accessLevel, accessibleEntity, applicableTo, restrictAccessTo, skipRoleCheck, skipDomainCheck) {
      if (gs.nil(appliesToRelationship) || gs.nil(accessibleEntity)) {
          return [];
      }

      // If accessLevel is not passed, default it to READ
      accessLevel = accessLevel || global.CSMRelationshipConstants.ACCESS.READ;

      var appliesToRelationshipObject = this.getAppliesToRelationshipFromCache(appliesToRelationship);
      if (gs.nil(appliesToRelationshipObject))
          return [];

      this.context.isDomainSupportPluginActive = new global.CSManagementUtils().isDomainSupportPluginActive();
      this.context.userDomainId = gs.getSession().getCurrentDomainID();

      var responsibilities = this._getResponsibilitiesFromAccessLevelKey(appliesToRelationshipObject[accessLevel], accessibleEntity, applicableTo, restrictAccessTo, skipRoleCheck, skipDomainCheck) || [];

      // If accessLevel is a part of FULL_ACCESS_LEVEL_LIST, then return responsibilities that matches with FULL access level also
      if (this.FULL_ACCESS_LEVEL_LIST.indexOf(accessLevel) >= 0) {
          var responsibilitiesFromFullAccess = this._getResponsibilitiesFromAccessLevelKey(appliesToRelationshipObject[global.CSMRelationshipConstants.ACCESS.FULL], accessibleEntity, applicableTo, restrictAccessTo, skipRoleCheck, skipDomainCheck) || [];
          responsibilities = this.mergeLists(responsibilities, responsibilitiesFromFullAccess);
      }

      return responsibilities;
  },

  /*
   * Builds private cache catalog RESPONSIBILITY_ACCESS_CONFIG_CACHE, if it doesn't exist; and
   * Returns below Object
   * 
   * Access level (String) : {
   *           Accessible Entity (String): [
   *               {
   *                   "responsibility": sys_id of the responsibility,
   *                   "name": Name (derived from responsibility),
   *                   "domainId": Domain ID of the responsibility (derived from responsibility),
   *                   "roles": [
   *                       role1, role2, ...
   *                   ],
   *                   "applicableTo": List (derived from responsibility),
   *                   "restrictAccessTo": String
   *               }
   * 
   */
  getAppliesToRelationshipFromCache: function(appliesToRelationship) {
      if (gs.nil(appliesToRelationship))
          return {};

      if (!this._isCacheCatalogAvailable()) {
          var responsibilityAccessConfig = this.buildResponsibilityAccessConfigCache() || {};
          return responsibilityAccessConfig[appliesToRelationship] || {};
      }

      var appliesToRelationshipObjectString = GlideCacheManager.get(this.CACHE_NAME, appliesToRelationship) || '{}';
      return JSON.parse(appliesToRelationshipObjectString);
  },

  /*
   * Returns list of responsibility sys_id's from accessLevelObject matching the parameter filters
   * 
   */
  _getResponsibilitiesFromAccessLevelKey: function(accessLevelObject, accessibleEntity, applicableTo, restrictAccessTo, skipRoleCheck, skipDomainCheck) {
      if (gs.nil(accessLevelObject) || gs.nil(accessibleEntity) || gs.nil(accessLevelObject[accessibleEntity]))
          return [];

      var responsibilityMap = {};
      var accessibleEntityObject = accessLevelObject[accessibleEntity] || [];
      accessibleEntityObject.forEach(function(responsibilityObject) {
          if (this._isValidResponsibility(responsibilityObject, applicableTo, restrictAccessTo, skipRoleCheck, skipDomainCheck))
              responsibilityMap[responsibilityObject.responsibility] = true;
      }, this);

      return Object.keys(responsibilityMap);
  },

  /*
   * Returns
   * true : if the responsibilityObject matches with the other params
   * false : otherwise
   */
  _isValidResponsibility: function(responsibilityObject, applicableTo, restrictAccessTo, skipRoleCheck, skipDomainCheck) {
      if (gs.nil(responsibilityObject))
          return false;

      // Nil responsibilityObject.applicableTo is not valid
      if (!gs.nil(applicableTo)) {
          if (applicableTo.contains(','))
              return false;
          if (gs.nil(responsibilityObject.applicableTo) || responsibilityObject.applicableTo.split(',').indexOf(applicableTo) == -1)
              return false;
      }

      // Nil responsibilityObject.restrictAccessTo is valid for all
      if (!gs.nil(restrictAccessTo)) {
          if (restrictAccessTo.contains(','))
              return false;
          if (!gs.nil(responsibilityObject.restrictAccessTo) && restrictAccessTo != responsibilityObject.restrictAccessTo)
              return false;
      }

      if (!(skipRoleCheck == true || skipRoleCheck == 'true')) {
          if (!gs.hasRole(responsibilityObject.roles))
              return false;
      }

      if (!(skipDomainCheck == true || skipDomainCheck == 'true')) {
          // global.CSMDomainSeparationUtils() is available only if domain support plugin is active
          if (this.context.isDomainSupportPluginActive == true) {
              // This context is set at getResponsibilitiesFromCache() public method
              if (!new global.CSMDomainSeparationUtils().hasAccessToDomain(responsibilityObject.domainId, this.context.userDomainId))
                  return false;
          }
      }

      return true;
  },




  /***********************     METHODS FOR BUILDING/FLUSHING CACHE    *****************************/

  /*
   * For each appliesToRelationship in Responsibility Access Config Table,
   * creates a cache entry with 
   * key = appliesToRelationship
   * value = {
   *   Object
   * }
   * 
   * where Object structure is as follows:
   * Access level (String) : {
   *           Accessible Entity (String): [
   *               {
   *                   "responsibility": sys_id of the responsibility,
   *                   "name": Name (derived from responsibility),
   *                   "domainId": Domain ID of the responsibility (derived from responsibility),
   *                   "roles": [
   *                       role1, role2, ...
   *                   ],
   *                   "applicableTo": List (derived from responsibility),
   *                   "restrictAccessTo": String
   *               }
   */
  buildResponsibilityAccessConfigCache: function() {
      var responsibilityAccessConfig = this.populateResponsibilityAccessConfig() || {};
      this._initPrivateCache();
      Object.keys(responsibilityAccessConfig).forEach(function(key) {
          GlideCacheManager.put(this.CACHE_NAME, key, JSON.stringify(responsibilityAccessConfig[key]));
      }, this);
      return responsibilityAccessConfig;
  },

  /*
   * Performs full cache flush
   * 
   */
  flushResponsibilityAccessConfigCache: function() {
      GlideCacheManager.flush(this.CACHE_NAME);
  },

  /*
   * Returns below Object after processing each records in Responsibility access config table
   * 
   * Access level (String) : {
   *           Accessible Entity (String): [
   *               {
   *                   "responsibility": sys_id of the responsibility,
   *                   "name": Name (derived from responsibility),
   *                   "domainId": Domain ID of the responsibility (derived from responsibility),
   *                   "roles": [
   *                       role1, role2, ...
   *                   ],
   *                   "applicableTo": List (derived from responsibility),
   *                   "restrictAccessTo": String
   *               }
   */
  populateResponsibilityAccessConfig: function() {
      this.context.responsibilityDefinitionMap = this.getResponsibilityDefinitions();
      var responsibilityAccessConfig = {};
      var gr = new GlideRecord(global.CSMBaseConstants.RESPONSIBILITY_ACCESS_CONFIG_TABLE);
      gr.queryNoDomain();
      while (gr.next()) {
          this._populateAppliesToRelationship(responsibilityAccessConfig, gr);
      }
      return responsibilityAccessConfig;
  },

  /*
   * Queries Responsibility Definition table and returns a map
   * responsibilityId : {
   *   name : responsibility name,
   *   applicableTo : applicable to,
   *   domainId : domain of the responsibility
   * }
   * 
   */
  getResponsibilityDefinitions: function() {
      var responsibilityDefinitions = {};
      var gr = new GlideRecord(global.CSMBaseConstants.RESPONSIBILITY_DEFINITION_TABLE);
      gr.queryNoDomain();
      while (gr.next()) {
          responsibilityDefinitions[gr.sys_id + ''] = {
              name: gr.name + '',
              applicableTo: gr.applicable_to + '',
              domainId: gr.sys_domain + ''
          };
      }
      return responsibilityDefinitions;
  },

  /*
   * Creates private cache catalog 'RESPONSIBILITY_ACCESS_CONFIG_CACHE', with key
   * _created_on_ : current time
   *
   */
  _initPrivateCache: function() {
      if (!this._isCacheCatalogAvailable()) {
          GlideCacheManager.addPrivateCacheable(this.CACHE_NAME);
          GlideCacheManager.put(this.CACHE_NAME, "_created_on_", new GlideDateTime().getNumericValue());
      }
  },

  _isCacheCatalogAvailable: function() {
      return !(GlideCacheManager.get(this.CACHE_NAME, "_created_on_") === null);
  },

  /*
   * param1 : Object
   * param2 : GlideRecord of Responsibility Access Configuration
   * 
   */
  _populateAppliesToRelationship: function(responsibilityAccessConfig, accessConfigGR) {
      if (gs.nil(accessConfigGR) || gs.nil(accessConfigGR.applies_to_relationship))
          return;

      var appliesToRelationship = accessConfigGR.applies_to_relationship + '';
      this._initializeObject(responsibilityAccessConfig, appliesToRelationship);
      this._populateAccessLevels(responsibilityAccessConfig[appliesToRelationship], accessConfigGR);
  },

  /*
   * param1 : Object
   * param2 : GlideRecord of Responsibility Access Configuration
   * 
   */
  _populateAccessLevels: function(appliesToRelationshipObj, accessConfigGR) {
      if (gs.nil(appliesToRelationshipObj) || gs.nil(accessConfigGR) || gs.nil(accessConfigGR.access_levels))
          return;

      var accessLevelList = (accessConfigGR.access_levels + '').split(',');
      accessLevelList.forEach(function(accessLevel) {
          this._initializeObject(appliesToRelationshipObj, accessLevel);
          this._populateAccessibleEntities(appliesToRelationshipObj[accessLevel], accessConfigGR);
      }, this);
  },

  /*
   * param1 : Object
   * param2 : GlideRecord of Responsibility Access Configuration
   * 
   */
  _populateAccessibleEntities: function(accessLevelObj, accessConfigGR) {
      if (gs.nil(accessLevelObj) || gs.nil(accessConfigGR) || gs.nil(accessConfigGR.accessible_entities))
          return;

      var accessibleEntityList = (accessConfigGR.accessible_entities + '').split(',');
      accessibleEntityList.forEach(function(accessibleEntity) {
          this._initializeObject(accessLevelObj, accessibleEntity, this.TYPE_ARRAY);
          this._populateResponsibilityData(accessLevelObj[accessibleEntity], accessConfigGR);
      }, this);
  },
  /*
   * Populates responsibility, roles, restrictAccessTo, applicableTo, responsibility name, responsibility domain ID
   * param1 : Object
   * param2 : GlideRecord of Responsibility Access Configuration
   * 
   */
  _populateResponsibilityData: function(accessibleEntityArray, accessConfigGR) {
      if (gs.nil(accessibleEntityArray) || gs.nil(accessConfigGR) || gs.nil(accessConfigGR.responsibility))
          return;

      if (!(accessConfigGR.active == true))
          return;

      var responsibilityId = accessConfigGR.responsibility + '';

      // Create separate objects for each restrictAccessTo to avoid duplicates
      var restrictAccessToList = (accessConfigGR.restrict_access_to + '').split(',');
      restrictAccessToList.forEach(function(restrictAccessTo) {
          var responsibilityObject = {
              responsibility: responsibilityId,
              name: this.context.responsibilityDefinitionMap[responsibilityId].name,
              domainId: this.context.responsibilityDefinitionMap[responsibilityId].domainId,
              roles: (accessConfigGR.roles + '').split(','),
              applicableTo: this.context.responsibilityDefinitionMap[responsibilityId].applicableTo,
              restrictAccessTo: restrictAccessTo
          };
          this.__processResponsibility(accessibleEntityArray, responsibilityObject);
      }, this);
  },

  /*
   * param1 : Array
   * param2 : Candidate object that can be pushed to the array, or merged with any existing objects in the array
   * 
   */
  __processResponsibility: function(accessibleEntityArray, newResponsibilityObject) {
      // The params {accessibleEntityArray} and {newResponsibilityObject} are always not null here.

      var needsInsert = true;
      accessibleEntityArray.forEach(function(existingObject) {
          if (existingObject.responsibility != newResponsibilityObject.responsibility)
              return;

          if (existingObject.restrictAccessTo != newResponsibilityObject.restrictAccessTo)
              return;

          needsInsert = false;
          existingObject.roles = this.mergeLists(existingObject.roles, newResponsibilityObject.roles);
      }, this);

      if (needsInsert)
          accessibleEntityArray.push(newResponsibilityObject);
  },

  mergeLists: function(list1, list2) {
      var listMap = {};
      if (!gs.nil(list1)) {
          list1.forEach(function(listItem) {
              listMap[listItem] = true;
          });
      }
      if (!gs.nil(list2)) {
          list2.forEach(function(listItem) {
              listMap[listItem] = true;
          });
      }
      return Object.keys(listMap);
  },

  /*
   * If {key} doesn't exist in {obj}, then create it
   * 
   */
  _initializeObject: function(obj, key, type) {
      if (Object.keys(obj).indexOf(key) == -1)
          obj[key] = (type == this.TYPE_ARRAY) ? [] : {};
  },

  CACHE_NAME: "RESPONSIBILITY_ACCESS_CONFIG_CACHE",
  TYPE_ARRAY: "TYPE_ARRAY",
  FULL_ACCESS_LEVEL_LIST: new global.CSManagementUtils().getFullAccessLevelList(),
  type: 'ResponsibilityAccessConfigCacheUtilSNC'
};

Sys ID

85439da653712110706eddeeff7b1233

Offical Documentation

Official Docs: