Security

Guillotina provides an imperative security system. Permissions are computed for a given node in the resource tree using some concept we are going to describe in this document.

Basics

We’ll be explaining the security system by showing examples. Fist, make sure to follow the steps from Getting started.

Now you should have a resource tree that we can represent like the following:

db
└── todo
    ├── <fist_todo_id>
    └── <second_todo_id>

Where db is the database, todo a container with to content inside.

More than that we need some users in order to be able to compute permssion(s) for them, to do so we are going to install guillotina_dbusers, once installed create two users, let’s say “Bob” and “Alice”.

You can find more information about this addon especially how to get Bearer Authorization JWT see training’s users section.

Note that at this moment the resource tree can be represented like this:

db
└── todo
    ├── <fist_todo_id>
    ├── <second_todo_id>
    ├── users
    │   ├── Bob
    │   └── Alice
    └── groups

Now login with “Bob” and try access /db/todo endpoint:

http

GET /db/todo/ HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I
Host: localhost:8080

curl

curl -i http://localhost:8080/db/todo/ -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I'

wget

wget -S -O- http://localhost:8080/db/todo/ --header='Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I'

httpie

http http://localhost:8080/db/todo/ Authorization:'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I'

python-requests

requests.get('http://localhost:8080/db/todo/', headers={'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I'})

response

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
    "auths": [
        "Bob"
    ],
    "content": "< Container at /todo by 140237937521992 >",
    "reason": "You are not authorized to view"
}

Like you can see in the response you are not authorized to view.

Let’s grant “Bob” view permission for this db/todo/ resource tree node:

http

POST /db/todo/@sharing HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "prinperm": [
        {
            "permission": "guillotina.ViewContent",
            "principal": "bob",
            "setting": "Allow"
        }
    ]
}

curl

curl -i -X POST http://localhost:8080/db/todo/@sharing -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"prinperm": [{"permission": "guillotina.ViewContent", "principal": "bob", "setting": "Allow"}]}' --user root:root

wget

wget -S -O- http://localhost:8080/db/todo/@sharing --header='Accept: application/json' --header='Content-Type: application/json' --post-data='{"prinperm": [{"permission": "guillotina.ViewContent", "principal": "bob", "setting": "Allow"}]}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "prinperm": [
    {
      "permission": "guillotina.ViewContent",
      "principal": "bob",
      "setting": "Allow"
    }
  ]
}' | http POST http://localhost:8080/db/todo/@sharing Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.post('http://localhost:8080/db/todo/@sharing', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'prinperm': [{'permission': 'guillotina.ViewContent', 'principal': 'bob', 'setting': 'Allow'}]}, auth=('root', 'root'))

response

HTTP/1.1 200 OK
Content-Type: application/json

You can now access to /db/todo endpoint using Bob user:

http

GET /db/todo/ HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I
Host: localhost:8080

curl

curl -i http://localhost:8080/db/todo/ -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I'

wget

wget -S -O- http://localhost:8080/db/todo/ --header='Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I'

httpie

http http://localhost:8080/db/todo/ Authorization:'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I'

python-requests

requests.get('http://localhost:8080/db/todo/', headers={'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIyNTM3NDcsImlkIjoiQm9iIn0.1-JbNe1xNoHJgPEmJ05oULi4I9OMGBsviWFHnFPvm-I'})

response

HTTP/1.1 200 OK
Content-Type: application/json

{
    "@id": "http://localhost:8080/db/todo",
    "@name": "todo",
    "@type": "Container",
    "@uid": "6e63e13b4d1647d5a4ef5ef61ea040f1",
    "UID": "6e63e13b4d1647d5a4ef5ef61ea040f1",
    "__behaviors__": [],
    "__name__": "todo",
    "creation_date": "2018-07-22T07:33:19.098099+00:00",
    "is_folderish": true,
    "items": [
        {
            "@id": "http://localhost:8080/db/todo/9eca9e3e84ce4e79883f19fdbbe694b1",
            "@name": "9eca9e3e84ce4e79883f19fdbbe694b1",
            "@type": "ToDo",
            "@uid": "6e6|9eca9e3e84ce4e79883f19fdbbe694b1",
            "UID": "6e6|9eca9e3e84ce4e79883f19fdbbe694b1"
        },
        {
            "@id": "http://localhost:8080/db/todo/ae45417c8115463aa2d6437de3577d02",
            "@name": "ae45417c8115463aa2d6437de3577d02",
            "@type": "ToDo",
            "@uid": "6e6|ae45417c8115463aa2d6437de3577d02",
            "UID": "6e6|ae45417c8115463aa2d6437de3577d02"
        },
        {
            "@id": "http://localhost:8080/db/todo/groups",
            "@name": "groups",
            "@type": "GroupManager",
            "@uid": "6e6|ff31eda7808044488dc492d2075e4e13",
            "UID": "6e6|ff31eda7808044488dc492d2075e4e13"
        },
        {
            "@id": "http://localhost:8080/db/todo/users",
            "@name": "users",
            "@type": "UserManager",
            "@uid": "6e6|753405ce2dfe4455930c8fc850f38157",
            "UID": "6e6|753405ce2dfe4455930c8fc850f38157"
        }
    ],
    "length": 4,
    "modification_date": "2018-07-22T09:33:13.486834+00:00",
    "parent": {},
    "title": "ToDo List",
    "type_name": "Container",
    "uuid": "6e63e13b4d1647d5a4ef5ef61ea040f1"
}

What we’ve done so far looks like we’ve grant user “Bob” view access to this node, but that’s not totally true.

As you can see in the permission definition we grant permission to a principal. A principal is like a tag and we grant permission to that tag. The user’s id is the “principal” here but more on that later.

Another important thing is the setting attribute, which defined the permission propagation in the resource tree, this attribute can have only three value:

  • Allow: set on resource and children will inherit
  • Deny: set on resource and children will inherit (good way to stop propagation)
  • AllowSingle: set on resource and children will not inherit (also a good way to stop propagation)
  • Unset: you remove the setting

Note that we’ve defined a permission with “Allow” propagation setting at this level of the resource tree:

db
└── todo                   <-- permission was granted here
    ├── <fist_todo_id>
    ├── <second_todo_id>
    ├── users
    │   ├── Bob
    │   └── Alice
    └── groups

Which means that user “Bob” can view todo container, but also all todo, users and groups, but cannot db database. Try it.

The last parameter in our permission definition we’ve talk so far is the permission parameter itself, Guillotina provided a lot of permission by default, you can find an exhaustive like by reading Guillotina permissions definitions from the source code.

Most of the application permissions your application should be defined there, but you can also define your own, more on that later.

Groups

Groups can be assigned to users, each group names are also principals, this is the way we can add principals to users.

Let’s add a group named todo_viewer:

http

POST /db/todo/groups HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "@type": "Group",
    "id": "todo_viewer",
    "title": "TODO Viewer"
}

curl

curl -i -X POST http://localhost:8080/db/todo/groups -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"@type": "Group", "id": "todo_viewer", "title": "TODO Viewer"}' --user root:root

wget

wget -S -O- http://localhost:8080/db/todo/groups --header='Accept: application/json' --header='Content-Type: application/json' --post-data='{"@type": "Group", "id": "todo_viewer", "title": "TODO Viewer"}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "@type": "Group",
  "id": "todo_viewer",
  "title": "TODO Viewer"
}' | http POST http://localhost:8080/db/todo/groups Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.post('http://localhost:8080/db/todo/groups', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'@type': 'Group', 'id': 'todo_viewer', 'title': 'TODO Viewer'}, auth=('root', 'root'))

response

HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:8080/db/todo/groups/todo_viewer

{
    "@id": "http://localhost:8080/db/todo/groups/todo_viewer",
    "@name": "todo_viewer",
    "@type": "Group",
    "@uid": "6e6|ff3|14f624ef23094362961df0e083cd77e4",
    "groupname": null,
    "id": "todo_viewer",
    "title": null,
    "roles": [],
    "users": {
        "items": [],
        "items_total": 0
    }
}

And add “Bob” and “Alice” to that group.

http

PATCH /db/todo/users/Bob HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "user_groups": [
        "todo_viewer"
    ]
}

curl

curl -i -X PATCH http://localhost:8080/db/todo/users/Bob -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"user_groups": ["todo_viewer"]}' --user root:root

wget

wget -S -O- --method=PATCH http://localhost:8080/db/todo/users/Bob --header='Accept: application/json' --header='Content-Type: application/json' --body-data='{"user_groups": ["todo_viewer"]}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "user_groups": [
    "todo_viewer"
  ]
}' | http PATCH http://localhost:8080/db/todo/users/Bob Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.patch('http://localhost:8080/db/todo/users/Bob', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'user_groups': ['todo_viewer']}, auth=('root', 'root'))

response

HTTP/1.1 204 No Content
Content-Type: application/json

http

PATCH /db/todo/users/Alice HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "user_groups": [
        "todo_viewer"
    ]
}

curl

curl -i -X PATCH http://localhost:8080/db/todo/users/Alice -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"user_groups": ["todo_viewer"]}' --user root:root

wget

wget -S -O- --method=PATCH http://localhost:8080/db/todo/users/Alice --header='Accept: application/json' --header='Content-Type: application/json' --body-data='{"user_groups": ["todo_viewer"]}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "user_groups": [
    "todo_viewer"
  ]
}' | http PATCH http://localhost:8080/db/todo/users/Alice Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.patch('http://localhost:8080/db/todo/users/Alice', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'user_groups': ['todo_viewer']}, auth=('root', 'root'))

response

HTTP/1.1 204 No Content
Content-Type: application/json

Let’s grant todo_viewer view permission for this db/todo/ resource tree node:

http

POST /db/todo/@sharing HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "prinperm": [
        {
            "permission": "guillotina.ViewContent",
            "principal": "todo_viewer",
            "setting": "Allow"
        }
    ]
}

curl

curl -i -X POST http://localhost:8080/db/todo/@sharing -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"prinperm": [{"permission": "guillotina.ViewContent", "principal": "todo_viewer", "setting": "Allow"}]}' --user root:root

wget

wget -S -O- http://localhost:8080/db/todo/@sharing --header='Accept: application/json' --header='Content-Type: application/json' --post-data='{"prinperm": [{"permission": "guillotina.ViewContent", "principal": "todo_viewer", "setting": "Allow"}]}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "prinperm": [
    {
      "permission": "guillotina.ViewContent",
      "principal": "todo_viewer",
      "setting": "Allow"
    }
  ]
}' | http POST http://localhost:8080/db/todo/@sharing Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.post('http://localhost:8080/db/todo/@sharing', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'prinperm': [{'permission': 'guillotina.ViewContent', 'principal': 'todo_viewer', 'setting': 'Allow'}]}, auth=('root', 'root'))

response

HTTP/1.1 200 OK
Content-Type: application/json

Now Alice should be able to view todo container and all it’s children.

At the moment Alice can view users and groups which is not convenient for a todo_viewer group, let’s deny that.

http

POST /db/todo/users/@sharing HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "prinperm": [
        {
            "permission": "guillotina.ViewContent",
            "principal": "todo_viewer",
            "setting": "Deny"
        }
    ]
}

curl

curl -i -X POST http://localhost:8080/db/todo/users/@sharing -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"prinperm": [{"permission": "guillotina.ViewContent", "principal": "todo_viewer", "setting": "Deny"}]}' --user root:root

wget

wget -S -O- http://localhost:8080/db/todo/users/@sharing --header='Accept: application/json' --header='Content-Type: application/json' --post-data='{"prinperm": [{"permission": "guillotina.ViewContent", "principal": "todo_viewer", "setting": "Deny"}]}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "prinperm": [
    {
      "permission": "guillotina.ViewContent",
      "principal": "todo_viewer",
      "setting": "Deny"
    }
  ]
}' | http POST http://localhost:8080/db/todo/users/@sharing Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.post('http://localhost:8080/db/todo/users/@sharing', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'prinperm': [{'permission': 'guillotina.ViewContent', 'principal': 'todo_viewer', 'setting': 'Deny'}]}, auth=('root', 'root'))

response

HTTP/1.1 200 OK
Content-Type: application/json

http

POST /db/todo/groups/@sharing HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "prinperm": [
        {
            "permission": "guillotina.ViewContent",
            "principal": "todo_viewer",
            "setting": "Deny"
        }
    ]
}

curl

curl -i -X POST http://localhost:8080/db/todo/groups/@sharing -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"prinperm": [{"permission": "guillotina.ViewContent", "principal": "todo_viewer", "setting": "Deny"}]}' --user root:root

wget

wget -S -O- http://localhost:8080/db/todo/groups/@sharing --header='Accept: application/json' --header='Content-Type: application/json' --post-data='{"prinperm": [{"permission": "guillotina.ViewContent", "principal": "todo_viewer", "setting": "Deny"}]}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "prinperm": [
    {
      "permission": "guillotina.ViewContent",
      "principal": "todo_viewer",
      "setting": "Deny"
    }
  ]
}' | http POST http://localhost:8080/db/todo/groups/@sharing Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.post('http://localhost:8080/db/todo/groups/@sharing', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'prinperm': [{'permission': 'guillotina.ViewContent', 'principal': 'todo_viewer', 'setting': 'Deny'}]}, auth=('root', 'root'))

response

HTTP/1.1 200 OK
Content-Type: application/json

Now both Alice and Bob can’t access to users and groups, if you want Bob to be able to access those endpoints you should explicitly set permission for principal “Bob” on those ones.

Roles

Roles are granted permissions, which means that a principal with one role will inherit all that role permissions.

Guillotina defined serval default roles, see developer roles section. But remember that you can defined your own ones(more on that later).

For example let’s give to principal “Alice” the guillotina.Editor role on /db/todo/<first_todo_id> resource tree node, which grants the following permissions:

  • guillotina.AccessContent
  • guillotina.ViewContent
  • guillotina.ModifyContent
  • guillotina.ReindexContent

To do use run (don’t forget to replace <first_todo_id_> with your first todo id):

http

POST /db/todo/<first_todo_id>/@sharing HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "prinrole": [
        {
            "principal": "alice",
            "role": "guillotina.Editor",
            "setting": "Allow"
        }
    ]
}

curl

curl -i -X POST 'http://localhost:8080/db/todo/<first_todo_id>/@sharing' -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"prinrole": [{"principal": "alice", "role": "guillotina.Editor", "setting": "Allow"}]}' --user root:root

wget

wget -S -O- 'http://localhost:8080/db/todo/<first_todo_id>/@sharing' --header='Accept: application/json' --header='Content-Type: application/json' --post-data='{"prinrole": [{"principal": "alice", "role": "guillotina.Editor", "setting": "Allow"}]}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "prinrole": [
    {
      "principal": "alice",
      "role": "guillotina.Editor",
      "setting": "Allow"
    }
  ]
}' | http POST 'http://localhost:8080/db/todo/<first_todo_id>/@sharing' Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.post('http://localhost:8080/db/todo/<first_todo_id>/@sharing', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'prinrole': [{'principal': 'alice', 'role': 'guillotina.Editor', 'setting': 'Allow'}]}, auth=('root', 'root'))

response

HTTP/1.1 200 OK
Content-Type: application/json

Now Alice can access, view, modify and reindex the first todo but Bob still only view to it.

You can also add permission for a role at/from a given resource tree node for a given role, for example at the moment principal “Alice” which have “guillotina.Editor” role on /db/todo/<first_todo_id> cannot delete it.

Let’s fix that by giving “guillotina.DeleteContent” permission to “guillotina.Editor” role at this specific resource tree node:

http

POST /db/todo/<first_todo_id>/@sharing HTTP/1.1
Accept: application/json
Authorization: Basic cm9vdDpyb290
Content-Type: application/json
Host: localhost:8080

{
    "roleperm": [
        {
            "permission": "guillotina.DeleteContent",
            "role": "guillotina.Editor",
            "setting": "Allow"
        }
    ]
}

curl

curl -i -X POST 'http://localhost:8080/db/todo/<first_todo_id>/@sharing' -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"roleperm": [{"permission": "guillotina.DeleteContent", "role": "guillotina.Editor", "setting": "Allow"}]}' --user root:root

wget

wget -S -O- 'http://localhost:8080/db/todo/<first_todo_id>/@sharing' --header='Accept: application/json' --header='Content-Type: application/json' --post-data='{"roleperm": [{"permission": "guillotina.DeleteContent", "role": "guillotina.Editor", "setting": "Allow"}]}' --auth-no-challenge --user=root --password=root

httpie

echo '{
  "roleperm": [
    {
      "permission": "guillotina.DeleteContent",
      "role": "guillotina.Editor",
      "setting": "Allow"
    }
  ]
}' | http POST 'http://localhost:8080/db/todo/<first_todo_id>/@sharing' Accept:application/json Content-Type:application/json -a root:root

python-requests

requests.post('http://localhost:8080/db/todo/<first_todo_id>/@sharing', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'roleperm': [{'permission': 'guillotina.DeleteContent', 'role': 'guillotina.Editor', 'setting': 'Allow'}]}, auth=('root', 'root'))

response

HTTP/1.1 200 OK
Content-Type: application/json

Now anyone who have “guillotina.Editor” role on that node, including only Alice at the moment, will be able to delete it.

Security Levels

Security for every operation is managed against three definitions (in order of priority):

  • Local
  • Global
  • Code

“Local” means for a given resource tree node.

“Global” stand for application level.

And finally “Code” for code level, like services, containers or whatever code exposed to the API.

This means that principal or role could be mandatory to access them.

Locals can defined:

  • Permission for principal with propagation definition
  • Role for principal with propagation definition
  • Permission for role with propagation definition

Globals:

  • Role for principal
  • Permission for principal

Code:

  • Role for principal
  • Permission for principal
  • Permission for role

Roles

There are two kind of roles: Global and Local. The ones that are defined to be local can’t be used globally and vice-versa. On indexing, the global roles are the ones that are indexed for security in addition to the flat user/group information from each resource.

Python helper functions


# Code to get the global roles that have access_content to an object
from guillotina.security.utils import get_roles_with_access_content
get_roles_with_access_content(obj)

# Code to get the user list that have access content to an object
from guillotina.security.utils import get_principals_with_access_content
get_principals_with_access_content(obj)


# Code to get all the security info
from guillotina.security.utils import settings_for_object
settings_for_object(obj)

# Code to get the Interaction object ( security object )
from guillotina.interfaces import ISecurityPolicy

policy = get_utility(ISecurityPolicy)

# Get the list of global roles for a user and some groups
policy.global_principal_roles(principal, groups)

# Get if the authenticated user has permission on a object
policy.check_permission(permission, obj)

REST APIs

Get all the endpoints and their security

[GET] APPLICATION_URL/@apidefinition (you need guillotina.GetContainers permission)

Get the security info for a resource (with inherited info)

[GET] RESOURCE/@sharing (you need guillotina.SeePermissions permission)

Modify the local roles/permission for a resource

[POST] RESOURCE/@sharing (you need guillotina.ChangePermissions permission)

{
"prinperm": [
  {
    "principal": "foobar",
    "permission": "guillotina.ModifyContent",
    "setting": "Allow"
  }
],
"prinrole": [
  {
    "principal": "foobar",
    "role": "guillotina.Owner",
    "setting": "Allow"
  }
],
"roleperm": [
  {
    "permission": "guillotina.ModifyContent",
    "role": "guillotina.Member",
    "setting": "Allow"
  }
]
}

Propagation setting

The different types are:

  • Allow: set on resource and children will inherit
  • Deny: set on resource and children will inherit (good way to stop propagation)
  • AllowSingle: set on resource and children will not inherit (also a good way to stop propagation)
  • Unset: you remove the setting