# Conditions

You write a condition as a JSON object with two properties, expressed as key-value pairs:

- `type`: One of the following values:
  - `Expression`
  - `And`
  - `Or`
- `expression`: A JavaScript expression.


If the expression evaluates to `true`, then the policy is eligible to apply to the current intent.
However, the policy is only actually selected if it has the highest rank of all eligible policies.

## Context

You write the expression using the `context` object. This object has the following two child objects:

- `context.request`: Gives access to the values stored in the intent object.
- `context.references`: Gives access to objects referenced from an intent request.


You can use these objects to write conditional expressions, for example, this value must be equal to, not equal to, or greater than a certain value.

Whenever a user creates a new intent, the data in the request becomes available through `context.request`.

In the request, there can also be IDs that refer to other entities, for example, the request to create an account contains the `vaultId`. This additional object is loaded in memory and you can access it through `context.references`. Only entities that are explicitly referenced in the request are accessible through `context.references`.

For a full list of the properties available, see the API reference:

- New intent creation: [Propose a new intent](/products/custody/v1.15/api/reference/openapi/intents/createintent).
- Referenced entity: [Detail query](/products/custody/v1.15/api/get-started/key-operations/query#detail-queries) for the entity.


You must ensure that the expression can always evaluate either as `true` or `false`. If a condition refers to an object which is not available for all intents (a custom property) we recommended you include a check for the existence of the property in the expression, for example, `hasOwnProperty('propertyName')`. In this way, if the property does not exist, the condition can still be evaluated.

### context.request examples

For a policy defined to govern account creation, you have access to the property `context.request.payload.ledgerId` since specification of the ledger on which to create the account is a requirement of account creation. We can use this property to write an expression of type:


```json
{
    "expression": "context.request.payload.ledgerId == ‘bitcoin’",
    "type": "Expression"
}
```

Another example is the request author. Since every intent has an author, it is possible to specify that this policy be enforced for all the intents of a specific user, with an expression like the following:


```json
{
    "expression": "context.request.author.id == ‘....’",
    "type": "Expression"
}
```

You can create more advanced conditions using JavaScript methods, such as the following example using the `_includes()_` method:


```json
{
    "expression": "context.request.payload.roles.includes(‘admin’)",
    "type": "Expression"
}
```

### context.references examples

In the intent for creating an account, we can access the `vaultId` using `context.request`, and we can also load the vault object to access additional properties referenced by the vault that are not directly part of the intent request.

For example, if we write the following expression:


```json
{
    "expression": "context.references[‘vaults’][context.request.payload.vaultId].pubKey == ‘MCow...SE=’",
    "type": "Expression"
}
```

This points to the referenced vault object, that the request uses (through the `vaultId`) to extract the public key of this specific vault. We can then test the value of the public key in the expression.

You can write more complex expressions with a `type` of `And` and `Or`. The syntax is similar in both cases. The format is as follows:


```json
[
    {
        "left": policyConditionObj,
        "right": policyConditionObj,
        "type": "And"
    }
]
```

`policyConditionObj` is a placeholder. This means that the policy can be enforced when the condition on the `"left"` and the condition on the `"right"` are both met. The left and right conditions are actually objects themselves. A fully expanded example is as follows:


```json
{
    "left": {
        "expression": "context.request.payload.ledgerId == ‘bitcoin",
        "type": "Expression"
    },
    "right": {
        "expression": "context.request.author.id == ‘....’",
        "type": "Expression"
    },
    "type": "And"
}
```

In this example, the policy can be applied to the intent if the intent is initiated by a given author and the ledger is `bitcoin`. If we want only one condition or the other to apply, we can specify the same expression with `"type" : "Or"`.

## Example conditions

These examples apply to the creation of transaction orders and users.

The examples cover the usage of the context object and the reference to any `customProperty` defined.

### Differentiate transaction order based on the risk level

We can define a scenario where the customer wants to create policies based on the level risk of the transaction as follows.

#### High risk transaction

Let's assume that the requirements for this kind of transaction are:

- The intent is submitted by a user with the role of `operator` **AND**
- The transaction is performed on the Bitcoin ledger **AND**
- The amount of the transaction is higher than 1 Bitcoin (1e8 Satoshi) **OR**
- The sender account has a customized property named `escalatePolicy = true` )



```json
{
    "expression" : "context.references.users[context.request.author.id].roles.includes('operator')   &&   context.request.payload.parameters.type == 'Bitcoin'   &&   (context.request.payload.parameters.outputs[0].amount >= '100000000' || context.references.accounts[context.request.payload.accountId].metadata.customProperties.escalatePolicy == 'true')",
    "type": "Expression"
}
```

In this expression the customProperty `escalatePolicy` is used. The following image shows how to build the path to reference this field of the account entity:

![](/assets/context-references.69067cf7957fdbb8bc88302907817d2c6d7411eb1edade8a45e5ee83b87f36cc.136bae00.png)

#### Medium risk transaction

The specific requirements are:

- The intent is submitted by a user with the role of `operator` **AND**
- The transaction is for the Bitcoin ledger **AND**
- The amount of the transaction is lower than 1 Bitcoin (1e8 Satoshi) **AND**
- The sender account does not include an `escalatePolicy` property **AND**
- The destination point is either an endpoint with a trust score below 50 **OR** it is not an internal Ripple Custody account.



```json
{
    "left": {
        "expression": "context.references.users[context.request.author.id].roles.includes('operator')   &&   context.request.payload.parameters.type == 'Bitcoin'   &&   context.request.payload.parameters.outputs[0].amount <= '100000000'   &&   context.references.accounts[context.request.payload.accountId].metadata.customProperties.escalatePolicy != 'true'   &&   context.request.payload.parameters.outputs[0].destination.type == 'Address'",
        "type": "Expression"
    },
    "right": {
        "expression": "context.references.users[context.request.author.id].roles.includes('operator')   &&   context.request.payload.parameters.type == 'Bitcoin'   &&   context.request.payload.parameters.outputs[0].amount <= '100000000'   &&   context.references.accounts[context.request.payload.accountId].metadata.customProperties.escalatePolicy != 'true'   &&   context.request.payload.parameters.outputs[0].destination.type == 'Endpoint'   &&   context.references.endpoints[context.request.payload.parameters.outputs[0].destination.endpointId].trustScore <= 50",
        "type": "Expression"
    },
    "type": "Or"
}
```

#### Low risk transaction

The specific requirements are:

- The intent is submitted by a user with the role of `operator` **AND**
- The transaction is for the Bitcoin ledger **AND**
- The amount of the transaction is lower than 1 Bitcoin (1e8 Satoshi) **AND**
- The sender account does not include an `escalatePolicy` property **AND**
- The destination point is either an endpoint with a trust score above 50 **OR** an internal Ripple Custody account



```json
{
    "left": {
        "expression": "context.references.users[context.request.author.id].roles.includes('operator')   &&   context.request.payload.parameters.type == 'Bitcoin'   &&   context.request.payload.parameters.outputs[0].amount <= '100000000'   &&   context.references.accounts[context.request.payload.accountId].metadata.customProperties.escalatePolicy != 'true'   &&   context.request.payload.parameters.outputs[0].destination.type == 'Account'",
        "type": "Expression"
    },
    "type": "Or",
    "right": {
        "expression": "context.references.users[context.request.author.id].roles.includes('operator')   &&   context.request.payload.parameters.type == 'Bitcoin'   &&   context.request.payload.parameters.outputs[0].amount <= '100000000'   &&    context.references.accounts[context.request.payload.accountId].metadata.customProperties.escalatePolicy != 'true'   &&   context.request.payload.parameters.outputs[0].destination.type == 'Endpoint'   &&   context.references.endpoints[context.request.payload.parameters.outputs[0].destination.endpointId].trustScore >= 50",
        "type": "Expression"
    }
}
```

This example assumes that the transaction is performed to a single destination.

### Create/update a user based on their role

In order to securely manage an existing domain, the creation of a new user (or updating of an existing one) must also be carefully controlled with implementation of appropriate policies.

We consider a scenario where if the user to be created or updated has a certain role, for example, `admin` or `compliance`, then a different workflow applies than for creation of users with another role.

#### Create/update user whose role includes `admin` or `compliance`

To identify this scenario, we need to create a policy with the following condition:


```json
{
    "expression": "context.request.payload.roles.includes('admin')   ||   context.request.payload.roles.includes('compliance')",
    "type": "Expression"
}
```

#### Create/update user whose role does not include `admin` or `compliance`

For this second scenario, we need to create another policy with the following condition:


```json
{
    "expression": "!context.request.payload.roles.includes('admin')   &&   !context.request.payload.roles.includes('compliance')",
    "type": "Expression"
}
```