Script permissions

This document is about the script permissions system used in the CrossmarX Scripting API.

What are script permissions?

Every application defines, in one way or the other, a number of rules that determine which functionality of that application is available, or permitted to specific (groups of) users. In the blueprint of your application, for every class, field, action, etc., you can define permissions that determine what a user of a certain user group is allowed to see and do. This allows for a fine-tuned security strategy regarding the data in your application. In the same way, not all functions in the CrossmarX Scripting API are readily available to any arbitrary user. The security mechanism implementing this is the Script permissions system. These permissions determine which users are allowed to access certain API objects and methods from their scripts.

Permission tokens

The script permissions mechanism is built around the notion of permission tokens, which govern which objects and methods may be accessed from a script, in a certain situation. Consider the method FileSystem.get(string), from the io module. This method returns a handle to a file (an object of type io.File) for a given path on the file system it is invoked upon. Needless to say, this method should not be available to any user - even though that user may not prohibited from writing scripts per se - as it ultimately allows for insight into, or even modification of, the resource files of your application, for one. To facilitate this restricted availability, this method (and most other methods from the io module) requires that the user invoking this method is in possession of, or "has", the File I/O permission token. In case the user does not have this token, a security exception is raised, preventing the use of this method.

Whether a user has a certain permission token may depend on the role of that user in your application. If the user group of a user allows access to your application files (property File permission), this user will be granted the File I/O permission token automatically, by virtue of their user group. Users of user groups that do not have the file permission property, will not automatically be granted the File I/O token.

Extended permissions

Suppose you are writing a script for an action that needs to perform some operation on the file system, which would require the File I/O token when the script is executed by a user. It may however, for obvious reasons, very well be undesirable to always grant File access permission to the user group in question. To mitigate this problem, any required permission tokens for the successful evaluation of a script may also be granted "to the script itself", or rather, to the context in which the script is executed (this distinction is important, on which more later). This means that if you provide a script to a user, lacking some required permission token themselves, in a context that does provide that token, that script will execute without issues. Note that this does not raise security concerns, for the script (and the context in which it is executed) are defined by you, the developer, and not by the user, and there is still no way for an arbitrary user to execute a script using more permission tokens than they have themselves, because they would never be able to provide a context within a script would have more permission tokens than their own.

There is a number of contexts in which a script may be executed, but for the intents of this documents we will only consider the situation for blueprint scripts - that is: scripts that are defined by you in actions, calculations, etc. in the blueprint of your application.

Hierarchy and scope of permission tokens

In the example above, where we considered an action, the script implementing that action executes in the context of the blueprint. All scripts executing in this context are automatically granted the Blueprint permission token, regardless of the user's own permission tokens. (Note that you, as a developer, always have this Blueprint permission token - because of your role as developer precisely.) This is a very important token to have, because all* (see below) permission tokens available to you are part of a hierarchical structure, of which Blueprint is of the highest order, thus encompassing all subordinate permission tokens. The full hierarchy of permission tokens that are available to developers is:

  • Blueprint: all permissions regarding the definition of your application
    • Application manager : permissions regaring administrative functions within your application
      • Account: permission to inspect and/or modify user accounts
      • Email: permission to read, create, and send email messages
      • File I/O : permission to access the file system(s) of your application
    • Model: access to the components contituting the blueprint of your application
    • Allow grant permissions: permission to grant and revoke extra permissions in scripts
      • Permissions: permission to inquire after user permissions

As is apparent from the hierarchy, the script of an action will always be allowed to access files on the file system, since the granting of the Blueprint permission token means the File I/O token is implicitly granted as well.

Permission tokens are not necessarily the final word on what parts of your application a certain user executing a script may or may not have access to. Possession of the permission token Account for example, does not imply that every single user account in your application can be read or modified, but rather that script functions having to do with user accounts are available. Access to individual accounts is still checked for compliance with the account permissions as defined in the blueprint. Likewise, the Model token gives access to the classes in your blueprint - i.e. objects of type Class - but not necessarily access to the records of any of those particular classes: the latter is still checked against the class permissions as defined in the blueprint. For example, when a script executes a query, only those records that are visible to the user will be returned - if any at all.

The appliance of these complementary permissions regarding the use of actual application data, may in certain cases be undesirable. Especially scripts that are specifically intended to handle data that the user would not be able to access directly, should not be hindered by the user's data permissions. In order to instruct functionality in the Crossmarx Scripting API to not apply these permissions when handling application data, the special permission token Ignore data permissions is used. This permission token exists outside of the hierarchy described above, and is not inherent to any of the other tokens, but instead has to be granted seperately.

A clear case where Ignore data permissions should be applied is in scripts of calculations. A calculation should have a consistent outcome, i.e. under all circumstances should the same source values lead to the exact same result, regardless of the current user and their permissions. Therefore, in the context of a calculation the token Ignore data permissions is always automatically granted. The same goes for other (scripted) helpers, with the exception of that for actions. For actions it may very well be that only data that is visible to, or modifiable by, the user is to be acted upon, and granting Ignore data permissions automatically forces the developer (you) to always explicitly check data permissions of records throughout your scripts. Given that actions are typically relatively complex scripts, this would be a nuisance, and for that reason, whether or not Ignore data permissions should be automatically granted in the context of an action, can be configured in the action helper's parameters.

Application methods and script permissions

This far we have only discussed very static situations with regards to script permissions. Either a user has the required tokens or they don't, and depending on the specific context of a script, a fixed set of extra permission tokens is granted, if any at all. In a following documentation page (soon to be published), the very useful tools that are application methods are discussed. Without going into much detail here, application methods allow you to define your own methods, which can be used throughout your application's scripts (somewhat like Velocity macros, but far more powerful). Besides offering reusability of your code, application methods each have their own, configurable sets of permission tokens, namely those that are to be automatically granted as extra tokens when the application method is invoked, and those that are required (of the user or context) in order to allow the application method to be invoked at all.

One thing this allows you to do, for example, is create an application method that executes a script with the Model token (regardless of whether the user has this token) - but only if that application method is invoked by a user or in a context that has the Account token.