Server-side debugging

Server-side debugging can consist of debugging server-side scripts and other behavior, as well as performance and security issues. Debugging server-side scripts can often be slightly more difficult, as the exact source of the undesired behavior is not necessarily logged or thrown as an error message visible on the client. Instead, you must search through the logs for thrown errors, and sometimes use trial-and-error and custom log messages to determine the exact source of the issue. For this reason, using try/catch() blocks in your server-side code can be a good idea. This is also true of client-side code in fact, but it is especially important with server-side code.

Note

While try/catch() blocks are a great way to build in error-handling behavior, it should not be relied upon to control the flow of your code. They should only be used when the catch block can handle the error in some sensible way. Otherwise, pass the error up the call stack and perhaps a higher-level function will be able to handle it more effectively. The following is an example of how not to use try/catch():

var gr = new GlideRecord('task'); 
gr.addQuery(myEncodedQuery); 
gr.query(); 
if (gr.next()) { 
    try { 
        var stateVal = gr.incident_state.toString(); 
    } catch(ex) { 
        gs.info(gr.getValue('number') + ' is not an incident. Getting value from State field.'); 
        var stateVal = gr.state.toString(); 
    } 
    return stateVal; 
} 
return false;

Sometimes, strange behavior (or even poor performance) can result from bloated, corrupted, or stagnant instance cache. Issues can arise from changing field names or other dictionary data, altering schema information, or other major changes like that. These changes might not immediately have impact on cached server-side data, resulting in aberrant behavior, but this can often be easily remedied by clearing the instance cache. This can be done quite simply, by navigating to /cache.do on your instance.

Flushing your system cache can cause a slight performance degradation until the cache is repopulated, but if you suspect an issue, it is usually worth It to clear the cache as an added troubleshooting step.

Reference versus value

Another unique property of server-side code, is the structure of a GlideRecord. A GlideRecord consists of field-value pairs; the name of the GlideRecord object property corresponds to the field name (that is, gr.number refers to the number field of the corresponding record). However, on the client, these properties of the GlideRecord object are strings; whereas on the server, these properties refer to GlideElement objects.

Why is this important, you ask? To answer that question, we must first understand one of the quirks of JavaScript: pass-by-reference. In JavaScript, a variable can hold one of two types of values: a primitive value, or a reference. A primitive value might be a string, a number, a Boolean, null or undefined.

Primitive values are stored on the stack, and are accessed directly by the variable. You might say that they are contained within a variable. A reference value on the other hand, is merely a pointer (or, you might say, a reference!) to an object which is stored on the heap. The difference between the heap and stack isn't important here, but what is important is that they're different. A variable in JavaScript does not technically contain an object, but rather a reference to that object. Consider what might print out, if we run the following in a background script:

var parent = { prop1: 'val1' }; 
var child = parent; 
child.prop1 = 'new value'; 
gs.print(parent.prop1); 

In the preceding example, we declare an object: parent, with a property: prop1, set to a value: val1.

On line two, we then declare child, and set it as a reference to the same object as parent. In doing this, we might think that we are setting it to an instance of parent, but that is not the case!

On line three then, we set prop1 in the child object to new value, and then finally on line four, we print out the same property of the parent object.

So, what prints out? Although one might expect the prop1 property of the parent object to remain unchanged, due to the fact that both variables are references to the same object, modifying child also modified parent! Thus, on line four, we print out the new value, new value.

This applies just the same to GlideRecord objects on the server, since their properties are not a primitive value like a string (as they are on the client), but GlideElement objects. Consider the following code:

var num; 
var gr = new GlideRecord('incident'); 
gr.setLimit(2); 
gr.orderBy('number'); 
gr.query(); 
while (gr.next()) { 
   if (gr.number == 'INC0000001') { 
        num = gr.number; 
    } 
} 
gs.print(num); 

Above, we set a limit of 2 records to return, and order them by number. This should give us INC0000001 and INC0000002. In this code, we've specifically set a condition so that we will only set the num value, if the number we get ends in 0001. However, the next time the loop is run, we change the value of the GlideElement object that resides at gr.number, which the variable num references. When we print the contents of num, we're really printing out the contents of gr.number at the moment we access it. Therefore, we print out INC0000002 instead of the otherwise expected INC0000001.

Debugging security

Aside from UI policies and client scripts, we also alluded to ACLs being a potential cause for a field being read-only or hidden. ACLs are evaluated and execute server-side. While the JavaScript Log and Field Watcher does show you some information about when different ACLs execute on a given field, there is a great deal of additional information specific to ACLs that can be found by enabling the System Diagnostics | Session Debug | Debug Security module. This causes some information to display below the form/list for each ACL that's evaluated. These messages look like the following:

Debugging security

A blue circle indicates that it has been evaluated from the cache, whereas the green circle indicates that the ACL was evaluated based on data on the server, and passed. A red circle obviously means that the ACL check was not successful.

At least one ACL rule is checked and logged for each field on the form when it is loaded, as well as ones for the table and record itself. Whenever a user requests access to an object (a record, a field/value, or even a table), the system checks for any ACL rules matching that object. If a match is not found, the default security rule applies. When the High Security Settings plugin is enabled, this defaults to denying access. However (and more commonly), when a matching rule is found, the permissions of that rule are evaluated against the user. The user must then pass all three conditions of the ACL:

  • Does the user have one of the required roles (if specified)?
  • Is the condition true?
  • Does the script (if specified) return true?

If any one of these checks fails, then the user is denied access to the requested object. If a user is denied access to read a specific field on a form for example, it will not be displayed on the form at all. If the user is denied write access on the other hand, the field is shown as read-only (the same as if it were set as read-only by a UI policy).

As we learned in a previous chapter, setting a field to read-only on the client alone is not a secure way to prevent users from writing to it. However, an ACL has a server-side component as well. Even if users bypass the read-only field on the form, they will not be able to set the field value on the server if an ACL does not allow it. This is similar to the behavior of a UI policy/data policy pair.

When you activate a server-side debugging module, it remains active until one of the following occurs:

  • You activate the Stop Debugging module, located in system security
  • You log out from the instance
  • The session expires (for example, the session times out)
  • You close the browser
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.199.243