# Users, groups and permissions in OpenPlatform

> How a user reaches an application in OpenPlatform: groups decide which applications the user sees and which permission values each application receives.

Framework: openplatform
Product: OpenPlatform (openplatform@5)
Language: en
Content-SHA256: bf071417d9206260fbcb3592fc8ca09a567f81e2d1c8ea1f513e1615cfb33afc
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: 
Review: not-recorded

OpenPlatform separates **who** (users), **where** (applications) and **what** (permissions) with groups in the middle:

- A **user** has a name, an email, a language, a password and flags (`sa` for administrator, `isconfirmed`, `isdisabled`, `isinactive`, `notifications`, `sounds`...) and belongs to any number of groups (schema `@User`, `plugins/setup/schemas/users.js`).
- A **group** has a name, a colour, an icon, an optional `reference` and a list of permissions (schema `@Group`, `plugins/setup/schemas/groups.js`).
- An **application** declares its own permissions: each has a name and a `value`, a plain string that the application understands (`plugins/setup/schemas/apps.js`).

## How the access is computed

The function `FUNC.permissions(userid, callback)` in `definitions/func.js` builds, for a user:

1. the groups of the user that are not disabled;
2. the rows of `tbl_group_permission` of those groups: a row with a permission gives that permission of an application, and a row **without** a permission just gives the application (the user sees it and receives an empty list of permissions);
3. the `value` of each granted permission, only for applications that are not removed and not disabled.

The result has three parts: the applications of the user (`apps`), the permission values by application (`permissions`) and the groups (`groups`). It is stored as JSON in the column `cache` of the user, with a `cachefilter` that lists the groups (`G<id>`) and the applications (`A<id>`) it depends on. When a group or an application changes, `FUNC.clearcache(id)` clears the cache of every user whose filter contains that identifier, and the next request rebuilds it.

## Where the application sees it

- The portal lists only the applications in `apps` and refuses to open any other one ("App not found").
- The application receives its own list in `permissions` when it verifies a launch (an array of the `value` strings), together with the ids of the groups, so it can decide what to show ([how an app connects](/en/openplatform/how-an-app-connects/)).
- The setup screen decides who may use it by the flag `sa` of the user.

A good habit, from the way the code works: name the `value` of a permission after the action in your application (`orders.read`, `orders.write`) and map groups to those values in OpenPlatform, so that your application only checks strings.
