# Permissions

Location: [gRPC API](https://developer.m-files.com/APIs/gRPC-API/index.md) > [Concepts](https://developer.m-files.com/APIs/gRPC-API/index.md#concepts)

HTML version: https://developer.m-files.com/APIs/gRPC-API/concepts/permissions/

Every call runs as the user who logged in. What that user may not see is silently left out of
searches and listings, reading it usually fails with "Not found." or "Access denied.", and an
object created without an ACL ends up invisible even to its creator: always send an ACL when you
create objects. The server checks two kinds of rights:

```text
vault-level rights     what the user may do in the vault at all
  (LogIn response: session_data.access_rights.vault_access)
  create_objects, see_all_objects, see_deleted_objects, undelete_objects,
  destroy_objects, change_metadata_structure, manage_workflows, ...

object permissions     what the user may do with one object version
  (the version's AccessControlList)
  read, edit, delete, change permissions
```

Value list items, object types, classes and property definitions carry ACLs of their own (the
`acl` fields of [ValueList](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.ValueList/index.md), [ObjectClass](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.ObjectClass/index.md)
and [PropertyDef](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.PropertyDef/index.md)), with the caller's resulting rights in fields such
as `ObjectClass.current_user_permissions`.

## Object ACLs

An [AccessControlList](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.AccessControlList/index.md) has:

- `custom_component` ([AccessControlListComponent](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.AccessControlListComponent/index.md)):
  either a reference to a **named ACL** (`has_named_acl` true and `named_acl_id`) or explicit
  entries in `permissions`, each an [AccessControlEntry](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.AccessControlEntry/index.md) with
  a subject (a user, a user group, or a pseudo-user such as "the user in the object's Owner
  property") and the permissions granted.
- `restrictive_components` and `additive_components`: automatic permissions, which an object
  gets through lookup values to items that pass their permissions on (see
  `PropertyDef.enable_automatic_permissions`).
- `checked_out_to_user`: the user who has the object checked out and therefore extra rights to
  it while the check-out lasts.

**Named ACLs** are reusable, named permission sets. List them with
[GetNamedACLs](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCNamedACLs/GetNamedACLs/index.md), with `include_builtin` true and
`types` set to the [NACLType](https://developer.m-files.com/APIs/gRPC-API/Reference/Enums/MFiles.NACLType/index.md) values you want as bits (1 for normal
named ACLs); `types` 0 returns nothing. The built-in named ACLs include -1 "Full control for all
internal users" and -20 "Only for me". The Sample Vault adds its own, such as 1 "Visible to
company management only".

## Give new objects an ACL

[AddObjectWithFiles](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/AddObjectWithFiles/index.md) and
[AddObject](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/AddObject/index.md) do not compute a default ACL from the
class or object type. **An unset `acl` creates an object with an empty ACL**: no entries, so
once the object is checked in, only users with the vault-level right to see all objects (vault
administrators, for example) can read it, **not even its creator**. In the Sample Vault, a
normal user who created a document without an ACL could no longer read it after checking it in:
`AddObject` answered with `latest_visible` false, and the `created_object` that
`AddObjectWithFiles` returned had no title or properties.

Send a named ACL reference instead; the server fills in its entries:

```text
acl { custom_component { has_named_acl: true  named_acl_id: -1 } }
```

The document created this way stored group 1 (All internal users) with full control, and its
creator could read it. A reference alone works for named ACLs that do not depend on the current
user. For "Only for me" (-20), a reference alone leaves the object without permissions: send the
named ACL's full `acl_for_objects` from `GetNamedACLs` instead, which names the user.

To have the server recalculate an existing object's ACL from its property
values, call [SetProperties](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/SetProperties/index.md) with
`acl_mode` `ACLENFORCING_MODE_RESET_TO_DEFAULT`
([ACLEnforcingMode](https://developer.m-files.com/APIs/gRPC-API/Reference/Enums/MFiles.ACLEnforcingMode/index.md)); in the Sample Vault that also produced
named ACL -1.

## Reading permissions

| Question | Call |
| --- | --- |
| What may I do in this vault? | `session_data.access_rights` in the [LogIn](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCLogin/LogIn/index.md) response |
| What is the ACL of this object version? | [GetSecurity](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetSecurity/index.md) |
| Who can do what with this object version? | [GetEffectivePermissions](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetEffectivePermissions/index.md) |
| Would an ACL give me some access? | [CheckAccess](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/CheckAccess/index.md) |
| Change an object's ACL | [ChangeSecurity](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/ChangeSecurity/index.md) |
| Value list item permissions | [GetValueListItemsWithPermissions](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCValueLists/GetValueListItemsWithPermissions/index.md) with `include_permissions` |

`GetEffectivePermissions` lists every user who has access, one
[EffectivePermissions](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.EffectivePermissions/index.md) per user ID with `can_user_see`,
`can_user_edit`, `can_user_delete` and `can_user_change_permissions`; a normal user can call it.

## What "access denied" looks like

A caller who lacks rights sees one of three outcomes:

1. **Silence.** Searches and listings leave out what the caller may not see. In the Sample
   Vault the same class search returned 0 contracts to a normal user and 13 to an administrator.
   An object history the caller may not read comes back empty.
2. **"Not found."** Reading an object the caller cannot see at all, such as an object checked out
   to another user and never checked in, or a deleted object, fails like a missing object.
3. **"Access denied."** Acting on something the caller can identify but lacks rights for.

Errors arrive with gRPC status `UNKNOWN`; the status details hold the message. The trailer
`mfiles-error-serialized-bin` holds an [RPCErrorInfoArray](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.RPCErrorInfoArray/index.md)
whose `error_code` values identify the error (`int32`, so 0x800407E4 reads as -2147219484). An
access denial includes 0x800407E4, usually with a second code for the reason:

| Case (seen in the Sample Vault) | Message | Reason code |
| --- | --- | --- |
| No access to the object version | "Access denied. You do not have sufficient access rights to the object." | 0x800400AA |
| Missing vault-level right (an admin service, undelete, destroy) | "Access denied. You do not have the access rights required by this operation." | 0x800400A9 |
| Workflow state transition not allowed | 'Access denied. The state transition "..." is not allowed.' | 0x800400C3 |
| Object or version not visible, or not existing | "Not found." | 0x8004000B (no 0x800407E4) |

The messages contain a line break after "Access denied." An expired or invalid session is the
exception: it arrives as gRPC status `UNAUTHENTICATED` (see
[Authentication and sessions](https://developer.m-files.com/APIs/gRPC-API/runtime/authentication/index.md#when-a-call-answers-unauthenticated)).

Treat access denied as final for the current user and request: retrying the same call does not
help. [Errors](https://developer.m-files.com/APIs/gRPC-API/runtime/errors/index.md) shows how to decode the error trailer and lists the other
common codes.
