# Permissions

## Concepts

Debusine uses a permission system inspired from Role-Based Access Control, where permissions are assigned on resources based on the roles that a user has on them.

### Resources

Resources are concrete objects in Debusine’s data model, like scopes, workspaces, collections, artifacts, work requests, and so on.

### Roles

Roles define the access level of a group of users on a resource. They are often written in all-uppercase, like `OWNER`, `ADMIN`, `CONTRIBUTOR`, `VIEWER`. Note that roles are assigned to groups, not users, as Debusine is built on the idea that all individual work could become teamwork with minimal effort.

### Groups

Groups of users are the main actor in the permission system.

A group is uniquely identified by a scope, a name, and optionally a workspace: for example, there can be only one “Admin” group in a scope that is not assigned to a workspace, although each workspace can have its own “Admin” group.

When a user is added to a group they are also assigned a role on the group, which can currently be `MEMBER` or `ADMIN`, to explicitly allow some users to add and remove members from the group.

#### Roles can be inferred

Checking for permissions on a resource does not only depend on the roles the user has on that resource, because roles can be inferred from other roles:

- Having certain roles on a scope gives some permissions over its workspaces, collections, artifacts, workflows, and so on, without needing direct roles over them.

- Having roles on a workspace gives permissions over collections, artifacts, workflows, and so on, without needing direct roles over them.

In other words, permission checks on a resource may take into consideration whether the user has broader roles or roles on a containing resource. For example, any workspace `CONTRIBUTOR` is also a workspace `VIEWER`, and any scope `OWNER` is also a workspace `OWNER`.

Roles may also be inferred from resource properties. For example, if `debusine.db.models.Workspace.public` attribute is `True` then any user will have the `VIEWER` role on the workspace.

### Permissions

Permissions are checked by permission predicates, which are methods of resource objects that take the current user as input and check if a permission should be granted.

#### Permission checks

Permission predicates can be used to test permissions on an individual resource: can the user display the contents of the collection being requested? Can the user write to it?

#### Permission filters

Permission predicates can be used to filter resources to display for UI navigation or selection lists in forms. For example:

- list visible workspaces

- list executable workflows

- list writable collections as targets for a workflow

## Example of a permission check

Let’s see, as an example, what happens if a user tries to display a workspace.

Workspaces have a `Workspace.can_display` method that is called by the web UI or the server API whenever a workspace is accessed, and the method checks if the current user has the `VIEWER` role.

Roles are not assigned directly to users, so Debusine will check roles on all the groups that the current user is a member of. If the user is a member of any group with a `VIEWER` role on the workspace, then the predicate will succeed, otherwise it will fail and Debusine will deny the request.

The `VIEWER` role is defined so it can be:

- directly assigned to a group

- implied from the `CONTRIBUTOR` role

- implied by the workspace being public

The `CONTRIBUTOR` role is defined so it can be assigned directly or implied by the `OWNER` role. In turn the `OWNER` role can be assigned directly or implied by the `OWNER` role on the containing scope. The `OWNER` role on the containing scope can only be assigned directly.

There can be complex sets of implications, but they are set up so that Debusine is able to efficiently resolve them. In this example, the `Workspace.can_display` permission predicate will succeed if either the workspace is public, or if the user is a member of any group for which any of these condition is valid:

- The group has been assigned the `VIEWER` role on the workspace

- The group has been assigned the `CONTRIBUTOR` role on the workspace

- The group has been assigned the `OWNER` role on the workspace

- The group has been assigned the `OWNER` role on the containing scope

## Further reading

For more details on the permission system, see Permissions reference.