Having issue with Query business rule on Knowledge Article table

Musab Rasheed
Tera Sage
Tera Sage

Hello Experts,

I have a requirement to show knowledge articles to users who are satisfying can read and cannot read criteria , I'm doing this to get rid of 'Security constraints' message which is annoying to customers, I have written query business rule to query can read and cannot read fields but it is not working 100%. kindly help to identify issue here. Below is the code.

I have considered below scenarios to write this BR.

1) Can Read , Cannot read - Empty.

2) Can Read - Empty , Cannot read - Not empty.

3) Can read - Not empty , Cannot read - Empty.

4) Can Read - Not empty , Cannot read - Not empty.

 

(function executeRule(current, previous /*null when async*/ ) {

var allUserCriteria = SNC.UserCriteriaLoader.getAllUserCriteria();

//Can read not empty
var canReadQuery = allUserCriteria.join('^ORcan_read_user_criteriaLIKE');
canReadQuery = 'can_read_user_criteriaLIKE' + canReadQuery;

//Cannot read not empty
var cann = allUserCriteria.join('^cannot_read_user_criteriaNOT LIKE');
cann = 'cannot_read_user_criteriaNOT LIKE' + cann;

var canempty = 'can_read_user_criteriaISEMPTY';
var cannottempty = 'can_read_user_criteriaISNOTEMPTY';
var cannotempty = 'cannot_read_user_criteriaISEMPTY';
var cannotnotempty = 'cannot_read_user_criteriaISNOTEMPTY';

var gr1 = canempty + '^' + cannotempty;
var gr2 = canempty + '^' + cannotnotempty + '^' + cann;
var gr3 = cannotempty + '^' + cannottempty + '^' + canReadQuery;
var gr4 = cannottempty + '^' + cannotnotempty + '^' + canReadQuery + '^' + cann;

var err = gr1 + '^NQ' + gr2 + '^NQ' + gr3 + '^NQ' + gr4;

current.addEncodedQuery(err);

})(current, previous);

Please hit like and mark my response as correct if that helps
Regards,
Musab
1 ACCEPTED SOLUTION

Disclaimer: An ACL is definitely the recommended way to do this! The method below could be very inefficient depending on the number of records in your kb_knowledge table.

If I'm understanding correctly, you just need to query based on the sys_ids in the kb_knowledge table that the current user can read, right? You should be able to leverage the GlideRecord.canRead() function here. Get all articles, then iterate them and return the sys_ids of the ones where kb.canRead() is true.

(function executeRule(current, previous) {
  var allowedIds = [];

  var kb = new GlideRecord('kb_knowledge');

  kb.query();

  while (kb.next()) {
    if (kb.canRead()) {
      allowedIds.push(kb.getUniqueValue());
    }
  }

  current.addEncodedQuery('sys_idIN' + allowedIds);
})(current, previous);

View solution in original post

13 REPLIES 13

Disclaimer: An ACL is definitely the recommended way to do this! The method below could be very inefficient depending on the number of records in your kb_knowledge table.

If I'm understanding correctly, you just need to query based on the sys_ids in the kb_knowledge table that the current user can read, right? You should be able to leverage the GlideRecord.canRead() function here. Get all articles, then iterate them and return the sys_ids of the ones where kb.canRead() is true.

(function executeRule(current, previous) {
  var allowedIds = [];

  var kb = new GlideRecord('kb_knowledge');

  kb.query();

  while (kb.next()) {
    if (kb.canRead()) {
      allowedIds.push(kb.getUniqueValue());
    }
  }

  current.addEncodedQuery('sys_idIN' + allowedIds);
})(current, previous);

Hello @david.arbour ,

 

Thanks for this, basically this will work only for Can read but it will not work for 'cannot read', as of now it is still showing security message as above code is not doing anything to filter 'cannot read' criteria records.

 

Example : If user satisfies 'can read' as well as 'cannot read' so in this case record should not be displayed hence I'm still seeing 'security constraint' message. Please help.

Please hit like and mark my response as correct if that helps
Regards,
Musab

You have to disable the ACL that's causing the security constraint message. If you have a query Business Rule in place, that will handle the filtering of records so you can disable the ACL. If you ONLY pass in the sys_ids that the user can read, those that the user cannot read will not be included in the query. Now you may already have a default query that we're only adding to with this Business Rule. To find out what your query is after the Business Rule is applied, just add a logging statement to the end of the script. This should log the query you are sending to the database to retrieve your records.

(function executeRule(current, previous) {
  var allowedIds = [];

  var kb = new GlideRecord('kb_knowledge');

  kb.query();

  while (kb.next()) {
    if (kb.canRead()) {
      allowedIds.push(kb.getUniqueValue());
    }
  }

  current.addEncodedQuery('sys_idIN' + allowedIds);

  gs.log('Testing query Business Rule: ' + current.getEncodedQuery());
})(current, previous);

@David Arbour : Looks like your solution is working fine but I have one doubt, Can we make BR runs only on one condition like 'kb.addEncodedQuery('sys_class_name!=kb_knowledge_block^kb_knowledge_base=bb0370019f22120047a2d126c42e7073^workflow_state=published');...? I tried adding this in code as well as in Conditions tab it is showing articles matching that conditions even if user clicks on All articles.? Can this be done or I have to control using roles like in below screenshot.?

 

find_real_file.png

Please hit like and mark my response as correct if that helps
Regards,
Musab

Adding that encoded query should remove records that meet the query terms. What do you get when you call the logging statement in your scri

gs.log('Testing query Business Rule: ' + current.getEncodedQuery());