Skip to main content
Version: 2.0.0

Operators

When building conditions, you need to be aware of the different types of operators you can use to construct your complex condition rules. There are two types of operators that you need to be aware of - Logical and Comparison.

Logical Operators

There are currently three types of logical operators you need to be aware of. These work like logic gates and represent a boolean function.

Logical OperatorAlias (if any)
ANDallOf
ORanyOf
NOTnot

Comparison Operators

Comparison operators enable us to construct much more complex conditions and introduce more concrete rules to our policies.

TextString used in conditionDescriptionValid for type
EQUALSequalsa = bBool, Number, String
DOES NOT EQUALnot-equalsa != bBool, Number, String
LESS THANless-thana < bNumber
GREATER THANgreater-thana > bNumber
LESS THAN EQUALSless-than-equalsa ≤ bNumber
GREATER THAN EQUALSgreater-than-equalsa ≥ bNumber
CONTAINScontains"aaa??bbbbbb"String
ARRAY CONTAINSarray_contains["a", "b", "c"] has "a"Array
ARRAY SUBSETarray_subset["a", "b"] has ["a", "b", "c"]Array
ARRAY SUPERSETarray_superset["a", "b", "c"] has ["a", "b"]Array
ARRAY INTERSECTarray_intersect["a", "b", "c"] and ["c", "d", "e"] share at least one valueArray
EQUALS REF (reference)refE.G. equals user emailNumber, Array, String
NOT EQUAL REF (reference)refE.G. not equals user keyNumber, Array, String
CONTAINS REF (reference)refE.G. tenant name contains user first_nameString
ARRAY CONTAINS REF (reference)ref["admin", "editor"] contains user roleArray
LESS THAN (reference)refa < bReference to number value E.G user.age
GREATER THAN (reference)refa > bReference to number value E.G user.age
LESS THAN EQUALS (reference)refa ≤ bReference to number value E.G user.age
GREATER THAN EQUALS (reference)refa ≥ bReference to number value E.G user.age
info

The ref operators are mentioned using a nested object in the condition set.

For example, if you want to check if the user's email is equal to the user's first name, you can use the following condition:

{
"allOf": [
{
"user.email": {
"contains": {
"ref": "user.first_name"
}
}
}
]
}

Object Match Operators

Object-match operators enables us to run multiple comparisons on object-like (or dictionary-like) attributes, as well as object-array attributes.

Matching a single Object-typed attribute

Assuming you have a user attribute called user.organization with type Object:

{
"name": "Cool Inc",
"country": "US"
"subscription": "pro",
...
}

And you want to have a condition set that filters all users who are working in companies located in the US and have "pro" subscriptions:

If we map each attribute from our source data into a separate attribute in Permit, the conditions would look like this:

{
"allOf": [
{"user.country": {"equals": "US"}},
{"user.subscription": {"equals": "pro"}}
]
}

In other words, normal comparison operators will do the trick.

However with object-typed attributes, we can have a single user.organization attribute:

{
"allOf": [
{
"user.organization": {
"object_match": {
"match": {
"country": {"equals": "US"},
"subscription": {"equals": "pro"}
}
}
}
}
]
}

As you can see, when you match an object you can use comparison operators within the match object, for each object-attributes and only if all the conditions match - the operator will return a true result.

This is beneficial in case you want to map your data as closely to the source data format in your db, but it becomes crucial if you data is an array of dictionaries (or object-array).

Matching Object Array typed attribute

Assuming you have a user attribute called user.organizations with type Object Array:

[
{
"name": "Cool Inc",
"country": "US"
"subscription": "pro",
...
},
{
"name": "Awesome Inc",
"country": "IN"
"subscription": "enterprise",
...
},
{
"name": "Sweet Inc",
"country": "US"
"subscription": "enterprise",
...
},
]

In other words, a user can belong to multiple companies, and you still wish to have a condition set that filters all users who are working in companies located in the US and have "pro" subscriptions.

In this case, it is not possible to split the user.organizations attribute, instead we can match each item of the array:

{
"allOf": [
{
"user.organizations": {
"any_match": {
"match": {
"country": {"equals": "US"},
"subscription": {"equals": "pro"}
}
}
}
}
]
}

This will return true if a single item in the user.organizations array is an object where item.country == "US" and item.subscription == "pro".

Finally if we want to check if all items in the array match a certain condition we can replace any_match with all_match:

{
"allOf": [
{
"user.organizations": {
"all_match": {
"match": {
"country": {"equals": "US"},
"subscription": {"equals": "pro"}
}
}
}
}
]
}

Object Match Operator Reference

TextString used in conditionDescriptionValid for type
Object Matchobject_matchapply conditions to multiple sub-attributes of an object-typed attribute and return true if all the conditions are metObject
Any Matchany_matchapply conditions to each item of an object-array attribute (use comparison operators on each sub attribute of the item) an return true if all the conditions are met for at least one item in the arrayObject Array
All Matchall_matchapply conditions to each item of an object-array attribute (use comparison operators on each sub attribute of the item) an return true if all the conditions are met for all the items of the arrayObject Array

Object Match using a "foreign key"

In some cases, we have an attribute on one resource that references the key of other resource.
For example, a resource repo has an attribute of organization ( string ) that holds the organization key of that repo, similar to a foreign key in a database.
In case we want to create a condition that checks if the organization of the repo is located in the US, we can the object_match operator with a reference to the organization object by adding the fk_resource_type key and provide the foreign resource type in it.
The following example will extract the stored attributes of the organization in the organization attribute of the repo resource queried and apply the conditions on those extracted organization attributes:

{
"allOf": [
{
"resource.organization": {
"object_match": {
"match": {
"country": {"equals": "US"}
},
"fk_resource_type": "organization"
}
}
}
]
}

Same can be done using the any_match and all_match operators for array of foreign keys attributes.
For example, A resource repo has an attribute of issues ( array of string ) that holds the foreign keys to the issues of that repository.
In case we want to create a condition that checks that all the repo issues are closed we can use the any_match or all_match operators with the fk_resource_type key and provide the foreign resource type in it.
The following example will extract the stored attributes of each issue in the issues attribute of the repo resource queried and apply the conditions on those extracted issue attributes:

{
"allOf": [
{
"resource.issues": {
"all_match": {
"match": {
"status": {"equals": "closed"}
},
"fk_resource_type": "issue"
}
}
}
]
}

This can also be done with any_match:

{
"allOf": [
{
"resource.issues": {
"any_match": {
"match": {
"status": {"not-equals": "closed"}
},
"fk_resource_type": "issue"
}
}
}
]
}
info

While other ABAC operators can be used by attributes from the check arguments or attributes stored in Permit/PDP,
the foreign key condition aims to solve cases where we already store the attributes in Permit Cloud and want to have a condition that does not need to pass them explicitly as part of the check function.

Now that we have a basic understanding of the language to construct conditions, lets jump into creating Condition Sets.