Permissions

View as Markdown

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:

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, ObjectClass and PropertyDef), with the caller's resulting rights in fields such as ObjectClass.current_user_permissions.

Object ACLs

An AccessControlList has:

Named ACLs are reusable, named permission sets. List them with GetNamedACLs, with include_builtin true and types set to the NACLType 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 and AddObject 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:

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 with acl_mode ACLENFORCING_MODE_RESET_TO_DEFAULT (ACLEnforcingMode); 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 response
What is the ACL of this object version? GetSecurity
Who can do what with this object version? GetEffectivePermissions
Would an ACL give me some access? CheckAccess
Change an object's ACL ChangeSecurity
Value list item permissions GetValueListItemsWithPermissions with include_permissions

GetEffectivePermissions lists every user who has access, one EffectivePermissions 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 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).

Treat access denied as final for the current user and request: retrying the same call does not help. Errors shows how to decode the error trailer and lists the other common codes.