Name

sn_grc_workbench.GRCWorkbenchService

Description

GRC Workbench service

Script

var GRCWorkbenchService = Class.create();
GRCWorkbenchService.prototype =  Object.extendsObject(global.AbstractAjaxProcessor, {
  getDependenciesClassesInfo: function() {
  	var result = {};
  	var availableClasses = [];
  	var profileClassList = '';
  	var entityId = this.getParameter('sysparm_clicked_node_id');
  	var type = this.getParameter('sysparm_type');
  	var direction = this.getParameter('sysparm_direction');		
  	
  	var profile = this._getProfile(type, entityId);
  	
  	// Could not get the profile of selected node
  	if (profile == null)
  		return null;			
  	
  	if (direction == 'upstream')
  		profileClassList = new sn_grc.GRCUtils().getUpstreamProfileClassListFromProfileClassModel(profile);
  	else
  		profileClassList = new sn_grc.GRCUtils().getDownstreamProfileClassListFromProfileClassModel(profile);
  	
  	if (profileClassList != '') {	
  		var returnAlreadyAssociated = type == 'risk';
  		var profileClassArr = profileClassList.split(',');
  		for (var i = 0; i < profileClassArr.length; i++) {
  			var profileList = new sn_grc.GRCUtils().getProfilesFromProfileClass(profileClassArr[i], profile, direction, returnAlreadyAssociated);

  			// If no profiles are under the profile class, do not add the profile class to the result
  			if (profileList == '')
  				continue;

  			// If no risk are under the profiles, do not add the profile class to the result
  			if ((type == 'risk') && !this._risksExistForProfileList(profileList, direction, entityId))
  				continue;

  			var pc = new GlideRecord('sn_grc_profile_class');
  			if (pc.get(profileClassArr[i])) {
  				availableClasses.push({
  					'sys_id' : profileClassArr[i],
  					'ci_type_label' :  pc.name + '',
  					'node_type' : 'class',
  					'loading' : false,
  					'expanded' : false,
  					'has_extensions' : true,
  					'level'  : 0,
  					'children' : []
  				});
  			}						

  		}
  	}
  	
  	result = {
  		'results' : availableClasses,
  		'msg'     : (availableClasses.length == 0)? gs.getMessage('No {0} relationships are available for the selected node', direction) : ''
  	};
  	
  	return this.encodeJson(result);
  },
  
  _getProfile: function(type, entityId) {
  	if (type == 'risk') {
  		var r = new GlideRecord('sn_risk_risk');
  		if (r.get(entityId) && r.active)
  			entityId = r.profile + '';			
  	}
  		
  	var p = new GlideRecord('sn_grc_profile');
  	if (p.get(entityId) && p.active)
  		return p;	
  	return null;
  },
  
  _risksExistForProfileList: function(profileList, stream, entityId) {
  	var hasRisk = false;
  	var risk = new GlideRecord('sn_risk_risk');
  	risk.addQuery('state', '!=', 'retired');
  	risk.addQuery('profile', 'IN', profileList);
  	risk.query();

  	while (risk.next()) {
  		var m2mRisk = new GlideRecord('sn_risk_m2m_risk_risk');
  		m2mRisk.addQuery(stream + '_risk', risk.sys_id + '');
  		if (stream == 'upstream')
  			m2mRisk.addQuery('downstream_risk', entityId);
  		else
  			m2mRisk.addQuery('upstream_risk', entityId);
  		m2mRisk.query();
  		
  		if (m2mRisk.next())
  			continue;
  		
  		hasRisk = true;
  	}
  	return hasRisk;
  },
  
  getHierarchy: function() {		
  	return this.encodeJson(this._getHierarchy());
  },
  
  _getHierarchy: function() {
  	var root = new GlideRecord('sn_grc_profile_class');
  	root.addQuery('is_root', true);
  	root.setLimit(1);
  	root.query();
      
  	this.nodeCount = {};
  	var hierarchy = {};
  	if(root.next()) {
  		this.nodeCount[root.sys_id] = 1;
  		hierarchy = this._dfs(root);
  	}
  	return { 'hierarchy' : hierarchy,
  				'node_count' : this.nodeCount };		
  },
  
  _dfs: function(node) {
  	var info = {};
  	info['sys_id'] = node.sys_id + '';
  	info['name'] = node.name + '';

  	var child = new GlideRecord('sn_grc_profile_class');
  	child.addQuery('roll_up_to', 'CONTAINS', node.sys_id);
  	child.query();

  	var children = [];
  	while(child.next()) {     
  		if(!this.nodeCount[child.sys_id]) {
  			this.nodeCount[child.sys_id] = 1;
  			children.push(this._dfs(child));
  		} else {
  			this.nodeCount[child.sys_id] ++;
              var childInfo = {};
              childInfo['sys_id'] = child.sys_id + '';
              childInfo['name'] = child.name + '';
              childInfo['children'] = [];
              children.push(childInfo);
          }
  	}
  	info['downstream'] = children;
  	return info;       
  },
  
  getClasses: function() {
  	return this.encodeJson(this._getProfileClasses());
  },
  
  _getProfileClasses: function() {
  	var fieldList = ['sys_id', 'name', 'roll_up_to', 'is_root'];
  	var profileClass = new GlideRecord('sn_grc_profile_class');
  	profileClass.orderBy('name');
  	profileClass.query();
  	
  	var classes = [];
  	var rootIndex;
  	
  	while(profileClass.next()) {
  		var info = {};
  		for(var i = 0 ; i < fieldList.length ; i++) 
  			info[fieldList[i]] = profileClass.getValue(fieldList[i]);							
  		classes.push(info);
  	}
  	
  	return classes;
  },
  
  removeClass: function() {
  	var classId = this.getParameter('sysparm_class_id');
  	var profileClass = new GlideRecord('sn_grc_profile_class');
  	if (profileClass.get(classId)) {
  		profileClass.deleteRecord();
  		return 'true';
  	}
  	return null;
  },
  									  
  createProfileClass: function() {
  	var className = this.getParameter('sysparm_class_name');
  	var profileClass = new GlideRecord('sn_grc_profile_class');
  	profileClass.setValue('name', className);
  	
  	if(profileClass.insert()) 
  		return this.encodeJson('true');		
  	else 
  		return this.encodeJson({
  			error: gs.getMessage('Could not insert class, could be duplicate entry')
  		});
  },
  
  saveHierarchy: function() {
  	var hierarchy = new global.JSON().decode(this.getParameter('sysparm_hierarchy'));		
      
      // Remove earlier changes
      var profileClass = new GlideRecord('sn_grc_profile_class');
      profileClass.query();
      
      while(profileClass.next()) {
          profileClass.setValue('is_root', false);
          profileClass.setValue('roll_up_to', '');
          profileClass.update();        
      }
      
      // Set the root
      profileClass = new GlideRecord('sn_grc_profile_class');
      
      if(profileClass.get(hierarchy.sys_id)) {   
          profileClass.setValue('is_root', true);
          profileClass.update();
      }
     
  	var classes = {};
  	var classesArr = [];
  	var queue = [];
      var node = {};		
  	var child = {};
      var i = 0;
  	
  	if(hierarchy.name) 
  		queue.push(hierarchy);
  	
  	// Get the classes in hierarchy format by doing BFS
      while(queue.length != 0) {
          node = queue.shift();
  		
  		if(!classes[node.sys_id]) {
  			var nodeData = {name: '', roll_up_to : [], sys_id: node.sys_id};
  			classesArr.push(nodeData);
  			classes[node.sys_id] = nodeData;			
  		}
  		classes[node.sys_id].name = node.name;		
  		if(node.downstream) {
  			for(i = 0 ; i < node.downstream.length ; i++) {
  				child = node.downstream[i];
  				if(!classes[child.sys_id]) {
  					var childNode = {name: child.name, roll_up_to : [], sys_id: child.sys_id};
  					classesArr.push(childNode);
  					classes[child.sys_id] = childNode;
  				}
  				
  				if(classes[child.sys_id].roll_up_to.indexOf(node.sys_id) == -1)
  					classes[child.sys_id].roll_up_to.push(node.sys_id);
  				queue.push(child);
  			}            
  		}
      }
  	
  	return this._saveClasses(classesArr);		                				
  },
  
  _saveClasses : function(classesArr) {
  	var error = false;
  	for(var i = 0 ; i < classesArr.length ; i++) {
  		var sys_id = classesArr[i].sys_id;

  		var profileClass = new GlideRecord('sn_grc_profile_class');
  		if(profileClass.get(sys_id)) {
  			profileClass.setValue('roll_up_to', classesArr[i].roll_up_to);
  			if(!profileClass.update()) 
  				error = true;                
  		}
  		else 
  			error = true;            
  	}       

  	if(error)       
  		return false;
  	return true;
  },	
  
  getClassesInfo: function() {
  	var classes = this._getClassesForGivenProfile();				
  	return this.encodeJson(classes);	
  },
  
  _getClassesForGivenProfile: function() {
  	var profileWithNoClassLabel = gs.getMessage('( Empty )');
  	var classes = [];
  	var profile = new GlideAggregate('sn_grc_profile');
  	profile.addQuery('active', 'true');
  	profile.addAggregate('count');
  	profile.groupBy('profile_class');
  	profile.orderBy('profile_class.name');
  	profile.query();
  	
  	while (profile.next()) {
  		var profileClassId = profile.profile_class + '';
  		var numberOfProfiles = profile.getAggregate('count');
  		
  		if ((profileClassId == '') && (numberOfProfiles == 0))
  			continue;
  		
  		classes.push({
  			'sys_id' : (profileClassId == '')? '-1': profileClassId,
  			'ci_type_label' :  (profileClassId == '')? profileWithNoClassLabel : profile.profile_class.name + '',
  			'node_type' : 'class',
  			'loading' : false,
  			'expanded' : false,
  			'has_extensions' : (numberOfProfiles > 0)? true : false,
  			'level'  : 0,
  			'children' : []
  		});			
  		
  	}	
  	return classes;
  },	
  
  getListHierarchy: function () {
  	var results = [];
  	var entityId = this.getParameter('sysparm_selected_node_id');
  	var direction = this.getParameter('sysparm_direction');
  	var entityType = this.getParameter('sysparm_type');
  	var profileOrClassId = this.getParameter('sysparm_id');
  	profileOrClassId = profileOrClassId == '-1'? '' : profileOrClassId;
  	var dependencyType = this.getParameter('sysparm_page_type');	
  	var entityProfileId = this.getParameter('sysparm_profile_id');

  	if (entityType == 'class') {
  		if (direction)
  			results = this._getListHierarchyForEligibles(profileOrClassId, entityId, direction, dependencyType);
  		else
  			results = this._getListHierarchyForAll(profileOrClassId, dependencyType, entityProfileId);
  	}
  	else if (entityType == 'profile') {
  		var profile = new GlideRecord('sn_grc_profile');
  		profile.addActiveQuery();
  		profile.addQuery('sys_id', profileOrClassId);
  		profile.query();
  		if (!profile.next())
  			return this.encodeJson(null);
  		
  		var risk = new GlideRecord('sn_risk_risk');
  		risk.addQuery('state', '!=', 'retired');
  		risk.addQuery('profile', profileOrClassId);
  		risk.query();
  		
  		while (risk.next()) {
  			if (direction && this._relationshipExists(risk.sys_id + '', direction, entityId))
  				continue;					
  			
  			results.push({
  				'ci_type_label' : risk.getDisplayValue() + '',
  				'sys_id' : risk.sys_id + '',
  				'node_type' : 'risk',
  				'loading' : false,
  				'expanded' : false,
  				'has_extensions' : false,
  				'level' : 2,
  				'draggable' : direction ? true : false,
  				'children' : []
  			});					
  		}
  	}
  	
  	return this.encodeJson(results);		
  },
  
  _relationshipExists: function(riskId, direction, entityId) {
  	var m2mRisk = new GlideRecord('sn_risk_m2m_risk_risk');
  	m2mRisk.addQuery(direction + '_risk', riskId);
  	if (direction == 'upstream')
  		m2mRisk.addQuery('downstream_risk', entityId);
  	else
  		m2mRisk.addQuery('upstream_risk', entityId);
  	m2mRisk.query();

  	if (m2mRisk.hasNext())
  		return true;
  	return false;
  },
  
  _getListHierarchyForAll: function(profileOrClassId, dependencyType, profileId) {		
  	var results = [];
  	var profile = new GlideRecord('sn_grc_profile');
  	profile.addActiveQuery();
  	profile.addQuery('profile_class', profileOrClassId);
  	profile.query();

  	if (profile.getRowCount() == 0)
  		return null;
  	
  	while (profile.next()) {
  		var profileInfo = {
  			'ci_type_label' : profile.getDisplayValue() + '',
  			'sys_id' : profile.sys_id + '',
  			'node_type' : 'profile',
  			'loading' : false,
  			'expanded' : false,
  			'has_extensions' : false,
  			'level' : 1,
  			'children' : [],
  			'draggable' : false					
  		};

  		if (dependencyType == 'risk') {				
  			if ((profileId != '') && (profile.sys_id + '' == profileId)) {
  				var risksInfo = this._getRisks(profileId);
  				profileInfo.expanded = true;
  				profileInfo.has_extensions = true;
  				profileInfo.children = risksInfo;
  			}
  			else {
  				var risk = new GlideRecord('sn_risk_risk');
  				risk.addQuery('state', '!=', 'retired');
  				risk.addQuery('profile', profile.sys_id + '');
  				risk.query();
  				
  				profileInfo.has_extensions = risk.hasNext();
  			}
  			
  		}
  		results.push(profileInfo);					

  	}
  	return results;
  },
  
  _getListHierarchyForEligibles: function(profileOrClassId, entityId, direction, dependencyType) {	
  	var results = [];
  	var entityProfile = this._getProfile(dependencyType, entityId);
  	if (entityProfile == null)
  		return null;
  	
  	var profileList = new sn_grc.GRCUtils().getProfilesFromProfileClass(profileOrClassId, entityProfile, direction, dependencyType == 'risk');
  	
  	var profileListArr = profileList.split(',');

  	for (var m = 0; m < profileListArr.length; m++) {			
  		var profile = new GlideRecord('sn_grc_profile');

  		if (profile.get(profileListArr[m])) {
  			if (dependencyType == 'profile') {
  				results.push({
  					'ci_type_label' : profile.getDisplayValue() + '',
  					'sys_id' : profile.sys_id + '',
  					'node_type' : 'profile',
  					'loading' : false,
  					'expanded' : false,
  					'has_extensions' : false,
  					'level' : 1,
  					'children' : [],
  					'draggable' : true
  				});						
  			}
  			else {
  				if (!this._hasAvailableRisks(profile, direction, entityId))
  					continue;
  				
  				var risk = new GlideRecord('sn_risk_risk');
  				risk.addQuery('state', '!=', 'retired');
  				risk.addQuery('profile', profile.sys_id + '');
  				risk.query();

  				results.push({
  					'ci_type_label' : profile.getDisplayValue() + '',
  					'sys_id' : profile.sys_id + '',
  					'node_type' : 'profile',
  					'loading' : false,
  					'expanded' : false,
  					'has_extensions' : risk.hasNext(),
  					'level' : 1,
  					'children' : [],
  					'draggable' : false
  				});						 
  			}					
  		}
  	}
  	return results;
  },
  
  _hasAvailableRisks: function(profiles, stream, currentRiskID) {
  	var risk = new GlideRecord('sn_risk_risk');
  	risk.addQuery('state', '!=', 'retired');
  	risk.addQuery('profile', profiles.sys_id);
  	risk.query();

  	while(risk.next()) {
  		var m2m = new GlideRecord('sn_risk_m2m_risk_risk');
  		if(stream == 'upstream'){
  			m2m.addQuery('upstream_risk', risk.sys_id);
  			m2m.addQuery('downstream_risk', currentRiskID);
  		}
  		else {
  			m2m.addQuery('upstream_risk', currentRiskID);
  			m2m.addQuery('downstream_risk', risk.sys_id);
  		}

  		m2m.query();
  		if(!m2m.next())
  			return true;
  	}	
  	return false;
  },
  
  getDependencies: function() {		
  	var id = this.getParameter('sysparm_id');
  	var type = this.getParameter('sysparm_type');
  	
  	var gr;
  	
  	if(type == "profile") 
  		gr = new GlideRecord("sn_grc_profile");
  	else if(type == "risk")
  		gr = new GlideRecord("sn_risk_risk");
  	
  	if(!gr.get(id) || !gr.active) 
  	   return null;		

  	var dependencies = {'name': gr.getDisplayValue() + '',
  					   'sys_id': gr.sys_id + '',
  					   'upstream': this._getUpstream(id, type),
  					   'downstream': this._getDownstream(id, type),
  					   'profile_id' : type == "profile" ?  gr.sys_id + '' : gr.profile + '',
  					   'profile_class_id' : type == "profile" ? gr.profile_class + '' : gr.profile.profile_class + ''
  					   };

  	return this.encodeJson(dependencies);
  },

  _getUpstream: function(id, type) {
  	var m2m;
  			
  	if(type == "profile")
  		m2m = new GlideRecord("sn_grc_m2m_profile_profile");
  	else if(type == "risk") 
  		m2m = new GlideRecord("sn_risk_m2m_risk_risk");
  	
  	m2m.addQuery("downstream_" + type, id);
  	m2m.query();		
  	
  	var items = [];

  	while(m2m.next()) {			
  		var obj = {'name': m2m['upstream_' + type].getDisplayValue() + '',
  				  'sys_id': m2m['upstream_' + type].sys_id + ''};
  		items.push(obj);
  	}

  	return items;    
  },

  _getDownstream: function(id, type) {
  	var m2m;
  	
  	if(type == "profile")
  		m2m = new GlideRecord("sn_grc_m2m_profile_profile");
  	else if(type == "risk")
  		m2m = new GlideRecord("sn_risk_m2m_risk_risk");
  	
  	m2m.addQuery("upstream_" + type, id);
  	m2m.query();

  	var items = [];

  	while(m2m.next()) {
  		var obj = {'name': m2m['downstream_' + type].getDisplayValue() + '',
  				  'sys_id': m2m['downstream_' + type].sys_id + ''};
  		items.push(obj);
  	}

  	return items;   
  },		
  
  deleteDependency: function() {
  	var upstream = this.getParameter('sysparm_upstream');
  	var downstream = this.getParameter('sysparm_downstream');
  	var type = this.getParameter('sysparm_type');
  	var isParent = this.getParameter('sysparm_is_parent');				
  	var id = isParent == 'true'? upstream : downstream;		
  	
  	
  	var m2m;
  	if(type == "profile")			
  		m2m = new GlideRecord("sn_grc_m2m_profile_profile");
  	else if(type == "risk")
  		m2m = new GlideRecord("sn_risk_m2m_risk_risk");
  	
  	m2m.addQuery("upstream_" + type, upstream);
  	m2m.addQuery("downstream_" + type, downstream);
  	m2m.query();
  	if(m2m.next()) {
  		m2m.deleteRecord();
  		return this._getProfileAndClassInfo(id, type);
  	}
  	return false;
  },
  
  _getProfileAndClassInfo: function(id, type) {
  	var gr;
  	
  	if(type == "profile")
  		gr = new GlideRecord("sn_grc_profile");
  	else
  		gr = new GlideRecord("sn_risk_risk");
  	
  	if(!gr.get(id))
  		return;
  	
  	var info = {'profile_id' : type == "profile" ?  gr.sys_id + '' : gr.profile + '',
  				'profile_name' : type == "profile" ?  gr.getDisplayValue() + '' : gr.profile.getDisplayValue() + '',
  				'class_id' : type == "profile" ? gr.profile_class + '' : gr.profile.profile_class + ''};
  	if(info.classId != '') 
  		info.class_name	= type == "profile" ? gr.profile_class.getDisplayValue() + '' : gr.profile.profile_class.getDisplayValue() + '';
  				
  	return this.encodeJson(info);
  },
  
  getSearchResults: function() {
  	var results = [];
  	var searchVal = this.getParameter('sysparm_search_term');
  	var dependencyType = this.getParameter('sysparm_page_type');
  	var direction = this.getParameter('sysparm_direction');
      var entityId = this.getParameter('sysparm_selected_node_id');
      
  	var profile = this._getProfilesForSearchResult(dependencyType, direction, entityId);
  	var pc = this._getProfileClassesForSearchResult(searchVal, profile); // Get the profile class list based on the profile
      
      // Search for risk table if it is on risk dependency page
  	if (dependencyType == 'risk') {
  		var risk = this._getRisksForSearchResults(searchVal, profile, direction, entityId);
  		
  		while (risk.next()) {
  			results.push({
  				'sys_id' : risk.sys_id + '',
  				'ci_type_label'   : gs.getMessage('{0} - {1}', [risk.profile.getDisplayValue(), risk.getDisplayValue()]),
  				'title'  : gs.getMessage('{0} - {1}', [risk.profile.getDisplayValue(), risk.getDisplayValue()]),
  				'node_type'   : 'risk',
  				'has_extensions' : false
  			});				
  		}
  	}
      
      // Filtering the profiles based on the search value
      profile.addActiveQuery();
  	profile.addQuery(profile.getDisplayName(), 'CONTAINS', searchVal);
  	profile.orderBy('name');
  	profile.setLimit(5);
  	profile.query();
  	
  	while (profile.next()) {
  		results.push({
  			'sys_id' : profile.sys_id + '',
  			'ci_type_label'   : gs.getMessage('{0}', profile.getDisplayValue()),
  			'type'   : 'profile',
  			'has_extensions' : false
  		});
  	}
  			
  	while (pc.next()) {						
  		results.push({
  			'sys_id' : pc.sys_id + '',
  			'ci_type_label'  : gs.getMessage('{0}', pc.name),
  			'title'  : gs.getMessage('{0}', pc.name),
  			'node_type'   : 'class',
  			'has_extensions' : false
  		});			
  	}
  	
  	if (results.length == 0)
  		results.push({
  			'sys_id' : -1,
  			'ci_type_label'  : gs.getMessage('No results found'),
  			'node_type'   : '',
  			'has_extensions' : false
  		});	
  	
  	return this.encodeJson(results);
  },
  
  _getProfilesForSearchResult : function(dependencyType, direction, entityId) {
  	var profile = new GlideRecord('sn_grc_profile');                 		
  	// Restrict profile to upstream/downstream if searching value for filter in the upstream/downstream
  	if(direction) {
  		var profileClassList = [];
  		var entityProfile = this._getProfile(dependencyType, entityId);

  		if (direction == "upstream")
  			profileClassList = new sn_grc.GRCUtils()._getUpstreamProfileClassListFromProfileClassModel(entityProfile);
  		else
  			profileClassList = new sn_grc.GRCUtils()._getDownstreamProfileClassListFromProfileClassModel(entityProfile);

  		var returnAlreadyAssociated = dependencyType == 'risk';			
  		var profileIds = new sn_grc.GRCUtils().getProfilesFromProfileClass(profileClassList, entityProfile, direction, returnAlreadyAssociated);
  		var p = new GlideRecord("sn_grc_profile");
  		// Remove the profile that do not have any upstream/downstream risks from the search list
  		if(dependencyType == 'risk') {
  			for(var i = 0; i < profileIds ; i++) {
  				p.get(profileIds[i]);
  				if (!this._hasAvailableRisks(p, direction, entityId))
  				profileIds.splice(i,1);
  			}
  		}
  		profile.addQuery("sys_id", "IN", profileIds);
  	}
  	
  	return profile;
  },
  
  _getProfileClassesForSearchResult: function(searchVal, profile) {
      profile.query();
      var profileClasses = {};
      while(profile.next()) 
          profileClasses[profile.profile_class.sys_id] = true;            
      var profileClassList = Object.keys(profileClasses);               
      
      var pc = new GlideRecord('sn_grc_profile_class');
      pc.addQuery("sys_id", "IN", profileClassList);
  	pc.addQuery('name', 'CONTAINS', searchVal);
  	pc.orderBy('name');
  	pc.setLimit(5);
  	pc.query();        
      return pc;
  },
  
  _getRisksForSearchResults: function(searchVal, profile, direction, entityId) {                 
  	var profileIds = [];
      profile.query();
  	
  	while(profile.next()) 
  		profileIds.push(profile.sys_id + '');		
      var risk;
      // Filter out the risks that are alreday associated.
      var riskIds = [];

  	risk = new GlideRecord("sn_risk_risk");
  	risk.addQuery('profile', "IN", profileIds.join(","));
  	risk.query();
  	while(risk.next()) {
  		if(direction && this._relationshipExists(risk.sys_id + '', direction, entityId)) 
  			continue;							
  		riskIds.push(risk.sys_id + '');            
  	}
      
      risk = new GlideRecord('sn_risk_risk');        
      risk.addQuery("sys_id", "IN", riskIds.join(","));
      risk.addQuery('state', '!=', 'retired');
      risk.addQuery(risk.getDisplayName(), 'CONTAINS', searchVal);
      risk.orderBy('name');
      risk.setLimit(5);
      risk.query();
      
      return risk;
  },
  
  getSearchResultsHierarchy: function() {
  	var results = [];
  	var profileInfo = [];
  	var id = this.getParameter('sysparm_id');
  	var type = this.getParameter('sysparm_type');
  	var dependencyType = this.getParameter('sysparm_page_type');
      var direction = this.getParameter('sysparm_direction');        
      var entityId = this.getParameter('sysparm_selected_node_id');
      
  	var riskInfo = [];		
      
  	if (type == 'class') {
  		var pc = new GlideRecord('sn_grc_profile_class');
  		if (pc.get(id)) {				
  			var profile = new GlideRecord('sn_grc_profile');
              if(direction) { // Get all available upstream/ downstream profiles for the particular class
                  var profileIds = this._getProfilesForSearchHierarchy(id, dependencyType, entityId, direction);
                  profile.addQuery("sys_id", "IN", profileIds);
              }
  			profile.addActiveQuery();
  			profile.addQuery('profile_class', id);
  			profile.query();
  			
  			while (profile.next()) {
  				if (dependencyType == 'risk')
  					riskInfo = this._getRisks(profile.sys_id + '', direction, entityId);
  				
  				profileInfo.push({
  					'sys_id' : profile.sys_id + '',
  					'ci_type_label'  : profile.getDisplayValue() + '',
  					'node_type'   : 'profile',
  					'loading' : false,
  					'expanded' : true,
  					'has_extensions' : riskInfo.length == 0? false : true,
  					'level' : 1,
  					'children' : (dependencyType == 'profile') ? [] : riskInfo,
  					'highlight' : false,		
  					'draggable' : ((dependencyType == 'profile') && direction)? true : false
  				});
  			}
  			
  			results.push({
  				'sys_id' : id,
  				'ci_type_label'  : pc.name + '',
  				'node_type'   : 'class',
  				'loading' : false,
  				'expanded' : true,
  				'has_extensions' : profileInfo.length == 0 ? false: true,
  				'level' : 0,
  				'children' : profileInfo,
  				'matched'  : true,
  				'highlight' : false,
  				'draggable' : false					
  			});
  		}
  	}
  	else if (type == 'profile') {
  		var profile2 = new GlideRecord('sn_grc_profile');
  		if (profile2.get(id)) {
  			if (dependencyType == 'risk')
  				riskInfo = this._getRisks(profile2.sys_id + '', direction, entityId);
  			
  			profileInfo.push({
  				'sys_id' : id,
  				'ci_type_label'  : profile2.getDisplayValue() + '',
  				'node_type'   : 'profile',
  				'loading' : false,
  				'expanded' : true,
  				'has_extensions' : riskInfo.length == 0 ? false : true,
  				'level' : 1,
  				'matched' : true,
  				'highlight' : false,
  				'children' : (dependencyType == 'profile') ? [] : riskInfo,
  				'draggable' : ((dependencyType == 'profile') && direction)? true : false	
  			});
  			
  			results.push({
  				'sys_id' : profile2.profile_class + '' == ''? '-1': profile2.profile_class + '',
  				'ci_type_label'  : profile2.profile_class + '' == '' ? gs.getMessage('( Empty )') : profile2.profile_class.name + '',
  				'node_type'   : 'class',
  				'loading' : false,
  				'expanded' : true,
  				'has_extensions' : true,
  				'level' : 0,
  				'children' : profileInfo,
  				'highlight' : false,
  				'draggable' : false
  			});
  		}
  	}
  	else if (type == 'risk') {
  		var risk = new GlideRecord('sn_risk_risk');
  		if (risk.get(id)) {
  			riskInfo.push({
  				'sys_id' : id,
  				'ci_type_label'  : risk.getDisplayValue() + '',
  				'node_type'   : 'risk',
  				'loading' : false,
  				'expanded' : true,
  				'has_extensions' : false,
  				'level' : 2,
  				'matched' : true,
  				'highlight' : false,
  				'children' : [],
  				'draggable' : direction? true : false						
  			});
  			
  			profileInfo.push({
  				'sys_id' : risk.profile + '',
  				'ci_type_label'  : risk.profile.getDisplayValue() + '',
  				'node_type'   : 'profile',
  				'loading' : false,
  				'expanded' : true,
  				'has_extensions' : true,
  				'level' : 1,
  				'highlight' : false,
  				'children' : riskInfo,
  				'draggable' : false						
  			});
  			
  			results.push({
  				'sys_id' : risk.profile.profile_class + '' == '' ? '-1' : risk.profile.profile_class + '',
  				'ci_type_label'  : risk.profile.profile_class + '' == '' ? gs.getMessage('( Empty )') : risk.profile.profile_class.name + '',
  				'node_type'   : 'class',
  				'loading' : false,
  				'expanded' : true,
  				'has_extensions' : true,
  				'level' : 0,
  				'children' : profileInfo,
  				'highlight' : false,
  				'draggable' : false						
  			});
  		}
  	}
  	
  	return this.encodeJson(results);
  },
  
  _getProfilesForSearchHierarchy: function(profileClassId, dependencyMap, entityId, direction) {
      var returnAlreadyAssociated = dependencyMap == 'risk';
      var entityProfile = this._getProfile(dependencyMap, entityId);        
      var profileIds = new sn_grc.GRCUtils().getProfilesFromProfileClass(profileClassId, entityProfile, direction, returnAlreadyAssociated);
      return profileIds;
  },
  
  _getRisks: function(profileId, direction, entityId) {      
      var results = [];
  	var risk = new GlideRecord('sn_risk_risk');
  	risk.addQuery('state', '!=', 'retired');
  	risk.addQuery('profile', profileId);
  	risk.query();
  	
  	while (risk.next()) {
  		if(direction && this._relationshipExists(risk.sys_id + '', direction, entityId)) 
  			continue;			

  		results.push({
  			'sys_id' : risk.sys_id + '',
  			'ci_type_label'  : risk.getDisplayValue() + '',
  			'node_type'   : 'risk',
  			'loading' : false,
  			'expanded' : true,
  			'has_extensions' : false,
  			'level' : 2,
  			'children' : [],
  			'highlight' : false,
  			'draggable' : direction ? true: false,					
  		});
  	}
  	return results;
  },

  createDependency: function() {
  	var upstream = this.getParameter('sysparm_upstream');
  	var downstream = this.getParameter('sysparm_downstream');
  	var type = this.getParameter('sysparm_type');
  	
  	var m2m;
  	if(type == "profile")			
  		m2m = new GlideRecord("sn_grc_m2m_profile_profile");
  	else if(type == "risk")
  		m2m = new GlideRecord("sn_risk_m2m_risk_risk");
  	
  	m2m.setValue("upstream_" + type, upstream);
  	m2m.setValue("downstream_" + type, downstream);
  	if(m2m.insert())
  		return true;
  	return false;
  },
  
  getRiskRecord: function() {
  	var riskID = this.getParameter('sysparm_risk_id');
  	var riskRecord = new GlideRecord('sn_risk_risk');
  	var exists = riskRecord.get(riskID);
  	
  	if(!exists)
  		return null;
  	
  	var profileID = riskRecord.profile + '';
  	var profile = new GlideRecord('sn_grc_profile');
  	var profileClassID = '';

  	if(profile.get(profileID))
  		profileClassID = profile.profile_class + '';

  	var name = riskRecord.getDisplayValue();

  	return this.encodeJson({root_id: riskID, profile_id: profileID, profile_class_id: profileClassID, name: name});
  },
  
  getMenuData: function() {
  	var direction = this.getParameter('sysparm_direction');
  	var nodeId = this.getParameter('sysparm_nodeId');   
  	
  	if(direction == null || nodeId == null) 
  		return;
  	
  	// If the node is the root, only root can be added as its downstream
  	var classNode = new GlideRecord("sn_grc_profile_class");
  	if(!classNode.get(nodeId))
  		return;

  	if(classNode.is_root == true) {
  		if(direction == "upstream")
  			return this.encodeJson("");
  		else if(direction == "downstream") 
  			return this._getClasses(true);			
  	}
  	else  // If anything else upstream and downstream would be all classes except root
  		return this._getClasses(false);				
  },
  
  _getClasses: function(isRoot) {
  	var classesArr = [];
  	var classes = new GlideRecord("sn_grc_profile_class");
  	if(!isRoot)
  		classes.addQuery("is_root", false);
  	classes.query();

  	while(classes.next()) {
  		var obj = {name: classes.name + '', id: classes.sys_id + ''};		
  		classesArr.push(obj);
  	}
  	return this.encodeJson(classesArr);
  },
  
  encodeJson: function(object) {
  	var json = new global.JSON();
  	return json.encode(object);	
  },
  
  getRiskStatements: function(){
      return this.encodeJson(this._getRiskStatements());  
  },
  
  _getRiskStatements: function(){
      var results = [];
      var riskStmt = new GlideRecord('sn_risk_definition');
      riskStmt.addEncodedQuery('parent=NULL');
      riskStmt.orderBy('name');
      riskStmt.query();
      
      while (riskStmt.next()) {       
          var childRiskStmt = new GlideRecord('sn_risk_definition');
          childRiskStmt.addQuery('parent',riskStmt.getUniqueValue());
          childRiskStmt.query();
          
          results.push({
              'sys_id' : riskStmt.sys_id+'',
              'ci_type_label' : riskStmt.name + '',
              'node_type' : 'class',
              'loading' : false,
              'expanded' : false,
              'has_extensions' : childRiskStmt.getRowCount() > 0 ? true : false,
              'level'  : 0,
              'children' : []
          });                     
      }       
      return results;
  },
  getListHierarchyRiskStatement: function () {
      var results = [];
      var riskStmtId = this.getParameter('sysparm_id');
      var direction = this.getParameter('sysparm_direction');
      var currentLevel = parseInt(this.getParameter('sysparm_level'));
      var riskStmt = new GlideRecord('sn_risk_definition');
      riskStmt.addActiveQuery();
      riskStmt.addQuery('parent', riskStmtId);
      riskStmt.orderBy('name');
      riskStmt.query();
      while (riskStmt.next()) {   
          var childRiskStmt = new GlideRecord('sn_risk_definition');
          childRiskStmt.addQuery('parent',riskStmt.getUniqueValue());
          childRiskStmt.query();
          results.push({
              'ci_type_label' : riskStmt.getDisplayValue() + '',
              'sys_id' : riskStmt.getUniqueValue(),
              'node_type' : 'riskStatement',
              'loading' : false,
              'expanded' : false,
              'has_extensions' :  childRiskStmt.getRowCount() > 0 ? true : false,
              'level' : currentLevel + 1,
              'draggable' : direction ? true : false,
              'children' : []
          });                 
      }
      return this.encodeJson(results);        
  },

  getRiskStatementDependencies: function() {      
      var id = this.getParameter('sysparm_id'); 
      var level = parseInt(this.getParameter('sysparm_level'));
      var gr = new GlideRecord("sn_risk_definition");
      var upstream;
      
      if(!gr.get(id) || !gr.active) 
         return null;     
      if (gr.parent && gr.parent != ''){
          upstream = [{'name' : gr.parent.getDisplayValue()+'',
                      'sys_id' :gr.parent.sys_id + ''}];
      }
      else 
          upstream = [];
      var dependencies = {'name': gr.getDisplayValue() + '',
                          'sys_id': gr.getUniqueValue(),
                          'upstream': upstream,
                          'downstream': this._getDownstreamRiskStatement(id,level),
                          'risk_stmt_id':gr.parent.sys_id + '',
                          };

      return this.encodeJson(dependencies);
      
  },

  _getDownstreamRiskStatement: function(id,currLevel) {
  var riskStmt = new GlideRecord("sn_risk_definition");
  riskStmt.addQuery("parent", id);
  riskStmt.orderBy('name');
  riskStmt.query();
  var items = [];
  while (riskStmt.next()) {
      var childRiskStmt = new GlideRecord('sn_risk_definition');
      childRiskStmt.addQuery('parent', riskStmt.getUniqueValue());
      childRiskStmt.query();
      var obj = {
          'ci_type_label': riskStmt.getDisplayValue() + '',
          'name' : riskStmt.name + '',
          'sys_id': riskStmt.getUniqueValue(),
          'node_type': 'riskStatement',
          'loading': false,
          'expanded': false,
          'has_extensions': childRiskStmt.getRowCount() > 0 ? true : false,
          'level': currLevel + 1,
          'draggable': false,
          'children': []
      };
      items.push(obj);
  }

  	return items;
  },
  
  type: 'GRCWorkbenchService'
});

Sys ID

0f64d525c3531200dd921a4112d3ae3a

Offical Documentation

Official Docs: