Edgewall Software
Modify

Opened 7 years ago

Closed 7 years ago

#12929 closed defect (fixed)

Known users cache may not be invalidated when creating a session

Reported by: Ryan J Ollos Owned by: Ryan J Ollos
Priority: normal Milestone: 1.2.3
Component: general Version:
Severity: normal Keywords:
Cc: Branch:
Release Notes:
API Changes:

Authenticated session without any session attributes is persisted when the session is saved. Previously the session would only be persisted if one or more session attributes were set.

Internal Changes:

Description

The case was missed in #11868. The known users cache will not be invalidated when creating a session without setting the name and email.

session = DetachedSession(self.env, sid)
session['authenticated'] = True
session.save()

Attachments (0)

Change History (3)

comment:1 by Ryan J Ollos, 7 years ago

Proposed changes: [54236d4d1/rjollos.git].

comment:2 by Jun Omae, 7 years ago

The authenticated is an attribute of session object, not an item of the object.

-session['authenticated'] = True
+session.authenticated = True
>>> from trac.test import EnvironmentStub, MockRequest
>>> from trac.web.session import Session
>>> env = EnvironmentStub()
>>> req = MockRequest(env, authname='user')
>>> req.authname
'user'
>>> sess = Session(env, req)
>>> sess.authenticated
True
>>> list(env.get_known_users())
[]
>>> sess.save()
>>> list(env.get_known_users())
[]  # should be 1 entry

Currently, new session without associated data is not be persisted, even if authenticated/anonymous session.

    def save(self):
        items = self.items()
        if not self._old and not items:
            # The session doesn't have associated data, so there's no need to
            # persist it
            return

If we should persist new authenticated session without associated data:

  • trac/web/session.py

    diff --git a/trac/web/session.py b/trac/web/session.py
    index 2b43535e5..d1ef6fd40 100644
    a b class DetachedSession(SessionDict):  
    136136                self._old = {}
    137137
    138138    def save(self):
    139         items = self.items()
    140         if not self._old and not items:
    141             # The session doesn't have associated data, so there's no need to
    142             # persist it
    143             return
    144 
    145139        authenticated = int(self.authenticated)
    146140        now = int(time_now())
     141        items = self.items()
     142        if not authenticated and not self._old and not items:
     143            # The session for anonymous doesn't have associated data,
     144            # so there's no need to persist it
     145            return
    147146
    148147        # We can't do the session management in one big transaction,
    149148        # as the intertwined changes to both the session and
    class DetachedSession(SessionDict):  
    173172                    db.rollback()
    174173                    return
    175174
     175            if authenticated and \
     176                    (new or self._old.get('name') != self.get('name') or \
     177                     self._old.get('email') != self.get('email')):
     178                self.env.invalidate_known_users_cache()
     179
    176180            # Remove former values for session_attribute and save the
    177181            # new ones. The last concurrent request to do so "wins".
    178182
    179183            if self._old != self:
    180                 if new or self._old.get('name') != self.get('name') or \
    181                         self._old.get('email') != self.get('email'):
    182                     self.env.invalidate_known_users_cache()
    183184                if not items and not authenticated:
    184185                    # No need to keep around empty unauthenticated sessions
    185186                    db("DELETE FROM session WHERE sid=%s AND authenticated=0",
  • trac/web/tests/session.py

    diff --git a/trac/web/tests/session.py b/trac/web/tests/session.py
    index 6f0b01b91..f20984e21 100644
    a b class SessionTestCase(unittest.TestCase):  
    563563        """Setting attribute on a new session invalidates known_users cache."""
    564564        sid = 'user'
    565565        session = DetachedSession(self.env, sid)
    566         session['authenticated'] = True
     566        session.authenticated = True
    567567
    568568        self.assertEqual([], list(self.env.get_known_users()))
    569569        session.save()
    class SessionTestCase(unittest.TestCase):  
    573573        self.assertIsNone(known_users[0][1])
    574574        self.assertIsNone(known_users[0][2])
    575575
     576    def test_create_new_anonymous_session(self):
     577        """Setting attribute on a new anonymous session doesn't invalidate
     578        known_users cache."""
     579        sid = 'anonymous'
     580        session = DetachedSession(self.env, sid)
     581        session.authenticated = False
     582
     583        self.assertEqual([], list(self.env.get_known_users()))
     584        # insert a session record without invalidating cache
     585        self.env.insert_users([('user', 'Name' 'user@example.com', 1)])
     586        session.save()
     587        self.assertEqual([], list(self.env.get_known_users()))
     588
     589        self.env.invalidate_known_users_cache()
     590        self.assertEqual(1, len(list(self.env.get_known_users())))
     591
    576592    def test_session_set_email(self):
    577593        """Setting session email invalidates known_users cache."""
    578594        sid = 'user'

comment:3 by Ryan J Ollos, 7 years ago

API Changes: modified (diff)
Resolution: fixed
Status: assignedclosed

Committed with comment:2 changes in r16364, merged to trunk in r16365.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Ryan J Ollos.
The resolution will be deleted. Next status will be 'reopened'.
to The owner will be changed from Ryan J Ollos to the specified user.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.