Source code for overwatch.webApp.routing

#!/usr/bin/env python

""" Contains routing functions.

Contains functions to ensure safe routing and redirection of the next URL. These functions are from
http://flask.pocoo.org/snippets/62/, and were written by the author of Flask.

Slight modifications were made to :func:`redirectBack` to ensure that a login-logout loop was avoided
under particular circumstances.

.. codeauthor:: Raymond Ehlers <raymond.ehlers@cern.ch>, Yale University
"""

from flask import request, url_for, redirect

# Handle python 2/3
try:
    from urllib.parse import urlparse, urljoin
except ImportError:
    from urlparse import urlparse, urljoin

# Logging
import logging
logger = logging.getLogger(__name__)

[docs]def isSafeUrl(target): """ Checks URL for safety to ensure that it does not redirect unexpectedly. Note: Relies on the flask.request object. Args: target (str): URL for the target to test. Returns: bool: True if the URL is safe. """ ref_url = urlparse(request.host_url) test_url = urlparse(urljoin(request.host_url, target)) return test_url.scheme in ('http', 'https') and ref_url.netloc == test_url.netloc
[docs]def getRedirectTarget(): """ Extracts the Next target and checks its safety. Note: Relies on the flask.request object. Args: None Returns: str: URL if the target is safe. """ for target in [request.values.get('next'), request.referrer]: if not target: continue if isSafeUrl(target): return target
[docs]def redirectBack(endpoint, **values): """ Handles safe redirection. It extracts the value of Next from flask.request. If the target is not safe, then redirect back to ``endpoint`` instead. Note: Relies on the request.form dict. Args: endpoint (str): Where to redirect in case the Next url is not safe **values (dict): Arguments to pass to url_for() in case of needing to redirect to endpoint instead. Returns: redirect to NextUrl: Redirect is called on the next URL if it is safe. Redirects to the given endpoint if the URL is not safe. """ target = request.form['next'] # If an unauthenticated user attempted to access /logout, then after logging in, it would redirect # them to logout, causing a loop. So instead we just redirect to the default location in such a case. # Also prevent downloading test data since it would lead to a confusing situation where the user stays # on the login page after logging in. # This logout and test data specific change is the only one made in these functions if not target or not isSafeUrl(target) or "logout" in target or "testingDataArchive" in target: target = url_for(endpoint, **values) #logger.debug("target for redirectBack: {target}".format(target = target)) return redirect(target)