Authorization library for Django, with ACL, not depends on models.
Project description
django-keeper
Authorization library for Django, not depends on models.
- Won't depend on models
- Won't depend on datastores
- Won't depend on Django's permission system
- Won't depend on Django's User model
Supported versions:
- Python3.8
- Python 3.9
- Django 2.2
- Django 3.0
- Django 3.1
- Django 3.2
- Django 4.1
- Django 4.2
Install
$ pip install django-keeper
And add to INSTALLED_APPS
INSTALLED_APPS = [
...
'keeper',
]
At A Glance
Declarative permission mapping for models.
from django.conf import settings
from keeper.security import Allow
from keeper.operators import Everyone, Authenticated, IsUser
class Issue(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
...
def __acl__(self):
return [
(Allow, Everyone, 'view'),
(Allow, Authenticated, 'add_comment'),
(Allow, IsUser(self.author), 'edit'),
]
Instances of model allow:
- Every requests to view
- Autheticated requests to add comments
- it's author to edit
Then, apply @keeper
for views.
from keeper.views import keeper
# Model Permissions
@keeper(
'view',
model=Issue,
mapper=lambda request, issue_id: {'id': issue_id},
)
def issue_detail(request, issue_id):
""" View requires 'view' permission of Issue model
* An issue object will be retrieved
* keeper will check whether the rquests has 'view' permission for the issue
The third argument function can return keyword argument to retrieve the issue object.
"""
request.k_context # Will be instance of the issue object
...
@keeper(
'add_comment',
model=Issue,
mapper=lambda request, issue_id: {'id': issue_id},
)
def add_comment(request, issue_id):
...
Global Permission
Not just for model permissions django-keeper
can handle global permissions.
First, write class having __acl__
method in models.py.
class Root:
def __acl__(self):
return [
(Allow, Authenticated, 'view_dashboard'),
(Allow, Authenticated, 'add_issue'),
]
It's not necessary to put it in models.py
,
but easy to understand.
And specify it in settings.
KEEPER_GLOBAL_CONTEXT = 'myapp.models.Root'
Then you can use global permission in views.
Simply just apply @keeper
and permission names.
@keeper('add_issue')
def issue_list(request):
""" View requires 'add_issue' permission of Root Context
"""
Operators
Operators is just Callable[[HttpRequest], bool]
.
By default django-keeper has these operators:
keeper.operators.Everyone
keeper.operators.Authenticated
keeper.operators.IsUser
keeper.operators.Staff
Also you can create your own operators easily.
from keeper.operators import Authenticated, Operator
class IsIP(Operator):
def __init__(self, ip):
self.ip = ip
def __call__(self, request):
return request.META.get('REMOTE_ADDR') == self.ip
class BelongsTeam(Authenticated):
def __init__(self, team, role):
self.team = team
def __call__(self, request):
if not super().__call__(request):
return False
return request.user.team == self.team
Use it in ACL
class Article(models.Model):
team = models.ForeignKey(Team)
def __acl__(self):
return [
(Allow, Everyone, 'view'),
(Allow, BelongsTeam(self.team), 'edit'),
(Allow, IsIP(settings.COMPANY_IP_ADDRESS), 'edit'),
]
Combining operators
You can use bitwise operators to combine multiple "Operators".
class Article(models.Model):
def __acl__(self):
return [
(Allow, Authenticated() & IsIP(settings.COMPANY_IP_ADDRESS), 'view'),
]
There operators can be used
a & b
a | b
a ^ b
~a
On Fail Actions
You can change actions when requests can't pass ACLs.
from keeper.views import keeper, login_required
@keeper(
'view_articles',
on_fail=login_required(),
)
def dashboard(request):
...
This view will behave just like @login_required
decorator of Django
when requests don't have 'view' permission.
Also you can use other actions.
keeper.views.login_required
keeper.views.permission_denied
keeper.views.not_found
keeper.views.redirect
Use in template
Handling permissions in templates is also supported.
{% load keeper %}
{% has_permission issue 'edit' as can_edit %}
{% if can_edit %}
<a href="...">Edit</a>
{% endif %}
When checking global permission, use has_global_permission
.
{% load keeper %}
{% has_global_permission 'add_issue' as can_add_issue %}
{% if can_add_issue %}
<a href="...">New Issue</a>
{% endif %}
With Django Core
Add the authentication backend:
AUTHENTICATION_BACKENDS = (
'keeper.permissions.ObjectPermissionBackend',
'django.contrib.auth.backends.ModelBackend',
)
Now User.has_perm
method will consider permissions of django-keeper.
Alternative
- django-guardian
- It depends on databases
- Not way to handle global permissions, not just for a model
- django-rules
- Basiaclly, rules is used with Django's permissions, but keeper isn't (basiacally).
- rules doesn't support view decorators or mixins for it's "rules" system (for Django's permission, yes).
FAQ
- Can I filter models by using ACL?
- Not supported
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file django-keeper-0.4.1.tar.gz
.
File metadata
- Download URL: django-keeper-0.4.1.tar.gz
- Upload date:
- Size: 7.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/44.0.0 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.8.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b97d0e09f6774e9e975fa3932ee5856a621a746ab74e5a3e431b1c907df1f06c |
|
MD5 | fb61a65f019a91665a49817faf767d0b |
|
BLAKE2b-256 | 4693af149a9a0a5a5ea8a6336c07879494764485b56a1ed7a0387da163e57067 |
File details
Details for the file django_keeper-0.4.1-py3-none-any.whl
.
File metadata
- Download URL: django_keeper-0.4.1-py3-none-any.whl
- Upload date:
- Size: 7.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/44.0.0 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.8.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 35b50b552133dc8407968a129df6dea9cea4c1adc31441e397b29b83a2b66987 |
|
MD5 | 0da159ec3763d0df06994ba9b38afe3c |
|
BLAKE2b-256 | 362ad2ab0622c42b2e31e808a34022ae5fe4ae5b08cbd1f960c4aa4b780a5af4 |