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

How are you getting that filter into this record? What you can do is remove the last and condition in the filter and use addQuery() something like this



gr.addEncodedQuery(options.filter);


gr.addQuery('sys_id','IN',new SPKBHelper().getPinnedArticleIds());


The filter is really just being manually typed/pasted into the textbox there in the UI I have in the screenshot, so it's being ingested as plain string. The Widget that's using the filter is a very generic "Simple List" widget, simply displaying whatever table and filter is passed into it, so I couldn't quite add the addQuery call there.



It looks like that might be my only option at this point though, so I may just settle with wrapping the Simple List widget inside one whose only job is to create a concatenated filter ("sys_idIN"+new SPKBHelper().getPinnedArticleIds(); as you suggested) and pass into the inner Simple List widget. Kind of a waste of a what's really an entire angular controller, but better than nothing.



Thank you Abhinay for the help! This should give me the functionality we're needing, though the original question remains as to why this just wasn't working in the first place, especially with getRowCount, hasNext(), and next() being capable of just not matching up. For the sake of education and future potential solutions, it would be great to know why such a seemingly simple function is being obstructed by whatever all this is.


Is it not working for non-admins? Are you talking about widget's server script?


I apologize, I might be jumping around a bit and making things confusing. No, I mean the widget's instance options. Like when you drag a widget into the Service Portal page designer and click the edit/pencil button and fill out the values as the widget's option schema has been set up to take them in. For example, the OOB widget that my widget derives from is Simple List, its options schema has a "Filter" text field, and there you can put a query filter, which is taken in and put through addEncodedQuery inside of the Simple List's server script. I can't alter Simple List's server script to add the query by making the script include call first, then taking that string and giving it to the GlideRecord, because Simple List is for displaying a collection of records for any table, hard coding that filter and addQuery call in there wouldn't make any sense outside this one specific use case.



That being the case, my thinking is that I'll have to make a new widget. This new widget's server script will call the script include, take the resulting string, and concatenate that onto the rest of the filter string I have, and pass that to an embedded instance of Simple List, like below.


find_real_file.png


Doing a quick test, this approach does work for both admin and non-admin users. So it does give me a work around so I can get the functionality that I'm looking for that brought me to this point. I would argue that it is a bad approach because I'm using an entire angular controller as a simple, singularly purposed wrapper, which isn't optimal, but it technically works.



However, it still doesn't explain my original question and why I can't just use sys_idINjavascript: new SPKBHelper().getPinnedArticleIds(); in an encoded query, specifically in the view context of non-admin users. It doesn't explain why I can do a GlideRecord query and have it return a number greater than 0 when I do getRowCount(), return true when I call hasNext(), but then return false when I call next(). I could very well mark an answer in here as correct and say I've got what I wanted via a workaround, but the disconcerting core issue I've opened my question with remains. What's keeping that small script include function from working for non-admin users when run via a filter?


Abhinay Erra
Giga Sage

Did you get this working?