logo

NJP

User Criteria on Any table.. Including Custom Tables

Import · Feb 05, 2019 · article

User criteria is one of the wonderful features SN provided, but it is opened to only a set of tables. It is a handy configuration to grant access to the record against user information like companies, roles, groups.

Recently there was a requirement where we need to grant read access to records dynamically. After a little research, I found out that there are similar needs by many developers. Below are some of scenarios that I came across

  • Catalogs
  • News
  • Announcements(Fixed in London)

Here is what I had implemented

1. Create a m2m relation between User Criteria and desired table (u_news). Navigate to sys_m2m.LIST and submit the details as shown in the screenshot

image

image

2. Add the user criteria related list to News form by Configure > Related Lists

image

3. Create a script include

Name: UserCriteria

Client callable: False

Script

var UserCriteria = Class.create();
UserCriteria.prototype = {
    initialize: function() {
    },


    canAccess: function(table, record, id){

        //Get all the user criteria's for the seleted record
        var usr_crit = new GlideRecord(table);
        usr_crit.addQuery(record, id);
        usr_crit.query();

        // Grant access to record If there are no user criteria's for the record
        if(usr_crit.getRowCount() == 0)
            return true;

        while (usr_crit.next()) {

            var crit = new GlideRecord('user_criteria');
            crit.addQuery('sys_id', usr_crit.u_user_criteria);
            crit.addActiveQuery();
            crit.query();

            while(crit.next()){

                //Get company, location and department information of the current user. 
                var gr = new GlideRecord('sys_user');
                gr.addQuery('sys_id', gs.getUserID());
                gr.query();

                var company, location, department = '';

                if(gr.next()){

                    company = gr.company;
                    location = gr.location;
                    department = gr.department;
                }

                var groups = [];
                groups = crit.group.toString();

                var evaluator = new GlideScopedEvaluator();

                var match_arr = [];

                // Check if the current user is one of the users in user criteria
                if(crit.user != ''){

                    if(crit.user.indexOf(gs.getUserID()) > -1)
                        match_arr.push(true);
                    else
                        match_arr.push(false);
                }

                // Check if the Groups of a user belong to is one of groups in user criteria
                if(crit.group!= ''){
                    match_arr.push(this._isMyGroup(groups));
                }


                // Check if logged in user roles is one of roles in user criteria
                if(crit.role != ''){
                    match_arr.push(gs.hasRole(crit.role.getDisplayValue()));
                }

                // Check if the logged in user company is one of companies in user criteria
                if(crit.company != '' && company != ''){

                    if(crit.company.indexOf(company) > -1)
                        match_arr.push(true);
                    else
                        match_arr.push(false);
                }

                // Check if the logged in user location is one of locations in user criteria
                if(crit.location != '' && location != ''){
                    if(crit.location.indexOf(location) > -1)
                        match_arr.push(true);
                    else
                        match_arr.push(false);
                }

                // Check if the logged in user department is one of departments in user criteria
                if(crit.department != '' && department != ''){
                    if(crit.department.indexOf(department) > -1)
                        match_arr.push(true);
                    else
                        match_arr.push(false);
                }

                //execute the script in user criteria
                if(crit.advanced == true){
                    match_arr.push(evaluator.evaluateScript(crit, 'script', ''));
                }


                var matched;

                //If Match all, in user criteria is marked false, then any one of fields match is enough
                if(crit.match_all == false){

                    if(match_arr.indexOf(true) > -1)
                        matched = true;
                    else
                        matched = false;
                }

                // If Match all is marked true then all of the values should be true
                else{
                    if(match_arr.every(this._isValueTrue) == true)
                        matched = true;
                    else
                        matched = false;
                }

                // Matching one of the user criteria should return the value. No need to execute the rest of the user criteria
                if(matched == true){
                    return true;
                }

            }
        }
        // If none of the user criteria matches then return false
        return false;

    },

    _isMyGroup: function(groupIDs){

        var groups_arr = groupIDs.split(',');

        for(i=0; i<groups_arr.length; i++){
            if(gs.getUser().isMemberOf(groups_arr[i]))
                return true;
        }
        return false;
    },

    // Function to verify if all the values in an array are true
    _isValueTrue: function (currentValue) {
        return currentValue == true;
    },

    type: 'UserCriteria'
};

4. Create a read acl to restrict read access to the record and use the below script

answer = new UserCriteria().canAccess('u_m2m_news_user_criteria', 'u_news', current.sys_id);

/* canAccess menthod accepts the following input paramenters
table: M2M table name
record: Field name of News reference field on M2M table
id: sys_id of news record
*/

5. Use GlideRecordSecure for reference qualifers and glide queries, as GlideRecordSecure enforce read ACL rules.

Hope this helps!!

View original source

https://www.servicenow.com/community/in-other-news/user-criteria-on-any-table-including-custom-tables/ba-p/2276859