Business Rule or similar to update the manager field when a user logs in
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
7 hours ago
Hi,
I have an issue where when a user logs in I want the system to change the manager to a set person if the manager field is either empty or the manager in there is either inactive or locked out.
I have an async business rule set to run after update and run the below script but it doesn't seem to be triggering or working as expected.
(function executeRule(current, previous /*null when async*/) {
var currentUserID = currentUser.getID();
var user = new GlideRecord('sys_user');
if (user.get(currentUserID)) {
var managerID = user.manager;
var manager = new GlideRecord('sys_user');
// Check if manager is empty
if (!managerID) {
jslog('No manager assigned. Changing manager for user: ' + user.user_name);
user.manager = '7c7b45b31bfa7910bc98eb59b04bcb76'; // Replace with the new manager's sys_id
user.update();
return;
}
// Check if the current manager is active or not locked out
if (manager.get(managerID)) {
if (!manager.active || manager.locked_out) {
jslog('Manager is inactive or locked out. Changing manager for user: ' + user.user_name);
user.manager = '7c7b45b31bfa7910bc98eb59b04bcb76'; // Replace with the new manager's sys_id
user.update();
}
}
}
function jslog(message) {
gs.info('Business Rule: Update Manager on Login - ' + message);
}
})(current, previous);
Any help to get this working would be greatly appreciated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
7 hours ago
ServiceNow – Set/Correct a User’s Manager at Login (without recursion)
Why your current approach fails
- An AFTER UPDATE Business Rule on sys_user will NOT run on login (logging in does not update sys_user).
- The code uses currentUser.getID() (undefined). Use gs.getUserID().
- Calling user.update() from arbitrary contexts can retrigger BRs; prefer a login-triggered context and a silent update.
Two supported patterns
======================
Pattern A — Script Action on 'user.login' (recommended)
------------------------------------------------------
1) Go to: System Policy > Script Actions → New
2) Set:
- Active: true
- When to run: After
- Event name: user.login (built-in event fired on successful login)
3) Script (replace MANAGER_SYSID with your manager user sys_id):
(function() {
var MANAGER_SYSID = '7c7b45b31bfa7910bc98eb59b04bcb76';
var uid = gs.getUserID();
if (!uid) return;
// Do not run for special users if desired
// if (gs.hasRole('admin')) return; // optional
var u = new GlideRecord('sys_user');
if (!u.get(uid)) return;
var needsChange = false;
// If manager is empty
if (!u.getValue('manager')) {
needsChange = true;
} else {
// Load manager and validate
var mgr = u.getElement('manager').getRefRecord();
if (!mgr || mgr.active == false || mgr.locked_out == true) {
needsChange = true;
}
}
if (needsChange) {
u.setWorkflow(false); // avoid BR/Flow/Notifications
u.setUseEngines(false);
u.setValue('manager', MANAGER_SYSID);
u.update();
}
})();
Notes:
- Runs ONLY when a user logs in (no need to watch table updates).
- setWorkflow(false)/setUseEngines(false) prevents side effects.
Pattern B — Business Rule on sys_user_session (after insert)
------------------------------------------------------------
1) Table: sys_user_session
2) When: After Insert (a row is created at login)
3) Condition: current.user IS NOT EMPTY
4) Script:
(function executeRule(current, previous /*null when async*/) {
var MANAGER_SYSID = '7c7b45b31bfa7910bc98eb59b04bcb76';
var uid = current.user.toString();
if (!uid) return;
var u = new GlideRecord('sys_user');
if (!u.get(uid)) return;
var needsChange = false;
if (!u.getValue('manager')) {
needsChange = true;
} else {
var mgr = u.getElement('manager').getRefRecord();
if (!mgr || mgr.active == false || mgr.locked_out == true) {
needsChange = true;
}
}
if (needsChange) {
u.setWorkflow(false);
u.setUseEngines(false);
u.setValue('manager', MANAGER_SYSID);
u.update();
}
})(current, previous);
Troubleshooting & tips
----------------------
- Ensure the MANAGER_SYSID points to an ACTIVE, not locked_out user.
- Avoid recursion: never place this on an UPDATE rule against sys_user.
- Logging: use gs.info(...) in the script action while testing.
- Security: confirm the account running the script has rights to update sys_user.manager.
- If you must run conditionally (e.g., only for certain companies), add checks before update.
TL;DR
-----
Don’t use an AFTER UPDATE Business Rule on sys_user for login logic. Use a **Script Action on user.login** (or BR on sys_user_session AFTER INSERT), then do a **silent update** of the manager when empty/inactive/locked_out.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
5 hours ago
ServiceNow – Update a User’s Manager on Login (Working Patterns & Fixes)
Your current approach (async BR, using currentUser) won’t trigger on login and has a few issues:
- A Business Rule won’t run “on login” unless a field on sys_user actually changes. (Login does update last_login / last_login_time.)
- In a BR script you cannot use currentUser; use gs.getUserID().
- You’re re-querying the same user; use current (if the BR is on sys_user) or a clean GlideRecord with guards.
- Prevent recursion when you update sys_user from a sys_user BR.
Below are two reliable patterns. Prefer Pattern A.
------------------------------------------------------------
Pattern A (Recommended): Script Action on Login Event
------------------------------------------------------------
• Runs when the platform fires the 'user.login' event.
• No need to rely on sys_user field changes.
1) Create Script Action
- Navigate: System Policy → Events → Registry → ensure event 'user.login' exists (it is OOB).
- Go to: System Policy → Events → Script Actions → New
• Name: Set Manager on Login
• Event name: user.login
• Active: true
• Order: 100
2) Script (Script Action)
(function() {
var TARGET_MANAGER = '7c7b45b31bfa7910bc98eb59b04bcb76'; // TODO: replace
// The user who just logged in is passed in parm1 (OOB)
var uid = event.parm1 || gs.getUserID();
if (!uid) return;
var usr = new GlideRecord('sys_user');
if (!usr.get(uid)) return;
function setManager(gr, mgrSysId) {
// safety: avoid loops and system updates
gr.setValue('manager', mgrSysId);
gr.setWorkflow(false);
gr.autoSysFields(false);
gr.update();
}
var mgrId = usr.getValue('manager');
if (!mgrId) {
gs.info('Login manager fix: assigning default manager to ' + usr.getValue('user_name'));
setManager(usr, TARGET_MANAGER);
return;
}
var mgr = new GlideRecord('sys_user');
if (!mgr.get(mgrId)) {
gs.info('Login manager fix: existing manager missing, assigning default manager to ' + usr.getValue('user_name'));
setManager(usr, TARGET_MANAGER);
return;
}
var inactive = (mgr.getValue('active') == 'false');
var locked = (mgr.getValue('locked_out') == 'true');
if (inactive || locked) {
gs.info('Login manager fix: manager inactive/locked, assigning default manager to ' + usr.getValue('user_name'));
setManager(usr, TARGET_MANAGER);
}
})();
Notes
- event.parm1 is the sys_id of the user who logged in (OOB behavior).
- Keep this Script Action lightweight to avoid login latency.
------------------------------------------------------------
Pattern B: Business Rule on sys_user (last_login change)
------------------------------------------------------------
• Runs when sys_user.last_login_time (or last_login) changes at login.
1) Create Business Rule
- Table: sys_user
- When: after update (can be async = true)
- Condition: current.last_login_time.changes() || current.last_login.changes()
- Advanced: ✓
2) Script (Business Rule)
(function executeRule(current, previous) {
var TARGET_MANAGER = '7c7b45b31bfa7910bc98eb59b04bcb76'; // TODO: replace
// guard: don't run if already set to target
if (current.getValue('manager') == TARGET_MANAGER)
return;
var mgrId = current.getValue('manager');
// helper to update safely without re-triggering the rule
function updateManager(gr, mgrSysId) {
var u = new GlideRecord('sys_user');
if (!u.get(gr.getUniqueValue())) return;
u.setValue('manager', mgrSysId);
u.setWorkflow(false);
u.autoSysFields(false);
u.update();
}
if (!mgrId) {
gs.info('Login manager BR: assigning default manager to ' + current.getValue('user_name'));
updateManager(current, TARGET_MANAGER);
return;
}
var mgr = new GlideRecord('sys_user');
if (!mgr.get(mgrId)) {
gs.info('Login manager BR: manager ref broken, assigning default manager to ' + current.getValue('user_name'));
updateManager(current, TARGET_MANAGER);
return;
}
var inactive = (mgr.getValue('active') == 'false');
var locked = (mgr.getValue('locked_out') == 'true');
if (inactive || locked) {
gs.info('Login manager BR: manager inactive/locked, assigning default manager to ' + current.getValue('user_name'));
updateManager(current, TARGET_MANAGER);
}
})(current, previous);
Notes
- Use changes() on last_login_time or last_login so the rule only runs on login updates.
- Use a second GlideRecord with setWorkflow(false) to avoid recursive triggers.
- Don’t use currentUser.getID(); use gs.getUserID() when needed.
------------------------------------------------------------
Debugging checklist
------------------------------------------------------------
- Confirm 'user.login' events are firing (System Logs → Events → filter by name = user.login).
- If using BR: verify that last_login_time changes on login in your instance version.
- Ensure the target manager sys_id is valid and user is active/unlocked.
- Add temporary gs.info() logs to verify paths.
- Test with a non-admin user; admins may have atypical profiles (e.g., no company, impersonation behavior).
------------------------------------------------------------
Security & Governance
------------------------------------------------------------
- Document why you’re defaulting managers; consider excluding privileged accounts (admin, security_admin).
- Wrap behind a system property (e.g., glide.company.default_manager) to avoid hardcoding.
- Consider a one-time data correction job if many users lack a manager today, then keep this logic for future logins only.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
5 hours ago
Hi @wiganmichae ,
I tried your code in my PDI and it is working fine for me please check below code
(function executeRule(current, previous /*null when async*/ ) {
// Add your code here
var currentUserID = current.sys_id; // I made changes here
gs.log("currentUserID = " + currentUserID);
var user = new GlideRecord('sys_user');
if (user.get(currentUserID)) {
var managerID = user.manager;
gs.log("Manager çheck = " + managerID);
var manager = new GlideRecord('sys_user');
// Check if manager is emptyi
if (!managerID) {
gs.log('No manager assigned. Changing manager for user: ' + user.user_name);
user.manager = '4ddc2f1193576a109305f520ed03d681'; // Replace with the new manager's sys_id
user.update()
}
// Check if the current manager is active or not locked out
if (manager.get(managerID)) {
if (!manager.active || manager.locked_out) {
gs.log('Manager is inactive or locked out. Changing manager for user: ' + user.user_name);
user.manager = '4ddc2f1193576a109305f520ed03d681'; // Replace with the new manager's sys_id
user.update()
}
}
}
})(current, previous);
Result
Please mark my answer correct and helpful if this works for you
Thanks and Regards,
Sarthak
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
4 hours ago
I did this thing on Before BR
Please mark my answer correct and helpful if this works for you
Thanks and Regards,
Sarthak
