Skip to content

Declaring roles and permissions

Creating yml file

Respo provides complete and easy way of declaring roles and permissions.

The whole idea is to have all of them in single yml file that will be source of truth for the app. (later, we will convert it to pickle format after validation).

For this tutorial, we will work on file respo_model.yml that will be used in next sections.

Content of respo_model.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
permissions:
  - user.read_basic
  - user.read_all
  - user.read_all_better
  - user.update

  - book.list
  - book.read
  - book.sell
  - book.buy

principles:
  - when: book.list
    then: [book.read]

  - when: user.read_all
    then: [user.read_basic]

  - when: user.read_all_better
    then: [user.read_all]

roles:
  - name: default
    permissions:
      - user.read_all
      - book.list

  - name: admin
    include: [default]
    permissions:
      - user.read_all_better

  - name: pro_user
    include: [default]
    permissions:
      - book.sell

  - name: superadmin
    include: [admin, pro_user]
    permissions:
      - user.update

Permissions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
permissions:
  - user.read_basic
  - user.read_all
  - user.read_all_better
  - user.update

  - book.list
  - book.read
  - book.sell
  - book.buy

Note

To avoid issues, every permission must be two lowercase asci alphanumeric strings (at least length of 1), separated by a dot. Full regex is ^[a-z_0-9]{1,}\.[a-z_0-9]{1,}$

First we need to define unique permissions for resources. This could be anything, but suggested convention is "user.read" or "book.list" etc. where first part is named collection or group (many permissions can share the same collection) and the second is specific name in this collection. The more self-describing names, the better.

Every API endpoint SHOULD require exactly one permission (or zero, of course), ideally the name of endpoint should be similar to required permission.

Principles

1
2
3
4
5
6
7
8
9
principles:
  - when: book.list
    then: [book.read]

  - when: user.read_all
    then: [user.read_basic]

  - when: user.read_all_better
    then: [user.read_all]

Note

This section is not obligatory in yml file. If you don't need stronger permissions, just skip it

Permissions may also contain other permissions. For example, in our API read.read_all is more powerful than read.read_basic so we can write:

1
2
3
principles:
  - when: read.read_all
    then: [read.read_basic]

Consider two endpoints:

  • POST /read/read_all
  • POST /read/read_basic

Someone with a permission to read every information: read.read_all (whatever it is), logically should also be able to read basic informations. By decalring it here in principles part, you can avoid if statements here and there in the app.

Roles

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
roles:
  - name: default
    permissions:
      - user.read_all
      - book.list

  - name: admin
    include: [default]
    permissions:
      - user.read_all_better

  - name: pro_user
    include: [default]
    permissions:
      - book.sell

  - name: superadmin
    include: [admin, pro_user]
    permissions:
      - user.update

Note

Every role name must be a lowercase asci alphanumeric string (at least length of 1). Full regex is ^[a-z_0-9]{1,}$

The last part of file is a list of roles. Every role has unique name, list of permission (that this role has, defined in permissions section) and optionally attribute include (list of other role names defined in this section), so role can extend other roles.