Wiki

Clone wiki

django-extauth / Home

This page is a work in progress.

Roles

ExtAuth Roles lets you define what a users "role" is, relative to a particular instance of a model. You can then give users in that role additional permissions to that particular instance.

Setup

ExtAuth provides several components that you will need to add to your Django project.

  • Add extauth to your settings.INSTALLED_APPS
  • Add extauth.session.CaptureRequestUser to your settings.MIDDLEWARE_CLASSES. This enables ExtAuth to find the current request.user without you having to specify it. This is especially helpful in library functions where you may not want to pass in request or user objects. Alternately, you can just call extauth.session.set_current_user(user) in your own middleware.
  • Call extauth.roles.autodiscover() in your urls.py. This is just like how the Django Admin app works.
  • Run ./manage.py updateroles and ./manage.py updateperms. These should be run by the syncdb signals, but if you are using something like South that signal may not be called, so the management commands are provided as well.

Defining Roles

ExtAuth Roles are defined much like ModelAdmins are defined for the django.contrib.auth module. You must define a roles.py module in the base of your application. This file is read during a syncdb call, and will automatically add entries into your database for the defined roles.

For each Model you want to manage through ExtAuth Roles, you must register it with a RoleManager class:

from extauth import roles

class WidgetRoles(roles.RoleManager):
    pass
    
roles.register(examples.models.Widget, WidgetRoles)

By User

ExtAuth provides two role types that connect a user to a Model instance, IsSelf and UserIs.

A user has the IsSelf role only on instances of django.contrib.auth.models.User that represent their own user account.

A user has the UserIs role when the specified field in the Model instance is a ForeignKey to their own user account, or a text field who's value matches their username.

from extauth import roles

class WidgetRoles(roles.RoleManager):
    supplier = roles.UserIs('supplier')
    
roles.register(examples.models.Widget, WidgetRoles)

This will give the user the 'supplier' role when their user account is the value of the ForeignKey Widget.supplier.

By Group

ExtAuth also supplies the UserIn role type that connects a user to a Model instance through the user's membership in a group associated with the Model instance.

from extauth import roles

class WidgetRoles(roles.RoleManager):
    supplier = roles.UserIs('supplier')
    dept_member = roles.UserIn('department__membership')
        
roles.register(examples.models.Widget, WidgetRoles)

This will give the user the 'dept_member' role when they are a member of the group specified in the Department.membership ForeignKey for the Department specified in the Widget.department ForeignKey.

Note how the field specified in the role definition can span multiple levels of ForeignKeys by separating them with two underscores, keeping with the convention used by Django's QuerySet.

Custom Roles

While these pre-defined roles will handle most role definitions you could need, you are by no means limited to just those. You can create your own subclass or extauth.roles.RoleBase to create the role definition you need.

Role Permissions

Django lets you associate Permissions to Users and Groups. ExtAuth also lets you associate Permissions to named Roles. When a user is determined to be in that role in relation to a particular Model instance, they will be given the additional permissions specified in the role.

You can do the same by getting an instance of the RoleManager defined for that Model instance:

from extauth import roles

widget_instance = examples.models.Widget()
roles = roles.get_roles(widget_instance)

You can then check if the current user has a specific permission:

roles.has_perm('examples.change_widget')

Or a combination of permissions:

roles.has_all_perms('examples.change_widget', 'examples.modify_widget__name')

roles.has_any_perm('examples.read_widget', 'examples.view_widget__name')

You can also get a list of roles, by name, that the user has in relation to that Model instance:

user_has = roles.getUserRoles()

Authentication Backend

Django 1.2 introduced an API to check per-object permissions. ExtAuth provides a Role-based Backend that implements this feature, just add extauth.backend.RoleBackend to your settings.AUTHENTICATION_BACKENDS.

Then you will get role permission checks without referencing ExtAuth at all:

widget_instance = examples.models.Widget()
can_change = request.user.has_perm('examples.change_widget', widget_instance)

Updated