Single Click Impersonation Return

/, UI scripts/Single Click Impersonation Return

Single Click Impersonation Return

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!

One-Click Unimpersonate Button

This solution leverages some ideas I presented in a previous post about impersonating users from any record in the system. Check it out if you’re interested in other nice ways to make the user-impersonation process more useful and convenient.

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.

‘AddUnimpersonate Button’ UI script
Name: AddUnimpersonate Button
Global: True
Description: Add a button during user impersonations to allow one-click return to original session.
Script:

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(
                '<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;
}
By | 2018-07-09T14:59:58-06:00 July 18th, 2011|Categories: System Definition, UI scripts|Tags: , |36 Comments

About the Author:

36 Comments

  1. Jérôme Lambercy July 18, 2011 at 8:46 am - Reply

    Coolest feature ever!

  2. Bill Collins July 18, 2011 at 11:16 am - Reply

    Awesome! Thank you again.

  3. Konstantin July 19, 2011 at 3:07 am - Reply

    Greate feature! Thanks!

  4. Jay Ford July 19, 2011 at 7:58 am - Reply

    Nice one Mark!

    I also combined this article with the download attachments to zip (http://www.servicenowguru.com/scripting/download-attachments-zip-file/) article to make a nice paperclip with a download arrow button on my forms for downloading all attachments.

    • Mark Stanger July 19, 2011 at 9:59 am - Reply

      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.

      • Jay Ford July 19, 2011 at 2:17 pm - Reply

        I have a UI Script ‘addDownloadAll Button’

        addLoadEvent(addDownloadAll);

        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.

        var hasAttachmentsAjax = Class.create();

        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.

        • Mark Stanger July 19, 2011 at 2:20 pm - Reply

          Nice. Thanks for sharing!

  5. Richard Glover July 19, 2011 at 3:00 pm - Reply

    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.

    • Mark Stanger July 19, 2011 at 3:11 pm - Reply

      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!

  6. Russell Miller July 19, 2011 at 8:12 pm - Reply

    Fantastic, saves me a truckload of clicks!

  7. Bill Collins July 20, 2011 at 1:32 pm - Reply

    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.

    • Mark Stanger July 20, 2011 at 1:34 pm - Reply

      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.

  8. quik July 26, 2011 at 4:31 am - Reply

    Great Tip as always

  9. Drew August 16, 2011 at 6:26 am - Reply

    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?

    • Mark Stanger August 16, 2011 at 6:50 am - Reply

      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.

      • Drew August 16, 2011 at 6:59 am - Reply

        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.

  10. Joe August 17, 2011 at 12:19 pm - Reply

    Wow, awesome, thank you!

  11. Dennis September 20, 2011 at 11:05 am - Reply

    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?

    • Mark Stanger September 20, 2011 at 3:17 pm - Reply

      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.

  12. Peter October 27, 2011 at 4:27 am - Reply

    Just implemented this feature as I’m doing some testing. This is an absolute Godsend. It’s brilliant.
    Keep up the good work!

    • Mark Stanger October 27, 2011 at 5:34 am - Reply

      Thanks! It was a great idea for sure.

  13. Andreas October 25, 2012 at 5:15 pm - Reply

    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”:

    addLoadEvent(hideLanguageBar);

    function hideLanguageBar() {
       if(gel('language') != null &amp;&amp; !g_user.hasRoles()){
          gel('select_decorations').style.display = 'inline';
          gel('language').style.display = 'none';
          gel('language').style.visibility = '';
       }
    }
    • Mark Stanger October 25, 2012 at 10:08 pm - Reply

      I think the problem is that your script is failing and causing other client-side javascript to fail. Try this instead.

      addLoadEvent(hideLanguageBar);

      function hideLanguageBar() {
         if(!g_user.hasRoles()){
            try{
               $('language').hide();
            }catch(e){}
         }
      }
      • Andreas December 4, 2012 at 3:57 pm - Reply

        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:

        addLoadEvent(hideLanguageBar);

        function hideLanguageBar() {
           try {
              if($('language') != null && !g_user.hasRoles()){
                 $('select_decorations').style.display = 'inline';
                 $('language').style.display = 'none';
                 $('language').style.visibility = '';
              }
           } catch (e) {}
        }
  14. MARK BAILEY February 7, 2014 at 7:18 pm - Reply

    Simply one of the best cut and paste scripts I have found. I love this.

  15. Tim Black February 25, 2014 at 2:13 pm - Reply

    It’s the little things that matter. This feature is priceless!

  16. Andreas September 15, 2014 at 8:57 am - Reply

    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:

    after: '<span id="unimpersonate_span"><span class="icon-power" style="cursor:pointer;cursor:hand; font-size: 22px;" title="${gs.getMessage('End impersonation')}" onclick="unimpersonateMe();" /></span>'
    • Mark Stanger September 15, 2014 at 9:35 am - Reply

      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.

  17. Chris Murphy January 13, 2015 at 10:18 am - Reply

    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.

    • Mark Stanger April 21, 2015 at 6:05 am - Reply

      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.

  18. Brandon Grimes March 23, 2015 at 1:32 pm - Reply

    Hey Mark,

    I noticed that this breaks for me on Fuji. I’ve attempted to adjust the code for a ‘Fuji Friendly’ version.

    addLoadEvent(addUnimpersonateButton);

    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;
    }
  19. Christina Peters December 9, 2015 at 5:53 am - Reply

    Has anybody tried to add this to the new UI16 in Geneva?

    • Mark Stanger December 9, 2015 at 9:01 am - Reply

      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.

      • Christina Peters December 11, 2015 at 1:29 am - Reply

        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.

Leave A Comment