A quick example

Models

Suppose that we have a Django model called Organization we want to manage with django-tutelary. We mark up the basic model definition using a decorator (permissioned_model) and a metadata class (TutelaryMeta):

from django.db import models
from tutelary.decorators import permissioned_model

@permissioned_model
class Organization(models.Model):
    name = models.CharField(max_length=100)

    class TutelaryMeta:
        perm_type = 'organization'
        path_fields = ('name',)
        actions = [('org.list',   {'permissions_object': None}),
                   ('org.create', {'permissions_object': None}),
                   'org.delete']

Here, the TutelaryMeta class carries metadata describing the actions that can be performed on an Organization object, and how to represent instances of Organization as django-tutelary objects. Here, an Organization with name = "Cadasta" would be represented by the django-tutelary object organization/Cadasta, based on the perm_type and path_fields values.

Views

The link between the view used to perform particular operations on Django objects and the django-tutelary permissions required to perform those operations is made in the following way:

from django.core.urlresolvers import reverse_lazy
import django.views.generic.edit as edit
from tutelary.mixins import PermissionRequiredMixin
from .models import Organization

class OrganizationDelete(PermissionRequiredMixin,
                         edit.DeleteView):
    model = Organization
    success_url = reverse_lazy('organization-list')
    permission_required = 'org.delete'

Here, we use a normal Django class-based view and mix in django-tutelary’s PermissionRequiredMixin. This mixin uses the permission_required attribute on the OrganizationDelete view to determine which django-tutelary action this view corresponds to. If a user attempts to delete an organization, the user’s associated permission set (generated from the policies assigned to the user) is used to determine whether the org.delete action is allowed on the organization in question. If the action is allowed, view processing proceeds as normal. If the action is denied, a PermissionDenied exception is raised.

Policies

Policies can be read from JSON files or stored in a database. Here’s a simple example of reading a couple of policy documents from files, creating a role from them and assigning the role to a user:

from django.contrib.auth.models import User
from tutelary.models import Policy

default_p = Policy(name='default',
                   body=open('default-policy.json').read())
default_p.save()
sysadmin_p = Policy(name='sys-admin-policy',
                    body=open('sys-admin-policy.json').read())
sysadmin_p.save()

sysadmin_role = Roles.objects.create(
    name='sys-admin', policies=[default_p, sysadmin_p]
)

sysadmin = User.objects.get(username='admin')
sysadmin.assign_policies(sysadmin_role)

After the call to User.assign_policies, any subsequent permissions queries against the admin user will be answered according to the contents of the policies in the default-policy.json and sys-admin-policy.json files.