Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Help with Deny Unless ACL to hide attachments

Marcel H_
Tera Guru

I am having some trouble getting a Deny Unless ACL working to hide attachments in the header of records on a specific table.

 

I have a table named u_contacts that already has ACLs to restrict visibility of records based on group membership using the following script:

answer = false;

var groupList = current.u_share_with_group.toString();

var group = new GlideRecord("sys_user_group");
group.addQuery("sys_idIN" + groupList);
group.query();

while (group.next()) {
    if (gs.getUser().isMemberOf(group.name.toString())) {
        answer = true;
    }
}

 

This is working as expected in an Allow If ACL, however what I need to do it hide any attachments on the record as well if this ACL fails. I had no luck using various Allow If configurations, and was only able to hide attachments by putting a Deny Unless ACL on the sys_attachment table.

 

This hides read for all attachments system wide though, and I can't seem to figure out the best way to target attachments only on the u_contacts table.

 

I think that what I need to do is the following, but can't seem to get it working quite right:

Table = sys_attachment

User has role snc_internal

Applies to attachments with table_name = u_contacts

User is a member of a group listed in the u_share_with_group field on the current record on u_contacts

 

2 ACCEPTED SOLUTIONS

Marcel H_
Tera Guru

I was able to get this working with the following script in a Deny Unless ACL

// Default to deny access
answer = false;

if (
    current.getValue('table_name') === 'u_contacts' ) 
{
    // Get the sys_id of the parent record
    var parentSysId = current.getValue('table_sys_id');

    // Query the parent table to get the group list
    var parentRecord = new GlideRecord(current.getValue('table_name'));
    if (parentRecord.get(parentSysId)) {
        var groupList = parentRecord.u_share_with_group.toString();

        // Check if groupList has any values
        if (groupList) {
            // Retrieve the user's group membership
            var userGroupIds = [];
            var userGroups = new GlideRecord('sys_user_grmember');
            userGroups.addQuery('user', gs.getUserID());
            userGroups.query();

            while (userGroups.next()) {
                userGroupIds.push(userGroups.group.toString());
            }

            // Check if the user is a member of any of the required groups
            var requiredGroups = groupList.split(',');
            for (var i = 0; i < requiredGroups.length; i++) {
                if (userGroupIds.includes(requiredGroups[i])) {
                    answer = true; // Allow access
                    break;
                }
            }
        }
    }
} else {
    // Allow attachments on other tables
    answer = true;
}

View solution in original post

Hi @Marcel H_ - This might be more efficient...

// Default to deny access
answer = false;

if (current.getValue('table_name') === 'u_contacts') {
    // Get the sys_id of the parent record
    var parentSysId = current.getValue('table_sys_id');

    // Query the parent table to get the group list
    var parentRecord = new GlideRecord('u_contacts');
    if (parentRecord.get(parentSysId)) {
        var groupList = parentRecord.u_share_with_group.toString();

        if (groupList) {
            // Query user groups and check for membership
            var userGroups = new GlideRecord('sys_user_grmember');
            userGroups.addQuery('user', gs.getUserID());
            userGroups.addQuery('group.sys_id', 'IN', groupList); // Filter directly by required groups
            userGroups.query();

            // If any match is found, allow access
            if (userGroups.hasNext()) {
                answer = true;
            }
        }
    }
} else {
    // Allow attachments on other tables
    answer = true;
}

Instead of collecting the user's group memberships into an array and comparing manually, the addQuery('group.sys_id', 'IN', groupList) directly filters user groups against the u_share_with_group values.

View solution in original post

2 REPLIES 2

Marcel H_
Tera Guru

I was able to get this working with the following script in a Deny Unless ACL

// Default to deny access
answer = false;

if (
    current.getValue('table_name') === 'u_contacts' ) 
{
    // Get the sys_id of the parent record
    var parentSysId = current.getValue('table_sys_id');

    // Query the parent table to get the group list
    var parentRecord = new GlideRecord(current.getValue('table_name'));
    if (parentRecord.get(parentSysId)) {
        var groupList = parentRecord.u_share_with_group.toString();

        // Check if groupList has any values
        if (groupList) {
            // Retrieve the user's group membership
            var userGroupIds = [];
            var userGroups = new GlideRecord('sys_user_grmember');
            userGroups.addQuery('user', gs.getUserID());
            userGroups.query();

            while (userGroups.next()) {
                userGroupIds.push(userGroups.group.toString());
            }

            // Check if the user is a member of any of the required groups
            var requiredGroups = groupList.split(',');
            for (var i = 0; i < requiredGroups.length; i++) {
                if (userGroupIds.includes(requiredGroups[i])) {
                    answer = true; // Allow access
                    break;
                }
            }
        }
    }
} else {
    // Allow attachments on other tables
    answer = true;
}

Hi @Marcel H_ - This might be more efficient...

// Default to deny access
answer = false;

if (current.getValue('table_name') === 'u_contacts') {
    // Get the sys_id of the parent record
    var parentSysId = current.getValue('table_sys_id');

    // Query the parent table to get the group list
    var parentRecord = new GlideRecord('u_contacts');
    if (parentRecord.get(parentSysId)) {
        var groupList = parentRecord.u_share_with_group.toString();

        if (groupList) {
            // Query user groups and check for membership
            var userGroups = new GlideRecord('sys_user_grmember');
            userGroups.addQuery('user', gs.getUserID());
            userGroups.addQuery('group.sys_id', 'IN', groupList); // Filter directly by required groups
            userGroups.query();

            // If any match is found, allow access
            if (userGroups.hasNext()) {
                answer = true;
            }
        }
    }
} else {
    // Allow attachments on other tables
    answer = true;
}

Instead of collecting the user's group memberships into an array and comparing manually, the addQuery('group.sys_id', 'IN', groupList) directly filters user groups against the u_share_with_group values.