|
| 1 | +(function executeAutoUserCleanup() { |
| 2 | + |
| 3 | + /*************************************************************** |
| 4 | + * AUTO CLEANUP INACTIVE USERS - MONTHLY JOB |
| 5 | + * ------------------------------------------------------------ |
| 6 | + * This script automatically deactivates users who have not |
| 7 | + * logged in for a defined number of months. It can also send |
| 8 | + * notifications to both the user and their manager. |
| 9 | + * |
| 10 | + * SAFETY: Use DRY_RUN = true first to test (no updates). |
| 11 | + ***************************************************************/ |
| 12 | + |
| 13 | + // === CONFIGURATION === |
| 14 | + var MONTHS_THRESHOLD = 3; // Inactive period threshold (in months) |
| 15 | + var DRY_RUN = true; // true = test mode, no database updates |
| 16 | + var BATCH_LIMIT = 1000; // Max records per execution |
| 17 | + var FROM_EMAIL = 'no-reply@yourcompany.com'; // sender email address |
| 18 | + |
| 19 | + // === STEP 1: Calculate cutoff date === |
| 20 | + var cutoffDate = new GlideDateTime(); |
| 21 | + cutoffDate.addMonths(-MONTHS_THRESHOLD); |
| 22 | + |
| 23 | + gs.info('[UserCleanup] Job started. Cutoff date: ' + cutoffDate.getDisplayValue() + |
| 24 | + ' | DRY_RUN: ' + DRY_RUN + ' | Threshold: ' + MONTHS_THRESHOLD + ' months'); |
| 25 | + |
| 26 | + // === STEP 2: Query eligible users === |
| 27 | + var userGr = new GlideRecord('sys_user'); |
| 28 | + userGr.addQuery('active', true); // only active users |
| 29 | + userGr.addQuery('sys_created_on', '<=', cutoffDate); // created before cutoff |
| 30 | + userGr.addQuery('last_login_time', '<=', cutoffDate); // no recent login |
| 31 | + userGr.setLimit(BATCH_LIMIT); // safety limit |
| 32 | + userGr.query(); |
| 33 | + |
| 34 | + var totalFound = 0; |
| 35 | + var totalDeactivated = 0; |
| 36 | + |
| 37 | + // === STEP 3: Loop through each user === |
| 38 | + while (userGr.next()) { |
| 39 | + totalFound++; |
| 40 | + |
| 41 | + var userName = userGr.name.toString(); |
| 42 | + var userEmail = userGr.email.toString(); |
| 43 | + var lastLogin = userGr.last_login_time ? userGr.last_login_time.getDisplayValue() : 'Never'; |
| 44 | + var managerEmail = (userGr.manager && userGr.manager.email) ? userGr.manager.email.toString() : null; |
| 45 | + |
| 46 | + gs.info('[UserCleanup] Found user: ' + userName + |
| 47 | + ' | Email: ' + userEmail + |
| 48 | + ' | Last Login: ' + lastLogin + |
| 49 | + ' | Manager: ' + (managerEmail || 'None')); |
| 50 | + |
| 51 | + if (!DRY_RUN) { |
| 52 | + |
| 53 | + // === STEP 4: Deactivate the user === |
| 54 | + userGr.active = false; |
| 55 | + userGr.update(); |
| 56 | + totalDeactivated++; |
| 57 | + |
| 58 | + // === STEP 5: Send notification to user === |
| 59 | + if (userEmail) { |
| 60 | + var subjectUser = 'Your ServiceNow account has been deactivated due to inactivity'; |
| 61 | + var bodyUser = |
| 62 | + 'Hello ' + userName + ',\n\n' + |
| 63 | + 'Your ServiceNow account has been automatically deactivated because there has been no login activity ' + |
| 64 | + 'for over ' + MONTHS_THRESHOLD + ' months.\n\n' + |
| 65 | + 'If you believe this is a mistake or require access, please contact the IT Service Desk.\n\n' + |
| 66 | + 'Regards,\nIT Service Management Team'; |
| 67 | + |
| 68 | + gs.email(FROM_EMAIL, userEmail, subjectUser, bodyUser); |
| 69 | + gs.info('[UserCleanup] Email sent to user: ' + userEmail); |
| 70 | + } |
| 71 | + |
| 72 | + // === STEP 6: Send notification to manager === |
| 73 | + if (managerEmail) { |
| 74 | + var subjectMgr = 'User under your management has been deactivated'; |
| 75 | + var bodyMgr = |
| 76 | + 'Hello,\n\n' + |
| 77 | + 'The following user under your management has been deactivated due to inactivity:\n\n' + |
| 78 | + 'User: ' + userName + '\n' + |
| 79 | + 'Last Login: ' + lastLogin + '\n\n' + |
| 80 | + 'If this account is still required, please raise a ServiceNow access request.\n\n' + |
| 81 | + 'Regards,\nIT Service Management Team'; |
| 82 | + |
| 83 | + gs.email(FROM_EMAIL, managerEmail, subjectMgr, bodyMgr); |
| 84 | + gs.info('[UserCleanup] Email sent to manager: ' + managerEmail); |
| 85 | + } |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + // === STEP 7: Log summary === |
| 90 | + gs.info('[UserCleanup] Total users found: ' + totalFound); |
| 91 | + gs.info('[UserCleanup] Total users deactivated: ' + totalDeactivated + |
| 92 | + (DRY_RUN ? ' (Dry Run - no records updated)' : '')); |
| 93 | + |
| 94 | +})(); |
| 95 | + |
0 commit comments