Package: django-rbac
OverviewFirst of all, I would like to show some drawbacks of
Django’s current permission system:Permissions are tied directly to theUsermodel fromdjango.contrib.auth, so you cannot use any other existing
model in your application.The task of mantaining this list of permissions in the current Django system
is responsibility of a superuser or some other kind of centralized entity.You can certainly assign permissions toGroupmodel instances, but all
users in this group will share the same permissions.Last, but not least, until Django v1.2 will come and ticket#11010implemented, the permission system is model-level – it doesn’t allow granular
permissions (row-level), which means you can give a user authorization to do
something based on all instances of a model class, but not to a
single model instance (an object).Many applications, and specially today’s web applications – which involve
concepts as collaboration or content driven by the users – need the flexibility
to support delegation of permission granting to objects by other trusted agents.
A clear example is a social networking site, where the users want to allow or
deny access to their profiles or pictures, open or close their different
communication channels like receiving friendship requests or private messages.
django-rbac tries to champion this by introducing some key features from the
Role-Based Access Control (RBAC) proposal. In this implementation users
(subjects) are assigned different roles that, in turn, have (or not) privileges
over objects. With this permission system, the owner of an object can give
privileges to certain roles. For example, a user can grant access to other users
trying to read some personal info only if they belong to, at least, one of
the roles specified in the permission rule.I initially developed the first version of this app for a social network, to
give its users the ability to control who has privileges upon their profiles,
photo albums, personal information, and such. If you are in a similar situation,
you’ll find that django-rbac suits perfect for your purposes. But, as long as a
general-purpose access control is being implemented, even if you are building
any other kind of application which needs this level of permission control,
django-rbac will help you out. I think I have made it enough generic to match a
wide range of use cases.I you are interested, you can read theintroduced formal modelby
F. Ferraiolo and D. R. Kuhn.Download & InstallationStable codeYou can use your favorite management tool to install (the old and well-known
easy_install or the better pip:easy_install django-rbac
pip install django-rbacOr you can download and install the source code yourself
(python setup.py install) from here:http://bitbucket.org/nabucosound/django-rbac/downloads/Latest Development codeSource code is hosted in Bitbuckethere.InstallMercurialif you don’t have it yet, and clone the repository:hg clone http://bitbucket.org/nabucosound/django-rbac/Symlink to the folder calledrbacinsidedjango-rbacfrom somewhere
in your PYTHONPATH – could be the system-widesite-packagespython folder,
or the path your virtualenv project is using, if you are usingVirtualenv(which I strongly encourage). And if you do and are also usingVirtualenvwrapperthen you can easilyadd2virtualenv.DependenciesBe sure you havedjango.contrib.contenttypesinstalled in you project.OverviewThe following elements conform a RBAC permission in django-rbac:Theowner: The proprietary of either the object being accessed or the
permission rule itself, e.g. a site user or a community administrator.Theobject: The element being accessed on which the permission is being
checked upon, e.g. a profile or photo album.Theoperation: The action requested, e.g. display, create, delete, show
birth date, send message or request friendship.Theroles: Define who are the requesting users in relation to the owner
or the object, e.g anonymous, friend, family, coworker, or roommate.This is best explained with a simple example:UserFritzwants to seeMr. Natural’sprofile. Thus,Fritz(subject)
requests permission to access (operation) the profile (object) ofMr. Natural(owner).Fritzis an ‘anonymous’ user (role), a role that everybody holds
initially in the system. AsFritzandMr. Naturalare friends, the role
‘friend’ is appended to theroles. So we have a role list containing
‘anonymous’ and ‘friend’.The privacy framework performs its magic to pull an answer: hasFritzpermission to access this profile?For the ‘anonymous’ role, the system denies the access.For the ‘friend’ role the access is granted, asMr. Naturalhad set
access only to friends to his profile.Access is granted, soFritzcan go ahead and view all the stuff.Permissions can be assigned to either a single object (“per-object permission”
category, also known as “granular permissions” or “row level permissions”)
like in the example above, or to all objects of the same model class. For this
reason, django-rbac implements two classes respectively:RBACPermissionandRBACGenericPermission.How it worksAsking for permission in django-rbac is a 2-step process:1. Get the roles: The user that tries to perform the operation over an object
or model does so within a context given between him and the owner or the
object/model itself. You have to provide a python list ofRBACRoleobjects to the function that will later check authorization.
2. Call theget_permissionmethod from one of the two RBAC permission
objects (RBACPermission.objects.get_permissionorRBACGenericPermission.objects.get_permission). The method will returnTrueorFalseif the operation is authorized or not.You are totally responsible of executing step 1. The ways that roles can be
assigned to users are endless, particular to each application or project, so
django-rbac cannot provide any generic method to accomplish this task. Jump to
the subsection “Writing functions to get roles” in the “Roles” section for
more information.OperationsTheRBACOperationmodel defines operations that can be done in the system,
e.g. ‘display_profile’, ‘send_message’, ‘request_friendship’, or ‘show_email’.
You can define what you want, just try to stick to a common syntax convention
and short names for your own sake.RolesOriginally a role is a job function within the context of an organization, but
it can also be seen like a relationship between the requesting user (subject)
and the owner. Users trying to perform operations over objects can do so in
multiple fashions. For example, someone asks for permission to see, let’s say,
a photo album from another user. Such requesting user can be friend or family
of the album owner, a member of a photography community, or maybe an anonymous
folk with a deep interest in other’s pics. Thus, ‘anonymous’, ‘friend’,
‘community_member’ or ‘family’ would be names ofRBACRoleroles that users
can belong to.Writing functions to get rolesYou need to provide your app some programming logic to know which roles is the
requesting user going to play. A common case is therequest.userin a
Django view. See this example extracted from the project that comes with the
django-rbac package in theexamplefolder:from rbac.models import RBACRole

def get_user_roles(user, target_user):
    roles = []
    # These two functions below would validate the relationship
    # between the two users.
    # If any exist, append the corresponding role to the roles
    # list to be returned.
    if users_are_friends(user, target_user):
        #Assuming 'friend' role object exists
        roles.append(RBACRole.objects.get(name='friend'))
    if users_are_coworkers(user, target_user):
        #Assuming 'coworker' role object exists
        roles.append(RBACRole.objects.get(name='coworker'))
    return rolesPermissionsOnce you have your operations and roles ready, you can start creating
permissions. RBAC enables the conditions for the implementaiton of what is
called theSeparation of Duties(SoD), so tipically applications or projects
using django-rbac will set mechanisms to delegate creating new permissions
to owners. That is, the owner of an object will be who is setting the
permission level to all the operations that can be done with the object.
You are again responsible of providing the user an interface to accomplish
this task. Classical social networks, for example, give their users a
‘privacy’ page with forms to change different permission settings.As mentioned in the beginning of this document, the scope of a permission can
be row level (RBACPermission) or model class level
(RBACGenericPermission). Both models receive:The model instance of the permission owner, e.g. aUserobject.AnRBACOperationobject for an operation, e.g. ‘display_profile’.A list ofRBACRoleobjects, e.g. ‘anonymous’, ‘friend’ and ‘coworker’.The object:RBACPermissionreceives a model instance (for example, aGroupobject), whileRBACGenericPermissionreceives a class model
(for example, aGroupmodel).Two things to keep in mind when planning your permissions:django-rbac follows this golden rule:if a permission doesn’t exist, the
operation is denied. This is for convenience, because fewer permission
objects need to be created.Try to avoid defining permissions that contain mutually exclusive roles.
For example, a permission could have ‘friend’ and ‘anonymous user’ into his
list of roles. The first allows the permission operation to everybody, while
the second restricts an access only to friends, so both are mutually exclusive.