2008-02-25 14:02:35 +08:00
import base64
import cPickle as pickle
try :
from functools import wraps
except ImportError :
from django . utils . functional import wraps # Python 2.3, 2.4 fallback.
2006-05-02 09:31:56 +08:00
from django import http , template
from django . conf import settings
2006-06-29 00:37:02 +08:00
from django . contrib . auth . models import User
from django . contrib . auth import authenticate , login
2006-05-02 09:31:56 +08:00
from django . shortcuts import render_to_response
Merged Unicode branch into trunk (r4952:5608). This should be fully
backwards compatible for all practical purposes.
Fixed #2391, #2489, #2996, #3322, #3344, #3370, #3406, #3432, #3454, #3492, #3582, #3690, #3878, #3891, #3937, #4039, #4141, #4227, #4286, #4291, #4300, #4452, #4702
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5609 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2007-07-04 20:11:04 +08:00
from django . utils . translation import ugettext_lazy , ugettext as _
2008-08-02 13:56:57 +08:00
from django . utils . hashcompat import md5_constructor
2005-10-18 12:21:07 +08:00
Merged Unicode branch into trunk (r4952:5608). This should be fully
backwards compatible for all practical purposes.
Fixed #2391, #2489, #2996, #3322, #3344, #3370, #3406, #3432, #3454, #3492, #3582, #3690, #3878, #3891, #3937, #4039, #4141, #4227, #4286, #4291, #4300, #4452, #4702
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5609 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2007-07-04 20:11:04 +08:00
ERROR_MESSAGE = ugettext_lazy ( " Please enter a correct username and password. Note that both fields are case-sensitive. " )
2005-10-18 12:21:07 +08:00
LOGIN_FORM_KEY = ' this_is_the_login_form '
def _display_login_form ( request , error_message = ' ' ) :
request . session . set_test_cookie ( )
2007-04-26 21:30:48 +08:00
if request . POST and ' post_data ' in request . POST :
2005-10-18 12:21:07 +08:00
# User has failed login BUT has previously saved post data.
post_data = request . POST [ ' post_data ' ]
elif request . POST :
# User's session must have expired; save their post data.
post_data = _encode_post_data ( request . POST )
else :
post_data = _encode_post_data ( { } )
2006-05-02 09:31:56 +08:00
return render_to_response ( ' admin/login.html ' , {
2005-11-25 10:18:37 +08:00
' title ' : _ ( ' Log in ' ) ,
2008-05-10 21:19:19 +08:00
' app_path ' : request . path ,
2005-10-18 12:21:07 +08:00
' post_data ' : post_data ,
' error_message ' : error_message
2006-05-02 09:31:56 +08:00
} , context_instance = template . RequestContext ( request ) )
2005-10-18 12:21:07 +08:00
def _encode_post_data ( post_data ) :
pickled = pickle . dumps ( post_data )
2008-08-02 13:56:57 +08:00
pickled_md5 = md5_constructor ( pickled + settings . SECRET_KEY ) . hexdigest ( )
2005-10-18 12:21:07 +08:00
return base64 . encodestring ( pickled + pickled_md5 )
def _decode_post_data ( encoded_data ) :
encoded_data = base64 . decodestring ( encoded_data )
pickled , tamper_check = encoded_data [ : - 32 ] , encoded_data [ - 32 : ]
2008-08-02 13:56:57 +08:00
if md5_constructor ( pickled + settings . SECRET_KEY ) . hexdigest ( ) != tamper_check :
2005-10-18 12:21:07 +08:00
from django . core . exceptions import SuspiciousOperation
raise SuspiciousOperation , " User may have tampered with session cookie. "
return pickle . loads ( pickled )
def staff_member_required ( view_func ) :
"""
Decorator for views that checks that the user is logged in and is a staff
member , displaying the login page if necessary .
"""
def _checklogin ( request , * args , * * kwargs ) :
2006-07-19 10:09:26 +08:00
if request . user . is_authenticated ( ) and request . user . is_staff :
2005-10-18 12:21:07 +08:00
# The user is valid. Continue to the admin page.
2007-04-26 21:30:48 +08:00
if ' post_data ' in request . POST :
2006-01-17 02:54:41 +08:00
# User must have re-authenticated through a different window
# or tab.
request . POST = _decode_post_data ( request . POST [ ' post_data ' ] )
2005-10-18 12:21:07 +08:00
return view_func ( request , * args , * * kwargs )
2006-05-02 09:31:56 +08:00
assert hasattr ( request , ' session ' ) , " The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert ' django.contrib.sessions.middleware.SessionMiddleware ' . "
2005-10-18 12:21:07 +08:00
# If this isn't already the login page, display it.
2007-04-26 21:30:48 +08:00
if LOGIN_FORM_KEY not in request . POST :
2005-10-18 12:21:07 +08:00
if request . POST :
2005-11-25 10:18:37 +08:00
message = _ ( " Please log in again, because your session has expired. Don ' t worry: Your submission has been saved. " )
2005-10-18 12:21:07 +08:00
else :
message = " "
return _display_login_form ( request , message )
# Check that the user accepts cookies.
if not request . session . test_cookie_worked ( ) :
2005-11-25 10:18:37 +08:00
message = _ ( " Looks like your browser isn ' t configured to accept cookies. Please enable cookies, reload this page, and try again. " )
2005-10-18 12:21:07 +08:00
return _display_login_form ( request , message )
# Check the password.
2006-06-29 00:37:02 +08:00
username = request . POST . get ( ' username ' , None )
password = request . POST . get ( ' password ' , None )
user = authenticate ( username = username , password = password )
if user is None :
2005-10-18 12:21:07 +08:00
message = ERROR_MESSAGE
if ' @ ' in username :
# Mistakenly entered e-mail address instead of username? Look it up.
2008-05-17 06:53:39 +08:00
users = list ( User . objects . filter ( email = username ) )
if len ( users ) == 1 :
message = _ ( " Your e-mail address is not your username. Try ' %s ' instead. " ) % users [ 0 ] . username
2005-10-18 12:21:07 +08:00
else :
2008-08-02 13:56:57 +08:00
# Either we cannot find the user, or if more than 1
2008-05-17 06:53:39 +08:00
# we cannot guess which user is the correct one.
message = _ ( " Usernames cannot contain the ' @ ' character. " )
2005-10-18 12:21:07 +08:00
return _display_login_form ( request , message )
# The user data is correct; log in the user in and continue.
else :
2006-09-29 21:37:58 +08:00
if user . is_active and user . is_staff :
2006-06-29 00:37:02 +08:00
login ( request , user )
# TODO: set last_login with an event.
2007-04-26 21:30:48 +08:00
if ' post_data ' in request . POST :
2005-10-18 12:21:07 +08:00
post_data = _decode_post_data ( request . POST [ ' post_data ' ] )
2007-04-26 21:30:48 +08:00
if post_data and LOGIN_FORM_KEY not in post_data :
2005-10-18 12:21:07 +08:00
# overwrite request.POST with the saved post_data, and continue
request . POST = post_data
request . user = user
return view_func ( request , * args , * * kwargs )
else :
request . session . delete_test_cookie ( )
2006-05-02 09:31:56 +08:00
return http . HttpResponseRedirect ( request . path )
2005-10-18 12:21:07 +08:00
else :
return _display_login_form ( request , ERROR_MESSAGE )
2008-02-25 14:02:35 +08:00
return wraps ( view_func ) ( _checklogin )