Django

Code

Changeset 518

Show
Ignore:
Timestamp:
08/16/05 17:54:05 (3 years ago)
Author:
adrian
Message:

Fixed #1 -- Added anonymous session support via middleware and request.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.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/bin/daily_cleanup.py

    r3 r518  
    88    # Clean up old database records 
    99    cursor = db.cursor() 
    10     cursor.execute("DELETE FROM auth_sessions WHERE start_time < NOW() - INTERVAL '2 weeks'") 
     10    cursor.execute("DELETE FROM core_sessions WHERE expire_date < NOW()") 
    1111    cursor.execute("DELETE FROM registration_challenges WHERE request_date < NOW() - INTERVAL '1 week'") 
    1212    db.commit() 
  • django/trunk/django/conf/global_settings.py

    r376 r518  
    4848# Host for sending e-mail. 
    4949EMAIL_HOST = 'localhost' 
    50  
    51 # Name of the session cookie. This can be whatever you want. 
    52 AUTH_SESSION_COOKIE = 'rizzo' 
    5350 
    5451# List of locations of the template source files, in search order. 
     
    114111) 
    115112 
     113############ 
     114# SESSIONS # 
     115############ 
     116 
     117SESSION_COOKIE_NAME = 'hotclub'           # Cookie name. This can be whatever you want. 
     118SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks). 
     119SESSION_COOKIE_DOMAIN = None              # A string like ".lawrence.com", or None for standard domain cookie. 
     120 
    116121######### 
    117122# CACHE # 
     
    121126# possible values. 
    122127CACHE_BACKEND = 'simple://' 
    123  
    124 # Set to a string like ".lawrence.com", or None for a standard domain cookie. 
    125 REGISTRATION_COOKIE_DOMAIN = None 
    126128 
    127129#################### 
  • django/trunk/django/contrib/comments/views/comments.py

    r316 r518  
    33from django.core.exceptions import Http404, ObjectDoesNotExist 
    44from django.core.extensions import DjangoContext as Context 
    5 from django.models.auth import session
     5from django.models.auth import user
    66from django.models.comments import comments, freecomments 
    77from django.models.core import contenttypes 
     
    216216    # so they don't have to enter a username/password again. 
    217217    if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']): 
    218         sessions.start_web_session(manipulator.get_user_id(), request, response
     218        request.session[users.SESSION_KEY] = manipulator.get_user_id(
    219219    if errors or request.POST.has_key('preview'): 
    220220        class CommentFormWrapper(formfields.FormWrapper): 
  • django/trunk/django/core/handlers/modpython.py

    r511 r518  
    9696            return self._raw_post_data 
    9797 
    98     def _load_session_and_user(self): 
    99         from django.models.auth import sessions 
    100         from django.conf.settings import AUTH_SESSION_COOKIE 
    101         session_cookie = self.COOKIES.get(AUTH_SESSION_COOKIE, '') 
    102         try: 
    103             self._session = sessions.get_session_from_cookie(session_cookie) 
    104             self._user = self._session.get_user() 
    105         except sessions.SessionDoesNotExist: 
    106             from django.parts.auth import anonymoususers 
    107             self._session = None 
    108             self._user = anonymoususers.AnonymousUser() 
    109  
    110     def _get_session(self): 
    111         if not hasattr(self, '_session'): 
    112             self._load_session_and_user() 
    113         return self._session 
    114  
    115     def _set_session(self, session): 
    116         self._session = session 
    117  
    11898    def _get_user(self): 
    11999        if not hasattr(self, '_user'): 
    120             self._load_session_and_user() 
     100            from django.models.auth import users 
     101            try: 
     102                user_id = self.session[users.SESSION_KEY] 
     103                if not user_id: 
     104                    raise ValueError 
     105                self._user = users.get_object(pk=user_id) 
     106            except (AttributeError, KeyError, ValueError, users.UserDoesNotExist): 
     107                from django.parts.auth import anonymoususers 
     108                self._user = anonymoususers.AnonymousUser() 
    121109        return self._user 
    122110 
     
    131119    REQUEST = property(_get_request) 
    132120    raw_post_data = property(_get_raw_post_data) 
    133     session = property(_get_session, _set_session) 
    134121    user = property(_get_user, _set_user) 
    135122 
  • django/trunk/django/core/handlers/wsgi.py

    r511 r518  
    7777            return self._raw_post_data 
    7878 
    79     def _load_session_and_user(self): 
    80         from django.models.auth import sessions 
    81         from django.conf.settings import AUTH_SESSION_COOKIE 
    82         session_cookie = self.COOKIES.get(AUTH_SESSION_COOKIE, '') 
    83         try: 
    84             self._session = sessions.get_session_from_cookie(session_cookie) 
    85             self._user = self._session.get_user() 
    86         except sessions.SessionDoesNotExist: 
    87             from django.parts.auth import anonymoususers 
    88             self._session = None 
    89             self._user = anonymoususers.AnonymousUser() 
    90  
    91     def _get_session(self): 
    92         if not hasattr(self, '_session'): 
    93             self._load_session_and_user() 
    94         return self._session 
    95  
    96     def _set_session(self, session): 
    97         self._session = session 
    98  
    9979    def _get_user(self): 
    10080        if not hasattr(self, '_user'): 
    101             self._load_session_and_user() 
     81            from django.models.auth import users 
     82            try: 
     83                user_id = self.session[users.SESSION_KEY] 
     84                if not user_id: 
     85                    raise ValueError 
     86                self._user = users.get_object(pk=user_id) 
     87            except (AttributeError, KeyError, ValueError, users.UserDoesNotExist): 
     88                from django.parts.auth import anonymoususers 
     89                self._user = anonymoususers.AnonymousUser() 
    10290        return self._user 
    10391 
     
    11199    REQUEST = property(_get_request) 
    112100    raw_post_data = property(_get_raw_post_data) 
    113     session = property(_get_session, _set_session) 
    114101    user = property(_get_user, _set_user) 
    115102 
  • django/trunk/django/middleware/admin.py

    r325 r518  
    22from django.core import template_loader 
    33from django.core.extensions import DjangoContext as Context 
    4 from django.models.auth import sessions, users 
     4from django.models.auth import users 
    55from django.views.registration import passwords 
    66from django.views.auth.login import logout 
     
    3030        # conf, which is a little uglier than this. Same goes for the logout 
    3131        # view. 
     32 
    3233        if view_func in (passwords.password_reset, passwords.password_reset_done, logout): 
    3334            return 
     35 
     36        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__ 
    3437 
    3538        # Check for a logged in, valid user 
     
    3740            return 
    3841 
    39         # If this isn't alreay the login page, display it 
     42        # If this isn't already the login page, display it 
    4043        if not request.POST.has_key('this_is_the_login_form'): 
    4144            if request.POST: 
     
    6568        else: 
    6669            if self.authenticate_user(user, request.POST.get('password', '')): 
     70                request.session[users.SESSION_KEY] = user.id 
    6771                if request.POST.has_key('post_data'): 
    6872                    post_data = decode_post_data(request.POST['post_data']) 
     
    7175                        request.POST = post_data 
    7276                        request.user = user 
    73                         request.session = sessions.create_session(user.id) 
    7477                        return 
    7578                    else: 
    76                         response = httpwrappers.HttpResponseRedirect(request.path) 
    77                         sessions.start_web_session(user.id, request, response) 
    78                         return response 
     79                        return httpwrappers.HttpResponseRedirect(request.path) 
    7980            else: 
    8081                return self.display_login_form(request, ERROR_MESSAGE) 
  • django/trunk/django/models/auth.py

    r469 r518  
    4545        meta.ManyToManyField(Permission, name='user_permissions', blank=True, filter_interface=meta.HORIZONTAL), 
    4646    ) 
     47    module_constants = { 
     48        'SESSION_KEY': '_auth_user_id', 
     49    } 
    4750    ordering = ('username',) 
    4851    exceptions = ('SiteProfileNotAvailable',) 
     
    173176        return ''.join([choice(allowed_chars) for i in range(length)]) 
    174177 
    175 class Session(meta.Model): 
    176     fields = ( 
    177         meta.ForeignKey(User), 
    178         meta.CharField('session_md5', maxlength=32), 
    179         meta.DateTimeField('start_time', auto_now=True), 
    180     ) 
    181     module_constants = { 
    182         'TEST_COOKIE_NAME': 'testcookie', 
    183         'TEST_COOKIE_VALUE': 'worked', 
    184     } 
    185  
    186     def __repr__(self): 
    187         return "session started at %s" % self.start_time 
    188  
    189     def get_cookie(self): 
    190         "Returns a tuple of the cookie name and value for this session." 
    191         from django.conf.settings import AUTH_SESSION_COOKIE, SECRET_KEY 
    192         import md5 
    193         return AUTH_SESSION_COOKIE, self.session_md5 + md5.new(self.session_md5 + SECRET_KEY + 'auth').hexdigest() 
    194  
    195     def _module_create_session(user_id): 
    196         "Registers a session and returns the session_md5." 
    197         from django.conf.settings import SECRET_KEY 
    198         import md5, random, sys 
    199         # The random module is seeded when this Apache child is created. 
    200         # Use person_id and SECRET_KEY as added salt. 
    201         session_md5 = md5.new(str(random.randint(user_id, sys.maxint - 1)) + SECRET_KEY).hexdigest() 
    202         s = Session(None, user_id, session_md5, None) 
    203         s.save() 
    204         return s 
    205  
    206     def _module_get_session_from_cookie(session_cookie_string): 
    207         from django.conf.settings import SECRET_KEY 
    208         import md5 
    209         if not session_cookie_string: 
    210             raise SessionDoesNotExist 
    211         session_md5, tamper_check = session_cookie_string[:32], session_cookie_string[32:] 
    212         if md5.new(session_md5 + SECRET_KEY + 'auth').hexdigest() != tamper_check: 
    213             raise SessionDoesNotExist 
    214         return get_object(session_md5__exact=session_md5, select_related=True) 
    215  
    216     def _module_destroy_all_sessions(user_id): 
    217         "Destroys all sessions for a user, logging out all computers." 
    218         for session in get_list(user_id__exact=user_id): 
    219             session.delete() 
    220  
    221     def _module_start_web_session(user_id, request, response): 
    222         "Sets the necessary cookie in the given HttpResponse object, also updates last login time for user." 
    223         from django.models.auth import users 
    224         from django.conf.settings import REGISTRATION_COOKIE_DOMAIN 
    225         user = users.get_object(pk=user_id) 
    226         user.last_login = datetime.datetime.now() 
    227         user.save() 
    228         session = create_session(user_id) 
    229         key, value = session.get_cookie() 
    230         cookie_domain = REGISTRATION_COOKIE_DOMAIN or None 
    231         response.set_cookie(key, value, domain=cookie_domain) 
    232  
    233178class Message(meta.Model): 
    234179    fields = ( 
  • django/trunk/django/models/core.py

    r477 r518  
    104104    def get_absolute_url(self): 
    105105        return self.url 
     106 
     107import base64, md5, random, sys 
     108import cPickle as pickle 
     109 
     110class Session(meta.Model): 
     111    fields = ( 
     112        meta.CharField('session_key', maxlength=40, primary_key=True), 
     113        meta.TextField('session_data'), 
     114        meta.DateTimeField('expire_date'), 
     115    ) 
     116    module_constants = { 
     117        'base64': base64, 
     118        'md5': md5, 
     119        'pickle': pickle, 
     120        'random': random, 
     121        'sys': sys, 
     122    } 
     123 
     124    def get_decoded(self): 
     125        from django.conf.settings import SECRET_KEY 
     126        encoded_data = base64.decodestring(self.session_data) 
     127        pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] 
     128        if md5.new(pickled + SECRET_KEY).hexdigest() != tamper_check: 
     129            from django.core.exceptions import SuspiciousOperation 
     130            raise SuspiciousOperation, "User tampered with session cookie." 
     131        return pickle.loads(pickled) 
     132 
     133    def _module_encode(session_dict): 
     134        "Returns the given session dictionary pickled and encoded as a string." 
     135        from django.conf.settings import SECRET_KEY 
     136        pickled = pickle.dumps(session_dict) 
     137        pickled_md5 = md5.new(pickled + SECRET_KEY).hexdigest() 
     138        return base64.encodestring(pickled + pickled_md5) 
     139 
     140    def _module_get_new_session_key(): 
     141        "Returns session key that isn't being used." 
     142        from django.conf.settings import SECRET_KEY 
     143        # The random module is seeded when this Apache child is created. 
     144        # Use person_id and SECRET_KEY as added salt. 
     145        while 1: 
     146            session_key = md5.new(str(random.randint(0, sys.maxint - 1)) + SECRET_KEY).hexdigest() 
     147            try: 
     148                get_object(session_key__exact=session_key) 
     149            except SessionDoesNotExist: 
     150                break 
     151        return session_key 
     152 
     153    def _module_save(session_key, session_dict, expire_date): 
     154        s = Session(session_key, encode(session_dict), expire_date) 
     155        if session_dict: 
     156            s.save() 
     157        else: 
     158            s.delete() # Clear sessions with no data. 
     159        return s 
  • django/trunk/django/parts/auth/anonymoususers.py

    r9 r518  
    1 """ 
    2 Anonymous users 
    3 """ 
    4  
    51class AnonymousUser: 
    6  
    72    def __init__(self): 
    83        pass 
     
    4136        return [] 
    4237 
    43     def add_session(self, session_md5, start_time): 
    44         "Creates Session for this User, saves it, and returns the new object" 
    45         raise NotImplementedError 
    46  
    4738    def is_anonymous(self): 
    4839        return True 
  • django/trunk/django/parts/auth/formfields.py

    r3 r518  
    1 from django.models.auth import sessions, users 
     1from django.models.auth import users 
    22from django.core import formfields, validators 
    33 
     
    2424 
    2525    def hasCookiesEnabled(self, field_data, all_data): 
    26         if self.request and (not self.request.COOKIES.has_key(sessions.TEST_COOKIE_NAME) or self.request.COOKIES[sessions.TEST_COOKIE_NAME] != sessions.TEST_COOKIE_VALUE): 
     26        if self.request and not self.request.test_cookie_worked(): 
    2727            raise validators.ValidationError, "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in." 
    2828 
  • django/trunk/django/views/auth/login.py

    r515 r518  
    22from django.core import formfields, template_loader 
    33from django.core.extensions import DjangoContext as Context 
    4 from django.models.auth import session
     4from django.models.auth import user
    55from django.models.core import sites 
    66from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect 
     
    1818            if not redirect_to or '://' in redirect_to or ' ' in redirect_to: 
    1919                redirect_to = '/accounts/profile/' 
    20             response = HttpResponseRedirect(redirect_to) 
    21             sessions.start_web_session(manipulator.get_user_id(), request, response) 
    22             return response 
     20            request.session[users.SESSION_KEY] = manipulator.get_user_id() 
     21            return HttpResponseRedirect(redirect_to) 
    2322    else: 
    2423        errors = {} 
    2524    response = HttpResponse() 
    26     # Set this cookie as a test to see whether the user accepts cookies 
    27     response.set_cookie(sessions.TEST_COOKIE_NAME, sessions.TEST_COOKIE_VALUE) 
     25    response.session.set_test_cookie() 
    2826    t = template_loader.get_template('registration/login') 
    2927    c = Context(request, { 
     
    3533    return response 
    3634 
    37 def logout(request): 
     35def logout(request, next_page=None): 
    3836    "Logs out the user and displays 'You are logged out' message." 
    39     if request.session: 
    40         # Do a redirect to this page until the session has been cleared. 
    41         response = HttpResponseRedirect(request.path) 
    42         # Delete the cookie by setting a cookie with an empty value and max_age=0 
    43         response.set_cookie(request.session.get_cookie()[0], '', max_age=0) 
    44         request.session.delete() 
    45         return response 
    46     else: 
     37    try: 
     38        del request.session[users.SESSION_KEY] 
     39    except KeyError: 
    4740        t = template_loader.get_template('registration/logged_out') 
    4841        c = Context(request) 
    4942        return HttpResponse(t.render(c)) 
     43    else: 
     44        # Do a redirect to this page until the session has been cleared. 
     45        return HttpResponseRedirect(next_page or request.path) 
    5046 
    5147def logout_then_login(request): 
    5248    "Logs out the user if he is logged in. Then redirects to the log-in page." 
    53     response = HttpResponseRedirect('/accounts/login/') 
    54     if request.session: 
    55         # Delete the cookie by setting a cookie with an empty value and max_age=0 
    56         response.set_cookie(request.session.get_cookie()[0], '', max_age=0) 
    57         request.session.delete() 
    58     return response 
     49    return logout(request, '/accounts/login/') 
    5950 
    6051def redirect_to_login(next): 
  • django/trunk/docs/faq.txt

    r394 r518  
    311311things: 
    312312 
    313     * Set the ``REGISTRATION_COOKIE_DOMAIN`` setting in your admin config file 
     313    * Set the ``SESSION_COOKIE_DOMAIN`` setting in your admin config file 
    314314      to match your domain. For example, if you're going to 
    315315      "http://www.mysite.com/admin/" in your browser, in 
    316       "myproject.settings.admin" you should set ``REGISTRATION_COOKIE_DOMAIN = 
     316      "myproject.settings.admin" you should set ``SESSION_COOKIE_DOMAIN = 
    317317      'www.mysite.com'``. 
    318318 
     
    321321      or another domain that doesn't have a dot in it, try going to 
    322322      "localhost.localdomain" or "127.0.0.1". And set 
    323       ``REGISTRATION_COOKIE_DOMAIN`` accordingly. 
     323      ``SESSION_COOKIE_DOMAIN`` accordingly. 
    324324 
    325325I can't log in. When I enter a valid username and password, it brings up the login page again, with a "Please enter a correct username and password" error.