Mercurial > p > roundup > code
comparison roundup/cgi/client.py @ 5319:62de601bdf6f
Fix commits although a Reject exception is raised
Fix the problem that changes are committed to the database (due to
commits to otk handling) even when a Reject exception occurs. The fix
implements separate database connections for otk/session handling and
normal database operation.
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Fri, 20 Apr 2018 18:46:28 +0200 |
| parents | 198b6e810c67 |
| children | 66a17c80e035 |
comparison
equal
deleted
inserted
replaced
| 5318:506c7ee9a385 | 5319:62de601bdf6f |
|---|---|
| 180 | 180 |
| 181 def destroy(self): | 181 def destroy(self): |
| 182 self.client.add_cookie(self.cookie_name, None) | 182 self.client.add_cookie(self.cookie_name, None) |
| 183 self._data = {} | 183 self._data = {} |
| 184 self.session_db.destroy(self._sid) | 184 self.session_db.destroy(self._sid) |
| 185 self.client.db.commit() | 185 self.session_db.commit() |
| 186 | 186 |
| 187 def get(self, name, default=None): | 187 def get(self, name, default=None): |
| 188 return self._data.get(name, default) | 188 return self._data.get(name, default) |
| 189 | 189 |
| 190 def set(self, **kwargs): | 190 def set(self, **kwargs): |
| 198 # XXX added when patching 1.4.4 for backward compatibility | 198 # XXX added when patching 1.4.4 for backward compatibility |
| 199 # XXX remove | 199 # XXX remove |
| 200 self.client.session = self._sid | 200 self.client.session = self._sid |
| 201 else: | 201 else: |
| 202 self.session_db.set(self._sid, **self._data) | 202 self.session_db.set(self._sid, **self._data) |
| 203 self.client.db.commit() | 203 self.session_db.commit() |
| 204 | 204 |
| 205 def update(self, set_cookie=False, expire=None): | 205 def update(self, set_cookie=False, expire=None): |
| 206 """ update timestamp in db to avoid expiration | 206 """ update timestamp in db to avoid expiration |
| 207 | 207 |
| 208 if 'set_cookie' is True, set cookie with 'expire' seconds lifetime | 208 if 'set_cookie' is True, set cookie with 'expire' seconds lifetime |
| 210 | 210 |
| 211 XXX the session can be purged within a week even if a cookie | 211 XXX the session can be purged within a week even if a cookie |
| 212 lifetime is longer | 212 lifetime is longer |
| 213 """ | 213 """ |
| 214 self.session_db.updateTimestamp(self._sid) | 214 self.session_db.updateTimestamp(self._sid) |
| 215 self.client.db.commit() | 215 self.session_db.commit() |
| 216 | 216 |
| 217 if set_cookie: | 217 if set_cookie: |
| 218 self.client.add_cookie(self.cookie_name, self._sid, expire=expire) | 218 self.client.add_cookie(self.cookie_name, self._sid, expire=expire) |
| 219 | 219 |
| 220 | 220 |
| 695 hour = 60*60 | 695 hour = 60*60 |
| 696 now = time.time() | 696 now = time.time() |
| 697 | 697 |
| 698 # XXX: hack - use OTK table to store last_clean time information | 698 # XXX: hack - use OTK table to store last_clean time information |
| 699 # 'last_clean' string is used instead of otk key | 699 # 'last_clean' string is used instead of otk key |
| 700 last_clean = self.db.getOTKManager().get('last_clean', 'last_use', 0) | 700 otks = self.db.getOTKManager() |
| 701 last_clean = otks.get('last_clean', 'last_use', 0) | |
| 701 if now - last_clean < hour: | 702 if now - last_clean < hour: |
| 702 return | 703 return |
| 703 | 704 |
| 704 self.session_api.clean_up() | 705 self.session_api.clean_up() |
| 705 self.db.getOTKManager().clean() | 706 otks.clean() |
| 706 self.db.getOTKManager().set('last_clean', last_use=now) | 707 otks.set('last_clean', last_use=now) |
| 707 self.db.commit(fail_ok=True) | 708 otks.commit() |
| 708 | 709 |
| 709 def determine_charset(self): | 710 def determine_charset(self): |
| 710 """Look for client charset in the form parameters or browser cookie. | 711 """Look for client charset in the form parameters or browser cookie. |
| 711 | 712 |
| 712 If no charset requested by client, use storage charset (utf-8). | 713 If no charset requested by client, use storage charset (utf-8). |
| 980 if otks.exists(key): | 981 if otks.exists(key): |
| 981 logger.error( | 982 logger.error( |
| 982 self._("csrf key used with wrong method from: %s"), | 983 self._("csrf key used with wrong method from: %s"), |
| 983 referer) | 984 referer) |
| 984 otks.destroy(key) | 985 otks.destroy(key) |
| 985 self.db.commit() | 986 otks.commit() |
| 986 # do return here. Keys have been obsoleted. | 987 # do return here. Keys have been obsoleted. |
| 987 # we didn't do a expire cycle of session keys, | 988 # we didn't do a expire cycle of session keys, |
| 988 # but that's ok. | 989 # but that's ok. |
| 989 return True | 990 return True |
| 990 | 991 |
| 1103 # our own. | 1104 # our own. |
| 1104 otks.clean() | 1105 otks.clean() |
| 1105 | 1106 |
| 1106 if xmlrpc: | 1107 if xmlrpc: |
| 1107 # Save removal of expired keys from database. | 1108 # Save removal of expired keys from database. |
| 1108 self.db.commit() | 1109 otks.commit() |
| 1109 # Return from here since we have done housekeeping | 1110 # Return from here since we have done housekeeping |
| 1110 # and don't use csrf tokens for xmlrpc. | 1111 # and don't use csrf tokens for xmlrpc. |
| 1111 return True | 1112 return True |
| 1112 | 1113 |
| 1113 # process @csrf tokens past this point. | 1114 # process @csrf tokens past this point. |
| 1123 # The key has been used or compromised. | 1124 # The key has been used or compromised. |
| 1124 # Delete it to prevent replay. | 1125 # Delete it to prevent replay. |
| 1125 otks.destroy(key) | 1126 otks.destroy(key) |
| 1126 | 1127 |
| 1127 # commit the deletion/expiration of all keys | 1128 # commit the deletion/expiration of all keys |
| 1128 self.db.commit() | 1129 otks.commit() |
| 1129 | 1130 |
| 1130 enforce=config['WEB_CSRF_ENFORCE_TOKEN'] | 1131 enforce=config['WEB_CSRF_ENFORCE_TOKEN'] |
| 1131 if key is None: # we do not have an @csrf token | 1132 if key is None: # we do not have an @csrf token |
| 1132 if enforce == 'required': | 1133 if enforce == 'required': |
| 1133 logger.error(self._("Required csrf field missing for user%s"), current_user) | 1134 logger.error(self._("Required csrf field missing for user%s"), current_user) |
| 1170 nonce_session is not None and \ | 1171 nonce_session is not None and \ |
| 1171 "@action" in self.form and \ | 1172 "@action" in self.form and \ |
| 1172 self.form["@action"].value == "Login": | 1173 self.form["@action"].value == "Login": |
| 1173 if header_pass > 0: | 1174 if header_pass > 0: |
| 1174 otks.destroy(key) | 1175 otks.destroy(key) |
| 1175 self.db.commit() | 1176 otks.commit() |
| 1176 return True | 1177 return True |
| 1177 else: | 1178 else: |
| 1178 self.add_error_message("Reload window before logging in.") | 1179 self.add_error_message("Reload window before logging in.") |
| 1179 ''' | 1180 ''' |
| 1180 # validate against user and session | 1181 # validate against user and session |
