Advanced Reference Qualifier only works for certain role
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-14-2015 11:12 AM
I have installed the Loaner Management application by Chuck Tomasi. This was made in an old version of ServiceNow and I have made it work in Fuji with some customization.
I am running into a major issue with the Advanced Reference Qualifier in the Record Producer on the field cmdb_ci.
The reference qualifier is designed to return only the particular loaner items that are available between the selected start and end date. Thus, if the loaner is already reserved for any date in between the selected date, it doesn't show up in the list.
This works great -- ONLY for users with the role "loaner_admin". I noticed that any user that doesnt have that role, the reference qualifier isn't working! The reference field returns ALL of the items, even if they are already booked for the time period.
I tried logging in as a loaner_admin user and it works, but when I log in as a user with any other role, ALL of the items are available in the list and this results in a DOBULE booking. Yikes!
I then granted my test user the loaner_admin role and it worked. So, I know it has to do with an ACL on that role.
I experimented with the ACL rules, I added the role "user" to the "write" action on the cmdb_ci field but that did not solve the issue.
Reference Qualifier on cmdb_ci
javascript: new LoanerUtilsClient(current).availableCis(current.variables.item_type, current.variables.depot, current.variables.start_date, current.variables.end_date);
- Labels:
-
Scripting and Coding
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-14-2015 02:01 PM
This must be where the issue is:
if (checkAvailProperty) { // Check only available matching items
if (this.isAvailable(id, start, end))
availableItems.push(id);
as it's the only place dealing with the dates.
Can you paste the isAvailable function?
That's what appears to be failing. (if we can confitm that the checkAvailProperty is returning true for both ess and la)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-14-2015 02:05 PM
Here's the entire script include
var LoanerUtils = Class.create();
LoanerUtils.prototype = {
/**********
* Initialization stuff here...
*
**********/
initialize : function() {
this.overdueRemindTime = gs.getProperty('glide.loaner.overdue.remindtime', 24);
this.pickupLeadTime = gs.getProperty('glide.loaner.pickup.leadtime', 24) * -1; //paramm to gs.daysAgo()
this.returnRemindTime = gs.getProperty('glide.loaner.return.remindtime', 24) * -1;
},
/**********
*
* getOverdueRequests - retrieve a list of overdue records
*
* @param - None
* @return: array of sys_ids
*
**********/
getOverdueRequests : function() {
var a = new Array();
var gr = new GlideRecord('loaner_request');
gr.addQuery('end_date', '<=', gs.nowDateTime());
gr.addQuery('state', 17);
gr.query();
while (gr.next()) {
a.push(gr.sys_id.toString());
}
return a;
},
/**********
*
* timeToRemindOverdue - Use the passed in ID to check if the record is time to remind again
*
* @param - id: sys_id of the loaner record to check
* @return - boolean: true = time to remind
*
**********/
timeToRemindOverdue : function(id) {
var gr = new GlideRecord('loaner_request');
if (!gr.get(id)) {
gs.log('>>>DEBUG: LoanerUtils: timeToRemindOverdue(): FAILED TO RETRIEVE RECORD');
return false;
}
var baseDate = (gr.last_overdue_reminder == '') ? gr.end_date : gr.last_overdue_reminder;
return (baseDate <= gs.hoursAgo(this.overdueRemindTime)) ? true : false;
},
/**********
*
* sendOverdueReminder - Queue an event to send a reminder and update the necessary
* record fields to indicate they've been reminded
*
* @param - id: sys_id of the loaner record to check
* @return - None
*
**********/
sendOverdueReminder : function(id) {
var gr = new GlideRecord('loaner_request');
if (!gr.get(id)) {
gs.log('>>>DEBUG: LoanerUtils: setLastOverdueReminder(): FAILED TO RETRIEVE RECORD');
return;
}
++gr.overdue_count;
// Record the last time a reminder was sent
gr.last_overdue_reminder = gs.nowDateTime();
gr.update();
// Send the overdue reminder
gs.eventQueue('loaner.overdue', gr, gr.start_time, gr.end_time);
},
/**********
*
* getNullPickupReminders - Get a list of records in state 'Ready for Pickup'
* that haven't been reminded before
*
* @param - None
* @return - array of sys_ids
*
**********/
getNullPickupReminders : function() {
var a = new Array();
var gr = new GlideRecord('loaner_request');
gr.addQuery('state', 16);
gr.addQuery('pickup_reminder', '');
gr.addQuery('start_date', '<=', gs.hoursAgo(this.pickupLeadTime));
gr.query();
while (gr.next()) {
a.push(gr.sys_id.toString());
}
return a;
},
/**********
*
* sendPickupReminder - Queue an event to send a reminder and update the pickup reminder field
*
* @param - id: sys_id of the loaner record to check
* @return - None
*
**********/
sendPickupReminder : function(id) {
var gr = new GlideRecord('loaner_request');
if (!gr.get(id)) {
gs.log('>>>DEBUG: LoanerUtils: sendPickupReminder(): FAILED TO RETRIEVE RECORD');
return;
}
// Log the time the pickup reminder was sent and avoid sending again
gr.pickup_reminder = gs.nowDateTime();
gr.update();
// Send the pickup reminder
gs.eventQueue('loaner.pickup', gr, gr.start_time, gr.end_time);
return;
},
/**********
*
* getNullReturnReminders - Get a list of records that need reminding to bring their item back
*
* @param - None
* @return - array of sys_ids
*
**********/
getNullReturnReminders : function() {
var a = new Array();
var gr = new GlideRecord('loaner_request');
gr.addQuery('state', 17);
gr.addQuery('return_reminder', '');
gr.addQuery('end_date', '<=', gs.hoursAgo(this.returnRemindTime));
gr.query();
while (gr.next()) {
a.push(gr.sys_id.toString());
}
return a;
},
/**********
*
* setReturnReminder - Queue a return reminder and update field when reminder was sent
*
* @param - id: sys_id of the loaner record to check
* @return - None
*
**********/
sendReturnReminder : function(id) {
var gr = new GlideRecord('loaner_request');
if (!gr.get(id)) {
gs.log('>>>DEBUG: LoanerUtils: sendReturnReminder(): FAILED TO RETRIEVE RECORD');
return;
}
// Set this record to never remind again
gr.return_reminder = gs.nowDateTime();
gr.update();
// Send the return reminder
gs.eventQueue('loaner.return', gr, gr.start_time, gr.end_time);
},
/*********
*
* withdrawRequest - Update a request and all related bits
* (child tasks are handled by a standard bus. rule)
*
* @param lr - GlideRecord of the request
* @return None
*
**********/
withdrawRequest : function(lr) {
var wf = new Workflow();
wf.cancel(lr);
lr.active=false;
lr.state=7;
lr.update();
gs.addInfoMessage(gs.getMessage('loaner_withdraw'));
},
/*********
*
* isAvailable - check to see if there are no conflicts w/ci
* being available between start and end times
* and CI is "in" (loaner request state=Requested, Closed, Withdrawn)
*
* @param ci - GlideRecord or sys_id of the CI being requested
* @param start - start date-time of the requested reservation
* @param end - end date-time of the requested reservation
* @return boolean - true=no conflicts
*
**********/
isAvailable : function(ci, start, end) {
var ci_id = ci;
var count = 0;
var lr = new GlideAggregate('loaner_request');
if (JSUtil.nil(ci))
return false; // Null CI defaults to "not available"
if (ci instanceof GlideRecord)
ci_id = ci.sys_id;
var myQuery = 'active=true^';
myQuery += 'cmdb_ci=' + ci + '^';
myQuery += 'start_date<' + end + '^';
myQuery += 'end_date>' + start + '^';
myQuery += 'NQ';
myQuery += 'active=true^';
myQuery += 'cmdb_ci=' + ci + '^';
myQuery += 'end_date<' + gs.daysAgo(0);
lr.addAggregate('COUNT');
lr.addQuery(myQuery);
lr.query();
if (lr.next()) {
count = lr.getAggregate('COUNT');
}
return (count == 0);
},
/**********
*
* availableCis - get a list of CIs in a class/depot that are available
*
* @param class_name - CI class
* @param depot_name - Name of the pick up location
* @param start - reservation start date
* @param end - reservation end date
* @return - comma separated list of sys_ids that are available at that time
*
**********/
availableCis : function(class_name, depot_name, start, end) {
var ci = new GlideRecord('cmdb_ci');
var installStatusProperty = gs.getProperty('glide.loaner.install_status');
var checkAvailProperty = gs.getProperty('glide.loaner.check_availability') == 'true';
var availableItems = [];
gs.log("Test loaner class: " + class_name);
if (!JSUtil.nil(installStatusProperty)) {
ci.addQuery('install_status', 'IN', installStatusProperty);
}
ci.addQuery('loaner', true);
ci.addQuery('sys_class_name', class_name);
ci.addQuery('depot', depot_name);
ci.query();
while (ci.next()) {
var id = ci.sys_id.toString();
if (checkAvailProperty) { // Check only available matching items
if (this.isAvailable(id, start, end))
availableItems.push(id);
} else { // Take any matching items
availableItems.push(id);
}
}
return availableItems.join(',');
},
type: 'LoanerUtils'
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-14-2015 02:10 PM
OK,
that isAvailable function is querying 'loaner_request'.
I would bet that this table has an ACL only allowing loaner_admin to read.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-14-2015 02:17 PM
Hm Ok I will look there again, but I disabled all the ACLs on that table actually.
I also tried adding Allow Read for all roles and that didn't work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-14-2015 02:47 PM
Hi Leslie,
A quick way to check is to add a new ACL of type "record" and operation "read". Leave the "Requires role" list empty, select the "loaner_request" table as the Name and leave the other select box (which lets you select fields) set to -- None --.
Check the box for "Advanced" and make this script:
answer = true;
This should give everyone read access to that table.
To confirm, enable ACL Debugging (in the left-hand nav search for "Debug Security") then Impersonate one of the users with this problem. Navigate directly to the loaner_request table and verify you can read the records there.