{ "info": { "author": "Jonathan Tushman", "author_email": "jonathan@zefr.com", "bugtrack_url": null, "classifiers": [], "description": "bouncer\n=======\n\nSimple Declarative Authentication DSL inspired by Ryan Bates\u2019 excellent\ncancan library\n\n.. image:: https://travis-ci.org/jtushman/bouncer.svg?branch=master\n :alt: travis-badge\n :target: https://travis-ci.org/bouncer-app/bouncer\n\nIntroduction\n------------\n\nMeet **bouncer**.\n\n**bouncer** is your faithful servant. Big, burly, trustworthy \u2013 smarter\nthan he looks, but very effective in what he does. You just have to talk\nsimply to him. For example:\n\n.. code:: python\n\n from bouncer import authorization_method\n from bouncer.constants import *\n\n @authorization_method\n def authorize(user, they):\n\n if user.is_admin:\n they.can(MANAGE, ALL)\n else:\n they.can(READ, ALL)\n they.cannot(READ, 'TopSecretDocs')\n\n def if_author(article):\n return article.author == user\n\n they.can(EDIT, 'Article', if_author)\n\n\nAnd once you have that setup, you can ask questions like:\n\n.. code:: python\n\n jonathan = User(name='jonathan',admin=False)\n marc = User(name='marc',admin=False)\n\n article = Article(author=jonathan)\n\n print can(jonathan, EDIT, article) # True\n print can(marc, EDIT, article) # False\n\n # Can Marc view articles in general?\n print can(marc, VIEW, Article) # True\n\nInstallation\n------------\n\n``pip install bouncer``\n\nDefining Abilities\n------------------\n\n@authorization_method\n~~~~~~~~~~~~~~~~~~~~~\nUser permissions are defined in a method decorated with\n``@authorize_method``\n\nA simple setup looks like so \u2026\n\n.. code:: python\n\n @authorization_method\n def authorize(user, they):\n\n if user.is_admin:\n they.can(MANAGE, ALL)\n else:\n they.can(READ, ALL)\n\n def if_author(article):\n return article.author == user\n\n they.can(EDIT, Article, if_author)\n\n\nIf you do not think the \u201cthey.can\u201d is pythonic enough you can use the ``append`` syntax\n\n.. code:: python\n\n @authorization_method\n def authorize(user, abilities):\n\n if user.is_admin:\n abilities.append(MANAGE, ALL)\n else:\n abilities.append(READ, ALL)\n\n # See I am using a string here\n abilities.append(EDIT, 'Article', author=user)\n \nAlternative syntax\n~~~~~~~~~~~~~~~~~~\n\n``dict`` syntax\n^^^^^^^^^^^^^^^\nYou can also use an alternative ``dict`` syntax. The following is equivalent to above:\n\n.. code:: python\n\n @authorization_method\n def authorize(user, they):\n\n if user.is_admin:\n they.can(MANAGE, ALL)\n else:\n they.can(READ, ALL)\n they.can(EDIT, Article, author=user)\n\nYou can add multiple conditions to the ``dict``:\n\n.. code:: python\n\n they.can(READ, Article, published=True, active=True)\n\nStrings instead of classes\n^^^^^^^^^^^^^^^^^^^^^^^^^^\nYou can use strings instead of classes. This means you do not need to import a bunch of files you are not using in initialization\n\n.. code:: python\n\n @authorization_method\n def authorize(user, they):\n\n if user.is_admin:\n they.can(MANAGE, ALL)\n else:\n they.can(READ, ALL)\n\n # Notice that I am using a string here\n they.can(EDIT, 'Article', author=user)\n\n\nCombining Rules\n^^^^^^^^^^^^^^^\nYou can (are encouraged to) combine similar rules on a single line:\n\n.. code:: python\n\n they.can((EDIT,READ,DELETE),(Article,Photo))\n \nCombining Abilities\n^^^^^^^^^^^^^^^^^^^\n\nIt is possible to define multiple abilites for the same resource. This is\nparticularly useful in combination with the ``cannot`` method\n\n.. code:: python\n\n they.can(MANAGE, ALL)\n then.cannot(DELETE, ('USER', 'ACCOUNT'))\n\nChecking Abilities\n------------------\nThere are two main ways for checking for authorization. ``can`` (and its brother ``cannot``) and ``ensure``\n\n* ``can`` returns a boolean\n* ``ensure`` will raise an ``AccessDenied`` Exception\n\n.. code:: python\n\n from bouncer import can, ensure\n from bouncer.constants import *\n\n jonathan = User(name='jonathan',admin=False)\n\n # can jonathan edit articles in general\n can(jonathan, EDIT, Article)\n\n # ensure jonathan edit articles in general -- otherwise we are going to throw an exception\n ensure(jonathan, EDIT, Article)\n\n article = Article(author=jonathan)\n\n # can jonathan delete this specific article\n can(jonathan, EDIT, article)\n \nDecorating your User Model\n~~~~~~~~~~~~~~~~~~~~~~~~~~\nOptionally, you can add helper methods into your User model by using ``@authorization_target``\n\nFor example:\n\n.. code:: python\n\n from bouncer import authorization_target\n\n @authorization_target\n class User(object):\n\n def __init__(self, **kwargs):\n self.id = kwargs.get('id', 1)\n self.name = kwargs.get('name', '')\n self.admin = kwargs.get('admin', False)\n pass\n \n @property\n def is_admin(self):\n return self.admin\n \n jonathan = User(name='jonathan',admin=False)\n marc = User(name='marc',admin=False)\n\n article = Article(author=jonathan)\n\n print jonathan.can(EDIT,article) # True\n print marc.can(EDIT,article) # False\n\nFlask\n-----\n\nIf you use Flask, I am currently working on a Flask extension \u2013 follow\nits progress here: `flask-bouncer`_.\n\nQuestions / Issues\n------------------\n\nFeel free to ping me on twitter: `@tushman`_\nor add issues or PRs at https://github.com/jtushman/bouncer\n \n.. _flask-bouncer: https://github.com/jtushman/flask-bouncer\n.. _@tushman: http://twitter.com/tushman\n", "description_content_type": null, "docs_url": "https://pythonhosted.org/bouncer/", "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/jtushman/bouncer", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "bouncer", "package_url": "https://pypi.org/project/bouncer/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/bouncer/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/jtushman/bouncer" }, "release_url": "https://pypi.org/project/bouncer/0.1.12/", "requires_dist": null, "requires_python": null, "summary": "Simple Declarative Authentication based on Ryan Bates excellent cancan library", "version": "0.1.12" }, "last_serial": 5619496, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "b0abd0bd7908c5043aa8a83a2a32626e", "sha256": "96b36a06ef4038a14e5b48beeed4392e1472aaa9e06b1545dc8d6b3495608aaa" }, "downloads": -1, "filename": "bouncer-0.0.1.tar.gz", "has_sig": false, "md5_digest": "b0abd0bd7908c5043aa8a83a2a32626e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2930, "upload_time": "2014-03-24T18:35:50", "url": "https://files.pythonhosted.org/packages/27/fd/7171ab5bf5510447bef30dc7dd9c7171ef8d2518f215caa32a7e9320825f/bouncer-0.0.1.tar.gz" } ], "0.1.10": [ { "comment_text": "", "digests": { "md5": "7166beb8bb1b010049aa99b3d16b5521", "sha256": "92c49a438edcf307c6ca593c5144e01433e60118c5ed2252af017dc112d57353" }, "downloads": -1, "filename": "bouncer-0.1.10.tar.gz", "has_sig": false, "md5_digest": "7166beb8bb1b010049aa99b3d16b5521", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5400, "upload_time": "2014-04-04T14:34:30", "url": "https://files.pythonhosted.org/packages/66/72/ac759492cbb443f258dcf9ae142eefbebae61fbd02be12c1260fe6837a42/bouncer-0.1.10.tar.gz" } ], "0.1.11": [ { "comment_text": "", "digests": { "md5": "a18cced66d8bf3e98072940dd2bd03ba", "sha256": "faf02517717cdf007fb883fb03edd5b6b275c8049441974b9984e5463b2430c8" }, "downloads": -1, "filename": "bouncer-0.1.11.tar.gz", "has_sig": false, "md5_digest": "a18cced66d8bf3e98072940dd2bd03ba", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5485, "upload_time": "2015-04-08T13:13:24", "url": "https://files.pythonhosted.org/packages/a5/49/1e9b088449ddb6b384fb98c72c0129b68f8421cf74d55ccdcc0546f3c6e7/bouncer-0.1.11.tar.gz" } ], "0.1.12": [ { "comment_text": "", "digests": { "md5": "3da333f749420c2baafc5aa6d546bf37", "sha256": "9a7753bf9e6e39063595529334dffef5b00c8e7760b9ac357172717878614a10" }, "downloads": -1, "filename": "bouncer-0.1.12.tar.gz", "has_sig": false, "md5_digest": "3da333f749420c2baafc5aa6d546bf37", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5496, "upload_time": "2015-04-08T13:26:01", "url": "https://files.pythonhosted.org/packages/8b/9f/7c4ee715ff73503937a9979a16a19574aaefc9acbdd2f7f728190c7974e8/bouncer-0.1.12.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "49025e83e8ff89b4af4b697b5829ceb3", "sha256": "d76862c25017707d660ad8ce8e28ed9e2cf3db9191a8f774d7d4e26c372fa9a3" }, "downloads": -1, "filename": "bouncer-0.1.2.tar.gz", "has_sig": false, "md5_digest": "49025e83e8ff89b4af4b697b5829ceb3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2925, "upload_time": "2014-03-26T13:24:30", "url": "https://files.pythonhosted.org/packages/6a/00/4509271cc6683973c135d9f1b6b88abc02bc66cb6c2a682f428ff7629bbd/bouncer-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "c6d22747a11e3a9c324de19d08b1a534", "sha256": "d5d4ba7d6be871c419de9104634ed4d93aa1a77e2a42a248125585e4f593088d" }, "downloads": -1, "filename": "bouncer-0.1.3.tar.gz", "has_sig": false, "md5_digest": "c6d22747a11e3a9c324de19d08b1a534", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2923, "upload_time": "2014-03-26T18:45:13", "url": "https://files.pythonhosted.org/packages/ef/86/3f2d7132872154dc682f739e4934867179c37129c7828b138cf84e3d1821/bouncer-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "f41ec9534a556a34a775d2bc90a0d40e", "sha256": "03bb461e513a88f4332329f0450e0dc244a480de9690a92db7071cc049f14c08" }, "downloads": -1, "filename": "bouncer-0.1.4.tar.gz", "has_sig": false, "md5_digest": "f41ec9534a556a34a775d2bc90a0d40e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2920, "upload_time": "2014-03-26T19:12:46", "url": "https://files.pythonhosted.org/packages/49/48/580634d2ecd05d03d464c99392c0e0cc68aac16202e5b8ace35b5f8a3cd7/bouncer-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "ab28b18a01f0181b58ad876f7c51c726", "sha256": "f507db547f3b55210fbf7e9f40afc4f97665512c050bf5c3b8c0ac3ccc94a496" }, "downloads": -1, "filename": "bouncer-0.1.5.tar.gz", "has_sig": false, "md5_digest": "ab28b18a01f0181b58ad876f7c51c726", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2982, "upload_time": "2014-03-31T13:31:07", "url": "https://files.pythonhosted.org/packages/37/b3/0fe6d5ca46e724dd17c0eb8d81e4942248254cde2ecfa2c7eddf05882c93/bouncer-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "80f15372cbc62a7ee2270ccc93558e11", "sha256": "62a43fa3bdd4850d48417698fd7db36a736655e4e1c844a203ce27331da8d9fc" }, "downloads": -1, "filename": "bouncer-0.1.6.tar.gz", "has_sig": false, "md5_digest": "80f15372cbc62a7ee2270ccc93558e11", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2980, "upload_time": "2014-03-31T13:50:36", "url": "https://files.pythonhosted.org/packages/e8/dc/539aee30943ba10a5c4a9ec771120091067bfa49623d7d7f6fba415f0018/bouncer-0.1.6.tar.gz" } ], "0.1.8": [ { "comment_text": "", "digests": { "md5": "7aeff2fff836b0d217d772633977565f", "sha256": "fbe017ac3fd855db8118aec475c56628df3620197e6500dd3e0d089e962604b7" }, "downloads": -1, "filename": "bouncer-0.1.8.tar.gz", "has_sig": false, "md5_digest": "7aeff2fff836b0d217d772633977565f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3025, "upload_time": "2014-04-01T15:29:12", "url": "https://files.pythonhosted.org/packages/9c/90/e1c36ebe9c93e3df2479052aed1b94245779c8a7588b39dd7a1d3183bd85/bouncer-0.1.8.tar.gz" } ], "0.1.9": [ { "comment_text": "", "digests": { "md5": "3dba3265cc754dcf4f0ae0749b264de3", "sha256": "33b224ddaf9befc5ec5506db5d9b55b4de3c898ce2ffa4aa19f5093cdec5159d" }, "downloads": -1, "filename": "bouncer-0.1.9.tar.gz", "has_sig": false, "md5_digest": "3dba3265cc754dcf4f0ae0749b264de3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3288, "upload_time": "2014-04-02T13:15:36", "url": "https://files.pythonhosted.org/packages/e9/6f/a6b7914f0b457e2e14cd2645ddb23bc2d5632842420bb0d946d69384c9a7/bouncer-0.1.9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3da333f749420c2baafc5aa6d546bf37", "sha256": "9a7753bf9e6e39063595529334dffef5b00c8e7760b9ac357172717878614a10" }, "downloads": -1, "filename": "bouncer-0.1.12.tar.gz", "has_sig": false, "md5_digest": "3da333f749420c2baafc5aa6d546bf37", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5496, "upload_time": "2015-04-08T13:26:01", "url": "https://files.pythonhosted.org/packages/8b/9f/7c4ee715ff73503937a9979a16a19574aaefc9acbdd2f7f728190c7974e8/bouncer-0.1.12.tar.gz" } ] }