Remove unassigned users


Last updated


Last updated
// moovIT GmbH
// Find unassigned users and delete them
// B Dimmel
// Version 1.0
// Date May 23rd 2025
// Changelog
// Initial commit
// Find up to 50 users in the "Unassigned" group
// Delete users who have never logged in or have not logged in since the purge date
// Return a JSON array of the results
// === Configuration ===
var baseUrl = "{stream.variable.helmut4URL}"; // your API base URL
var authToken = "Bearer {stream.variable.helmut4Bearer}"; // your Bearer token
var purgeDate = "{date.decrement.days.21}"; // purge threshold (YYYY-MM-DD)
// === API Endpoints ===
var listEndpoint = "/v1/members/users/search?groupFilter=Unassigned&limit=100&page=0&sortKey=lastLogin&sortDirectionDesc=true";
var deleteEndpoint = "/v1/members/users/"; // DELETE base path
// === Utilities ===
function pad(n) {
return (n < 10 ? '0' : '') + n;
}
function normalizeYMD(date) {
return date.getUTCFullYear() + "-" +
pad(date.getUTCMonth() + 1) + "-" +
pad(date.getUTCDate());
}
function asResponse(con) {
var inr = new java.io.BufferedReader(new java.io.InputStreamReader(con.getInputStream(), "UTF-8"));
var line, sb = new java.lang.StringBuffer();
while ((line = inr.readLine()) !== null) {
sb.append(line);
}
inr.close();
return { status: con.getResponseCode(), data: sb.toString() };
}
// === HTTP Methods ===
function httpGet(path) {
var url = new java.net.URL(baseUrl + path);
var con = url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Authorization", authToken);
con.setRequestProperty("Accept", "application/json");
return asResponse(con);
}
function httpDelete(path) {
var url = new java.net.URL(baseUrl + path);
var con = url.openConnection();
con.setRequestMethod("DELETE");
con.setRequestProperty("Authorization", authToken);
con.setRequestProperty("Accept", "application/json");
return { status: con.getResponseCode() };
}
// === Main Logic ===
var resp = httpGet(listEndpoint);
var output;
// Handle HTTP error
if (resp.status !== 200) {
output = {
message: "Failed to list users",
httpStatus: resp.status
};
// Handle no users found
} else {
var users = JSON.parse(resp.data);
if (!users || users.length === 0) {
output = {
message: "No unassigned users found"
};
// Process users
} else {
var results = [];
var purgeLimit = new Date(purgeDate + "T00:00:00.000Z");
var purgeYMD = normalizeYMD(purgeLimit);
users.forEach(function(u) {
var action, httpResp;
// decide Delete vs Skip
if (u.lastLogin == null || String(u.lastLogin).trim().toLowerCase() === "null") {
action = "Delete";
} else {
var lastLoginDate = new Date(u.lastLogin);
var lastYMD = normalizeYMD(lastLoginDate);
action = (lastYMD <= purgeYMD) ? "Delete" : "Skip";
}
// perform or skip
if (action === "Delete") {
var del = httpDelete(deleteEndpoint + u.id);
httpResp = "HTTP " + del.status;
} else {
httpResp = "Skipped";
}
// record result
results.push({
type: action,
username: u.username,
userId: u.id,
lastLogin: u.lastLogin,
httpResponse: httpResp
});
});
output = { results: results };
}
}
// Return the JSON string
JSON.stringify(output);// moovIT GmbH
// Parse result from unassigned users to html report
// B Dimmel
// Version 1.0
// Date May 23rd 2025
// Changelog
// Initial commit
// === Input ===
// Could be either a JS object or a JSON string
var resultJson = {node.result.d855b80d-2673-4ad6-9207-c6ca4ddd9c23};
// var resultJson = '[{"type":"Delete","username":"f.mustermann",...},...]';
// === Configuration ===
var host = "{stream.variable.helmut4URL}"; // base host for images
var cssHost = host + "/img";
// === Parse JSON if needed ===
var data;
if (typeof resultJson === "string") {
try {
data = JSON.parse(resultJson);
} catch (e) {
data = { message: "Invalid JSON input" };
}
} else {
data = resultJson;
}
// === Build HTML ===
var htmlContent = ""
+ "<!DOCTYPE html>"
+ "<html lang='en'>"
+ "<head>"
+ " <meta charset='UTF-8'>"
+ " <meta name='viewport' content='width=device-width, initial-scale=1.0'>"
+ " <title>Purge Results</title>"
// Preload icons
+ " <link rel='preload' href='" + cssHost + "/logo_fx.7e217855.png' as='image'>"
+ " <link rel='preload' href='" + cssHost + "/logo_io.40e6b230.png' as='image'>"
+ " <link rel='preload' href='" + cssHost + "/logo_co.7cbcd236.png' as='image'>"
+ " <link rel='preload' href='" + cssHost + "/logo_hk.5bccf0bb.png' as='image'>"
+ " <style>"
+ " html, body {"
+ " background-color: #FFFFFF;"
+ " color: #333333;"
+ " font-family: 'Helvetica Neue', Arial, sans-serif;"
+ " padding: 20px;"
+ " margin: 0;"
+ " text-align: center;"
+ " font-size: 16px;"
+ " }"
+ " h1 {"
+ " color: #005A9C;"
+ " font-size: 28px;"
+ " margin-bottom: 15px;"
+ " }"
+ " p {"
+ " line-height: 1.6;"
+ " font-size: 16px;"
+ " }"
+ " table {"
+ " margin: 20px auto;"
+ " border-collapse: collapse;"
+ " width: 90[<]%[>];"
+ " max-width: 800px;"
+ " }"
+ " th, td {"
+ " border: 1px solid #CCCCCC;"
+ " padding: 10px 14px;"
+ " font-size: 15px;"
+ " }"
+ " th {"
+ " background-color: #F2F2F2;"
+ " color: #333333;"
+ " text-align: left;"
+ " }"
+ " td {"
+ " background-color: #FFFFFF;"
+ " color: #333333;"
+ " }"
+ " .message {"
+ " font-size: 18px;"
+ " margin-top: 30px;"
+ " color: #555555;"
+ " }"
+ " .image-row {"
+ " margin-top: 40px;"
+ " }"
+ " .image-row img {"
+ " width: 100px;"
+ " height: auto;"
+ " margin: 0 10px;"
+ " vertical-align: middle;"
+ " }"
+ " </style>"
+ "</head>"
+ "<body>"
+ " <h1>Unassigned User (s) Purge Script Results</h1>";
// Top-level message or table
if (data.message) {
htmlContent += "<p class='message'>" + data.message + "</p>";
} else if (Array.isArray(data.results) && data.results.length) {
htmlContent += ""
+ "<table>"
+ " <thead>"
+ " <tr>"
+ " <th>Action</th>"
+ " <th>Username</th>"
+ " <th>User ID</th>"
+ " <th>Last Login</th>"
+ " <th>HTTP Response</th>"
+ " </tr>"
+ " </thead>"
+ " <tbody>";
data.results.forEach(function(r) {
htmlContent += ""
+ " <tr>"
+ " <td>" + r.type + "</td>"
+ " <td>" + (r.username || "") + "</td>"
+ " <td>" + (r.userId || "") + "</td>"
+ " <td>" + (r.lastLogin || "") + "</td>"
+ " <td>" + r.httpResponse + "</td>"
+ " </tr>";
});
htmlContent += ""
+ " </tbody>"
+ "</table>";
} else {
htmlContent += "<p class='message'>No results to display.</p>";
}
// Icon row using host variable
htmlContent += ""
+ " <div class='image-row'>"
+ " <img src='" + cssHost + "/logo_fx.7e217855.png' alt='Logo FX'>"
+ " <img src='" + cssHost + "/logo_io.40e6b230.png' alt='Logo IO'>"
+ " <img src='" + cssHost + "/logo_co.7cbcd236.png' alt='Logo CO'>"
+ " <img src='" + cssHost + "/logo_hk.5bccf0bb.png' alt='Logo HK'>"
+ " </div>"
+ "</body>"
+ "</html>";
// Return HTML
htmlContent;