# Setting ACL

### Components

Using Appmixer ACL feature you can control access to certain components. All of that can be configured from Backoffice or through the [API](https://docs.appmixer.com/6.0/5.0/api/acl#update-acl-rules).

If you open Appmixer Backoffice you can see an ACL section in the left menu. Then you can choose among *routes* and *components*.

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MEgrT8Q_esFOIfju3Hv%2F-MEh9f81WTpPAoQiJiht%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=dd15e28a-6267-43c4-b629-8c1d054427b5)

When you open *components* section you can see default ACL rules. Users with scope *admin, user* and *tester* can use all *non-private* components. Component can be hidden using [*private*](https://docs.appmixer.com/6.0/5.0/appmixer-self-managed/custom-component-helloappmixer#component-definition) property, then you can make these private components visible to certain users using ACL.&#x20;

This is the default ACL setting you will see.

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MEgrT8Q_esFOIfju3Hv%2F-MEhAf0GmwCvFCnl6HYQ%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=e10d70f3-c4d9-4f27-886d-b0a64bdc4cf4)

If you want to set ACL for different component start with deleting the general rule that allows users to access all components. Because if you did not do this step, the ultimate rule *user - \* - \** would overrule any other rule you would create for *user* scope.&#x20;

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG7xd0X_IL44pfwuWuT%2F-MG87b8sRSN5Cquf-Lr3%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=48afbb67-5105-474b-ab3a-402c3cd8ae04)

If you open Appmixer now (signed in as ordinary *user*) you will see no components in Designer.

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG7xd0X_IL44pfwuWuT%2F-MG88imxNLo6wcb9KZrA%2FAppmixer.png?alt=media\&token=4edd8168-ff21-47dc-b4f4-e000339c2bcf)

Let's now add all components from *appmixer* vendor back with the following rule:

![All appmixer components allowed to be used by all users.](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG7xd0X_IL44pfwuWuT%2F-MG8Aeir2e9XW03tOKjk%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=fb24a1fe-ff5a-4a4f-a996-134e782e4ae9)

When you refresh Appmixer now, you will see all the Appmixer components back.

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG7xd0X_IL44pfwuWuT%2F-MG8BhhNGsRD15hGvyh7%2FAppmixer.png?alt=media\&token=000f7c52-d5b8-48c3-9b16-4de10ecb0c03)

Let's break down those four properties you can set for each ACL rule.

* **role**: admin | user - those are the default roles/scopes in the system. You can also use an email address or a domain. It means you can define ACL(s) for a single users (email address) or for all users from certain email domain. Let's say your company is called *acme* and your employees all have an email address *<their-name@acme.com>*. Then the domain for ACL rule would be *acme.com*.&#x20;
* **resource**: component type prefix (*appmixer.google.gmail\**  for example). This allows to create rules for components belonging to certain vendor, service or module. In the example above we created a rule for all *appmixer* components. The resource string was *appmixer\** which will cover all *appmixer* components.
* **action**: action the rule is for. In case of components the only action is *use*. You can keep it to \*. There are more actions when it comes to rules for API routes.
* **attributes**: private or non-private. If set to *non-private* the rule will apply to component that do not have `private: true` set in component.json. If set to *private* it will allow users to see private components as well.&#x20;

Let's try more examples. Show only *utils, google* and *slack* components. We're going to add the following three rules:

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG7xd0X_IL44pfwuWuT%2F-MG8H8KAEkWgaWLJCIhU%2FAppmixer_Backoffice_-_ACL_and_Building_A_Cross_Country_Bike_With_More_Bite___Doddy_s_Perfect_Projects_-_YouTube_%F0%9F%94%8A.png?alt=media\&token=d155dc19-f237-4208-b532-f6d17c7f2c7d)

When you refresh Appmixer Designer you can see this:

![Only utils, google and slack components available.](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG7xd0X_IL44pfwuWuT%2F-MG8HVYP_HdQemqZAkpK%2FAppmixer.png?alt=media\&token=be064a35-3ace-40c4-bc69-e3202b10ed95)

Because we used attribute *non-private* for all our rules we can see only components where `private: true` is not set in their manifest. Most *appmixer* component modules user private auxiliary components for listing items into menus (slack channels for example). Therefore we don't see those private components in this menu:

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8HanokV-2WVPrH7SL%2F-MG8JsoVCIVMAKoO92xj%2FAppmixer.png?alt=media\&token=58090f50-6e9a-4234-8916-515a1a072f01)

Let's change the ACL rule for slack module to see those private components as well.

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8HanokV-2WVPrH7SL%2F-MG8Lw0Eg1yrSrV187nQ%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=10556b0e-6a5d-4c0a-bab5-9b026503d19e)

User can see private components now.

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8HanokV-2WVPrH7SL%2F-MG8M8XGuKkfd26_Eqdj%2FAppmixer.png?alt=media\&token=a76774d2-7e2c-4251-a170-6fe94cf264c6)

When you start writing your own components you should use your own vendor (not *appmixer*). We are adding Hello World component for example under vendor *acme*. Its component type is `acme.custom.component.HelloWorld`. Then we have to publish the component into Appmixer and create new ACL rule that will make it accessible to users.

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8HanokV-2WVPrH7SL%2F-MG8W6tPDveRsjM6kj4R%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=c320df65-7238-4085-9b6a-6bbc1297b157)

At this point we can find the new *Hello World* component among other components.

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8HanokV-2WVPrH7SL%2F-MG8WLhvdFg2vb2B2ens%2FAppmixer.png?alt=media\&token=649fd650-9283-4690-94cb-8a42785798fd)

Another example will show how you can user *resource* property to display only *gmail* modul&#x65;*.*

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8HanokV-2WVPrH7SL%2F-MG8XJnBW-NFiPbU7WLj%2FAppmixer.png?alt=media\&token=b790788d-2c52-46a0-9f6d-511e4dec2e52)

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8HanokV-2WVPrH7SL%2F-MG8X7vSvL6c8mf0F16x%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=2e0ecd64-378d-4fd2-8bc3-d59e5392a363)

###

### Routes

You can define ACLs to restrict access to [Flows](https://docs.appmixer.com/6.0/5.0/api/flows) API. The default setting is similar to the one for Components. All roles can access all actions on *flows* resource.&#x20;

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8Y3Yp2ZyHA1B1VSCK%2F-MG94k-WOzWzpgS3re8Z%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=30ece94e-7d9a-4422-adf9-666745e26083)

If you want to limit users from certain role, first you need to delete the general rule. We will show it on *user* role.&#x20;

![](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8Y3Yp2ZyHA1B1VSCK%2F-MG95Ikzju4Qw0lL1zy_%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=604937bd-4638-4fb7-ae16-f57d2b407b7c)

With this setting, any request to any [*/flows*](https://docs.appmixer.com/6.0/5.0/api/flows) endpoint will result in 403 response code. The following example will show you how to limit access to [*/flows*](https://docs.appmixer.com/6.0/5.0/api/flows) API for *user* scope to read only operations.

![Read only access to /flows endpoint.](https://3844357853-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LATDgYqVMe0hChW7efU%2F-MG8Y3Yp2ZyHA1B1VSCK%2F-MG982XMRg2vpgktuJDL%2FAppmixer_Backoffice_-_ACL.png?alt=media\&token=9a16cb61-ca9d-4b6e-b54c-d09d0dc02eeb)

Those rules are store in mongo DB in the following form:

```
{
    "type" : "routes",
    "acl" : [ 
        {
            "role" : "admin",
            "resource" : "flows",
            "action" : [ 
                "*"
            ],
            "attributes" : [ 
                "*"
            ]
        }, 
        {
            "role" : "tester",
            "resource" : "flows",
            "action" : [ 
                "*"
            ],
            "attributes" : [ 
                "*"
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "read"
            ],
            "attributes" : [ 
                "*"
            ]
        }
    ]
}
```

#### Attributes

The next example is not supported in the Backoffice UI, but can be implemented directly using [ACL](https://docs.appmixer.com/6.0/5.0/api/acl) API. Flows may contain [custom metadata](https://docs.appmixer.com/6.0/5.0/flows-metadata-and-filtering#setting-custom-metadata). You can use ACL to restrict access to those metadata. We can create a flow with custom metadata like this:

```
{
    "_id" : ObjectId("5f3696f502ea801d405bb112"),
    "userId" : ObjectId("5f3696f102ea801d405bb10e"),
    "flowId" : "c57f1d30-52fc-4a48-97d9-5d1c296064da",
    "stage" : "stopped",
    "name" : "Flow with metadata",
    "btime" : ISODate("2020-08-14T13:51:49.900Z"),
    "mtime" : ISODate("2020-09-01T14:57:43.536Z"),
    "flow" : {
    },
    "mode" : "module",
    "sharedWith" : [],
    "customFields" : {
        "category" : "test-example"
    }
}
```

where `flow.customFields.category = "test-example"`. This can be done through API. But we want only admin users to be able to do so. The following set of ACL rules will allow admins to create custom fields, but it will allow users to only read those fields.&#x20;

```
{
    "type" : "routes",
    "acl" : [ 
        {
            "role" : "admin",
            "resource" : "flows",
            "action" : [ 
                "*"
            ],
            "attributes" : [ 
                "*"
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "read"
            ],
            "attributes" : [ 
                "*   // are able to read all attributes, including custom fields
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "create"
            ],
            "attributes" : [ 
                "*", "!customFields"   // but they're not able to create them
            ]
        }
    ]
}
```

So if you try to send an API request to create new flow with the following body (as a user with *user* scope).

```
{
    "flow":{},
    "name":"New flow",
    "customFields": {
        "category": "test-category"
    }
}
```

The custom field *category* won't be created. Property *customFields* will be an empty object. Although if you create the same flow with *admin* user that customFields property with category will be created and your user with *user* role will be able to read it (API will return it).

With the following set of rules, users with *user* role won't be able to create and read property *customFields*.

```
{
    "type" : "routes",
    "acl" : [ 
        {
            "role" : "admin",
            "resource" : "flows",
            "action" : [ 
                "*"
            ],
            "attributes" : [ 
                "*"
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "read"
            ],
            "attributes" : [ 
                "*", 
                "!customFields"
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "create"
            ],
            "attributes" : [ 
                "*", 
                "!customFields"
            ]
        }
    ]
}
```

The same way you restrict access to each property on flows collection.

The next JSON shows different syntax with similar functionality. User with role *user* can read/create flows with properties *flow, name, flowId, stage, sharedWith*, but they won't be able to create *customFields* property.

```
{
    "type" : "routes",
    "acl" : [ 
        {
            "role" : "admin",
            "resource" : "flows",
            "action" : [ 
                "*"
            ],
            "attributes" : [ 
                "*"
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "read", 
                "create"
            ],
            "attributes" : [ 
                "flow", 
                "name", 
                "flowId", 
                "stage", 
                "sharedWith"
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "!create"
            ],
            "attributes" : [ 
                "customFields"
            ]
        }
    ]
}
```

You can also use nested objects as *attributes.* Let's say the customFields object contains two properties:

```
{
    "_id" : ObjectId("5f4e654c2c2d2f4d59ca89f9"),
    "userId" : ObjectId("5f3696f102ea801d405bb10e"),
    "flowId" : "46d80c28-72c3-42f1-94ba-2c161e26f041",
    "stage" : "stopped",
    "name" : "New flow",
    "btime" : ISODate("2020-09-01T15:14:20.999Z"),
    "mtime" : ISODate("2020-09-01T15:14:20.999Z"),
    "flow" : {},
    "mode" : "module",
    "sharedWith" : [],
    "customFields" : {
        "visible" : "test visible",
        "not-visible" : "test non visible"
    }
}
```

And we want the users to be able to see only *visible* property, the rules would look like this:

```
{
    "type" : "routes",
    "acl" : [ 
        {
            "role" : "admin",
            "resource" : "flows",
            "action" : [ 
                "*"
            ],
            "attributes" : [ 
                "*"
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "read"
            ],
            "attributes" : [ 
                "*", 
                "!customFields.not-visible"
            ]
        }, 
        {
            "role" : "user",
            "resource" : "flows",
            "action" : [ 
                "create"
            ],
            "attributes" : [ 
                "*", 
                "!customFields"
            ]
        }
    ]
}
```

Users are not able to create *customFields,* they are allowed to read *customFields.visible* property, but not the *customFields.not-visible.*&#x20;
