Restrict @mention to users with read access to record

Michael T
Tera Contributor

My client would like to limit who can be @mentioned on a ticket platform wide to only people with read access to the ticket. I created a Before Query business rule on the User table based on another community post - this business rule does work to limit @mention to users with the hr admin role, however I want to see if we can limit to users with read access to the record instead. Advice on how to modify business rule or a different approach would be appreciated! Thanks

 

(function executeRule(current, previous /*null when async*/ ) {
    try {
        if (gs.action.getGlideURI() != '') {
            if (gs.action.getGlideURI().getMap() != '') {
                if (gs.action.getGlideURI().toString().startsWith('api/now/form/mention/record/')) {
                    current.addEncodedQuery('roles=sn_hr_core.admin');
                    current.addActiveQuery();
					gs.addInfoMessage(current); // Returns "sys_user"
                }
            }
        }
    } catch (errObj) {
        gs.error('Global_Set_Filter_Mention-' + errObj);
    }
})(current, previous);

If we have a method to prevent any @mention from additional comments that would be +1 as the client is wondering this as well

10 REPLIES 10

jMarshal
Mega Sage
Mega Sage

You can use the ".canRead()" method.

I'm not very familiar with GlideURI methods, but after returning the sys user record, you can easily check that record with user.canRead() to return t/f if they can read the record in question.

https://developer.servicenow.com/dev.do#!/reference/api/tokyo/server/no-namespace/c_GlideElementScop...

Unfortunately we aren't returning a user record that is usable, the query business rule seems to be querying the whole table when it appears, see the snippet below

					gs.addInfoMessage(current); // Returns "sys_user"

yea, you need a while/next loop after the query to iterate the individual user results returned by the glideURI and check/try/test them against canread();

Something like this (not tested code, treat as pseudo code):

(function executeRule(current, previous /*null when async*/ ) {
    try {
        if (gs.action.getGlideURI() != '') {
            if (gs.action.getGlideURI().getMap() != '') {
                if (gs.action.getGlideURI().toString().startsWith('api/now/form/mention/record/')) {
                    //current.addEncodedQuery('roles=sn_hr_core.admin'); // unless you also need them to have that role...
                    current.addActiveQuery();
                    gs.addInfoMessage(current); // Returns "sys_user"


                    current.query();

                    while (current.next()) {

                        if (current.canRead()) {

                            var message = current + "can read this record";
                            gs.addInfoMessage(message);

                        }

                    }

                }
            }
        }
    } catch (errObj) {
        gs.error('Global_Set_Filter_Mention-' + errObj);
    }
})(current, previous);



So I think this is getting me close, when I @mention "Tester" it pulls up 2 test users but my infomessage shows them both having read access, I tried impersonating using some syntax I found in an OOB I think we need to impersonate these users because I read that canRead() only works with the logged in user, and when I implemented the impersonation it locks me out of my instance and I have to manually logout, would you know where I should reverse the impersonation if that is possible? Thanks for all the good tips

MichaelT_0-1699045883279.pngMichaelT_1-1699045907333.png

(function executeRule(current, previous /*null when async*/ ) {
    try {
        if (gs.action.getGlideURI() != '') {
            if (gs.action.getGlideURI().getMap() != '') {
                if (gs.action.getGlideURI().toString().startsWith('api/now/form/mention/record/')) {
                    //current.addEncodedQuery('roles=sn_hr_core.admin'); // unless you also need them to have that role...
                    current.addActiveQuery();
                    current.query();

                    while (current.next()) {
//                         var session = GlideSession.get();
// 						session.impersonate(current);
                        if (current.canRead()) {

                            var message = current.name + "can read this record";
                            gs.addInfoMessage(message);
                        }
                    }
                }
            }
        }
    } catch (errObj) {
        gs.error('Global_Set_Filter_Mention-' + errObj);
    }
})(current, previous);