{ "info": { "author": "Mike Hearing", "author_email": "mhearing@genepeeks.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.5", "Topic :: Security", "Topic :: Software Development :: Libraries :: Application Frameworks" ], "description": "# django-hats\n[![Coverage Status](https://coveralls.io/repos/github/GenePeeks/django-hats/badge.svg?branch=master)](https://coveralls.io/github/GenePeeks/django-hats?branch=master)\n[![PyPI](https://img.shields.io/pypi/pyversions/django-hats.svg)]()\n\nRole-based permissions system for Django. Everyone wears a different hat, some people wear multiple.\n\nIn a nutshell, django-hats is a reusable app, which doesn't try to re-invent the wheel by having Django Groups as its foundation. It provides a compact collection of easy to use patterns/utilities for role, and permission, based checks in CBVs and templates. They have the advantages of being: pragmatically defined, performant, clear syntax, and are well tested/documented!\n\n## Quick Start\n\nInstall with `pip`:\n\n```\npip install django-hats\n```\n\nOr, getting the latest build:\n```\npip install git+git://github.com/GenePeeks/django-hats.git@master\n```\n\nAdd `django_hats` to your `INSTALLED_APPS`:\n\n```python\nINSTALLED_APPS = (\n ...\n 'django_hats',\n ...\n)\n```\n\nCreate `roles.py` in any registered applications in your Django project:\n\n```python\nfrom django_hats.roles import Role\n\nclass Scientist(Role):\n class Meta:\n permissions = ('change_subject', 'change_specimen')\n\nclass GeneticCounselor(Role):\n pass\n```\n\nSynchronize your database with defined roles:\n\n```\npython manage.py synchronize_roles\n```\n\nYou're ready to go! Start defining permissions and securing your application!\n\n## Working with roles\n\nPragmatically assigning/removing/viewing `Permission` to role:\n\n```python\n>>> Scientist.add_permissions(perm_1, perm_2, ...)\n>>> GeneticCounselor.remove_permissions(perm_3)\n>>> Scientist.get_permissions()\n[, ]\n```\n\nAssigning/removing roles for a user(works with custom user models):\n\n```python\n>>> user = User.objects.first()\n>>> Scientist.assign(user)\n>>> Scientist.remove(user)\n```\n\nThen checking if a user has a role, or multiple roles:\n\n```python\n>>> from django_hats.utils import check_membership\n>>> Scientist.check_membership(user)\nTrue\n>>> GeneticCounselor.check_membership(user)\nFalse\n>>> check_membership(user, Scientist)\nTrue\n>>> check_membership(user, [Scientist, GeneticCounselor])\nFalse\n>>> check_membership(user, [Scientist, GeneticCounselor], any=True)\nTrue\n```\n\nList users with a given role:\n\n```python\n>>> Scientist.get_users()\n[, ]\n```\n\nRetrieving roles pragmatically:\n\n```python\n>>> from django_hats.roles import RoleFinder\n...\n>>> RoleFinder.by_user(user)\n[, ]\n>>> RoleFinder.by_name('genetic_counselor')\n\n>>> RoleFinder.by_group(group)\n\n```\n\n## Mixins\n\nEnforcing roles on the view:\n\n```python\nfrom django.views.generic import TemplateView\nfrom django_hats.mixins import RoleRequiredMixin\n\nfrom app.roles import GeneticCounselor, Scientist\n\nclass ProtectedGeneticReport(RoleRequiredMixin, TemplateView):\n role_required = GeneticCounselor\n template_name = 'template.html'\n\n\nclass ProtectedGeneticFiles(RoleRequiredMixin, TemplateView):\n # Works with existing Django `PermissionRequiredMixin`\n permission_required = ('change_subject', 'change_specimen')\n role_required = (GeneticCounselor, Scientist)\n role_required_any = True\n template_name = 'template.html'\n```\n\n## Templates\n\nChecking roles in the template like permissions: \n**NOTE**: This is the reccomended way to check for roles in the template\n\nsettings.py\n```\nTEMPLATE_CONTEXT_PROCESSORS = (\n ...\n 'django_hats.context_processors.roles',\n ...\n)\n```\n\ntemplate.html\n```html\n{% if roles.scientist %}PROTECTED CONTENT!{% endif %}\n\n{% if roles.genetic_counselor %}NOTE: Class names are converted to snake_case if not specified in role.Meta.name{% endif %}\n```\n\nChecking roles in the template with filter tag: \n**NOTE**: This works without the context processor, and is not required when using the context processor, if thats your thing\n\n```\n{% load roles %}\n\n{% if user|has_role:'scientist' or user|has_role:genetic_counselor_role %}PROTECTED CONTENT!{% endif %}\n```\n\n## Signals\n\n#### post_synchronize_roles\n- `sender`: django-hats `AppConfig`\n\n\n## Management Commands\n\nSynchronize roles/permissions from the database:\n\n```\npython manage.py synchronize_roles\n```\n\nMigrate a role which the class name/name has changed:\n\n```\npython manage.py migrate_role --old=OldRoleClass --new=NewRoleClass\n```\n\nRemove old roles/permissions from the database(only post migration if a name change occured):\n\n```\npython manage.py cleanup_roles\n```\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/GenePeeks/django-hats", "keywords": "", "license": "MIT License", "maintainer": "", "maintainer_email": "", "name": "django-hats", "package_url": "https://pypi.org/project/django-hats/", "platform": "", "project_url": "https://pypi.org/project/django-hats/", "project_urls": { "Homepage": "https://github.com/GenePeeks/django-hats" }, "release_url": "https://pypi.org/project/django-hats/1.1.2/", "requires_dist": [ "django (>=1.9.0)" ], "requires_python": "", "summary": "Role-based permissions system for Django. Everyone wears a different hat, some people wear multiple.", "version": "1.1.2" }, "last_serial": 3346580, "releases": { "1.1.0": [ { "comment_text": "", "digests": { "md5": "b90ddb1ae2338cd2341fd02df7206767", "sha256": "e98dc426c87e84e888f73888b75f239b79f52fd565f2dffa0748291a66b912bc" }, "downloads": -1, "filename": "django_hats-1.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b90ddb1ae2338cd2341fd02df7206767", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 35967, "upload_time": "2017-02-01T18:35:11", "url": "https://files.pythonhosted.org/packages/bb/16/988bfa7b21e29fdea6ae120b75845b77687b4b67714a8ffd31f0922d9d0c/django_hats-1.1.0-py2.py3-none-any.whl" } ], "1.1.2": [ { "comment_text": "", "digests": { "md5": "2697fe85fbe1e7eec49468127fe978ca", "sha256": "83c0083504fdcb2c10a64cc5d45e3e3661a4004d8befec6baae8d6c90f319b74" }, "downloads": -1, "filename": "django_hats-1.1.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "2697fe85fbe1e7eec49468127fe978ca", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 39784, "upload_time": "2017-11-19T21:23:18", "url": "https://files.pythonhosted.org/packages/23/93/e7b66b32e8301b88b16ba04f89840b1523370dde37ac38dd85a510d291ad/django_hats-1.1.2-py2.py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "2697fe85fbe1e7eec49468127fe978ca", "sha256": "83c0083504fdcb2c10a64cc5d45e3e3661a4004d8befec6baae8d6c90f319b74" }, "downloads": -1, "filename": "django_hats-1.1.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "2697fe85fbe1e7eec49468127fe978ca", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 39784, "upload_time": "2017-11-19T21:23:18", "url": "https://files.pythonhosted.org/packages/23/93/e7b66b32e8301b88b16ba04f89840b1523370dde37ac38dd85a510d291ad/django_hats-1.1.2-py2.py3-none-any.whl" } ] }