Skip to Content

Query Business Rule - Restrict Visible Records

Limit which records users can see based on custom criteria like location, department, or assignment group membership.

Table: incident When: before
#query #before #security #data-filtering #rbac #row-level-security

Script Code

JavaScript
1(function executeRule(current, previous /*null when async*/) {
2
3  // Skip for admin users
4  if (gs.hasRole('admin')) {
5    return;
6  }
7
8  // Configuration: Define restriction type
9  var restrictionType = 'department';  // Options: 'department', 'location', 'group', 'custom'
10
11  // Get current user
12  var userId = gs.getUserID();
13  var grUser = new GlideRecord('sys_user');
14  if (!grUser.get(userId)) {
15    gs.warn('Query BR: User not found: ' + userId);
16    return;
17  }
18
19  // Apply restrictions based on type
20  switch(restrictionType) {
21
22    case 'department':
23      // Users can only see incidents for their department
24      var userDept = grUser.getValue('department');
25      if (userDept) {
26        current.addQuery('caller_id.department', userDept);
27        gs.info('Query BR: Restricting to department: ' + grUser.department.getDisplayValue());
28      }
29      break;
30
31    case 'location':
32      // Users can only see incidents for their location
33      var userLocation = grUser.getValue('location');
34      if (userLocation) {
35        current.addQuery('caller_id.location', userLocation);
36        gs.info('Query BR: Restricting to location: ' + grUser.location.getDisplayValue());
37      }
38      break;
39
40    case 'group':
41      // Users can only see incidents assigned to their groups
42      var userGroups = [];
43      var grGroupMember = new GlideRecord('sys_user_grmember');
44      grGroupMember.addQuery('user', userId);
45      grGroupMember.query();
46
47      while (grGroupMember.next()) {
48        userGroups.push(grGroupMember.group.toString());
49      }
50
51      if (userGroups.length > 0) {
52        current.addQuery('assignment_group', 'IN', userGroups.join(','));
53        gs.info('Query BR: Restricting to ' + userGroups.length + ' groups');
54      } else {
55        // User not in any groups - show no records
56        current.addQuery('sys_id', 'NULL');
57      }
58      break;
59
60    case 'custom':
61      // Custom logic: Users can only see incidents they created or are assigned to
62      var orCondition = current.addQuery('caller_id', userId);
63      orCondition.addOrCondition('assigned_to', userId);
64      orCondition.addOrCondition('opened_by', userId);
65
66      // Also include records where user is in watch list (custom field)
67      // orCondition.addOrCondition('watch_list', 'CONTAINS', userId);
68
69      gs.info('Query BR: Restricting to user-related records');
70      break;
71
72    default:
73      gs.warn('Query BR: Unknown restriction type: ' + restrictionType);
74  }
75
76  // Optional: Add additional filters for all users
77  // Example: Only show active records
78  current.addQuery('active', 'true');
79
80  // Example: Exclude certain states
81  // current.addQuery('state', 'NOT IN', '6,7,8');  // Exclude Resolved, Closed, Cancelled
82
83  // Log the constructed query for debugging
84  gs.debug('Query BR: Final query - ' + current.getEncodedQuery());
85
86})(current, previous);

How to Use

1. Create a before Business Rule on your table 2. Check the "Query" checkbox (important!) 3. Set Order to 100 to run early 4. Choose your restriction type in the configuration 5. Test with users from different departments/locations/groups 6. Monitor system logs to verify query construction 7. Consider performance impact on large tables 8. Document restriction logic for compliance

Explore More Scripts

Browse our complete library of ServiceNow scripts

View All Scripts