Why is next() returning false for non-admin users?

tmgarcia
Giga Contributor

Initially I thought this might be related to the user's issue in this thread, but as it's a fairly old and unanswered thread, I'll open this up here with my own specific use case details.

I have a very simple function inside a Script Include that I'm trying to call through a filter. Here's the code, without all the logging statements cluttering it.

getPinnedArticleIds: function() {

  var result = [];

  var kbGR = new GlideRecord("kb_knowledge_keyword");

  kbGR.query();

  while (kbGR.next()) {

            result.push(kbGR.getValue('knowledge'));

  }

  return result;

}

This I call through a filter on the kb_knowledge table (either through GlideRecord's addEncodedQuery or directly through the list view filter UI, both give the same results) using

"sys_idINjavascript: new SPKBHelper().getPinnedArticleIds();".

Essentially I'm just trying to grab the sys_ids of all "featured" articles in our instance. What's odd is that it works just fine when run as an admin, but when I'm trying to use it through a filter as a standard user (that is, a user without any special roles or groups) it returns no results, just an empty array. Additionally, when I've got all my logging set up (see below), just before I enter the loop, I find that getRowCount() is returning the expected number of articles, hasNext() is returning true, but next() returns false. So the query is definitely finding the records in the table, it just can't iterate through them, which is why nothing's being returned. My guess is this has something to do with security permissions, because by default a standard user doesn't have read access via the kb_knowledge_keyword ACL?

After going through a whole slew of other Community threads, I've also tried using _next() rather than next(), and have renamed my GlideRecord var to random absurd names, to avoid potential random conflict with other scripts. Unfortunately, neither of those have made a difference.

getPinnedArticleIds: function() {

  var result = [];

  var kbGR = new GlideRecord("kb_knowledge_keyword");

  kbGR.query();

  gs.print('SPKBHelper - Rows: '+kbGR.getRowCount()); // Returns the correct # of "featured" articles we have

  gs.print('SPKBHelper - hasnext '+kbGR.hasNext()); // Returns true

  var keepIterating = kbGR.next(); // Returns false

  gs.print('SPKBHelper - keepIterating: '+keepIterating);

  gs.print('SPKBHelper - start while');

  while (keepIterating) {

            gs.print('SPKBHelper - next');

            result.push(kbGR.getValue('knowledge'));

            gs.print('SPKBHelper - '+kbGR);

            gs.print('SPKBHelper - '+kbGR.getValue('knowledge'));

            gs.print('SPKBHelper - '+kbGR.getDisplayValue('knowledge'));

            gs.print('SPKBHelper - '+kbGR.getDisplayValue('keywords'));

            keepIterating = kbGR.next();

  }

  gs.print('SPKBHelper - end while');

  gs.print(result);

  return result;

}

12 REPLIES 12

Abhinay Erra
Giga Sage

This is strange. ACL's should not restrict them from accessing the records, if you are using GlideRecord queries.


That's what I thought. Is it possible that it has to do with the function being run in the context of the filter's javascript call? Or should that not make a difference? A teammate of mine just tested running the same function through use of a business role, and noted that it seemed to work correctly even when impersonating a non-admin user.


Update your script include function to this



getPinnedArticleIds: function() {  


  var result = [];  


  var kbGR = new GlideRecord("kb_knowledge_keyword");  


  kbGR.query();  


  while (kbGR.next()) {  


            result.push(kbGR.getValue('knowledge'));  


  }  


  return result.join();  


}  



Then use this in the reference qualifier


javascript: "sys_idIN"+new SPKBHelper().getPinnedArticleIds();


The join() call definitely makes sense, and I've tested using toString() for a similar effect.


Unfortunately I can't quite apply your second suggestion since I'm not actually using the filter in a reference qualifier. The testing I'm doing is using it directly within the list view UI


find_real_file.png



And, in the actual use case this was written for, I'm using the filter as a string that's being passed to a Service Portal widget's server script, which passes it through GlideRecord addEncodedQuery()



Passing the filter to the widget's instance options:


find_real_file.png


The widget's server script:


find_real_file.png



So I do see where you're going with your suggestion, with getting the script include's result first, then appending that into what's being used as the filter condition, but I'm not sure how I can apply that when I'm using in places like this where the whole thing is being passed through UI rather than through a script that can concat the filter for me.