Skip to content

Commit

Permalink
Replace logo selection route with per-request global variable
Browse files Browse the repository at this point in the history
Getting the logo URL via the /org-logo route's redirect meant that the
logo had to be retrieved with every page load, which of course over
Tor can take several seconds. Selecting the logo at the start of each
request and storing its URL in the Flask globals allows the static URL
to be used in the templates, with the default caching of static
assets, eliminating the extra requests.
  • Loading branch information
rmol committed Mar 16, 2021
1 parent f81b937 commit 3241f65
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 28 deletions.
25 changes: 24 additions & 1 deletion securedrop/journalist_app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-

from datetime import datetime, timedelta
from pathlib import Path

from flask import (Flask, session, redirect, url_for, flash, g, request,
render_template)
from flask_assets import Environment
Expand Down Expand Up @@ -36,7 +38,23 @@
from werkzeug import Response # noqa: F401
from werkzeug.exceptions import HTTPException # noqa: F401

_insecure_views = ['main.login', 'main.select_logo', 'static']
_insecure_views = ['main.login', 'static']


def get_logo_url(app: Flask) -> str:
if not app.static_folder:
raise FileNotFoundError

custom_logo_filename = "i/custom_logo.png"
default_logo_filename = "i/logo.png"
custom_logo_path = Path(app.static_folder) / custom_logo_filename
default_logo_path = Path(app.static_folder) / default_logo_filename
if custom_logo_path.is_file():
return url_for("static", filename=custom_logo_filename)
elif default_logo_path.is_file():
return url_for("static", filename=default_logo_filename)

raise FileNotFoundError


def create_app(config: 'SDConfig') -> Flask:
Expand Down Expand Up @@ -157,6 +175,11 @@ def setup_g() -> 'Optional[Response]':
else:
g.organization_name = gettext('SecureDrop')

try:
g.logo = get_logo_url(app)
except FileNotFoundError:
app.logger.error("Site logo not found.")

if app.config["OS_PAST_EOL"]:
g.show_os_past_eol_warning = True
elif app.config["OS_NEAR_EOL"]:
Expand Down
12 changes: 0 additions & 12 deletions securedrop/journalist_app/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
import os

from datetime import datetime
from typing import Union

Expand Down Expand Up @@ -51,16 +49,6 @@ def logout() -> werkzeug.Response:
session.pop('nonce', None)
return redirect(url_for('main.index'))

@view.route('/org-logo')
def select_logo() -> werkzeug.Response:
if current_app.static_folder is None:
abort(500)
if os.path.exists(os.path.join(current_app.static_folder, 'i',
'custom_logo.png')):
return redirect(url_for('static', filename='i/custom_logo.png'))
else:
return redirect(url_for('static', filename='i/logo.png'))

@view.route('/')
def index() -> str:
unstarred = []
Expand Down
2 changes: 1 addition & 1 deletion securedrop/journalist_templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<div class="container">
{% block header %}
<div id="header">
<a href="{{ url_for('main.index') }}" class="no-bottom-border"><img src="{{ url_for('main.select_logo') }}" class="logo small" alt="{{ g.organization_name }} | Home" width="250"></a>
<a href="{{ url_for('main.index') }}" class="no-bottom-border"><img src="{{ g.logo }}" class="logo small" alt="{{ g.organization_name }} | Home" width="250"></a>
{% include 'locales.html' %}
</div>
{% endblock %}
Expand Down
2 changes: 1 addition & 1 deletion securedrop/journalist_templates/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ <h2 id="config-logoimage">{{ gettext('Logo Image') }}</h2>
<p>{{ gettext('Here you can update the image displayed on the SecureDrop web interfaces:') }}</p>

<p>
<img src="{{ url_for('main.select_logo') }}" class="logo small" alt="{{ g.organization_name }}" width="250">
<img src="{{ g.logo }}" class="logo small" alt="{{ g.organization_name }}" width="250">
</p>

<form method="post" enctype="multipart/form-data">
Expand Down
22 changes: 22 additions & 0 deletions securedrop/source_app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional

import werkzeug
Expand Down Expand Up @@ -28,6 +29,22 @@
from server_os import is_os_past_eol


def get_logo_url(app: Flask) -> str:
if not app.static_folder:
raise FileNotFoundError

custom_logo_filename = "i/custom_logo.png"
default_logo_filename = "i/logo.png"
custom_logo_path = Path(app.static_folder) / custom_logo_filename
default_logo_path = Path(app.static_folder) / default_logo_filename
if custom_logo_path.is_file():
return url_for("static", filename=custom_logo_filename)
elif default_logo_path.is_file():
return url_for("static", filename=default_logo_filename)

raise FileNotFoundError


def create_app(config: SDConfig) -> Flask:
app = Flask(__name__,
template_folder=config.SOURCE_TEMPLATES_DIR,
Expand Down Expand Up @@ -183,6 +200,11 @@ def setup_g() -> Optional[werkzeug.Response]:
else:
g.organization_name = gettext('SecureDrop')

try:
g.logo = get_logo_url(app)
except FileNotFoundError:
app.logger.error("Site logo not found.")

return None

@app.errorhandler(404)
Expand Down
2 changes: 1 addition & 1 deletion securedrop/source_app/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def ignore_static(f: Callable) -> Callable:
a static resource."""
@wraps(f)
def decorated_function(*args: Any, **kwargs: Any) -> Any:
if request.path.startswith("/static") or request.path == "/org-logo":
if request.path.startswith("/static"):
return # don't execute the decorated function
return f(*args, **kwargs)
return decorated_function
10 changes: 0 additions & 10 deletions securedrop/source_app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,6 @@ def generate() -> Union[str, werkzeug.Response]:
session['new_user'] = True
return render_template('generate.html', codename=codename, tab_id=tab_id)

@view.route('/org-logo')
def select_logo() -> werkzeug.Response:
if current_app.static_folder is None:
abort(500)
if os.path.exists(os.path.join(current_app.static_folder, 'i',
'custom_logo.png')):
return redirect(url_for('static', filename='i/custom_logo.png'))
else:
return redirect(url_for('static', filename='i/logo.png'))

@view.route('/create', methods=['POST'])
def create() -> werkzeug.Response:
if session.get('logged_in', False):
Expand Down
2 changes: 1 addition & 1 deletion securedrop/source_templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
{% block header %}
<div id="header">
<a href="{% if 'logged_in' in session %}{{ url_for('main.lookup') }}{% else %}{{ url_for('main.index') }}{% endif %}" class="no-bottom-border">
<img src="{{ url_for('main.select_logo') }}" class="logo small" alt="{{ g.organization_name }} | {{ gettext('SecureDrop Home') }}" width="250">
<img src="{{ g.logo }}" class="logo small" alt="{{ g.organization_name }} | {{ gettext('SecureDrop Home') }}" width="250">
</a>
{% include 'locales.html' %}
</div>
Expand Down
2 changes: 1 addition & 1 deletion securedrop/source_templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
See _source_index.sass for a more full understanding. #}
<div class="index-wrap">
<div class="header">
<img src="{{ url_for('main.select_logo') }}" alt="{{ g.organization_name }} | {{ gettext('Logo Image') }}" class="logo-image">
<img src="{{ g.logo }}" alt="{{ g.organization_name }} | {{ gettext('Logo Image') }}" class="logo-image">
<div id="index-locales">
{% include 'locales.html' %}
</div>
Expand Down

0 comments on commit 3241f65

Please sign in to comment.