0

Read before upgrading your plugins to version 11.0.3 – “GRC Business Users” 0 (0)

Hello all,

I was trying to search for comments or posts around this plugin upgrade version (11.0.3) but it seems it did slipper somehow.

ServiceNow introduced the new role “GRC Business User” in the latest release (11.0.3) and added to all users in the system. Yes, there is no way to stop that to happen (I raised a hi ticket) but there is a KB article that explains the reason behind this change and helps you to rollback this change in case: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0864247

GRC Business Users

The Governance, Risk, and Compliance (GRC) product line requires action from many users who do not have a traditional product role, such as Compliance Reader or Risk Reader.  Even the reader roles allow access to the product module, dashboard, reports, and read-only table access.

To improve the internal security of the product, we created a dedicated GRC Business User role.  This role should be assigned to users who require access only to GRC applications in the context of performing tasks assigned to them; for example, a business user who needs to respond to an attestation or risk assessment.  Users with the GRC Business User role are provided limited access to data and to information relevant to the tasks assigned to them. 

The number of users assigned to the GRC Business User role does not impact product licensing.  Product licensing is based on the number of users that perform GRC operations as opposed to the number of users with a role that allows access to GRC operations.

Important note: To keep the product behavior consistent on upgrade, we initially assign the GRC Business User role to all users in the sys_user table by adding them to the GRC Business Users group.  We do this to match the previous product behavior that tasks such as attestations can be assigned to any internal employee.  You can remove users from the GRC Business User role to restrict access for specific users.

I have improved ootb script to be more defensive and used an on demand schedule job to avoid to get the process hang during execution. That way the process would not be associated to an UI session and would run in the background without interruptions. 

Please use below script to delete all users from GRC Business Users group :

Steps:

1. Create a fix script called “Remove GRC Business User to all users”
Application: 
GRC: Profile
Script:

var rec = new GlideRecord('sysauto_script');
rec.get('name', 'remove_users_to_grc_business_group');
gs.executeNow(rec);

2. Create a Scheduled Execution Job (sysauto_script) called “remove_users_to_grc_business_group

Application: GRC: Profile

Run as: Administrator

Run: On Demand

Script:

var grGroup = new GlideRecord('sys_user_group');
if (grGroup.get('053cd11a5bda50106d8012300a81c721')) // ensure the group exists and we do not skip the addQuery condition
{
	var grMember = new GlideRecord('sys_user_grmember');
	grMember.addQuery('group', '053cd11a5bda50106d8012300a81c721');
	grMember.query();
	gs.info("KB0864247 - There are " + grMember.getRowCount() + " members of the GRC Business Users group");
	while(grMember.next())
	{
		gs.info("KB0864247 - We are deleting user: " + grMember.user.getDisplayValue() + " - from the group: " + grMember.group.getDisplayValue());
		grMember.deleteRecord();
	}
}

3. Execute the fix script.

If you have any questions, please let me know! Happy GRCommanding 

0

How to recreate a Glide List using last icons 0 (0)

Hi,

Most recently I tried to use the glide list and apparently the “macro” available is using the old version. Gosh no.

In order to improve it, I have created the following UI macro.

Name: GlideList2

Description: This is an optimized Glide List   ready for bootstrap. It was based on old macro lightweight_glide_list and recent HTML code.

Code:

<?xml version="1.0" encoding="utf-8" ?>

<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">

<g:evaluate var="jvar_current_user" expression="gs.getUserDisplayName()" />

<g:evaluate var="jvar_current_user_id" expression="gs.getUserID()" />

<!-- start bootstrap --> 

   <button data-original-title="Edit ${jvar_label}" id="${jvar_control_name}_unlock" data-target="#glide\.${jvar_control_name}" data-placement="auto" title="" data-auto-close="false" style="margin-right: 5px; display: inline-block;" data-type="glide_list_unlock" tabindex="0" class="btn btn-default btn-ref" data-ref="${jvar_control_name}">

   <span aria-hidden="true" class="icon icon-locked"></span>

   <span class="sr-only">Edit ${jvar_label}</span>

   </button>

   <!-- start mode edit -->

   <span id="${jvar_control_name}_edit" style="display: none;">

     <div class="glide-list">

     <select id="select_0${jvar_control_name}" style="direction:ltr; ;" name="select_0${jvar_control_name}" onchange="toggleGlideListIcons('${jvar_control_name}', false);" class="form-control" multiple="yes" size="6"></select>

     <div class="button-column">

     <j:if test="${jvar_can_add_me}">

     <button data-original-title="Add me" id="add_me.${jvar_control_name}" title="" data-user-id="${jvar_current_user_id}" style="display: inline-block;" data-type="glide_list_add_me" class="btn btn-default btn-ref" data-user="${jvar_current_user}" data-ref="${jvar_control_name}">

     <span aria-hidden="true" class="icon-user-add icon"></span><span class="sr-only">${jvar_label} Add me</span>

     </button>

     </j:if>

     

     <button data-original-title="Remove selected item" disabled="" id="remove.${jvar_control_name}" class="btn btn-default btn-ref" title="" style="display: inline-block;" data-type="glide_list_remove" data-ref="${jvar_control_name}">

     <span aria-hidden="true" class="icon icon-cross"></span>

     <span class="sr-only">Remove selected item</span>

     </button>

     <button data-original-title="View selected item" disabled="" id="view2link.${jvar_control_name}" title="" onmouseout="lockPopup(event)" name="view2.${jvar_control_name}" tabindex="-1" onclick="glideListViewSelection('${jvar_control_name}','deapr_glide','sys_user', 'false')" class="btn btn-default btn-ref" type="button" onmouseover="glideListPopupSelection(event, '${jvar_control_name}', 'sys_user')"><span aria-hidden="true" class="icon-view icon"></span>

     <span class="sr-only">View selected item</span>

     </button>

     

     <button data-original-title="Lookup using list" id="lookup.${jvar_control_name}" onclick="reflistOpen( '${jvar_control_name}','select_0${jvar_control_name}','${jvar_table}','null', 'false', ''); mousePositionSave(event); event.stop();" class="btn btn-default btn-ref" title="" name="lookup.{{ref}}">

   <span aria-hidden="true" class="icon icon-search"></span><span class="sr-only">Lookup using list</span>

   </button>

     <button data-original-title="Lock" id="${jvar_control_name}_lock" title="" style="align: left; padding-top: 3px; cursor: pointer; display: none" data-type="glide_list_lock" tabindex="0" class="btn btn-default btn-ref" type="button" data-ref="${jvar_control_name}">

     <span aria-hidden="true" class="icon icon-unlocked"></span><span class="sr-only">Lock"</span>

     </button>

     </div>

     </div>

   </span>

<!-- finish edit -->

<p data-original-title="${jvar_label}" id="${jvar_control_name}_nonedit" class="form-control-static" title="" style="direction:ltr; display: inline-block; "></p>

<input mandatory="false" id="${jvar_control_name}" value="" name="${jvar_control_name}" type="HIDDEN" />

<!--

<input value="" id="sys_original.${jvar_control_name}" name="sys_original.${jvar_control_name}" type="HIDDEN" />

 -->

<!-- finish bootstrap -->

<!-- End List -->

</j:jelly>

On your UI page, you just need to invoke it.

<!-- List -->	
<j:set var="jvar_label" value="Users" />

<j:set var="jvar_control_name" value="zListCollectorUsers" />

<j:set var="jvar_can_add_me" value="true" />

<j:set var="jvar_table" value="sys_user" />

<g:macro_invoke macro="GlideList2" />
0

Customise your UI Action Button or Navigation Bar of your forms 0 (0)

This onLoad client script shows how to change the background color of form buttons in ServiceNow. For this example, I set up the script to change the color of the ‘Approve and ‘Reject’ buttons on the approval form to green and red respectively. The script itself is pretty straight-forward and can be used as a model for targeting other DOM elements using client-side JavaScript.

function onLoad() {
   //Change the color of the 'Approve' button to green
   changeButtonColor('approve', '#00CC00');
   //Change the color of the 'Reject' button to red
   changeButtonColor('reject', '#CC0000');
}

function changeButtonColor(buttonID, backgroundColor) {
   try{
      //Find the button(s) by ID and change the background color
      $$('button[id=' + buttonID + ']').each(function(elmt) {
         elmt.style.backgroundColor = backgroundColor;
         elmt.style.color = '#ffffff'; //make the button text white
      });
   }catch(e){}
}

If you want to take this step a little bit further, you can add icons to UI actions.
Fortunately, with the addition of a new icon set in recent ServiceNow releases, this has become pretty simple to do.

image

The following script can be used in any standard form client script. The key is the ‘transformButton’ function at the bottom. This could be included as a global UI script in your instance so that you don’t need to include it in every single client script. Once that’s in place (whether in a global UI script or in the client script itself) you can just call ‘transformButton’ with the appropriate parameters to change the button however you want. The parameters used are as follows…

  1. UI action name (Mandatory)
  2. Button background color (Optional)
  3. Button text color (Optional)
  4. Button icon name (Optional)
function onLoad() {
    //Change the color of the 'Approve' button to green
    transformButton('approve', '#77FF77', 'white', 'icon-success-circle');
    //Change the color of the 'Reject' button to red
    transformButton('reject', '#FF0022', 'white', 'icon-error-circle');
    //Change the color of the 'Info' button to blue
    transformButton('info_button', '#31708f', 'white', 'icon-info');
    //Change the color of the 'Warning' button to yellow
    transformButton('warning_button', '#f0ad4e', 'white', 'icon-warning-circle');
}

function transformButton(buttonID, buttonBackgroundColor, buttonTextColor, buttonIconName) {
    try{
        //Find the button(s) by ID and change the background color
        $$('button[id=' + buttonID + ']').each(function(elmt) {
            elmt.style.backgroundColor = buttonBackgroundColor;
            if(buttonTextColor){
                elmt.style.color = buttonTextColor;
            }
            if(buttonIconName){
                elmt.addClassName(buttonIconName);
                //Add some spacing between the icon and button label
                elmt.innerHTML = ' ' + elmt.innerHTML;
            }
        });
    }catch(e){}
}

This same idea can be applied to form header colors as well by getting the HTML element of the form. You’re probably aware that ServiceNow provides a global CSS property to set the form and list header color. The global property can be found by navigating to System Properties -> CSS, and changing the ‘Banner and list caption background-color property.

function onLoad() {
   //Change the color of all form section headers
   var backgroundColor = 'red';
   $$('.navbar').each(function(elmt) {
      elmt.style.backgroundColor = backgroundColor;
   });
}
 (All credits go to ServiceNowGuru for this awesome finding!)

[Updated 30/09/2019]

As you may notice, the UI action element names differ (top from bottom) and for this, you need to add them also – you can verify the names by getting the HTML element of the form. (tested in Madrid)

function onLoad() {

changeButtonColor('approve', 'limegreen', 'white'); //approve button header
changeButtonColor('reject', 'red', 'white'); //reject button header
changeButtonColor('approve_bottom', 'limegreen', 'white'); //approve button bottom
changeButtonColor('reject_bottom', 'red', 'white'); //reject button bottom
}

function transformButton(buttonID, buttonBackgroundColor, buttonTextColor, buttonIconName) {
    try{
        //Find the button(s) by ID and change the background color
        $$('button[id=' + buttonID + ']').each(function(elmt) {
            elmt.style.backgroundColor = buttonBackgroundColor;
            if(buttonTextColor){
                elmt.style.color = buttonTextColor;
            }
            if(buttonIconName){
                elmt.addClassName(buttonIconName);
                //Add some spacing between the icon and button label
                elmt.innerHTML = ' ' + elmt.innerHTML;
            }
        });
    }catch(e){}
}

You can now change the colour by picking a form style.

I hope this helps.