Yet another access control list (ACL) per view for Django
- Clone this repo to your PC
- Run
pip install yaACL
- Put
yaacl
in INSTALLED_APPS, after auth and admin apps - Put
import yaacl
at the end of your current settings file - Run
./manage.py syncdb
or./manage.py migrate
- This app get information about your auth user model form settings
(
AUTH_USER_MODEL
) - If you also have custom group model, then define it in
settings.ACL_GROUP_USER_MODEL
(ie:cms_user.group
)
In views, import acl_register_view
or acl_register_class
, then
decorate views you want under control access. After all views are decorated,
run command ./manage.py sync_acl
, so all views will be registered in
database.
from yaacl.decorators import acl_register_view
from django.contrib.auth.decorators import login_required
@login_required
@acl_register_view('Short description about this view', 'resource_name')
def index(request):
pass
First parameter is name
the short name for this view (resource). Second
parameter is resource
, and isn't required. If name=None
,
resource
not supplied, the name for resource will be generated by joining
module name and function/class name
It's up to you how you name those resources, but I recommend (and use in
project I made this app) to name them as <app_label>.<view_name>
, so
later in templates you can check if user has access to all resources
in <app_label>.
Let's say, you have a typical CRUD view in you news application, so code would be like this:
from yaacl.decorators import acl_register_view
from django.contrib.auth.decorators import login_required
#decorationg standard function based views
@login_required
@acl_register_view('News list', 'news.create)
def index(request):
...
@login_required
@acl_register_view('Update news entry')
def update(request):
...
@login_required
@acl_register_view('Delete news entry')
def delete(request):
...
#decoration class-based views
@acl_register_class(u"Create news")
class Create(FormView):
...
So, your resources list will be like this:
news.views.index
News listnews.create
Create new newsnews.views.update
Update news entrynews.views.delete
Delete news entry
Now if you want to check if current user has access to news.index, then in templates you can check them by using code like:
{% load acl %}
...
{% if request.user|has_access:'news.index' %}
Yes it has access to news.index view.
{% else %}
No, it has not.
{% endif %}
But if you want to check if user has access to
{% if request.user|have_access:'news.' %}
Yes it has access to all resources in news.
{% else %}
No, it has not.
{% endif %}
Actually there is only one signal, yaacl.signals.register_resource
, which
is called before resource is registered in ACL.acl_list
. It's purpose is to
transform name
and/or resource
. The function should return dict with
keys name
and resource
.
Example usage is below, where I use it to remove the module
and views
from resource name
from yaacl.signals import register_resource
from django.dispatch import receiver
@receiver(register_resource)
def transform_resource(sender, resource, name, **kwargs):
resource_parts = resource.split('.')
if resource_parts and resource_parts[0] == 'module':
resource_parts.pop(0)
if len(resource_parts) >= 2 and resource_parts[-2] == 'views':
resource_parts.pop(-2)
resource = '.'.join(resource_parts)
return {'resource': resource, 'name': name}
- If flag
is_superuser
isTrue
, then always access is granted - No-access page template is located in
yaacl/no_access.html
file - Test in
has_access
template tag just check if resource name starts with given name
.travis.yml
- A flag, to indicates a resources that staff members has full access