Skip to content

The ACCESS file

The bundles, status actions and roles a project always has, written as code - reviewed like code, and the same on every machine.

# config/access.py - CLEARANCE = {'ACCESS': 'config.access.ACCESS'}
ACCESS = {
    'bundles': {
        'Branch managers': {'shop.order_view': 'branch', 'shop.order_approve': 'branch'},
        'Accountants': {'shop.order_view': 'all', 'shop.order_view_price': None},
    },
    'status_actions': {                  # for a model keeping Django's permissions
        'shop.Payment': {
            'refund': {'field': 'state', 'to': ['refunded'], 'from': ['paid']},
        },
    },
    'roles': {                           # with clearance.roles installed
        'customer': {
            'name': 'Customer',
            'ceiling': ['shop.order_view', 'shop.order_create'],
            'bundles': ['Customers'],
        },
    },
}

bundles

{name: {permission: scope}}. A permission is app_label.codename; a scope is a scope's code - all, a code scope, a rule scope - or None, for the model's default.

status_actions

{'app_label.Model': {code: spec}}, for a model that keeps Django's permissions. A model declaring its own with build_permissions declares its status actions there.

key
field required a field with choices, or a boolean
to required the values only this action writes
from optional the values it writes from; left out, from any
name optional what the admin site shows; left out, the code, readable

roles

With clearance.roles installed. {code: spec}:

key
name optional left out, the code, readable
ceiling optional a list of permissions; None for no ceiling; left out, nothing is permitted, as for a new role
bundles optional the starting bundles - declared in the file, or made in the admin site

What the file owns

  • The file owns what it names, and nothing else. A sync makes what the file adds, changes what it changes, and deletes what it once named and names no more. A bundle, role or status action made in the admin site is never touched until the file comes to name it; from then on the file owns it.
  • What the file owns is read only in the admin site - to everybody, the superuser too - because the next sync would put it back.
  • Who is given a bundle or a role is not the file's to say. That stays in the admin site, or in a project's own code.

Applying it

python manage.py clearance_sync --dry-run    # what would change, writing nothing
python manage.py clearance_sync --check      # in CI: fail when the database differs
python manage.py clearance_sync              # apply it, and say what changed

Or on every migrate, with SYNC_ON_MIGRATE. A sync is listed whole before anything is written, and applied in one transaction: a sync that would leave nobody able to manage access changes nothing. Start-up refuses a file that cannot be read or says something that cannot be (E001); whether every permission and scope it names exists in the database is --check's to say.