1 # -*- coding: utf-8 -*-
2 #############################################################################
3 # from http://djangosnippets.org/snippets/243/
5 from functools import wraps
8 from django.http import HttpResponse
9 from django.contrib.auth import authenticate, login
12 def view_or_basicauth(view, request, test_func, realm="", *args, **kwargs):
14 This is a helper function used by 'logged_in_or_basicauth' and
15 'has_perm_or_basicauth' (deleted) that does the nitty of determining if they
16 are already logged in or if they have provided proper http-authorization
17 and returning the view if all goes well, otherwise responding with a 401.
19 if test_func(request.user):
20 # Already logged in, just return the view.
22 return view(request, *args, **kwargs)
24 # They are not logged in. See if they provided login credentials
26 if 'HTTP_AUTHORIZATION' in request.META:
27 auth = request.META['HTTP_AUTHORIZATION'].split()
29 # NOTE: We are only support basic authentication for now.
31 if auth[0].lower() == "basic":
32 uname, passwd = base64.b64decode(auth[1]).split(':')
33 user = authenticate(username=uname, password=passwd)
38 return view(request, *args, **kwargs)
40 # Either they did not provide an authorization header or
41 # something in the authorization attempt failed. Send a 401
42 # back to them to ask them to authenticate.
44 response = HttpResponse()
45 response.status_code = 401
46 response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
51 def logged_in_or_basicauth(realm=""):
53 A simple decorator that requires a user to be logged in. If they are not
54 logged in the request is examined for a 'authorization' header.
56 If the header is present it is tested for basic authentication and
57 the user is logged in with the provided credentials.
59 If the header is not present a http 401 is sent back to the
60 requestor to provide credentials.
62 The purpose of this is that in several django projects I have needed
63 several specific views that need to support basic authentication, yet the
64 web site as a whole used django's provided authentication.
66 The uses for this are for urls that are access programmatically such as
67 by rss feed readers, yet the view requires a user to be logged in. Many rss
68 readers support supplying the authentication credentials via http basic
69 auth (and they do NOT support a redirect to a form where they post a
74 @logged_in_or_basicauth
78 You can provide the name of the realm to ask for authentication within.
80 def view_decorator(func):
81 def wrapper(request, *args, **kwargs):
82 return view_or_basicauth(func, request,
83 lambda u: u.is_authenticated(),
84 realm, *args, **kwargs)
89 #############################################################################
92 def factory_decorator(decorator):
93 """ generates a decorator for a function factory class
94 if A(*) == f, factory_decorator(D)(A)(*) == D(f)
98 def wrapper(*args, **kwargs):
99 return decorator(func(*args, **kwargs))