By default, there’s no built-in way to remove these “orphaned” users. However, you can create a cron task that scans all unassigned users, checks their last login date, and deletes any account whose last login is older than, say, 21 days.
Find unassigned users, last login 21 days ago
The JavaScript code returns a JSON payload containing all relevant information. A second JavaScript snippet can process that payload to generate a human-readable HTML page, which is then displayed via the send-message node.
// 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);