skip to navigation
skip to content

Not Logged In

bouncer 0.1.10

Simple Declarative Authentication based on Ryan Bates excellent cancan library

Package Documentation

Latest Version: 0.1.12

Simple Declarative Authentication DSL inspired by Ryan Bates’ excellent cancan library

Introduction

Meet bouncer.

bouncer is your faithful servant. Big, burly, trustworthy – smarter than he looks, but very effective in what he does. You just have to talk simply to him. For example:

from bouncer import authorization_method
from bouncer.constants import *

@authorization_method
def authorize(user, they):

    if user.is_admin:
        they.can(MANAGE, ALL)
    else:
        they.can(READ, ALL)
        they.cannot(READ, 'TopSecretDocs')

        def if_author(article):
            return article.author == user

        they.can(EDIT, 'Article', if_author)

And once you have that setup, you can ask questions like:

jonathan = User(name='jonathan',admin=False)
marc = User(name='marc',admin=False)

article = Article(author=jonathan)

print can(jonathan, EDIT, article)   # True
print can(marc, EDIT, article)       # False

# Can Marc view articles in general?
print can(marc, VIEW, Article)       # True

Installation

pip install bouncer

Defining Abilities

User permissions are defined in an method decorated with @authorize_method

A simple setup looks like so …

@authorization_method
def authorize(user, they):

    if user.is_admin:
        they.can(MANAGE, ALL)
    else:
        they.can(READ, ALL)

        def if_author(article):
            return article.author == user

        they.can(EDIT, Article, if_author)
  • If you do not think the “they.can” is pythonic enough you can use the append syntax
@authorization_method
def authorize(user, abilities):

    if user.is_admin:
        abilities.append(MANAGE, ALL)
    else:
        abilities.append(READ, ALL)

        # See I am using a string here
        abilities.append(EDIT, 'Article', author=user)

Alternative syntax

dict syntax

  • You can also use an alternative dict syntax. The following is equivalent to above:
@authorization_method
def authorize(user, they):

    if user.is_admin:
        they.can(MANAGE, ALL)
    else:
        they.can(READ, ALL)
        they.can(EDIT, Article, author=user)
  • You can add multiple conditions to the dict:
they.can(READ, Article, published=True, active=True)

Strings instead of classes

Use can use Strings instead of classes (so you do not need to import a bunch of files you are not using in initialization

@authorization_method
def authorize(user, they):

    if user.is_admin:
        they.can(MANAGE, ALL)
    else:
        they.can(READ, ALL)

        # Notice that I am using a string here
        they.can(EDIT, 'Article', author=user)

You can (are encouraged to) combine similar rules on a single line:

they.can((EDIT,READ,DELETE),(Article,Photo))

Combining Abilities

It is possible to define multiple abilites for the same resource. This is particularly useful in combination with the cannot method

they.can(MANAGE, ALL)
then.cannot(DELETE, ('USER', 'ACCOUNT')

Check Abilities & Authorization

There are two main way for checking for authorization. can (and its brother cannot) and ensure

  • can returns a boolean
  • while ensure will raise an AccessDenied Exception
from bouncer import can, ensure
from bouncer.constants import *

jonathan = User(name='jonathan',admin=False)

# can jonathan edit articles in general
can(jonathan, EDIT, Article)

# ensure jonathan edit articles in general -- otherwise we are going to throw an exception
ensure(jonathan, EDIT, Article)

article = Article(author=jonathan)

# can jonathan delete this specific article
can(jonathan, EDIT, article)

Decorating your User Model

Helper methods are mixed into your User model (once it is decorated with the @authorization_target)

For example:

from bouncer import authorization_target

@authorization_target
class User(object):

def __init__(self, **kwargs):
    self.id = kwargs.get('id', 1)
    self.name = kwargs.get('name', '')
    self.admin = kwargs.get('name', False)
    pass

@property
def is_admin(self):
    return self.admin

jonathan = User(name='jonathan',admin=False)
marc = User(name='marc',admin=False)

article = Article(author=jonathan)

print jonathan.can(EDIT,article)   # True
print marc.can(EDIT,article)       # False

Flask

If you use Flask, I am currently working on a Flask extension – follow its progress here: flask-bouncer.

Questions / Issues

Feel free to ping me on twitter: @tushman or add issues or PRs at https://github.com/jtushman/bouncer

 
File Type Py Version Uploaded on Size
bouncer-0.1.10.tar.gz (md5) Source 2014-04-04 5KB
  • Downloads (All Versions):
  • 0 downloads in the last day
  • 235 downloads in the last week
  • 1652 downloads in the last month