Don't create a session when the /misc/ping test endpoint is called. Fixes #3371

This commit is contained in:
Aditya Toshniwal 2018-07-05 11:12:03 +01:00 committed by Dave Page
parent 165c4744b0
commit 82d77c4608
6 changed files with 61 additions and 18 deletions

View File

@ -19,4 +19,5 @@ Bug fixes
| `Bug #3309 <https://redmine.postgresql.org/issues/3309>`_ - Fix Directory format support for backups. | `Bug #3309 <https://redmine.postgresql.org/issues/3309>`_ - Fix Directory format support for backups.
| `Bug #3319 <https://redmine.postgresql.org/issues/3319>`_ - Cleanup and fix handling of Query Tool Cancel button status. | `Bug #3319 <https://redmine.postgresql.org/issues/3319>`_ - Cleanup and fix handling of Query Tool Cancel button status.
| `Bug #3363 <https://redmine.postgresql.org/issues/3363>`_ - Fix restoring of restore options for sections. | `Bug #3363 <https://redmine.postgresql.org/issues/3363>`_ - Fix restoring of restore options for sections.
| `Bug #3371 <https://redmine.postgresql.org/issues/3371>`_ - Don't create a session when the /misc/ping test endpoint is called.
| `Bug #3457 <https://redmine.postgresql.org/issues/3457>`_ - Fix debugging of procedures in EPAS packages. | `Bug #3457 <https://redmine.postgresql.org/issues/3457>`_ - Fix debugging of procedures in EPAS packages.

View File

@ -391,3 +391,11 @@ if (SUPPORT_SSH_TUNNEL is True and
((sys.version_info[0] == 2 and sys.version_info[1] < 7) or ((sys.version_info[0] == 2 and sys.version_info[1] < 7) or
(sys.version_info[0] == 3 and sys.version_info[1] < 4))): (sys.version_info[0] == 3 and sys.version_info[1] < 4))):
SUPPORT_SSH_TUNNEL = False SUPPORT_SSH_TUNNEL = False
#########################################################################
# Skip storing session in files and cache for specific paths
#########################################################################
SESSION_SKIP_PATHS = [
'/misc/ping'
]

View File

@ -354,7 +354,9 @@ def create_app(app_name=None):
# register custom unauthorised handler. # register custom unauthorised handler.
app.login_manager.unauthorized_handler(pga_unauthorised) app.login_manager.unauthorized_handler(pga_unauthorised)
app.session_interface = create_session_interface(app) app.session_interface = create_session_interface(
app, config.SESSION_SKIP_PATHS
)
# Make the Session more secure against XSS & CSRF when running in web mode # Make the Session more secure against XSS & CSRF when running in web mode
if config.SERVER_MODE: if config.SERVER_MODE:

View File

@ -490,7 +490,7 @@ define('pgadmin.browser', [
// Ping the server every 5 minutes // Ping the server every 5 minutes
setInterval(function() { setInterval(function() {
$.ajax({ $.ajax({
url: url_for('misc.ping'), url: url_for('misc.cleanup'),
type:'POST', type:'POST',
success: function() {}, success: function() {},
error: function() {}, error: function() {},

View File

@ -74,7 +74,7 @@ class MiscModule(PgAdminModule):
Returns: Returns:
list: a list of url endpoints exposed to the client. list: a list of url endpoints exposed to the client.
""" """
return ['misc.ping', 'misc.index'] return ['misc.ping', 'misc.index', 'misc.cleanup']
# Initialise the module # Initialise the module
@ -92,14 +92,19 @@ def index():
########################################################################## ##########################################################################
# A special URL used to "ping" the server # A special URL used to "ping" the server
########################################################################## ##########################################################################
@blueprint.route("/ping", methods=('get', 'post')) @blueprint.route("/ping")
def ping(): def ping():
"""Generate a "PING" response to indicate that the server is alive.""" """Generate a "PING" response to indicate that the server is alive."""
driver.ping()
return "PING" return "PING"
# For Garbage Collecting closed connections
@blueprint.route("/cleanup", methods=['POST'])
def cleanup():
driver.ping()
return ""
@blueprint.route("/explain/explain.js") @blueprint.route("/explain/explain.js")
def explain_js(): def explain_js():
""" """

View File

@ -102,10 +102,11 @@ class SessionManager(object):
class CachingSessionManager(SessionManager): class CachingSessionManager(SessionManager):
def __init__(self, parent, num_to_store): def __init__(self, parent, num_to_store, skip_paths=[]):
self.parent = parent self.parent = parent
self.num_to_store = num_to_store self.num_to_store = num_to_store
self._cache = OrderedDict() self._cache = OrderedDict()
self.skip_paths = skip_paths
def _normalize(self): def _normalize(self):
if len(self._cache) > self.num_to_store: if len(self._cache) > self.num_to_store:
@ -115,6 +116,12 @@ class CachingSessionManager(SessionManager):
def new_session(self): def new_session(self):
session = self.parent.new_session() session = self.parent.new_session()
# Do not store the session if skip paths
for sp in self.skip_paths:
if request.path.startswith(sp):
return session
self._cache[session.sid] = session self._cache[session.sid] = session
self._normalize() self._normalize()
@ -143,6 +150,11 @@ class CachingSessionManager(SessionManager):
if not session: if not session:
session = self.parent.get(sid, digest) session = self.parent.get(sid, digest)
# Do not store the session if skip paths
for sp in self.skip_paths:
if request.path.startswith(sp):
return session
self._cache[sid] = session self._cache[sid] = session
self._normalize() self._normalize()
@ -150,23 +162,31 @@ class CachingSessionManager(SessionManager):
def put(self, session): def put(self, session):
self.parent.put(session) self.parent.put(session)
# Do not store the session if skip paths
for sp in self.skip_paths:
if request.path.startswith(sp):
return
if session.sid in self._cache: if session.sid in self._cache:
try: try:
del self._cache[session.sid] del self._cache[session.sid]
except Exception: except Exception:
pass pass
self._cache[session.sid] = session self._cache[session.sid] = session
self._normalize() self._normalize()
class FileBackedSessionManager(SessionManager): class FileBackedSessionManager(SessionManager):
def __init__(self, path, secret, disk_write_delay): def __init__(self, path, secret, disk_write_delay, skip_paths=[]):
self.path = path self.path = path
self.secret = secret self.secret = secret
self.disk_write_delay = disk_write_delay self.disk_write_delay = disk_write_delay
if not os.path.exists(self.path): if not os.path.exists(self.path):
os.makedirs(self.path) os.makedirs(self.path)
self.skip_paths = skip_paths
def exists(self, sid): def exists(self, sid):
fname = os.path.join(self.path, sid) fname = os.path.join(self.path, sid)
@ -185,6 +205,11 @@ class FileBackedSessionManager(SessionManager):
sid = str(uuid4()) sid = str(uuid4())
fname = os.path.join(self.path, sid) fname = os.path.join(self.path, sid)
# Do not store the session if skip paths
for sp in self.skip_paths:
if request.path.startswith(sp):
return ManagedSession(sid=sid)
# touch the file # touch the file
with open(fname, 'wb'): with open(fname, 'wb'):
pass pass
@ -233,6 +258,12 @@ class FileBackedSessionManager(SessionManager):
session.last_write = current_time session.last_write = current_time
session.force_write = False session.force_write = False
# Do not store the session if skip paths
for sp in self.skip_paths:
if request.path.startswith(sp):
return
fname = os.path.join(self.path, session.sid) fname = os.path.join(self.path, session.sid)
with open(fname, 'wb') as f: with open(fname, 'wb') as f:
dump( dump(
@ -242,9 +273,8 @@ class FileBackedSessionManager(SessionManager):
class ManagedSessionInterface(SessionInterface): class ManagedSessionInterface(SessionInterface):
def __init__(self, manager, skip_paths, cookie_timedelta): def __init__(self, manager, cookie_timedelta):
self.manager = manager self.manager = manager
self.skip_paths = skip_paths
self.cookie_timedelta = cookie_timedelta self.cookie_timedelta = cookie_timedelta
def get_expiration_time(self, app, session): def get_expiration_time(self, app, session):
@ -256,11 +286,6 @@ class ManagedSessionInterface(SessionInterface):
cookie_val = request.cookies.get(app.session_cookie_name) cookie_val = request.cookies.get(app.session_cookie_name)
if not cookie_val or '!' not in cookie_val: if not cookie_val or '!' not in cookie_val:
# Don't bother creating a cookie for static resources
for sp in self.skip_paths:
if request.path.startswith(sp):
return None
return self.manager.new_session() return self.manager.new_session()
sid, digest = cookie_val.split('!', 1) sid, digest = cookie_val.split('!', 1)
@ -301,10 +326,12 @@ def create_session_interface(app, skip_paths=[]):
FileBackedSessionManager( FileBackedSessionManager(
app.config['SESSION_DB_PATH'], app.config['SESSION_DB_PATH'],
app.config['SECRET_KEY'], app.config['SECRET_KEY'],
app.config.get('PGADMIN_SESSION_DISK_WRITE_DELAY', 10) app.config.get('PGADMIN_SESSION_DISK_WRITE_DELAY', 10),
skip_paths
),
1000,
skip_paths
), ),
1000
), skip_paths,
datetime.timedelta(days=1)) datetime.timedelta(days=1))