{
"info": {
"author": "Zhipeng Liu",
"author_email": "hustlzp@qq.com",
"bugtrack_url": null,
"classifiers": [
"Development Status :: 4 - Beta",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2.7",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Topic :: Software Development :: Libraries :: Python Modules"
],
"description": "Permission\n==========\n\n|Latest Version| |The MIT License|\n\nSimple and flexible permission control for Flask app.\n\nFeatures\n--------\n\n- **Simple**: all you need to do is subclassing ``Rule`` and\n ``Permission`` class.\n- **Flexible**: support rule inheritance and bitwise operations(\\ ``&``\n and ``|``) to build your own rules.\n\nInstallation\n------------\n\n::\n\n $ pip install permission\n\nRule\n----\n\n``Rule`` has 3 methods which can be overrided:\n\n- base(): define base rule.\n- check(): determine whether this rule should be passed or not.\n- deny(): will be executed when ``check()`` failed.\n\nYou should always override ``check()`` and ``deny()`` while overriding\n``base()`` as needed.\n\nPermission\n----------\n\n``Permission`` has 1 method which can be overrided:\n\n- rule(): define rule needed by this permission\n\nYou should always override ``rule()``.\n\n``Permission`` has 2 instance methods you can use in codes:\n\n- check(): call this to check rule of this permission\n- deny(): call this to execute codes when ``check()`` failed\n\nUsage\n-----\n\nFirst you need to define your own rules by subclassing ``Rule`` then\noverride ``check()`` and ``deny()``:\n\n.. code:: py\n\n # rules.py\n from flask import session, flash, redirect, url_for\n from permission import Rule\n\n\n class UserRule(Rule):\n def check(self):\n \"\"\"Check if there is a user signed in.\"\"\"\n return 'user_id' in session\n\n def deny(self):\n \"\"\"When no user signed in, redirect to signin page.\"\"\"\n flash('Sign in first.')\n return redirect(url_for('signin'))\n\nThen you define permissions by subclassing ``Permission`` and override\n``rule()``:\n\n.. code:: py\n\n # permissions.py\n from permission import Permission\n from .rules import UserRule\n\n\n class UserPermission(Permission):\n \"\"\"Only signin user has this permission.\"\"\"\n def rule(self):\n return UserRule()\n\nThere are 4 ways to use the ``UserPermission`` defined above:\n\n**1. Use as view decorator**\n\n.. code:: py\n\n from .permissions import UserPermission\n\n\n @app.route('/settings')\n @UserPermission()\n def settings():\n \"\"\"User settings page, only accessable for sign-in user.\"\"\"\n return render_template('settings.html')\n\n**2. Use in view codes**\n\n.. code:: py\n\n from .permissions import UserPermission\n\n\n @app.route('/settions')\n def settings():\n permission = UserPermission()\n if not permission.check()\n return permission.deny()\n return render_template('settings.html')\n\n**3. Use in view codes (using ``with`` statement)**\n\n.. code:: py\n\n from .permissions import UserPermission\n\n\n @app.route('/settions')\n def settings():\n with UserPermission():\n return render_template('settings.html')\n\n**Note**: if you don't raise an exception when the permission check\nfailed (in other words, a rule's ``deny()`` will be called),\n``PermissionDeniedException`` will be raised in order to stop the\nexecution of the with-body codes. By the way, you can import this\nexception as needed:\n\n.. code:: py\n\n from permission import PermissionDeniedException\n\n**4. Use in Jinja2 templates**\n\nFirst you need to inject your defined permissions to template context:\n\n.. code:: py\n\n from . import permissions\n\n\n @app.context_processor\n def inject_vars():\n return dict(\n permissions=permissions\n )\n\nthen in templates:\n\n.. code:: html\n\n {% if permissions.UserPermission().check() %}\n New\n {% endif %}\n\nRule Inheritance\n----------------\n\nNeed to say, inheritance here is not the same thing as Python class\ninheritance, it's just means you can use RuleA as the base rule of\nRuleB.\n\nWe achieve this by overriding ``base()``.\n\nLet's say an administrator user should always be a user:\n\n.. code:: py\n\n # rules.py\n from flask import session, abort, flash, redirect, url_for\n from permission import Rule\n\n\n class UserRule(Rule):\n def check(self):\n return 'user_id' in session\n\n def deny(self):\n flash('Sign in first.')\n return redirect(url_for('signin'))\n\n\n class AdminRule(Rule):\n def base(self):\n return UserRule()\n\n def check(self):\n user_id = int(session['user_id'])\n user = User.query.filter(User.id == user_id).first()\n return user and user.is_admin\n\n def deny(self):\n abort(403)\n\nRule Bitwise Operations\n-----------------------\n\n- ``RuleA & RuleB`` means it will be passed when both RuleA and RuleB\n are passed.\n- ``RuleA | RuleB`` means it will be passed either RuleA or RuleB is\n passed.\n\nLet's say we need to build a forum with Flask. Only the topic creator\nand administrator user can edit a topic:\n\nFirst define rules:\n\n.. code:: py\n\n # rules.py\n from flask import session, abort, flash, redirect, url_for\n from permission import Rule\n from .models import User, Topic\n\n\n class UserRule(Rule):\n def check(self):\n \"\"\"Check if there is a user signed in.\"\"\"\n return 'user_id' in session\n\n def deny(self):\n \"\"\"When no user signed in, redirect to signin page.\"\"\"\n flash('Sign in first.')\n return redirect(url_for('signin'))\n\n\n class AdminRule(Rule):\n def base(self):\n return UserRule()\n\n def check(self):\n user_id = int(session['user_id'])\n user = User.query.filter(User.id == user_id).first()\n return user and user.is_admin\n\n def deny(self):\n abort(403)\n\n\n class TopicCreatorRule(Rule):\n def __init__(self, topic):\n self.topic = topic\n super(TopicCreatorRule, self).__init__()\n\n def base(self):\n return UserRule()\n\n def check(self):\n return topic.user_id == session['user_id']\n\n def deny(self):\n abort(403)\n\nthen define permissions:\n\n.. code:: py\n\n # permissions.py\n from permission import Permission\n\n\n class TopicAdminPermission(Permission):\n def __init__(self, topic):\n self.topic = topic\n super(TopicAdminPermission, self).__init__()\n\n def rule(self):\n return AdminRule() | TopicCreatorRule(self.topic)\n\nso we can use ``TopicAdminPermission`` in ``edit_topic`` view:\n\n.. code:: py\n\n from .permissions import TopicAdminPermission\n\n\n @app.route('topic//edit')\n def edit_topic(topic_id):\n topic = Topic.query.get_or_404(topic_id)\n permission = TopicAdminPermission(topic)\n if not permission.check():\n return permission.deny()\n ...\n\nLicense\n-------\n\nMIT\n\n.. |Latest Version| image:: http://img.shields.io/pypi/v/permission.svg\n :target: https://pypi.python.org/pypi/permission\n.. |The MIT License| image:: http://img.shields.io/badge/license-MIT-blue.svg\n :target: https://github.com/hustlzp/permission/blob/master/LICENSE",
"description_content_type": null,
"docs_url": null,
"download_url": "",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://github.com/hustlzp/permission",
"keywords": "",
"license": "MIT",
"maintainer": "",
"maintainer_email": "",
"name": "permission",
"package_url": "https://pypi.org/project/permission/",
"platform": "UNKNOWN",
"project_url": "https://pypi.org/project/permission/",
"project_urls": {
"Homepage": "https://github.com/hustlzp/permission"
},
"release_url": "https://pypi.org/project/permission/0.4.1/",
"requires_dist": null,
"requires_python": "",
"summary": "Simple and flexible permission control for Flask app.",
"version": "0.4.1"
},
"last_serial": 1812501,
"releases": {
"0.1.0": [
{
"comment_text": "",
"digests": {
"md5": "4c8683db4234490acbabfd0988a32d9c",
"sha256": "065f3d925630d3593f291fcb38c0ab09454d43df709add47f5c8b51ee549ff16"
},
"downloads": -1,
"filename": "permission-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "4c8683db4234490acbabfd0988a32d9c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 2705,
"upload_time": "2014-09-10T09:42:55",
"url": "https://files.pythonhosted.org/packages/84/86/2442e66c770a0daf4860ceb5f0a23689096f41903f57587324e936f7bc22/permission-0.1.0.tar.gz"
}
],
"0.1.1": [
{
"comment_text": "",
"digests": {
"md5": "15844b43bce70f92558d59b347449a59",
"sha256": "44e7f333b54f82479e3638a5e8d65ba98c5bd4b93a19bef1458b6b52e27fdcd9"
},
"downloads": -1,
"filename": "permission-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "15844b43bce70f92558d59b347449a59",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 2811,
"upload_time": "2014-09-10T09:54:41",
"url": "https://files.pythonhosted.org/packages/95/2b/3c9ed45f0a32e1a5a0168c95765b9b10edc0cf70b82824f17c24a1bd9dd7/permission-0.1.1.tar.gz"
}
],
"0.1.2": [
{
"comment_text": "",
"digests": {
"md5": "932e256594e8041b65d2b5142dd37d8b",
"sha256": "8f907eb2030233c3481c6149e9ea1a278b0a3ae8bf5c894beb521425ac7ee9e9"
},
"downloads": -1,
"filename": "permission-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "932e256594e8041b65d2b5142dd37d8b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 4576,
"upload_time": "2014-09-12T09:35:06",
"url": "https://files.pythonhosted.org/packages/a6/0e/176d5afe36b53de12069222caad61e08b9800e04cd2e1c2170f76f86e973/permission-0.1.2.tar.gz"
}
],
"0.1.3": [
{
"comment_text": "",
"digests": {
"md5": "caee8bfeeac032caacfd17146d99ea67",
"sha256": "78e12b2d7f5cf9b53c079d8cd8a918636dbbee8fbd8573f6da0064b67a634ba4"
},
"downloads": -1,
"filename": "permission-0.1.3.tar.gz",
"has_sig": false,
"md5_digest": "caee8bfeeac032caacfd17146d99ea67",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 4561,
"upload_time": "2014-09-12T10:23:43",
"url": "https://files.pythonhosted.org/packages/a5/ee/5d230ba0347c895c3a316e6c1d9193810a5b567e76651db021793b827827/permission-0.1.3.tar.gz"
}
],
"0.2.0": [
{
"comment_text": "",
"digests": {
"md5": "183000b4f9f1c55f6c1f8ba393616000",
"sha256": "c4ccc34c4a5fdac9f1b5c007824d0524ddbb06c56bbf6c5cbc0825820a91a5c3"
},
"downloads": -1,
"filename": "permission-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "183000b4f9f1c55f6c1f8ba393616000",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 4457,
"upload_time": "2014-11-18T01:30:21",
"url": "https://files.pythonhosted.org/packages/dd/0f/44775056ade703f2d15d61550b6cc67d147bb29e1b5cf405985744945db8/permission-0.2.0.tar.gz"
}
],
"0.2.1": [
{
"comment_text": "",
"digests": {
"md5": "6d5a94c9e6cedef88002794001b85832",
"sha256": "9c4ef7525ad16e9b9b7e6ca1b0aac8120d594577b8594bc8ec5c30065f34b26f"
},
"downloads": -1,
"filename": "permission-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "6d5a94c9e6cedef88002794001b85832",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 4558,
"upload_time": "2014-11-25T11:25:40",
"url": "https://files.pythonhosted.org/packages/ec/92/73b91e72a083ede34f4138706e11cc55a9f427989dd43ec63aa82f94f9f6/permission-0.2.1.tar.gz"
}
],
"0.3.0": [
{
"comment_text": "",
"digests": {
"md5": "4a51db14842f7a98a3620d9157ec81cc",
"sha256": "5f62f03f0ee685f15a8fb0301a7ecb7e9a7077e47397099b0d6afde149aaf70f"
},
"downloads": -1,
"filename": "permission-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "4a51db14842f7a98a3620d9157ec81cc",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 4558,
"upload_time": "2015-03-14T09:34:32",
"url": "https://files.pythonhosted.org/packages/c5/6a/e307967e0e896da9b13a6f08de4fba89264d426b8014901f60520cd34ea5/permission-0.3.0.tar.gz"
}
],
"0.4.0": [
{
"comment_text": "",
"digests": {
"md5": "0971700ce0f7ec5f22a5ecdf369b95b8",
"sha256": "fce5c3e2946ab8fdcae936a1c1e1d6788a0496e37a069f610c70e27c963852c4"
},
"downloads": -1,
"filename": "permission-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "0971700ce0f7ec5f22a5ecdf369b95b8",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 4903,
"upload_time": "2015-11-11T16:18:18",
"url": "https://files.pythonhosted.org/packages/86/2c/9552f25a86ff341896a743b371df48e39897d91dc9b065ccd281def4ffff/permission-0.4.0.tar.gz"
}
],
"0.4.1": [
{
"comment_text": "",
"digests": {
"md5": "a8ef00354a25f6b205f30d4f8e817db9",
"sha256": "f2cd126123fb9f3f4f80a9640cf3aea688b06701525e02c25aa17221c0d871c8"
},
"downloads": -1,
"filename": "permission-0.4.1.tar.gz",
"has_sig": false,
"md5_digest": "a8ef00354a25f6b205f30d4f8e817db9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 5056,
"upload_time": "2015-11-12T03:06:43",
"url": "https://files.pythonhosted.org/packages/87/a1/dbcbaff2fccd3dd905f916a1fee9df8a9d4358ee475bbb0a8cfd53fc36ab/permission-0.4.1.tar.gz"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "a8ef00354a25f6b205f30d4f8e817db9",
"sha256": "f2cd126123fb9f3f4f80a9640cf3aea688b06701525e02c25aa17221c0d871c8"
},
"downloads": -1,
"filename": "permission-0.4.1.tar.gz",
"has_sig": false,
"md5_digest": "a8ef00354a25f6b205f30d4f8e817db9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 5056,
"upload_time": "2015-11-12T03:06:43",
"url": "https://files.pythonhosted.org/packages/87/a1/dbcbaff2fccd3dd905f916a1fee9df8a9d4358ee475bbb0a8cfd53fc36ab/permission-0.4.1.tar.gz"
}
]
}