Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Hutter
Tera Expert

Time to time someone may need to remove the "orphaned" user - role assignments from the "sys_user_has_role" table due to cloning or other activities.

find_real_file.png

I have written a fix script to easily remove this records and also include "inherited" roles which can't be simple deleted.
As I have not found a script in the community yet I like to share it with you.

I recognized a average processing speed of roughly 100.000 records per hour,
please feel free to share your run times for getting more accurate results / calculations

Note: If you actually want to delete the records, set the first variable to false

//set the following variable to false if the records should be actually deleted instead of only counted
var countonly = true;


//first count the "to be deleted" records
var totalamount = get_row_count();



if (!countonly) { //if the above variable is set to true, only count but do not delete anything
    var start = new GlideDateTime().getNumericValue(); //set a start timer (usefull for non fix scripts)

    update_roles_inherited(); //update the "inherited" roles first so we are able to delete them
    delete_roles(); //finally delete all orphaned roles


    var totaltime = parseInt(new GlideDateTime().getNumericValue() - start) / 1000 / 60; //calculate the total execution time in minutes
	totaltime = Math.round(totaltime);
    gs.log("Total execution for updating and removing (whithout counting) of " + totalamount + " records: " + totaltime + " minutes", "Orphaned role cleanup"); //finally log the total amount and execution time

} else { //only estimate the run time
    var estimatedtime = totalamount / 1666; //devide the counted records by 1666 (records per min)
	estimatedtime = Math.round(estimatedtime);
    gs.log("Found " + totalamount + " orphaned records which could be deleted in roughly " + estimatedtime + " minutes", "Orphaned role cleanup"); //finally log the total amount and execution time
}


//for quick counting GlideAggregate is used
function get_row_count() {
    var hasrole = new GlideAggregate("sys_user_has_role");
    hasrole.addQuery('user.user_name', ''); //user_name is what we check for as is should be there for any user
    hasrole.addAggregate("COUNT");
    hasrole.query();
    if (hasrole.next()) {
        return parseInt(hasrole.getAggregate("COUNT"));
    }
}

function update_roles_inherited() {
    var hasrole = new GlideRecord("sys_user_has_role");
    hasrole.addQuery('role.name', '!=', 'admin'); //exclude admin role just in case there is something wrong with the below query
    hasrole.addQuery('user.user_name', ''); //user_name is what we check for as is should be there for any user
    hasrole.addQuery('inherited', true); //only update "inherited" role assignments
    hasrole.setValue('inherited', false);
    hasrole.setWorkflow(false); //do not trigger any further scripts for performance
    hasrole.updateMultiple(); //update all
}

function delete_roles() {
    var hasrole = new GlideRecord("sys_user_has_role");
    hasrole.addQuery('role.name', '!=', 'admin'); //exclude admin role just in case there is something wrong with the below query
    hasrole.addQuery('user.user_name', ''); //user_name is what we check for as is should be there for any user
    hasrole.addQuery('inherited', false); //only delete "non-inherited" role assignments as we can't delete the others 
    hasrole.setWorkflow(false); //do not trigger any further scripts for performance
    hasrole.deleteMultiple(); //delete all
}
Comments
Jon G1
Kilo Sage

Very useful - bookmarked as I have a feeling I may need this later.  Thanks for posting!

Version history
Last update:
‎08-02-2021 11:36 PM
Updated by: