I
noticed an enhancement request from Matt Beran on Twitter over the weekend. The enhancement request was for an easier way to end a user impersonation session. Currently, you have to click the impersonation icon, wait for the dialog to appear, and select your original account to end an impersonation session. While this might not be a huge issue for some people, it can get kind of old if you’re trying to quickly do a lot of testing or troubleshooting that requires frequent user impersonations. This post explains how you can create a UI script to add a button that will end impersonation and return you to your original session in a single click!
The simplest way to add this functionality is to create a clickable image that will end the user impersonation and add it to the page header. The challenge is to do this without hacking the out-of-box UI macro and breaking upgrades to the impersonate functionality in the future. Fortunately this can all be accomplished with the creation of a global UI script! Here’s how you can set it up.
Name: AddUnimpersonate Button
Global: True
Description: Add a button during user impersonations to allow one-click return to original session.
Script:
function addUnimpersonateButton(){
try{
//Show un-impersonate icon if a user is being impersonated
if($('impersonating_toggle_id').value != ''){
//Insert the clickable icon in the dom
$('impersonate_span').insert(
'<span id="unimpersonate_span" class="icon-power" style="padding-left:5px; cursor:pointer;cursor:hand; font-size: 20px; visibility: visible" title="End impersonation" onclick="unimpersonateMe();" />'
);
}
}catch(e){}
}
function unimpersonateMe(){
//Return the user to their original session
top.location.href = 'ui_page_process.do?sys_id=b071b5dc0a0a0a7900846d21db8e4db6&sys_user='+ $('impersonating_toggle_id').value;
}
Coolest feature ever!
Awesome! Thank you again.
Greate feature! Thanks!
Nice one Mark!
I also combined this article with the download attachments to zip (https://servicenowguru.wpengine.com/scripting/download-attachments-zip-file/) article to make a nice paperclip with a download arrow button on my forms for downloading all attachments.
Nice. I assume you’re also doing some sort of check to see whether or not the document has attachments? If you shoot me the instructions I can post it here if you want.
I have a UI Script ‘addDownloadAll Button’
function addDownloadAll(){
var rec = checkAtt(g_form.getTableName(),g_form.getUniqueValue());
try{
if(rec == 'true'){
$('header_add_attachment').insert({ before: '<a id="download_all_attachments"><img onclick="downloadAll();" title="Download attachments to ZIP" src="download_attachment.gifx" height="16px" width="16px" style="cursor:pointer;cursor:hand"></img></a>'});
}
}
catch(e){}
}
function downloadAll(){
//Return the user to their original session
var record = g_form.getUniqueValue();
var table = g_form.getTableName();
top.location.href = 'exportAttachmentsToZip.do?sysparm_sys_id=' + record + '&sysparm_table=' + table;
}
function checkAtt(table,sys_id) {
var ga = new GlideAjax('hasAttachmentsAjax');
ga.addParam('sysparm_name','hasatt');
ga.addParam('sysparm_table',table);
ga.addParam('sysparm_sys_id',sys_id);
ga.getXMLWait();
return ga.getAnswer();
}
and I have a client callable script include ‘hasAttachmentsAjax’ that checks for attachments.
hasAttachmentsAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
ajaxFunction_hasatt: function() {
var tblID = this.getParameter('sysparm_table');
var sysID = this.getParameter('sysparm_sys_id');
var rec = new GlideRecord(tblID);
rec.get(sysID);
var ans = rec.hasAttachments();
return ans;}
});
I also created an icon and uploaded it. It’s a paperclip with a green down arrow on it.
Nice. Thanks for sharing!
Kewl stuff. Thanks so much.
On my instance the syntax checker reported an extra semi colon on one of the lines:
}catch(e){};
I took it out and the button worked perfectly. I did change it to show the button after the key because I’m a tad OCD and didn’t want the key to move positions on the page. It just seemed more natural that the new button add to the right instead of shifting the key.
I think we’re kindred spirits in the OCD department :). I missed that one though. I’ve updated the instructions above to match what you did. Thanks!
Fantastic, saves me a truckload of clicks!
Can the dialog_imp_user be modified to add attributes to the user? (really don’t want to do. will also open product enhancement request). In a system with many duplicate names, the sys_popup after selection is not the most efficient. I would be great to see items like company, location, department after the name of the user you are searching to impersonate.
I think it probably could, but I don’t have a solution for that at the moment. Best to open the enhancement request for that one.
Great Tip as always
I like this, added it to my instance, but I have one question. Is there a reason you went with a UI Script rather than a UI Macro?
Good question. A UI macro solution would work just fine too. The reason I went with the UI script is that it is less intrusive. With a UI macro, I would have had to modify an out-of-box UI macro to include the macro code in the header bar. That, of course, would break upgrades to that particular macro. With the UI script I get the same result but there were no modifications needed to out-of-box code.
Ok so you did it for the reason that I thought. I was using this as an example to add an icon to switch from UI11 to the old UI and back again based on a role. But I had to make it a UI Macro because I kept getting a script error saying that “g_user” was not defined so I just concluded that the object had not been created yet.
Wow, awesome, thank you!
I must be doing something wrong as I tried to create a new UI Scrpit called AddUnimpersonate Button and here is the syntax I used:
addLoadEvent(addUnimpersonateButton);
function addUnimpersonateButton(){
try{
//Show un-impersonate icon if a user is being impersonated
if($(‘impersonating_toggle_id’).value != ”){
//Insert the clickable icon in the dom
$(‘impersonate_span’).insert({
after: ”
});
}
}catch(e){}
}
function unimpersonateMe(){
//Return the user to their original session
top.location.href = ‘ui_page_process.do?sys_id=b071b5dc0a0a0a7900846d21db8e4db6&sys_user=’+ $(‘impersonating_toggle_id’).value;
}
Here is the error message I get when trying to check syntax:
Error:
Problem at line 4 character 1: Expected an identifier and instead saw ‘&’.
try{
What am I doing wrong?
Might be a copy/paste issue. If you’re using the syntax highlighter you’ll want to click the button to turn that off when you paste any code into it.
Just implemented this feature as I’m doing some testing. This is an absolute Godsend. It’s brilliant.
Keep up the good work!
Thanks! It was a great idea for sure.
Hi,
since we upgraded to Berlin we have the issue that the language picker is displayed for all users – even ESS.
After adding a global UI Script the language picker is no longer displayed for ESS users. Problem solved.
BUT when it is displayed (e.g. for ITIL users) the unimpersonation icon is no longer available.
Looking at the HTML source, it looks like the unimpersonisation icon code is not even added to the DOM. Any idea?
This is our UI Script “Control Language Picker”:
function hideLanguageBar() {
if(gel('language') != null && !g_user.hasRoles()){
gel('select_decorations').style.display = 'inline';
gel('language').style.display = 'none';
gel('language').style.visibility = '';
}
}
I think the problem is that your script is failing and causing other client-side javascript to fail. Try this instead.
function hideLanguageBar() {
if(!g_user.hasRoles()){
try{
$('language').hide();
}catch(e){}
}
}
Unfortunately it doesn’t change anything and it hides even more: of the main iframe only the header (“Add content”, “ITIL homepage” etc.) and footer (“delete page”) portion is left – no gauges are loaded.
What did the trick for me was wrapping the content of my function into try{} catch{}. Now it looks like this:
function hideLanguageBar() {
try {
if($('language') != null && !g_user.hasRoles()){
$('select_decorations').style.display = 'inline';
$('language').style.display = 'none';
$('language').style.visibility = '';
}
} catch (e) {}
}
Simply one of the best cut and paste scripts I have found. I love this.
Thanks Mark! I’m glad you found it useful.
It’s the little things that matter. This feature is priceless!
Hi,
since UI14 the stoip-sign-icon does no longer match the UI.
This little tweak uses the “power”-icon and allows for translation of “End impersonation”. Simply replace the content of line 9 in the script with the following:
Thanks Andreas! This is a good change, and one that I think I’ll incorporate into the code in the article once we get more people on the Eureka instance. One note about translation (gs.getMessage) though, is that I don’t think that will work because this is a UI script rather than a jelly-based UI macro or UI page.
This is amazing! I love it and it works so well. I have a question for you though. Is there any way to have this added to a fully customized ESS page? Our non-ITIL users don’t have access to the menu bar where this button resides. When we impersonate them, we have to log out and back in to end the impersonation. It would be nice to have it appear in the custom header we created.
Hey Chris, it was good seeing you at K15! I looked into this some more this morning and I’m able to get the icon to show consistently in the ESS. Unfortunately, ServiceNow gives us absolutely no way of knowing in the ESS whether a user is being impersonated or not. Because of that, it will show for ALL users rather than just admins or the user impersonating and there’s no way to get back to the impersonating user because the ESS doesn’t store it anywhere. Unfortunately, I don’t see any way around this other than what you’re doing already.
Hey Mark,
I noticed that this breaks for me on Fuji. I’ve attempted to adjust the code for a ‘Fuji Friendly’ version.
function addUnimpersonateButton(){
try{
//Show un-impersonate icon if a user is being impersonated
if($('impersonating_toggle_id').value != ''){
//create html string
var htmlString = '<span id="unimpersonate_span" style="visibility:visible; display:inline-block; zoom:1; vertical-align:middle;"><span data-placement="bottom" data-container="body" tabindex="0" class="icon-power sn-tooltip-basic" style="cursor:pointer; font-size:20px;" title="End impersonation" onclick="unimpersonateMe();"><span class="sr-only">End impersonation</span></span>'
//Insert the clickable icon in the dom
$('impersonate_span').insert({
after: htmlString
});
}
}catch(e){}
}
function unimpersonateMe(){
//Return the user to their original session
top.location.href = 'ui_page_process.do?sys_id=b071b5dc0a0a0a7900846d21db8e4db6&sys_user='+ $('impersonating_toggle_id').value;
}
Nice. Thanks for sharing Brandon!
Has anybody tried to add this to the new UI16 in Geneva?
I’ve looked at this and unfortunately ServiceNow has removed any of the hooks that allowed us to do this. If you want to see this in Geneva and onwards I suggest you contact ServiceNow and log an enhancement request.
Thank you Mark for your answer.
I raised an enhancement request. But it would be great if some others could also raise one. Because my other enhancement requests are open now for over a year and nothing happens.