[web/session] make sure not to modify an inner value of session.data (closes #11217958)
authorDavid Douard <david.douard@logilab.fr>
Mon, 29 Feb 2016 17:07:56 +0100
changeset 11339 67373614e125
parent 11338 dde85a5d47fc
child 11373 68f0678fc543
[web/session] make sure not to modify an inner value of session.data (closes #11217958) When we modify a mutable value stored in the session's data (dict-like object) we prevent an alternative session data handler (eg. pyramid-redis-session) from detecting this update and synchronizing it in its backend (like redis).
web/request.py
web/views/autoform.py
--- a/web/request.py	Fri Feb 19 12:11:31 2016 +0100
+++ b/web/request.py	Mon Feb 29 17:07:56 2016 +0100
@@ -884,9 +884,15 @@
             self.session.data.pop(self.pageid, None)
         else:
             try:
-                del self.session.data[self.pageid][key]
+                page_data = self.session.data[self.pageid]
+                del page_data[key]
             except KeyError:
                 pass
+            else:
+                # make sure we write the session data value in the
+                # self.session.data dict-like object so any session
+                # handler can "detect" and manage the persistency
+                self.session.data[self.pageid] = page_data
 
     # user-agent detection ####################################################
 
--- a/web/views/autoform.py	Fri Feb 19 12:11:31 2016 +0100
+++ b/web/views/autoform.py	Mon Feb 29 17:07:56 2016 +0100
@@ -484,13 +484,19 @@
 
 def _add_pending(req, eidfrom, rel, eidto, kind):
     key = 'pending_%s' % kind
-    pendings = req.session.data.setdefault(key, set())
-    pendings.add( (int(eidfrom), rel, int(eidto)) )
+    pendings = req.session.data.get(key, [])
+    value = (int(eidfrom), rel, int(eidto))
+    if value not in pendings:
+        pendings.append(value)
+        req.session.data[key] = pendings
 
 def _remove_pending(req, eidfrom, rel, eidto, kind):
     key = 'pending_%s' % kind
     pendings = req.session.data[key]
-    pendings.remove( (int(eidfrom), rel, int(eidto)) )
+    value = (int(eidfrom), rel, int(eidto))
+    if value in pendings:
+        pendings.remove(value)
+        req.session.data[key] = pendings
 
 @ajaxfunc(output_type='json')
 def remove_pending_insert(self, args):