← Script library

Script Includes

User and Group Utilities

Reusable functions for user and group operations.

JavaScript
var UserGroupUtils = Class.create();
UserGroupUtils.prototype = {

  /**
   * Check if user has a specific role
   *
   * @param {string} userId - sys_id of user
   * @param {string} roleName - Name of role to check
   * @returns {boolean} True if user has role
   */
  userHasRole: function(userId, roleName) {
    if (!userId || !roleName) {
      return false;
    }

    var grUser = new GlideRecord('sys_user');
    if (!grUser.get(userId)) {
      return false;
    }

    return grUser.hasRole(roleName);
  },

  /**
   * Get all users in a group
   *
   * @param {string} groupId - sys_id or name of group
   * @param {boolean} includeInactive - Include inactive users (default: false)
   * @returns {Array} Array of user objects {sys_id, name, email}
   */
  getUsersInGroup: function(groupId, includeInactive) {
    var users = [];

    // Get group record
    var grGroup = new GlideRecord('sys_user_group');
    if (!grGroup.get(groupId)) {
      // Try by name
      grGroup = new GlideRecord('sys_user_group');
      grGroup.addQuery('name', groupId);
      grGroup.setLimit(1);
      grGroup.query();

      if (!grGroup.next()) {
        return users;
      }
    }

    // Query group members
    var grMember = new GlideRecord('sys_user_grmember');
    grMember.addQuery('group', grGroup.sys_id);
    grMember.query();

    while (grMember.next()) {
      var grUser = new GlideRecord('sys_user');
      if (grUser.get(grMember.user)) {

        // Skip inactive users unless specified
        if (!includeInactive && grUser.active.toString() !== 'true') {
          continue;
        }

        users.push({
          sys_id: grUser.sys_id.toString(),
          name: grUser.name.toString(),
          email: grUser.email.toString(),
          first_name: grUser.first_name.toString(),
          last_name: grUser.last_name.toString()
        });
      }
    }

    return users;
  },

  /**
   * Get user's manager chain (up to specified levels)
   *
   * @param {string} userId - sys_id of user
   * @param {number} levels - Number of levels to traverse (default: 5)
   * @returns {Array} Array of manager objects {sys_id, name, level}
   */
  getManagerChain: function(userId, levels) {
    var managers = [];
    levels = levels || 5;

    var currentUserId = userId;
    var currentLevel = 1;

    while (currentUserId && currentLevel <= levels) {
      var grUser = new GlideRecord('sys_user');
      if (!grUser.get(currentUserId)) {
        break;
      }

      var managerId = grUser.manager.toString();
      if (!managerId) {
        break;
      }

      var grManager = new GlideRecord('sys_user');
      if (grManager.get(managerId)) {
        managers.push({
          sys_id: managerId,
          name: grManager.name.toString(),
          email: grManager.email.toString(),
          level: currentLevel
        });

        currentUserId = managerId;
        currentLevel++;
      } else {
        break;
      }
    }

    return managers;
  },

  /**
   * Get common manager between two users
   *
   * @param {string} userId1 - sys_id of first user
   * @param {string} userId2 - sys_id of second user
   * @returns {object} Common manager object or null
   */
  getCommonManager: function(userId1, userId2) {
    var chain1 = this.getManagerChain(userId1);
    var chain2 = this.getManagerChain(userId2);

    // Find first common manager
    for (var i = 0; i < chain1.length; i++) {
      for (var j = 0; j < chain2.length; j++) {
        if (chain1[i].sys_id === chain2[j].sys_id) {
          return chain1[i];
        }
      }
    }

    return null;
  },

  /**
   * Get on-call user for a group based on rotation schedule
   *
   * @param {string} groupId - sys_id of group
   * @param {GlideDateTime} dateTime - Date/time to check (defaults to now)
   * @returns {string} sys_id of on-call user or empty string
   */
  getOnCallUser: function(groupId, dateTime) {
    dateTime = dateTime || new GlideDateTime();

    // Get rotation schedule for group
    var grRotation = new GlideRecord('cmn_rota');
    grRotation.addQuery('group', groupId);
    grRotation.addQuery('active', 'true');
    grRotation.setLimit(1);
    grRotation.query();

    if (!grRotation.next()) {
      return '';
    }

    // Get current roster member
    var grRoster = new GlideRecord('cmn_rota_member');
    grRoster.addQuery('roster', grRotation.sys_id);
    grRoster.addQuery('from', '<=', dateTime);
    grRoster.addQuery('to', '>=', dateTime);
    grRoster.setLimit(1);
    grRoster.query();

    if (grRoster.next()) {
      return grRoster.member.toString();
    }

    return '';
  },

  /**
   * Check if user is member of any specified groups
   *
   * @param {string} userId - sys_id of user
   * @param {Array} groupNames - Array of group names to check
   * @returns {boolean} True if user is in any of the groups
   */
  isMemberOfAnyGroup: function(userId, groupNames) {
    if (!userId || !groupNames || groupNames.length === 0) {
      return false;
    }

    var grMember = new GlideRecord('sys_user_grmember');
    grMember.addQuery('user', userId);
    grMember.addQuery('group.name', 'IN', groupNames.join(','));
    grMember.setLimit(1);
    grMember.query();

    return grMember.hasNext();
  },

  /**
   * Get user's primary group (first active group they're a member of)
   *
   * @param {string} userId - sys_id of user
   * @returns {object} Group object {sys_id, name} or null
   */
  getPrimaryGroup: function(userId) {
    if (!userId) {
      return null;
    }

    var grMember = new GlideRecord('sys_user_grmember');
    grMember.addQuery('user', userId);
    grMember.addQuery('group.active', 'true');
    grMember.orderBy('group.name');
    grMember.setLimit(1);
    grMember.query();

    if (grMember.next()) {
      return {
        sys_id: grMember.group.toString(),
        name: grMember.group.name.toString()
      };
    }

    return null;
  },

  type: 'UserGroupUtils'
};

How to use it

1. Create a new Script Include 2. Set Name to "UserGroupUtils" 3. Leave "Client callable" unchecked 4. Copy the code above 5. Call from Business Rules or other Script Includes

Adapt the table names, fields, and conditions to your instance. Test the behavior in a development environment before using it in production.