Security Policies

Security Definitions are used throughout the application to provide limits on access to different elements like forms, kapps, and submissions.

Parts of a Security Definition

Each Security Definition has the same four elements.

Name

The Name is descriptive text that is presented in dropdowns. It must be Unique, even if it is for a different type.

Type

Because there is a different scope between Space and kapps, there are different types available.

Here are the avaiable Types for a Space:

Type (where they can be used)Available Bindings
Spaceidentity(...), space(...)
Teamidentity(...), space(...), team(...)
Useridentity(...), space(...), user(...)
Datastore Formidentity(...), space(...), form(...)
Datastore Submissionidentity(...), space(...), form(...), submission(...)

Avaialble Types for Kapps:

Type (where they can be used)Available Bindings
Kappidentity(...), space(...), kapp(...)
Formidentity(...), space(...), kapp(...), form(...)
Submissionidentity(...), space(...), kapp(...), form(...), submission(...)

Bindings

Bindings let you access various data from the platform. For example, identity(username) lets you access the authenticated user id. Think of bindinggs the same way you would use variables when creating an element on a form. The format and intent are the same. Using the identity example for authenticated user: identity('username'). There isn't a definitive list of bindings because they can change with the types of security and other external factors.

Message

The message is what is returned to the customer if the Rule evaluates to false.

Rule

The Security Definition rule is a single JavaScript expression that has to evaluate to either true or false.

An extremely basic example is:

identity('username') === "han.solo"

What is more realistic is evaluating a function to check for a team or role (better example below).

JavaScript provides a mechanism for wrapping scope (which also happens to be helpful for wrapping multiple statements and expressions into a single expression).

(function () {
    //insert multiple functions and expressions
})();

Adding something like this makes the definition much more flexible, but it can make it more complex.

In kinops we use this model for many of the Security Definitions we create:

(function() {
__// Helper method__
  var hasIntersection = function(obj1, obj2) {
// Ensure the objects are not empty
obj1 = (obj1 === null || obj1 === undefined) ? [] : obj1;
obj2 = (obj2 === null || obj2 === undefined) ? [] : obj2;
// If the parameters are not lists, wrap them in lists
var list1 = (obj1 instanceof Array) ? obj1 : [obj1];
var list2 = (obj2 instanceof Array) ? obj2 : [obj2];
// Find the intersection
var intersection = list1.filter(function(n) {
  return list2.indexOf(n) != -1;
});
// Return whether any intersecting values were found
return list1.find(function(value) {return hasValue(list2, value)}) !== undefined;
      };
      __// Helper method__
      var hasValue = function(list, value) {
return (list instanceof Array) && list.indexOf(value) != -1
      };

  __// Employee Check - unique portion of the Rule__
  return hasIntersection(identity('teams'), ['Role::Employee']);
})()

While this looks complex at first glance, it really only contains three pieces that are marked by comments.

The Helper methods are included in all the predefined kinops Security Definitions like this one. The top two sections are there to make sure that the first object in the hasIntersection function is present in the second object. In the above example, the Identity of the person's team is part of the Role::Employee. Another way to put this: is the person requesting access an employee.

Here is a little more complex version checking if the person is a member of the assigned team or are the assigned individual for a submission (This would replace the employee check section of the JavaScript expression above):

return (
    // Assigned Team
    hasIntersection(values('Assigned Team'), identity('teams'))
    // Assigned Individual
    || hasIntersection(values('Assigned Individual'), identity('username'))
    // Last updater (this is necessary so that a user can see that they successfully
    // re-assigned a submission)
    || submission('updatedBy') == identity('username')
    );

To put this in a more conversational way, is the person a member of the assigned team, or are they the assigned individual, or are they the last person to update the submission. The other JavaScipt functions are the same.

One last point for Security Definitions: A user that is a Space Admin is automatically granted permissions to everything. That is why you see the Rule for Space Admins set to false by default. If you aren't a space admin, it will always be false. If you are a space admin, you get to breal the rule anyway.