Name

global.ScopedAdministration

Description

Helper methods used by the Scoped Administration business rules and UI actions

Script

var ScopedAdministration = Class.create();
ScopedAdministration.prototype = {
  initialize: function() {
  },

  currentUserIsScopeAdmin: function(scope, strict) {	
  	var scopeAdminRoles = this._getScopeAdminRolesGr(scope);
  	var userRoles = gs.getSession().getRoles();
  	var allowAdminIfTurnedOff = false;
  	if (strict === undefined || !strict)
  		allowAdminIfTurnedOff = scope.getValue('scoped_administration') == 0;
  	
  	if (userRoles.indexOf('maint') >= 0)
  		return true;
  		
  	if (!scopeAdminRoles.hasNext() || allowAdminIfTurnedOff)
  		return userRoles.indexOf('admin') >= 0;
  	
  	while (scopeAdminRoles.next()) {
  		if (userRoles.indexOf(scopeAdminRoles.getDisplayValue()) >= 0)
  			return true;
  	}
  	return false;
  },
  
  adminRoleContainsScopeAdminRoles: function(scope) {
  	var adminRoleContains = this._getAdminRoleContainsGr();
  	var roles = [];
  	while (adminRoleContains.next())
  		roles.push(adminRoleContains.getValue('contains'));
  	
  	var scopeAdminRoles = this._getScopeAdminRolesGr(scope);
  	if (!scopeAdminRoles.hasNext())
  		return false;
  	
  	while (scopeAdminRoles.next())
  		if (roles.indexOf(scopeAdminRoles.getValue('sys_id')) < 0)
  			return false;
  	return true;
  },
  
  addScopeAdminRolesToAdminContains: function(scope) {
  	var adminRole = this._getAdminRoleGr();
  	var scopeAdminRoles = this._getScopeAdminRolesGr(scope);
  	while (scopeAdminRoles.next()) {
  		var adminRoleContains = new GlideRecord('sys_user_role_contains');
  		adminRoleContains.addQuery('role', adminRole.sys_id);
  		adminRoleContains.addQuery('contains', scopeAdminRoles.sys_id);
  		adminRoleContains.query();
  		if (adminRoleContains.hasNext())
  			continue;
  		adminRoleContains = new GlideRecord('sys_user_role_contains');
  		adminRoleContains.initialize();
  		adminRoleContains.setValue('role', adminRole.sys_id);
  		adminRoleContains.setValue('contains', scopeAdminRoles.sys_id);
  		adminRoleContains.insert();
  	}
  },
  
  removeScopeAdminRolesFromAdminContains: function(scope) {
  	var adminRole = this._getAdminRoleGr();
  	var scopeAdminRoles = this._getScopeAdminRolesGr(scope);
  	while (scopeAdminRoles.next()) {
  		var adminRoleContains = new GlideRecord('sys_user_role_contains');
  		adminRoleContains.addQuery('role', adminRole.sys_id);
  		adminRoleContains.addQuery('contains', scopeAdminRoles.sys_id);
  		adminRoleContains.deleteMultiple();
  	}
  },
  
  countNumberOfActiveScopeAdminIfContainsRemoved: function(container, contained) {
  	var usersWithContainer = [];
  	var gr = new GlideRecord('sys_user_has_role');
  	gr.addQuery('role', container);
  	gr.query();
  	while (gr.next())
  		usersWithContainer.push(gr.getValue('user'));
  	
  	var usersWithRoleButNotFromContainer = [];
  	gr = new GlideRecord('sys_user_has_role');
  	gr.addQuery('role', contained);
  	gr.query();
  	while (gr.next()) {
  		if (usersWithContainer.indexOf(gr.getValue('user')) >= 0 && gr.getValue('inh_count') == '1')
  			continue;
  		usersWithRoleButNotFromContainer.push(gr.getValue('user'));
  	}
  	
  	if (usersWithRoleButNotFromContainer.length() == 0)
  		return 0;
  	
  	var activeUsers = new GlideRecord('sys_user');
  	activeUsers.addActiveQuery();

  	// also check the users are not locked out, etc...

  	// PRB1296088: Empty password field should not be used
  	// to check whether a user is able to log in or not.
  	// Remove the check.
  	activeUsers.addQuery('locked_out', false).addOrCondition('locked_out', null);
  	activeUsers.addQuery('web_service_access_only', false).addOrCondition('web_service_access_only', null);
  	activeUsers.addQuery('internal_integration_user', false).addOrCondition('internal_integration_user', null);
  	
  	activeUsers.addQuery('sys_id', 'IN', usersWithRoleButNotFromContainer.join());
  	activeUsers.query();
  	return activeUsers.getRowCount();
  },
  
  countNumberOfActiveScopeAdminIfRoleRemoved: function(user, role) {
  	var gr = new GlideRecord('sys_user_has_role');
  	gr.addQuery('role', role);
  	gr.addQuery('user', '!=', user);
  	gr.addQuery('user.active', true);
  	gr.query();
  	return gr.getRowCount();
  },
  
  getScopeName: function(role) {
  	var gr = new GlideRecord('sys_metadata');
  	gr.addQuery('sys_id', role);
  	gr.query();
  	var result = 'global';
  	if (gr.next()) {
  		var scope = gr.sys_scope;
  		if ('global' != scope) {
  			var sysScopeRecord = new GlideRecord('sys_scope');
  			sysScopeRecord.addQuery('sys_id', scope);
  			sysScopeRecord.query();
  			if (sysScopeRecord.next())
  				result = sysScopeRecord.scope;
  		}
  	}
  	return result;
  },
  
  canDeleteScopedAdminContainedRoleRespectingAdminMinCountProperty: function(container, contained) {
  	adminMinCount = this.getScopedAdminMinCountIfConfigured(contained);
  	var numberOfActiveScopedAdminIfRoleRemoved = this.countNumberOfActiveScopeAdminIfContainsRemoved(container, contained);
  	return numberOfActiveScopedAdminIfRoleRemoved >= adminMinCount;
  },
  
  canDeleteActiveScopedAdminRespectingAdminMinCountProperty: function(user, role) {
  	adminMinCount = this.getScopedAdminMinCountIfConfigured(role);
  	var numberOfActiveScopedAdminIfRoleRemoved = this.countNumberOfActiveScopeAdminIfRoleRemoved(user, role);
  	return numberOfActiveScopedAdminIfRoleRemoved >= adminMinCount;
  },
  
  getScopedAdminMinCountIfConfigured: function(role) {
  	var adminMinCountPropertyName = this.getScopedAdminMinCountPropertyName(role);
  	var adminMinCount = GlideProperties.getInt(adminMinCountPropertyName, 1);
  	adminMinCount = adminMinCount < 2 ? 1 : adminMinCount;
  	return adminMinCount;
  },
  
  getScopedAdminMinCountPropertyName: function(role) {
  	var scopeName = this.getScopeName(role);
  	var adminMinCountPropertyName = scopeName.concat('.min_admin_count');
  	return adminMinCountPropertyName;
  },
  
  getUserScopeAdminRolesGr: function(userSysID) {
  	var gr = new GlideRecord('sys_user_has_role');
  	gr.addQuery('user', userSysID);
  	
  	// Then filter user role which is scoped admin, following existing logic in the function isScopeAdminRole
  	// So for user with 1000 user roles and 5 of them are scoped admin role, this filter will limit the number of return down to 5.
  	if (GlideTableDescriptor.fieldExists('sys_user_role', 'scoped_admin')) {
  		gr.addQuery('role.scoped_admin', 'true');
  	} else {
  		gr.addQuery('role.assignable_by', "SAMEAS", "sys_id"); // i.e. where field 'assignable_by' = field 'sys_id'
  	}
  	gr.addQuery('role.sys_scope.scoped_administration', 'true');
  	
  	gr.query();
  	return gr;
  },
  
  isScopeAdminRole: function(roleSysID) {
  	var gr = new GlideRecord('sys_user_role');
  	if (GlideTableDescriptor.fieldExists('sys_user_role', 'scoped_admin')) {
  		gr.addQuery('sys_id', roleSysID);
  		gr.addQuery('scoped_admin', 'true');
  	} else {
  		gr.addQuery('assignable_by', roleSysID);
  	}
  	gr.addQuery('sys_scope.scoped_administration', 'true');
  	gr.query();
  	return gr.getRowCount() > 0;
  },

  getContainsScopedAdminRoleIDs: function(roleSysID) {
      var rmAPI = new SNC.RoleManagementAPI();
      var containsIDs = rmAPI.findAllContainedRolesForRole(roleSysID);
      var it = containsIDs.iterator();
      // build scoped admin role result
      var scopedAdminRoleIDs = [];
      while (it.hasNext()) {
          var elem = it.next();
          if (this.isScopeAdminRole(elem))
              scopedAdminRoleIDs.push(elem);
      }
      return scopedAdminRoleIDs;
  },
      
  isScopedAdminIfRoleScopedAdminDisabled: function(scopeID, userID, roleID) {
  	var scopedAdminRoleIDs = this.getScopedAdminRoleIDs(scopeID);
  	var userScopedRolesIDs = this.getUserScopedRoleIDs(scopeID, userID);
  	var intersectRoles = new ArrayUtil().intersect(scopedAdminRoleIDs, userScopedRolesIDs);
  	if (intersectRoles.length == 1  && new ArrayUtil().contains(intersectRoles, roleID))
  		return false;
  	
  	return intersectRoles.length > 0;
  },
  
  getUserScopedRoleIDs: function(scopeID, userID) {
  	var roleIDs = [];
  	var gr = new GlideRecord('sys_user_has_role');
  	gr.addQuery('user', userID);
  	gr.addQuery('role.sys_scope', scopeID);
  	gr.query();
  	while (gr.next())
  		roleIDs.push(gr.role.toString());
  	
  	return roleIDs;
  },
  
  getScopedAdminRoleIDs : function(scopeID) {
  	var gr = this._getScopedAdminRolesGr(scopeID);
  	var res = [];
  	while (gr.next())
  		res.push(gr.getUniqueValue().toString());
  	
  	return res;
  },
  
  getScopeAdminRolesArray : function(scope) {
  	var gr = this._getScopeAdminRolesGr(scope);
  	var res = [];
  	while (gr.next())
  		res.push(gr.sys_id);
  	return res;
  },
  
  isScopedAdministrationOn: function(scopeID) {
  	var gr = new GlideRecord('sys_scope');
  	if (gr.get('sys_id', scopeID))
  		return JSUtil.getBooleanValue(gr, 'scoped_administration');
  	return false;
  },
  
  _getScopedAdminRolesGr: function(scopeID) {
  	var gr = new GlideRecord('sys_scope');
  	if (gr.get('sys_id', scopeID) && JSUtil.getBooleanValue(gr, 'scoped_administration'))
  		return this._getScopeAdminRolesGr(gr);
  	
  	return new GlideRecord('sys_user_role');
  },
  
  _getScopeAdminRolesGr : function(scope) {
  	var gr = new GlideRecord('sys_user_role');
  	if (GlideTableDescriptor.fieldExists('sys_user_role', 'scoped_admin')) {
  		gr.addQuery('sys_scope', scope.sys_id);
  		gr.addQuery('scoped_admin', 'true');
  	} else {
  		var jc = gr.addJoinQuery('sys_user_role', 'sys_id', 'assignable_by');
  		jc.addCondition('sys_scope', scope.sys_id);
  	}
  	gr.query();
  	return gr;
  },
  
  _getAdminRoleContainsGr : function() {
  	var adminRole = this._getAdminRoleGr();
  	
  	var roleContains = new GlideRecord('sys_user_role_contains');
  	roleContains.addQuery('role', adminRole.sys_id);
  	roleContains.query();
  	return roleContains;
  },
  
  _getAdminRoleGr : function () {
  	var adminRole = new GlideRecord('sys_user_role'); 
  	adminRole.get('name', 'admin');
  	return adminRole;
  },
  
  type: 'ScopedAdministration'
};

Sys ID

e941ec635b011200656847cc11f91aa4

Offical Documentation

Official Docs: