Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bouncer-app/bouncer
Declarative Authentication DSL inspired by Ryan Bates excellent cancan library
https://github.com/bouncer-app/bouncer
Last synced: 3 months ago
JSON representation
Declarative Authentication DSL inspired by Ryan Bates excellent cancan library
- Host: GitHub
- URL: https://github.com/bouncer-app/bouncer
- Owner: bouncer-app
- License: mit
- Created: 2014-03-13T19:42:39.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2015-04-08T13:25:53.000Z (over 9 years ago)
- Last Synced: 2024-06-30T22:32:23.318Z (4 months ago)
- Language: Python
- Homepage: https://pythonhosted.org/bouncer/
- Size: 622 KB
- Stars: 101
- Watchers: 7
- Forks: 9
- Open Issues: 2
-
Metadata Files:
- Readme: README.rst
- License: LICENSE
Awesome Lists containing this project
- starred-awesome - bouncer - Declarative Authentication DSL inspired by Ryan Bates excellent cancan library (Python)
README
bouncer
=======Simple Declarative Authentication DSL inspired by Ryan Bates’ excellent
cancan library.. image:: https://travis-ci.org/jtushman/bouncer.svg?branch=master
:alt: travis-badge
:target: https://travis-ci.org/bouncer-app/bouncerIntroduction
------------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:.. code:: python
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 == userthey.can(EDIT, 'Article', if_author)
And once you have that setup, you can ask questions like:
.. code:: python
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) # TrueInstallation
------------``pip install bouncer``
Defining Abilities
------------------@authorization_method
~~~~~~~~~~~~~~~~~~~~~
User permissions are defined in a method decorated with
``@authorize_method``A simple setup looks like so …
.. code:: python
@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 == userthey.can(EDIT, Article, if_author)
If you do not think the “they.can” is pythonic enough you can use the ``append`` syntax
.. code:: python
@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:.. code:: python
@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``:
.. code:: python
they.can(READ, Article, published=True, active=True)
Strings instead of classes
^^^^^^^^^^^^^^^^^^^^^^^^^^
You can use strings instead of classes. This means you do not need to import a bunch of files you are not using in initialization.. code:: python
@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)Combining Rules
^^^^^^^^^^^^^^^
You can (are encouraged to) combine similar rules on a single line:.. code:: python
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.. code:: python
they.can(MANAGE, ALL)
then.cannot(DELETE, ('USER', 'ACCOUNT'))Checking Abilities
------------------
There are two main ways for checking for authorization. ``can`` (and its brother ``cannot``) and ``ensure``* ``can`` returns a boolean
* ``ensure`` will raise an ``AccessDenied`` Exception.. code:: python
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
~~~~~~~~~~~~~~~~~~~~~~~~~~
Optionally, you can add helper methods into your User model by using ``@authorization_target``For example:
.. code:: python
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('admin', 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) # FalseFlask
-----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
.. _flask-bouncer: https://github.com/jtushman/flask-bouncer
.. _@tushman: http://twitter.com/tushman