Name

global.SPMUtilsFoundationImpl

Description

Implements extension point global.SPMUtils. Provides SPM Foundation functionality.

Script

var SPMUtilsFoundationImpl = Class.create();
SPMUtilsFoundationImpl.prototype = {
initialize: function() {
  	this.PORTFOLIO_ADMIN = 'portfolio_admin';
  	this.PORTFOLIO_EDITOR = 'portfolio_editor';
  	this.PORTFOLIO_VIEWER = 'portfolio_viewer';
  	this.SERVICE_ADMIN = 'service_admin';
  	this.SERVICE_EDITOR = 'service_editor';
  	this.SERVICE_VIEWER = 'service_viewer';
  	this.SERVICE_AUTHOR = 'service_author';

  	this.CMDB_CI_SERVICE = 'cmdb_ci_service';
  	this.CMDB_CI_BUSINESS_SERVICE = 'cmdb_ci_service_business';
  	this.CMDB_CI_TECHNICAL_SERVICE = 'cmdb_ci_service_technical';
  	this.SERVICE_OFFERING = 'service_offering';
  	this.SERVICE_OFFERING_COMMITMENT = 'service_offering_commitment';

  	this.DRAFT = 'draft';
  	this.PUBLISHED = 'published';
  	this.PUBLISHING = 'publishing';

  	this.currentUserId = gs.getUserID();
  },
  	
  /* 
   * Returns a boolean speciying in the current user is owner, delegate of the offering.
   * Will return true even if the current user is a owner, delegate of parent service or an owner of a node in the hierarchy.
   * Else returns false.
   */ 
  checkOfferingAuthorization: function(offeringGR) {
  	var isNew = offeringGR.isNewRecord();
  	var isOwner = offeringGR.owned_by.getValue() === this.currentUserId;
  	var isDelegate = offeringGR.service_owner_delegate.getValue() === this.currentUserId;
  	var isCreator = offeringGR.sys_created_by.getValue() === gs.getUserName();
  	
  	if (gs.hasRole(this.SERVICE_ADMIN))
  		return true;
  	
  	if (gs.hasRole(this.SERVICE_AUTHOR) && (isNew || isCreator))
  		return true;
  	
  	if (gs.hasRole(this.SERVICE_EDITOR) && (isOwner || isDelegate))
  		return true;
  	else
  		return this.checkServiceAuthorization(offeringGR.parent);
  	
  	return false;
  },

  /* 
   * Returns true if the current user is a owner, delegate of a service or an owner of a node in the hierarchy.
   * Else returns false.
   */ 
  checkServiceAuthorization: function(serviceGR) {
  	var isNew = serviceGR.isNewRecord();
  	var isOwner = serviceGR.owned_by.getValue() === this.currentUserId;
  	var isDelegate = serviceGR.service_owner_delegate.getValue() === this.currentUserId;
  	var isCreator = serviceGR.sys_created_by.getValue() === gs.getUserName();
  	
  	if (gs.hasRole(this.SERVICE_ADMIN))
  		return true;
  	
  	if (gs.hasRole(this.SERVICE_AUTHOR) && (isNew || isCreator))
  		return true;
  	
  	if (gs.hasRole(this.SERVICE_EDITOR) && (isOwner || isDelegate))
  		return true;
  	else
  		return this.checkTaxonomyNodeAuthorization(serviceGR.spm_taxonomy_node);
  	
  	return false;
  },
  
  checkTaxonomyNodeAuthorization: function(taxonomyGr) {
  	if (gs.hasRole(this.SERVICE_EDITOR)) {
  		var isRoot = false;
  		while (!isRoot) {
  			if (taxonomyGr.taxonomy_node_owner.getValue() === this.currentUserId)
  				return true;

  			var parentNode = new GlideRecord('spm_taxonomy_node');
  			if (parentNode.get(taxonomyGr.parent.getValue()))
  				taxonomyGr = parentNode;
  			else
  				isRoot = true;
  		}
  	}
  	return this.checkPortfolioAuthorization(taxonomyGr.spm_service_portfolio);

  },
  
  checkPortfolioAuthorization: function(portfolioGr) {
  		var isPortfolioOwner = portfolioGr.service_portfolio_owner.getValue() === this.currentUserId;
  		return gs.hasRole(this.PORTFOLIO_ADMIN) || (gs.hasRole(this.PORTFOLIO_EDITOR) && isPortfolioOwner);
  },
  
  /* 
   * Given the type of a node and it's unique id, it returns 
   * if the current user is in the ownership hierarchy of the node
   */ 
  checkNodeOwnership: function(type, sys_id) {
  	if (type == "taxonomy" || type == "leaf") {
  		var taxonomy = new GlideRecord("spm_taxonomy_node");
  		taxonomy.get(sys_id);
  		return this.checkTaxonomyNodeAuthorization(taxonomy);
  	} else if (type == "service") {
  		var serviceGR = new GlideRecord("cmdb_ci_service");
  		serviceGR.get(sys_id);
  		return this.checkServiceAuthorization(serviceGR);
  	} else if (type == "offering") {
  		var offeringGR = new GlideRecord("service_offering");
  		offeringGR.get(sys_id);
  		return this.checkOfferingAuthorization(offeringGR);
  	}
  },

  isValidPublishedService: function(service) {
  	if (this.isValidService(service.sys_class_name) && this.isServicePublished(service)) {
  		return true;
  	}

  	return false;
  },
  
  /*
   * Returns true if the service is supported in portfolio
   */
  isValidService: function(className) {
  	if (className == this.CMDB_CI_SERVICE || className == this.CMDB_CI_BUSINESS_SERVICE || className == this.CMDB_CI_TECHNICAL_SERVICE)
  		return true;
  	
  	return false;
  },
  
  /*
   * Returns true if the service is supported in portfolio
   */
  isValidServiceOrOffering: function(className) {
  	if (className == this.SERVICE_OFFERING || this.isValidService(className))
  		return true;
  	
  	return false;
  },
  
  /*
   * isServicePublished
   * returns true if service or offering is Published
   */
  isServicePublished: function(service) {
  	if (service.state == '' || service.state == this.PUBLISHED)
  		return true;
  	return false;
  },
  
  /*
   * isServiceNew
   * returns true if service or offering is in draft state without published
   * item reference
   */
  isServiceNew: function(service) {
  	if ((service.state == '' || service.state == this.DRAFT) && service.published_ref == '')
  		return true;
  	return false;
  },
  
  /*
   * didServicePublish
   * returns true if the service became published from draft state
   */
  didServicePublish: function(current, previous) {
  	if ((previous.state == this.DRAFT || previous.state == this.PUBLISHING) && current.state == this.PUBLISHED && 
  		(previous.published_ref == current.sys_id || previous.published_ref == ''))
  		return true;
  	return false;
  },
  
  /*
   * callEvent
   * allows global SPM events to be called from scoped apps
   */
  callEvent: function(eventName, current, param1, param2, queue) {
  	gs.eventQueue(eventName, current, param1, param2, queue);
  },
  
  /*
   * hasCommitments
   * returns true if record has any commitments in the commitments table
   */
  hasCommitments: function(recordId){
  	var commitments = new GlideRecord(this.SERVICE_OFFERING_COMMITMENT);
  	commitments.addQuery('service_offering', recordId);
  	commitments.query();
  	
  	return (commitments.getRowCount() > 0);
  },

  ifLegacyStatusMatches: function (table, record, portfolioStatus, serviceStatus) {
  	var gr = new GlideRecord(table);
  	gr.get(record.sys_id);

  	var legacyStatuses = new LifeCycleUtil().findMatchingLifeCycleControl(table, gr, true);

  	for (var i = 0; i < legacyStatuses.length; i++) {
  		if (legacyStatuses[i].primaryCol === 'portfolio_status' && legacyStatuses[i].subCol === 'service_status')
  			if ((!portfolioStatus || legacyStatuses[i].primaryValue === portfolioStatus) && (!serviceStatus || legacyStatuses[i].subValue === serviceStatus))
  				return true;
  	}

  	return false;
  },

  getLifeCycleStage: function (ci, portfolioStatus, serviceStatus) {
  	var gr = new GlideRecord('life_cycle_mapping');
  	gr.addQuery('table', 'cmdb_ci_service');
  	gr.addQuery('legacy_field_name', 'portfolio_status');
  	portfolioStatus ? gr.addQuery('legacy_field_value', portfolioStatus) : gr.addQuery('life_cycle_control.life_cycle_stage', ci.life_cycle_stage);
  	gr.addQuery('legacy_subfield_name', 'service_status');
  	serviceStatus ? gr.addQuery('legacy_subfield_value', serviceStatus) : gr.addQuery('life_cycle_control.life_cycle_stage_status', ci.life_cycle_stage_status);
  	gr.query();

  	if (gr.next()) {
  		return gr.life_cycle_control.life_cycle_stage;
  	}

  	return true;
  },
  getLifeCycleStageStatus: function(ci, portfolioStatus, serviceStatus) {
  	var gr = new GlideRecord('life_cycle_mapping');
  	gr.addQuery('table', 'cmdb_ci_service');
  	gr.addQuery('legacy_field_name', 'portfolio_status');
  	portfolioStatus ? gr.addQuery('legacy_field_value', portfolioStatus) : gr.addQuery('life_cycle_control.life_cycle_stage', ci.life_cycle_stage);
  	gr.addQuery('legacy_subfield_name', 'service_status');
  	serviceStatus ? gr.addQuery('legacy_subfield_value', serviceStatus) : gr.addQuery('life_cycle_control.life_cycle_stage_status', ci.life_cycle_stage_status);
  	gr.query();

  	if (gr.next()) {
  		return gr.life_cycle_control.life_cycle_stage_status;
  	}

  	return true;
  },

  lifeCycleStageChangesFrom: function(current, previous, portfolioStatus, serviceStatus) {
  	if (current.life_cycle_stage_status.changes()) {
  		var status = this.ifLegacyStatusMatches(current.sys_class_name, previous, portfolioStatus, serviceStatus);
  		return status;
  	}
  	else if (current.service_status.changes()) {  
  		return true;
  	}

  	return false;
  },
  
  type: 'SPMUtilsFoundationImpl'
};

Sys ID

0ef1f659b3403300f224a72256a8dc5e

Offical Documentation

Official Docs: