From 21b615f12031c3d78653b5c67b681cf9a69c3799 Mon Sep 17 00:00:00 2001
From: ReddySurendra <130588276+Suri123789@users.noreply.github.com>
Date: Tue, 27 May 2025 12:30:58 +0530
Subject: [PATCH 1/4] Code for Moveworks bot messages for Flow to include url
links
---
Moveworks messages html for Flow | 38 ++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Moveworks messages html for Flow
diff --git a/Moveworks messages html for Flow b/Moveworks messages html for Flow
new file mode 100644
index 0000000000..c228104146
--- /dev/null
+++ b/Moveworks messages html for Flow
@@ -0,0 +1,38 @@
+var article = fd_data._1__look_up_record.record;
+
+// Safely retrieve fields with null checks for a KB Article
+var sys_id = article.sys_id || '';
+var articleTitle = article.short_description || 'N/A';
+var requestedBy = fd_data.trigger.current.sys_created_by;
+var articleNumber = article.number || 'N/A';
+var requestedOn = article.sys_created_on || 'N/A';
+var kbName = (article.kb_knowledge_base && article.kb_knowledge_base.title) || 'N/A';
+var knowledgeManagers = (article.kb_knowledge_base && article.kb_knowledge_base.owner && article.kb_knowledge_base.owner.getDisplayValue()) || 'N/A';
+
+// Base URL
+var baseUrl = gs.getProperty('glide.servlet.uri') || '';
+var kbLink = baseUrl + 'kb_knowledge.do?sys_id=' + sys_id;
+//Below are links for opening the record in servicenow
+var approveLink = baseUrl + 'sysapproval_approver.do?action=approve&sys_id=' + sys_id;
+var rejectLink = baseUrl + 'sysapproval_approver.do?action=reject&sys_id=' + sys_id;
+//Below lines are for email template which is used to create email inbound template.
+var inst ='inspirebrandsdev';
+var approveSub = 'RE: '+ articleNumber +' Approve KB Article ';
+var body = 'Please do not change the subject, just click send message.';
+var rejectSub = 'RE: '+ articleNumber +' Reject KB Article ';
+
+
+// HTML message
+var message =
+ 'Pending approval request from ServiceNow
' +
+ '' + articleNumber + ': ' + articleTitle + '
' +
+ 'Requested by: ' + requestedBy + '
' +
+ 'Requested on: ' + requestedOn + '
' +
+ 'Knowledge Base: ' + kbName + '
' +
+ 'Knowledge Managers: ' + knowledgeManagers + '
' +
+ 'Approve link : Click here
'+
+ 'Reject link : Click here
';
+ //'Approve link : Click here to approve
' +
+ //'Reject link: Click here to reject';
+
+return message;
From 94f7b15b9606b44ed6875e5e1945789e9de6534c Mon Sep 17 00:00:00 2001
From: ReddySurendra <130588276+Suri123789@users.noreply.github.com>
Date: Tue, 28 Oct 2025 18:42:51 +0530
Subject: [PATCH 2/4] Create script.js
---
.../Clean up Inactive User access/script.js | 59 +++++++++++++++++++
1 file changed, 59 insertions(+)
create mode 100644 Server-Side Components/Scheduled Jobs/Clean up Inactive User access/script.js
diff --git a/Server-Side Components/Scheduled Jobs/Clean up Inactive User access/script.js b/Server-Side Components/Scheduled Jobs/Clean up Inactive User access/script.js
new file mode 100644
index 0000000000..5f2f426dfd
--- /dev/null
+++ b/Server-Side Components/Scheduled Jobs/Clean up Inactive User access/script.js
@@ -0,0 +1,59 @@
+///This is a Scheduled Job Script to be added in "Run this script"
+//replace the email in line 56- 'email.setFrom('xyz@service-now.com');'
+//replace the property name in line 44 'var recipientList = gs.getProperty('glide.xyz.admin.email.recipients');'
+
+var emailBody = 'Daily Inactive User Group/Role/Task Clean-up Completed: \n
';
+
+//REMOVE INACTIVE USERS FROM GROUPS
+var queryString = "user.active=false^user.web_service_access_only=false^user.sourceSTARTSWITHldap:"; //query to find inactive members belonging to groups and ignores any users with "web service access only" = TRUE.
+var recGrp = new GlideRecord('sys_user_grmember'); //searches the User Group Member table
+recGrp.addEncodedQuery(queryString);
+recGrp.query();
+while (recGrp.next()) {
+ emailBody += 'Inactive User, ' + recGrp.user.getDisplayValue() + ', member of Group: ' + recGrp.group.getDisplayValue() + ' was removed from Group.\n
';
+ gs.log('Inactive User, ' + recGrp.user.getDisplayValue() + ', member of Group: ' + recGrp.group.getDisplayValue() + ' was removed from Group.');
+ recGrp.deleteRecord(); //deletes group membership record from inactive user
+}
+
+//REMOVE ROLES FROM INACTIVE USERS THAT WERE NOT ADDED BY GROUP MEMBERSHIP
+var recRole = new GlideRecord('sys_user_has_role'); // search view User Has Role table
+var queryString2 = "user.active=false^user.web_service_access_only=false^user.sourceSTARTSWITHldap:^inherited=false";
+recRole.addEncodedQuery(queryString2); // find inactive users that have a role assigned and ignores any users with "web service access only" = TRUE.
+recRole.query();
+while (recRole.next()) {
+ emailBody += 'Inactive User, ' + recRole.user.name + ' found - Role: ' + recRole.role.getDisplayValue() + ', was removed.\n
';
+ gs.log('Inactive User, ' + recRole.user.name + ' found - Role: ' + recRole.role.getDisplayValue() + ', was removed.'); // add info message to system log about what user was inactive and role was removed
+ recRole.deleteRecord(); //deletes role record from inactive user
+}
+
+//CLEARS ASSIGNED TO ON ACTIVE TASKS ASSIGNED TO INACTIVE USERS
+var recTask = new GlideRecord('task'); // search task table
+var queryString3 = "assigned_to.active=false^assigned_to.web_service_access_only=false^active=true";
+recTask.addEncodedQuery(queryString3); // find inactive users that have active tasks assigned to them and ignores any users with "web service access only" = TRUE.
+recTask.query();
+while (recTask.next()) {
+ emailBody += 'Removed task from Inactive User: ' + recTask.assigned_to.getDisplayValue() + ' ' + recTask.number + '.\n
';
+ gs.log('Removed task from Inactive User: ' + recTask.assigned_to.getDisplayValue() + ' ' + recTask.number); // add message about what user was inactive tasks removed
+ recTask.work_notes = 'System Administrator removed "Assigned to" value as the user is no longer active.'; //add work note explanation without workflow
+ recTask.update();
+ recTask.assigned_to = '';
+ recTask.setWorkflow(false); //removes assigned_to value without workflow
+ recTask.update();
+}
+
+var recipientList = gs.getProperty('glide.xyz.admin.email.recipients');
+var email = new GlideEmailOutbound();
+email.setSubject('Daily Inactive User Group/Role/Task Clean-up Completed');
+email.setBody(emailBody);
+if (recipientList.includes(',')) {
+ var recipients = recipientList.split(",");
+ for (var i = 0; i < recipients.length; i++) {
+ email.addRecipient(recipients[i]); // Add recipients from system property
+ }
+} else {
+ email.addRecipient(recipientList); // Add single recipient from system property
+}
+email.setFrom('xyz@service-now.com');
+email.save();
+
+gs.log('Daily Inactive User Group/Role/Task Clean-up Completed: \n\n' + emailBody);
From 117c02695733883ef876481f2ed346fb5b34b29e Mon Sep 17 00:00:00 2001
From: ReddySurendra <130588276+Suri123789@users.noreply.github.com>
Date: Tue, 28 Oct 2025 18:47:25 +0530
Subject: [PATCH 3/4] Create readme.md
---
.../Clean up Inactive User access/readme.md | 82 +++++++++++++++++++
1 file changed, 82 insertions(+)
create mode 100644 Server-Side Components/Scheduled Jobs/Clean up Inactive User access/readme.md
diff --git a/Server-Side Components/Scheduled Jobs/Clean up Inactive User access/readme.md b/Server-Side Components/Scheduled Jobs/Clean up Inactive User access/readme.md
new file mode 100644
index 0000000000..efd3f7fa29
--- /dev/null
+++ b/Server-Side Components/Scheduled Jobs/Clean up Inactive User access/readme.md
@@ -0,0 +1,82 @@
+๐งน Inactive User Cleanup โ ServiceNow Scheduled Job
+๐ Overview
+
+This script automates daily cleanup of access and assignments for inactive users in ServiceNow.
+It removes orphaned access, ensures task accountability, and sends an email summary upon completion.
+
+โ
Features Included
+๐น Inactive Group Membership Cleanup
+
+Searches User Group Member table (sys_user_grmember)
+Identifies inactive users (excluding Web Service Access Only accounts)
+Removes them from all associated groups
+Logs each removal in system logs
+Adds removal details to the summary email
+
+๐น Direct Role Revocation
+
+Searches User Has Role table (sys_user_has_role)
+Removes roles not inherited via group membership
+Prevents unauthorized access after deactivation
+Logs each role removed
+Included in daily summary email
+
+๐น Task Ownership Cleanup
+
+Searches Task table (task)
+Finds active tasks assigned to inactive users
+Clears the Assigned To field without triggering workflow
+Adds work notes for audit traceability
+Logs entries + email reporting
+All actions skip users where: web_service_access_only = true
+
+๐ Script Placement & Configuration
+Field Value
+Script Type โ
Scheduled Script Execution
+Location Run this script section
+
+Before using in your instance, update the following in script:
+
+Line Update Required
+Line 56 Replace sender email in email.setFrom('xyz@service-now.com');
+Line 44 Replace system property name in gs.getProperty('glide.xyz.admin.email.recipients');
+๐ System Property Required
+
+Create or update the System Property to store email recipients:
+
+Name (example) Value (example)
+glide.xyz.admin.email.recipients admin@example.com,user@example.com
+
+Supports single or comma-separated recipients โ
+
+โ๏ธ Email Summary Includes
+
+Users removed from groups
+Direct roles removed
+Active tasks unassigned
+Timestamped logs for auditing
+
+๐ Work Notes Added
+
+For tasks reassigned:
+System Administrator removed "Assigned to" value as the user is no longer active.
+
+โ ๏ธ Best Practices
+
+Run in sub-prod first
+Ensure proper backups/audit compliance
+Schedule at low-traffic hours
+Monitor logs initially for data impact
+
+๐งฉ Extendability Ideas
+
+You can easily modify:
+Email template (HTML formatting)
+Query filters for additional cleanup criteria
+Logging to include sys_id values
+Scheduling frequency (default recommended: Daily)
+
+๐งโ๐ป Maintainers
+
+Feel free to update script name, System Property naming, and sender email for your organization.
+Pull requests & suggestions welcome! ๐
From d66db38bafc3a94ae80792488ab5bc5055ced557 Mon Sep 17 00:00:00 2001
From: ReddySurendra <130588276+Suri123789@users.noreply.github.com>
Date: Tue, 28 Oct 2025 19:01:17 +0530
Subject: [PATCH 4/4] Delete Moveworks messages html for Flow
---
Moveworks messages html for Flow | 38 --------------------------------
1 file changed, 38 deletions(-)
delete mode 100644 Moveworks messages html for Flow
diff --git a/Moveworks messages html for Flow b/Moveworks messages html for Flow
deleted file mode 100644
index c228104146..0000000000
--- a/Moveworks messages html for Flow
+++ /dev/null
@@ -1,38 +0,0 @@
-var article = fd_data._1__look_up_record.record;
-
-// Safely retrieve fields with null checks for a KB Article
-var sys_id = article.sys_id || '';
-var articleTitle = article.short_description || 'N/A';
-var requestedBy = fd_data.trigger.current.sys_created_by;
-var articleNumber = article.number || 'N/A';
-var requestedOn = article.sys_created_on || 'N/A';
-var kbName = (article.kb_knowledge_base && article.kb_knowledge_base.title) || 'N/A';
-var knowledgeManagers = (article.kb_knowledge_base && article.kb_knowledge_base.owner && article.kb_knowledge_base.owner.getDisplayValue()) || 'N/A';
-
-// Base URL
-var baseUrl = gs.getProperty('glide.servlet.uri') || '';
-var kbLink = baseUrl + 'kb_knowledge.do?sys_id=' + sys_id;
-//Below are links for opening the record in servicenow
-var approveLink = baseUrl + 'sysapproval_approver.do?action=approve&sys_id=' + sys_id;
-var rejectLink = baseUrl + 'sysapproval_approver.do?action=reject&sys_id=' + sys_id;
-//Below lines are for email template which is used to create email inbound template.
-var inst ='inspirebrandsdev';
-var approveSub = 'RE: '+ articleNumber +' Approve KB Article ';
-var body = 'Please do not change the subject, just click send message.';
-var rejectSub = 'RE: '+ articleNumber +' Reject KB Article ';
-
-
-// HTML message
-var message =
- 'Pending approval request from ServiceNow
' +
- '' + articleNumber + ': ' + articleTitle + '
' +
- 'Requested by: ' + requestedBy + '
' +
- 'Requested on: ' + requestedOn + '
' +
- 'Knowledge Base: ' + kbName + '
' +
- 'Knowledge Managers: ' + knowledgeManagers + '
' +
- 'Approve link : Click here
'+
- 'Reject link : Click here
';
- //'Approve link : Click here to approve
' +
- //'Reject link: Click here to reject';
-
-return message;