Fixed decorator to only check for permissions if user is logged in. Added permission_denied view to be used when permission check unsuccessful, e.g. with the new permission_required_or_403 decorator. The permission_required decorator will redirect to the login form by default.

This commit is contained in:
Jannis Leidel 2009-07-03 15:41:21 +02:00
parent 0f14d735a3
commit 287d2eccd5
3 changed files with 56 additions and 25 deletions

View file

@ -1,8 +1,9 @@
from django.contrib.flatpages.views import flatpage
from django.contrib.flatpages.models import FlatPage
from authority.decorators import permission_required
from authority.decorators import permission_required, permission_required_or_403
#@permission_required_or_403('flatpage_permission.top_secret', (FlatPage, 'url__contains')) # use this to return a 403 page
@permission_required('flatpage_permission.top_secret', (FlatPage, 'url__contains'))
def top_secret(request, url):
"""

View file

@ -10,38 +10,49 @@ from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth import REDIRECT_FIELD_NAME
from authority import permissions
from authority.views import permission_denied
def permission_required(perm, *args, **kwargs):
"""
Decorator for views that checks whether a user has a particular permission
enabled, redirecting to the log-in page if necessary.
"""
login_url = kwargs.pop('login_url', None)
if not login_url:
login_url = getattr(settings, 'LOGIN_URL', '/')
login_url = kwargs.pop('login_url', settings.LOGIN_URL)
redirect_field_name = kwargs.pop('redirect_field_name', REDIRECT_FIELD_NAME)
redirect_to_login = kwargs.pop('redirect_to_login', True)
model_lookups = args
def _permission_required(view_func, request, *args, **kwargs):
objs = []
# model_lookups = [('flatpages.flatpage', 'url__contains')]
for i, arguments in enumerate(model_lookups):
model, lookup = arguments
if isinstance(model, basestring):
model_class = get_model(*model.split("."))
else:
model_class = model
if model_class is None:
raise ValueError(
"The given argument '%s' is not a valid model." % model)
if inspect.isclass(model_class) and \
not issubclass(model_class, Model):
raise ValueError(
'The argument %s needs to be a model.' % model)
objs.append(get_object_or_404(model_class, **{lookup: args[i]}))
check = permissions.registry.get_check(request.user, perm)
if check is not None:
if check(*objs):
return view_func(request, *args, **kwargs)
#return HttpResponseForbidden("Permission")
raise PermissionDenied()
if request.user.is_authenticated():
for i, arguments in enumerate(model_lookups):
model, lookup = arguments
if isinstance(model, basestring):
model_class = get_model(*model.split("."))
else:
model_class = model
if model_class is None:
raise ValueError(
"The given argument '%s' is not a valid model." % model)
if inspect.isclass(model_class) and \
not issubclass(model_class, Model):
raise ValueError(
'The argument %s needs to be a model.' % model)
objs.append(get_object_or_404(model_class, **{lookup: args[i]}))
check = permissions.registry.get_check(request.user, perm)
if check is not None:
if check(*objs):
return view_func(request, *args, **kwargs)
if redirect_to_login:
path = urlquote(request.get_full_path())
tup = login_url, redirect_field_name, path
return HttpResponseRedirect('%s?%s=%s' % tup)
return permission_denied(request)
return decorator(_permission_required)
def permission_required_or_403(perm, *args, **kwargs):
"""
Decorator that wraps the permission_required decorator and returns a
permission denied (403) page instead of redirecting to the login URL.
"""
kwargs['redirect_to_login'] = False
return permission_required(perm, *args, **kwargs)

View file

@ -5,6 +5,7 @@ from django.db.models.loading import get_model
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext, ugettext_lazy as _
from django.template.context import RequestContext
from django.template import loader
from django.contrib.auth.decorators import login_required
from authority.models import Permission
@ -56,3 +57,21 @@ def delete_permission(request, permission_pk):
message=ugettext('You removed the permission.'))
next = request.REQUEST.get('next') or '/'
return HttpResponseRedirect(next)
def permission_denied(request, template_name=None, extra_context={}):
"""
Default 403 handler.
Templates: `403.html`
Context:
request_path
The path of the requested URL (e.g., '/app/pages/bad_page/')
"""
if template_name is None:
template_name = ('authority/403.html', '403.html')
context = {
'request_path': request.path,
}
context.update(extra_context)
return HttpResponseForbidden(loader.render_to_string(template_name, context,
context_instance=RequestContext(request)))