Permalink
Browse files

Fixed #1 -- Added anonymous session support via middleware and reques…

…t.session. Removed the former request.session, which wasn't being used anyway. Removed auth.Session model. See the BackwardsIncompatibleChanges wiki page for IMPORTANT notes on code you'll have to change and a DB table you'll have to create.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@518 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent f21ff30 commit 07889c13a63eeb3e8a73f1e02a21227def3ae548 @adrianholovaty adrianholovaty committed Aug 16, 2005
@@ -7,7 +7,7 @@
def clean_up():
# Clean up old database records
cursor = db.cursor()
- cursor.execute("DELETE FROM auth_sessions WHERE start_time < NOW() - INTERVAL '2 weeks'")
+ cursor.execute("DELETE FROM core_sessions WHERE expire_date < NOW()")
cursor.execute("DELETE FROM registration_challenges WHERE request_date < NOW() - INTERVAL '1 week'")
db.commit()
@@ -48,9 +48,6 @@
# Host for sending e-mail.
EMAIL_HOST = 'localhost'
-# Name of the session cookie. This can be whatever you want.
-AUTH_SESSION_COOKIE = 'rizzo'
-
# List of locations of the template source files, in search order.
TEMPLATE_DIRS = ()
@@ -113,6 +110,14 @@
"django.middleware.doc.XViewMiddleware",
)
+############
+# SESSIONS #
+############
+
+SESSION_COOKIE_NAME = 'hotclub' # Cookie name. This can be whatever you want.
+SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
+SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
+
#########
# CACHE #
#########
@@ -121,9 +126,6 @@
# possible values.
CACHE_BACKEND = 'simple://'
-# Set to a string like ".lawrence.com", or None for a standard domain cookie.
-REGISTRATION_COOKIE_DOMAIN = None
-
####################
# COMMENTS #
####################
@@ -2,7 +2,7 @@
from django.core.mail import mail_admins, mail_managers
from django.core.exceptions import Http404, ObjectDoesNotExist
from django.core.extensions import DjangoContext as Context
-from django.models.auth import sessions
+from django.models.auth import users
from django.models.comments import comments, freecomments
from django.models.core import contenttypes
from django.parts.auth.formfields import AuthenticationForm
@@ -215,7 +215,7 @@ def post_comment(request):
# If user gave correct username/password and wasn't already logged in, log them in
# so they don't have to enter a username/password again.
if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
- sessions.start_web_session(manipulator.get_user_id(), request, response)
+ request.session[users.SESSION_KEY] = manipulator.get_user_id()
if errors or request.POST.has_key('preview'):
class CommentFormWrapper(formfields.FormWrapper):
def __init__(self, manipulator, new_data, errors, rating_choices):
@@ -95,29 +95,17 @@ def _get_raw_post_data(self):
self._raw_post_data = self._req.read()
return self._raw_post_data
- def _load_session_and_user(self):
- from django.models.auth import sessions
- from django.conf.settings import AUTH_SESSION_COOKIE
- session_cookie = self.COOKIES.get(AUTH_SESSION_COOKIE, '')
- try:
- self._session = sessions.get_session_from_cookie(session_cookie)
- self._user = self._session.get_user()
- except sessions.SessionDoesNotExist:
- from django.parts.auth import anonymoususers
- self._session = None
- self._user = anonymoususers.AnonymousUser()
-
- def _get_session(self):
- if not hasattr(self, '_session'):
- self._load_session_and_user()
- return self._session
-
- def _set_session(self, session):
- self._session = session
-
def _get_user(self):
if not hasattr(self, '_user'):
- self._load_session_and_user()
+ from django.models.auth import users
+ try:
+ user_id = self.session[users.SESSION_KEY]
+ if not user_id:
+ raise ValueError
+ self._user = users.get_object(pk=user_id)
+ except (AttributeError, KeyError, ValueError, users.UserDoesNotExist):
+ from django.parts.auth import anonymoususers
+ self._user = anonymoususers.AnonymousUser()
return self._user
def _set_user(self, user):
@@ -130,7 +118,6 @@ def _set_user(self, user):
META = property(_get_meta)
REQUEST = property(_get_request)
raw_post_data = property(_get_raw_post_data)
- session = property(_get_session, _set_session)
user = property(_get_user, _set_user)
class ModPythonHandler(BaseHandler):
@@ -76,29 +76,17 @@ def _get_raw_post_data(self):
self._raw_post_data = self.environ['wsgi.input'].read(int(self.environ["CONTENT_LENGTH"]))
return self._raw_post_data
- def _load_session_and_user(self):
- from django.models.auth import sessions
- from django.conf.settings import AUTH_SESSION_COOKIE
- session_cookie = self.COOKIES.get(AUTH_SESSION_COOKIE, '')
- try:
- self._session = sessions.get_session_from_cookie(session_cookie)
- self._user = self._session.get_user()
- except sessions.SessionDoesNotExist:
- from django.parts.auth import anonymoususers
- self._session = None
- self._user = anonymoususers.AnonymousUser()
-
- def _get_session(self):
- if not hasattr(self, '_session'):
- self._load_session_and_user()
- return self._session
-
- def _set_session(self, session):
- self._session = session
-
def _get_user(self):
if not hasattr(self, '_user'):
- self._load_session_and_user()
+ from django.models.auth import users
+ try:
+ user_id = self.session[users.SESSION_KEY]
+ if not user_id:
+ raise ValueError
+ self._user = users.get_object(pk=user_id)
+ except (AttributeError, KeyError, ValueError, users.UserDoesNotExist):
+ from django.parts.auth import anonymoususers
+ self._user = anonymoususers.AnonymousUser()
return self._user
def _set_user(self, user):
@@ -110,7 +98,6 @@ def _set_user(self, user):
FILES = property(_get_files)
REQUEST = property(_get_request)
raw_post_data = property(_get_raw_post_data)
- session = property(_get_session, _set_session)
user = property(_get_user, _set_user)
class WSGIHandler(BaseHandler):
@@ -1,7 +1,7 @@
from django.utils import httpwrappers
from django.core import template_loader
from django.core.extensions import DjangoContext as Context
-from django.models.auth import sessions, users
+from django.models.auth import users
from django.views.registration import passwords
from django.views.auth.login import logout
import base64, md5
@@ -29,14 +29,17 @@ def process_view(self, request, view_func, param_dict):
# Otherwise the password reset would need its own entry in the httpd
# conf, which is a little uglier than this. Same goes for the logout
# view.
+
if view_func in (passwords.password_reset, passwords.password_reset_done, logout):
return
+ assert hasattr(request, 'session'), "The admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.middleware.sessions.SessionMiddleware' before %r." % self.__class__.__name__
+
# Check for a logged in, valid user
if self.user_is_valid(request.user):
return
- # If this isn't alreay the login page, display it
+ # If this isn't already the login page, display it
if not request.POST.has_key('this_is_the_login_form'):
if request.POST:
message = "Please log in again, because your session has expired. "\
@@ -64,18 +67,16 @@ def process_view(self, request, view_func, param_dict):
# The user data is correct; log in the user in and continue
else:
if self.authenticate_user(user, request.POST.get('password', '')):
+ request.session[users.SESSION_KEY] = user.id
if request.POST.has_key('post_data'):
post_data = decode_post_data(request.POST['post_data'])
if post_data and not post_data.has_key('this_is_the_login_form'):
# overwrite request.POST with the saved post_data, and continue
request.POST = post_data
request.user = user
- request.session = sessions.create_session(user.id)
return
else:
- response = httpwrappers.HttpResponseRedirect(request.path)
- sessions.start_web_session(user.id, request, response)
- return response
+ return httpwrappers.HttpResponseRedirect(request.path)
else:
return self.display_login_form(request, ERROR_MESSAGE)
@@ -0,0 +1,69 @@
+from django.conf.settings import SESSION_COOKIE_NAME, SESSION_COOKIE_AGE, SESSION_COOKIE_DOMAIN
+from django.models.core import sessions
+import datetime
+
+TEST_COOKIE_NAME = 'testcookie'
+TEST_COOKIE_VALUE = 'worked'
+
+class SessionWrapper(object):
+ def __init__(self, session_key):
+ self.session_key = session_key
+ self.modified = False
+
+ def __getitem__(self, key):
+ return self._session[key]
+
+ def __setitem__(self, key, value):
+ self._session[key] = value
+ self.modified = True
+
+ def __delitem__(self, key):
+ del self._session[key]
+ self.modified = True
+
+ def get(self, key, default=None):
+ return self._session.get(key, default)
+
+ def set_test_cookie(self):
+ self[TEST_COOKIE_NAME] = TEST_COOKIE_VALUE
+
+ def test_cookie_worked(self):
+ return self.get(TEST_COOKIE_NAME) == TEST_COOKIE_VALUE
+
+ def _get_session(self):
+ # Lazily loads session from storage.
+ try:
+ return self._session_cache
+ except AttributeError:
+ if self.session_key is None:
+ self._session_cache = {}
+ else:
+ try:
+ s = sessions.get_object(session_key__exact=self.session_key,
+ expire_date__gt=datetime.datetime.now())
+ self._session_cache = s.get_decoded()
+ except sessions.SessionDoesNotExist:
+ self._session_cache = {}
+ return self._session_cache
+
+ _session = property(_get_session)
+
+class SessionMiddleware:
+ def process_view(self, request, view_func, param_dict):
+ request.session = SessionWrapper(request.COOKIES.get(SESSION_COOKIE_NAME, None))
+
+ def process_response(self, request, response):
+ # If request.session was modified, or if response.session was set, save
+ # those changes and set a session cookie.
+ try:
+ modified = request.session.modified
+ except AttributeError:
+ modified = False
+ if modified:
+ session_key = request.session.session_key or sessions.get_new_session_key()
+ new_session = sessions.save(session_key, request.session._session,
+ datetime.datetime.now() + datetime.timedelta(seconds=SESSION_COOKIE_AGE))
+ # TODO: Accept variable session length and domain.
+ response.set_cookie(SESSION_COOKIE_NAME, session_key,
+ max_age=SESSION_COOKIE_AGE, domain=SESSION_COOKIE_DOMAIN)
+ return response
View
@@ -44,6 +44,9 @@ class User(meta.Model):
help_text="In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."),
meta.ManyToManyField(Permission, name='user_permissions', blank=True, filter_interface=meta.HORIZONTAL),
)
+ module_constants = {
+ 'SESSION_KEY': '_auth_user_id',
+ }
ordering = ('username',)
exceptions = ('SiteProfileNotAvailable',)
admin = meta.Admin(
@@ -172,64 +175,6 @@ def _module_make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwx
from random import choice
return ''.join([choice(allowed_chars) for i in range(length)])
-class Session(meta.Model):
- fields = (
- meta.ForeignKey(User),
- meta.CharField('session_md5', maxlength=32),
- meta.DateTimeField('start_time', auto_now=True),
- )
- module_constants = {
- 'TEST_COOKIE_NAME': 'testcookie',
- 'TEST_COOKIE_VALUE': 'worked',
- }
-
- def __repr__(self):
- return "session started at %s" % self.start_time
-
- def get_cookie(self):
- "Returns a tuple of the cookie name and value for this session."
- from django.conf.settings import AUTH_SESSION_COOKIE, SECRET_KEY
- import md5
- return AUTH_SESSION_COOKIE, self.session_md5 + md5.new(self.session_md5 + SECRET_KEY + 'auth').hexdigest()
-
- def _module_create_session(user_id):
- "Registers a session and returns the session_md5."
- from django.conf.settings import SECRET_KEY
- import md5, random, sys
- # The random module is seeded when this Apache child is created.
- # Use person_id and SECRET_KEY as added salt.
- session_md5 = md5.new(str(random.randint(user_id, sys.maxint - 1)) + SECRET_KEY).hexdigest()
- s = Session(None, user_id, session_md5, None)
- s.save()
- return s
-
- def _module_get_session_from_cookie(session_cookie_string):
- from django.conf.settings import SECRET_KEY
- import md5
- if not session_cookie_string:
- raise SessionDoesNotExist
- session_md5, tamper_check = session_cookie_string[:32], session_cookie_string[32:]
- if md5.new(session_md5 + SECRET_KEY + 'auth').hexdigest() != tamper_check:
- raise SessionDoesNotExist
- return get_object(session_md5__exact=session_md5, select_related=True)
-
- def _module_destroy_all_sessions(user_id):
- "Destroys all sessions for a user, logging out all computers."
- for session in get_list(user_id__exact=user_id):
- session.delete()
-
- def _module_start_web_session(user_id, request, response):
- "Sets the necessary cookie in the given HttpResponse object, also updates last login time for user."
- from django.models.auth import users
- from django.conf.settings import REGISTRATION_COOKIE_DOMAIN
- user = users.get_object(pk=user_id)
- user.last_login = datetime.datetime.now()
- user.save()
- session = create_session(user_id)
- key, value = session.get_cookie()
- cookie_domain = REGISTRATION_COOKIE_DOMAIN or None
- response.set_cookie(key, value, domain=cookie_domain)
-
class Message(meta.Model):
fields = (
meta.ForeignKey(User),
Oops, something went wrong. Retry.

0 comments on commit 07889c1

Please sign in to comment.