Permissions

Cliquet provides a mechanism to handle authorization on the stored objects.

Glossary

Authorization isn’t complicated, but requires the introduction of a few terms so that explanations are easier to follow:

Object:
The data that is stored into Cliquet. objects usually match the resources you defined; For one resource there are two objects: resource’s collection and resource’s records.
Principal:
An entity that can be authenticated. principals can be individual people, computers, services, or any group of such things.
Permission:
An action that can be authorized or denied. read, write, create are permissions.
Access Control Entity (ACE):
An association of a principal, an object and a permission. For instance, (Alexis, article, write).
Access Control List (ACL):
A list of Access Control Entities (ACE).

Overview

By default, the resources defined by Cliquet are public, and records are isolated by user. But it is also possible to define protected resources, which will required the user to have access to the requested resource.

from cliquet import authorization
from cliquet import resource


@resource.register(factory=authorization.RouteFactory)
class Toadstool(resource.ProtectedResource):
    mapping = MushroomSchema()

In this example, a route factory is registered. Route factories are explained in more details below.

A protected resource, in addition to the data property of request / responses, takes a permissions property which contains the list of principals that are allowed to access or modify the current object.

During the creation of the object, the permissions property is stored in the permission backend, and upon access, it checks the current principal has access the the object, with the correct permission.

Route factory

The route factory decides which permission is required to access one resource or another. Here is a summary of the permissions that are defined by the default route factory Cliquet defines:

Method permission
POST create
GET / HEAD read
PUT create if it doesn’t exist, write otherwise
PATCH write
DELETE write

Route factories are best described in the pyramid documentation

class cliquet.authorization.RouteFactory(request)

Authorization policy

Upon access, the authorization policy is asked if any of the current list of principals has access to the current resource. By default, the authorization policy Cliquet checks in the permission backend for the current object.

It is possible to extend this behavior, for instance if there is an inheritance tree between the defined resources (some ACEs should give access to its child objects).

In case the application should define its own inheritance tree, it should also define its own authorization policy.

To do so, subclass the default AuthorizationPolicy and add a specific get_bound_permission method.

from cliquet import authorization
from pyramid.security import IAuthorizationPolicy
from zope.interface import implementer

@implementer(IAuthorizationPolicy)
class AuthorizationPolicy(authorization.AuthorizationPolicy):
    def get_bound_permissions(self, *args, **kwargs):
    """Callable that takes an object ID and a permission and returns
    a list of tuples (<object id>, <permission>)."""
        return build_permissions_set(*args, **kwargs)
class cliquet.authorization.AuthorizationPolicy

Permissions backend

The ACLs are stored in a permission backend. Currently, permission backends exists for Redis and PostgreSQL, as well as a in memory one. It is of course possible to add you own permission backend, if you whish to store your permissions related data in a different database.

class cliquet.permission.PermissionBase(*args, **kwargs)
initialize_schema()

Create every necessary objects (like tables or indices) in the backend.

This is excuted with the cliquet migrate command.

flush()

Delete all data stored in the permission backend.

add_user_principal(user_id, principal)

Add an additional principal to a user.

Parameters:
  • user_id (str) – The user_id to add the principal to.
  • principal (str) – The principal to add.
remove_user_principal(user_id, principal)

Remove an additional principal from a user.

Parameters:
  • user_id (str) – The user_id to remove the principal to.
  • principal (str) – The principal to remove.
user_principals(user_id)

Return the set of additionnal principals given to a user.

Parameters:user_id (str) – The user_id to get the list of groups for.
Returns:The list of group principals the user is in.
Return type:set
add_principal_to_ace(object_id, permission, principal)

Add a principal to an Access Control Entry.

Parameters:
  • object_id (str) – The object to add the permission principal to.
  • permission (str) – The permission to add the principal to.
  • principal (str) – The principal to add to the ACE.
remove_principal_from_ace(object_id, permission, principal)

Remove a principal to an Access Control Entry.

Parameters:
  • object_id (str) – The object to remove the permission principal to.
  • permission (str) – The permission that should be removed.
  • principal (str) – The principal to remove to the ACE.
object_permission_principals(object_id, permission)

Return the set of principals of a bound permission (unbound permission + object id).

Parameters:
  • object_id (str) – The object_id the permission is set to.
  • permission (str) – The permission to query.
Returns:

The list of user principals

Return type:

set

principals_accessible_objects(principals, permission, object_id_match=None, get_bound_permissions=None)

Return the list of objects id where the specified principals have the specified permission.

Parameters:
  • principal (list) – List of user principals
  • permission (str) – The permission to query.
  • object_id_match (str) – Filter object ids based on a pattern (e.g. '*articles*').
  • get_bound_permissions (function) – The methods to call in order to generate the list of permission to verify against. (ie: if you can write, you can read)
Returns:

The list of object ids

Return type:

set

object_permission_authorized_principals(object_id, permission, get_bound_permissions=None)

Return the full set of authorized principals for a given permission + object (bound permission).

Parameters:
  • object_id (str) – The object_id the permission is set to.
  • permission (str) – The permission to query.
  • get_bound_permissions (function) – The methods to call in order to generate the list of permission to verify against. (ie: if you can write, you can read)
Returns:

The list of user principals

Return type:

set

check_permission(object_id, permission, principals, get_bound_permissions=None)

Test if a principal set have got a permission on an object.

Parameters:
  • object_id (str) – The identifier of the object concerned by the permission.
  • permission (str) – The permission to test.
  • principals (set) – A set of user principals to test the permission against.
  • get_bound_permissions (function) – The method to call in order to generate the set of permission to verify against. (ie: if you can write, you can read)
ping(request)

Test the permission backend is operationnal.

Parameters:request (Request) – current request object
Returns:True is everything is ok, False otherwise.
Return type:bool
object_permissions(object_id, permissions=None)

Return the set of principals for each object permission.

Parameters:
  • object_id (str) – The object_id the permission is set to.
  • permissions (list) – List of permissions to retrieve. If not define will try to find them all.
Returns:

The dictionnary with the list of user principals for each object permissions

Return type:

dict

replace_object_permissions(object_id, permissions)

Replace given object permissions.

Parameters:
  • object_id (str) – The object to replace permissions to.
  • permissions (str) – The permissions dict to replace.
delete_object_permissions(*object_id_list)

Delete all listed object permissions.

Parameters:object_id (str) – Remove given objects permissions.