We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Increase default session timeouts to 120 minutes
## Description

According to [this plot](https://metrics.torproject.org/torperf.html?start=2017-08-03&end=2017-11-01&source=all&server=onion&filesize=5mb), it currently takes about ~35 seconds to download a 5 MB file over Tor: 

![torperf-onion-2017-08-03-2017-11-01-all-5mb](https://user-images.githubusercontent.com/7832803/32303423-c305bdd8-bf25-11e7-9ac9-fffd8a95fbbd.png)

The maximum size of a SecureDrop submission is 500 MB, so the time it would take to download is 35 seconds * (500/5) = 3500 seconds, or just under an hour. As such, to be safe we should bump the session timeout to at least 120 minutes. 

## User Stories

As a SecureDrop source/journalist, I don't want to wait a very long time to upload/download a file over Tor, only to be logged out by the SecureDrop session timeout. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `securedrop/source_app/__init__.py`
Content:
```
1 from datetime import datetime, timedelta
2 from flask import (Flask, render_template, flash, Markup, request, g, session,
3                    url_for, redirect)
4 from flask_babel import gettext
5 from flask_assets import Environment
6 from flask_wtf.csrf import CSRFProtect, CSRFError
7 from jinja2 import evalcontextfilter
8 from os import path
9 from sqlalchemy.orm.exc import NoResultFound
10 
11 import crypto_util
12 import i18n
13 import store
14 import template_filters
15 import version
16 
17 from db import Source, db_session
18 from request_that_secures_file_uploads import RequestThatSecuresFileUploads
19 from source_app import main, info, api
20 from source_app.decorators import ignore_static
21 from source_app.utils import logged_in
22 
23 
24 def create_app(config):
25     app = Flask(__name__,
26                 template_folder=config.SOURCE_TEMPLATES_DIR,
27                 static_folder=path.join(config.SECUREDROP_ROOT, 'static'))
28     app.request_class = RequestThatSecuresFileUploads
29     app.config.from_object(config.SourceInterfaceFlaskConfig)
30 
31     # The default CSRF token expiration is 1 hour. Since large uploads can
32     # take longer than an hour over Tor, we increase the valid window to 24h.
33     app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24
34 
35     CSRFProtect(app)
36 
37     @app.errorhandler(CSRFError)
38     def handle_csrf_error(e):
39         msg = render_template('session_timeout.html')
40         session.clear()
41         flash(Markup(msg), "important")
42         return redirect(url_for('main.index'))
43 
44     assets = Environment(app)
45     app.config['assets'] = assets
46 
47     i18n.setup_app(app)
48 
49     app.jinja_env.trim_blocks = True
50     app.jinja_env.lstrip_blocks = True
51     app.jinja_env.globals['version'] = version.__version__
52     if getattr(config, 'CUSTOM_HEADER_IMAGE', None):
53         app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE
54         app.jinja_env.globals['use_custom_header_image'] = True
55     else:
56         app.jinja_env.globals['header_image'] = 'logo.png'
57         app.jinja_env.globals['use_custom_header_image'] = False
58 
59     app.jinja_env.filters['rel_datetime_format'] = \
60         template_filters.rel_datetime_format
61     app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br)
62     app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat
63 
64     for module in [main, info, api]:
65         app.register_blueprint(module.make_blueprint(config))
66 
67     @app.before_request
68     @ignore_static
69     def check_tor2web():
70         # ignore_static here so we only flash a single message warning
71         # about Tor2Web, corresponding to the initial page load.
72         if 'X-tor2web' in request.headers:
73             flash(Markup(gettext(
74                 '<strong>WARNING:</strong> You appear to be using Tor2Web. '
75                 'This <strong>does not</strong> provide anonymity. '
76                 '<a href="{url}">Why is this dangerous?</a>')
77                 .format(url=url_for('info.tor2web_warning'))),
78                   "banner-warning")
79 
80     @app.before_request
81     @ignore_static
82     def setup_g():
83         """Store commonly used values in Flask's special g object"""
84         g.locale = i18n.get_locale()
85         g.text_direction = i18n.get_text_direction(g.locale)
86         g.html_lang = i18n.locale_to_rfc_5646(g.locale)
87         g.locales = i18n.get_locale2name()
88 
89         if 'expires' in session and datetime.utcnow() >= session['expires']:
90             msg = render_template('session_timeout.html')
91 
92             # clear the session after we render the message so it's localized
93             session.clear()
94 
95             flash(Markup(msg), "important")
96 
97         session['expires'] = datetime.utcnow() + \
98             timedelta(minutes=getattr(config,
99                                       'SESSION_EXPIRATION_MINUTES',
100                                       30))
101 
102         # ignore_static here because `crypto_util.hash_codename` is scrypt
103         # (very time consuming), and we don't need to waste time running if
104         # we're just serving a static resource that won't need to access
105         # these common values.
106         if logged_in():
107             g.codename = session['codename']
108             g.filesystem_id = crypto_util.hash_codename(g.codename)
109             try:
110                 g.source = Source.query \
111                             .filter(Source.filesystem_id == g.filesystem_id) \
112                             .one()
113             except NoResultFound as e:
114                 app.logger.error(
115                     "Found no Sources when one was expected: %s" %
116                     (e,))
117                 del session['logged_in']
118                 del session['codename']
119                 return redirect(url_for('main.index'))
120             g.loc = store.path(g.filesystem_id)
121 
122     @app.teardown_appcontext
123     def shutdown_session(exception=None):
124         """Automatically remove database sessions at the end of the request, or
125         when the application shuts down"""
126         db_session.remove()
127 
128     @app.errorhandler(404)
129     def page_not_found(error):
130         return render_template('notfound.html'), 404
131 
132     @app.errorhandler(500)
133     def internal_error(error):
134         return render_template('error.html'), 500
135 
136     return app
137
```

Path: `securedrop/journalist_app/__init__.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 from datetime import datetime, timedelta
4 from flask import Flask, session, redirect, url_for, flash, g, request
5 from flask_assets import Environment
6 from flask_babel import gettext
7 from flask_wtf.csrf import CSRFProtect, CSRFError
8 from os import path
9 
10 import i18n
11 import template_filters
12 import version
13 
14 from db import db_session, Journalist
15 from journalist_app import account, admin, main, col
16 from journalist_app.utils import get_source
17 
18 
19 def create_app(config):
20     app = Flask(__name__,
21                 template_folder=config.JOURNALIST_TEMPLATES_DIR,
22                 static_folder=path.join(config.SECUREDROP_ROOT, 'static'))
23 
24     app.config.from_object(config.JournalistInterfaceFlaskConfig)
25 
26     CSRFProtect(app)
27     Environment(app)
28 
29     @app.errorhandler(CSRFError)
30     def handle_csrf_error(e):
31         # render the message first to ensure it's localized.
32         msg = gettext('You have been logged out due to inactivity')
33         session.clear()
34         flash(msg, 'error')
35         return redirect(url_for('main.login'))
36 
37     i18n.setup_app(app)
38 
39     app.jinja_env.trim_blocks = True
40     app.jinja_env.lstrip_blocks = True
41     app.jinja_env.globals['version'] = version.__version__
42     if hasattr(config, 'CUSTOM_HEADER_IMAGE'):
43         app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE
44         app.jinja_env.globals['use_custom_header_image'] = True
45     else:
46         app.jinja_env.globals['header_image'] = 'logo.png'
47         app.jinja_env.globals['use_custom_header_image'] = False
48 
49     app.jinja_env.filters['rel_datetime_format'] = \
50         template_filters.rel_datetime_format
51     app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat
52 
53     @app.teardown_appcontext
54     def shutdown_session(exception=None):
55         """Automatically remove database sessions at the end of the request, or
56         when the application shuts down"""
57         db_session.remove()
58 
59     @app.before_request
60     def setup_g():
61         """Store commonly used values in Flask's special g object"""
62         if 'expires' in session and datetime.utcnow() >= session['expires']:
63             session.clear()
64             flash(gettext('You have been logged out due to inactivity'),
65                   'error')
66 
67         session['expires'] = datetime.utcnow() + \
68             timedelta(minutes=getattr(config,
69                                       'SESSION_EXPIRATION_MINUTES',
70                                       30))
71 
72         uid = session.get('uid', None)
73         if uid:
74             g.user = Journalist.query.get(uid)
75 
76         g.locale = i18n.get_locale()
77         g.text_direction = i18n.get_text_direction(g.locale)
78         g.html_lang = i18n.locale_to_rfc_5646(g.locale)
79         g.locales = i18n.get_locale2name()
80 
81         if request.method == 'POST':
82             filesystem_id = request.form.get('filesystem_id')
83             if filesystem_id:
84                 g.filesystem_id = filesystem_id
85                 g.source = get_source(filesystem_id)
86 
87     app.register_blueprint(main.make_blueprint(config))
88     app.register_blueprint(account.make_blueprint(config),
89                            url_prefix='/account')
90     app.register_blueprint(admin.make_blueprint(config), url_prefix='/admin')
91     app.register_blueprint(col.make_blueprint(config), url_prefix='/col')
92 
93     return app
94
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/securedrop/journalist_app/__init__.py b/securedrop/journalist_app/__init__.py
--- a/securedrop/journalist_app/__init__.py
+++ b/securedrop/journalist_app/__init__.py
@@ -67,7 +67,7 @@
         session['expires'] = datetime.utcnow() + \
             timedelta(minutes=getattr(config,
                                       'SESSION_EXPIRATION_MINUTES',
-                                      30))
+                                      120))
 
         uid = session.get('uid', None)
         if uid:
diff --git a/securedrop/source_app/__init__.py b/securedrop/source_app/__init__.py
--- a/securedrop/source_app/__init__.py
+++ b/securedrop/source_app/__init__.py
@@ -97,7 +97,7 @@
         session['expires'] = datetime.utcnow() + \
             timedelta(minutes=getattr(config,
                                       'SESSION_EXPIRATION_MINUTES',
-                                      30))
+                                      120))
 
         # ignore_static here because `crypto_util.hash_codename` is scrypt
         # (very time consuming), and we don't need to waste time running if

{"golden_diff": "diff --git a/securedrop/journalist_app/__init__.py b/securedrop/journalist_app/__init__.py\n--- a/securedrop/journalist_app/__init__.py\n+++ b/securedrop/journalist_app/__init__.py\n@@ -67,7 +67,7 @@\n         session['expires'] = datetime.utcnow() + \\\n             timedelta(minutes=getattr(config,\n                                       'SESSION_EXPIRATION_MINUTES',\n-                                      30))\n+                                      120))\n \n         uid = session.get('uid', None)\n         if uid:\ndiff --git a/securedrop/source_app/__init__.py b/securedrop/source_app/__init__.py\n--- a/securedrop/source_app/__init__.py\n+++ b/securedrop/source_app/__init__.py\n@@ -97,7 +97,7 @@\n         session['expires'] = datetime.utcnow() + \\\n             timedelta(minutes=getattr(config,\n                                       'SESSION_EXPIRATION_MINUTES',\n-                                      30))\n+                                      120))\n \n         # ignore_static here because `crypto_util.hash_codename` is scrypt\n         # (very time consuming), and we don't need to waste time running if\n", "issue": "Increase default session timeouts to 120 minutes\n## Description\r\n\r\nAccording to [this plot](https://metrics.torproject.org/torperf.html?start=2017-08-03&end=2017-11-01&source=all&server=onion&filesize=5mb), it currently takes about ~35 seconds to download a 5 MB file over Tor: \r\n\r\n![torperf-onion-2017-08-03-2017-11-01-all-5mb](https://user-images.githubusercontent.com/7832803/32303423-c305bdd8-bf25-11e7-9ac9-fffd8a95fbbd.png)\r\n\r\nThe maximum size of a SecureDrop submission is 500 MB, so the time it would take to download is 35 seconds * (500/5) = 3500 seconds, or just under an hour. As such, to be safe we should bump the session timeout to at least 120 minutes. \r\n\r\n## User Stories\r\n\r\nAs a SecureDrop source/journalist, I don't want to wait a very long time to upload/download a file over Tor, only to be logged out by the SecureDrop session timeout. \n", "before_files": [{"content": "from datetime import datetime, timedelta\nfrom flask import (Flask, render_template, flash, Markup, request, g, session,\n                   url_for, redirect)\nfrom flask_babel import gettext\nfrom flask_assets import Environment\nfrom flask_wtf.csrf import CSRFProtect, CSRFError\nfrom jinja2 import evalcontextfilter\nfrom os import path\nfrom sqlalchemy.orm.exc import NoResultFound\n\nimport crypto_util\nimport i18n\nimport store\nimport template_filters\nimport version\n\nfrom db import Source, db_session\nfrom request_that_secures_file_uploads import RequestThatSecuresFileUploads\nfrom source_app import main, info, api\nfrom source_app.decorators import ignore_static\nfrom source_app.utils import logged_in\n\n\ndef create_app(config):\n    app = Flask(__name__,\n                template_folder=config.SOURCE_TEMPLATES_DIR,\n                static_folder=path.join(config.SECUREDROP_ROOT, 'static'))\n    app.request_class = RequestThatSecuresFileUploads\n    app.config.from_object(config.SourceInterfaceFlaskConfig)\n\n    # The default CSRF token expiration is 1 hour. Since large uploads can\n    # take longer than an hour over Tor, we increase the valid window to 24h.\n    app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24\n\n    CSRFProtect(app)\n\n    @app.errorhandler(CSRFError)\n    def handle_csrf_error(e):\n        msg = render_template('session_timeout.html')\n        session.clear()\n        flash(Markup(msg), \"important\")\n        return redirect(url_for('main.index'))\n\n    assets = Environment(app)\n    app.config['assets'] = assets\n\n    i18n.setup_app(app)\n\n    app.jinja_env.trim_blocks = True\n    app.jinja_env.lstrip_blocks = True\n    app.jinja_env.globals['version'] = version.__version__\n    if getattr(config, 'CUSTOM_HEADER_IMAGE', None):\n        app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE\n        app.jinja_env.globals['use_custom_header_image'] = True\n    else:\n        app.jinja_env.globals['header_image'] = 'logo.png'\n        app.jinja_env.globals['use_custom_header_image'] = False\n\n    app.jinja_env.filters['rel_datetime_format'] = \\\n        template_filters.rel_datetime_format\n    app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br)\n    app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat\n\n    for module in [main, info, api]:\n        app.register_blueprint(module.make_blueprint(config))\n\n    @app.before_request\n    @ignore_static\n    def check_tor2web():\n        # ignore_static here so we only flash a single message warning\n        # about Tor2Web, corresponding to the initial page load.\n        if 'X-tor2web' in request.headers:\n            flash(Markup(gettext(\n                '<strong>WARNING:</strong> You appear to be using Tor2Web. '\n                'This <strong>does not</strong> provide anonymity. '\n                '<a href=\"{url}\">Why is this dangerous?</a>')\n                .format(url=url_for('info.tor2web_warning'))),\n                  \"banner-warning\")\n\n    @app.before_request\n    @ignore_static\n    def setup_g():\n        \"\"\"Store commonly used values in Flask's special g object\"\"\"\n        g.locale = i18n.get_locale()\n        g.text_direction = i18n.get_text_direction(g.locale)\n        g.html_lang = i18n.locale_to_rfc_5646(g.locale)\n        g.locales = i18n.get_locale2name()\n\n        if 'expires' in session and datetime.utcnow() >= session['expires']:\n            msg = render_template('session_timeout.html')\n\n            # clear the session after we render the message so it's localized\n            session.clear()\n\n            flash(Markup(msg), \"important\")\n\n        session['expires'] = datetime.utcnow() + \\\n            timedelta(minutes=getattr(config,\n                                      'SESSION_EXPIRATION_MINUTES',\n                                      30))\n\n        # ignore_static here because `crypto_util.hash_codename` is scrypt\n        # (very time consuming), and we don't need to waste time running if\n        # we're just serving a static resource that won't need to access\n        # these common values.\n        if logged_in():\n            g.codename = session['codename']\n            g.filesystem_id = crypto_util.hash_codename(g.codename)\n            try:\n                g.source = Source.query \\\n                            .filter(Source.filesystem_id == g.filesystem_id) \\\n                            .one()\n            except NoResultFound as e:\n                app.logger.error(\n                    \"Found no Sources when one was expected: %s\" %\n                    (e,))\n                del session['logged_in']\n                del session['codename']\n                return redirect(url_for('main.index'))\n            g.loc = store.path(g.filesystem_id)\n\n    @app.teardown_appcontext\n    def shutdown_session(exception=None):\n        \"\"\"Automatically remove database sessions at the end of the request, or\n        when the application shuts down\"\"\"\n        db_session.remove()\n\n    @app.errorhandler(404)\n    def page_not_found(error):\n        return render_template('notfound.html'), 404\n\n    @app.errorhandler(500)\n    def internal_error(error):\n        return render_template('error.html'), 500\n\n    return app\n", "path": "securedrop/source_app/__init__.py"}, {"content": "# -*- coding: utf-8 -*-\n\nfrom datetime import datetime, timedelta\nfrom flask import Flask, session, redirect, url_for, flash, g, request\nfrom flask_assets import Environment\nfrom flask_babel import gettext\nfrom flask_wtf.csrf import CSRFProtect, CSRFError\nfrom os import path\n\nimport i18n\nimport template_filters\nimport version\n\nfrom db import db_session, Journalist\nfrom journalist_app import account, admin, main, col\nfrom journalist_app.utils import get_source\n\n\ndef create_app(config):\n    app = Flask(__name__,\n                template_folder=config.JOURNALIST_TEMPLATES_DIR,\n                static_folder=path.join(config.SECUREDROP_ROOT, 'static'))\n\n    app.config.from_object(config.JournalistInterfaceFlaskConfig)\n\n    CSRFProtect(app)\n    Environment(app)\n\n    @app.errorhandler(CSRFError)\n    def handle_csrf_error(e):\n        # render the message first to ensure it's localized.\n        msg = gettext('You have been logged out due to inactivity')\n        session.clear()\n        flash(msg, 'error')\n        return redirect(url_for('main.login'))\n\n    i18n.setup_app(app)\n\n    app.jinja_env.trim_blocks = True\n    app.jinja_env.lstrip_blocks = True\n    app.jinja_env.globals['version'] = version.__version__\n    if hasattr(config, 'CUSTOM_HEADER_IMAGE'):\n        app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE\n        app.jinja_env.globals['use_custom_header_image'] = True\n    else:\n        app.jinja_env.globals['header_image'] = 'logo.png'\n        app.jinja_env.globals['use_custom_header_image'] = False\n\n    app.jinja_env.filters['rel_datetime_format'] = \\\n        template_filters.rel_datetime_format\n    app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat\n\n    @app.teardown_appcontext\n    def shutdown_session(exception=None):\n        \"\"\"Automatically remove database sessions at the end of the request, or\n        when the application shuts down\"\"\"\n        db_session.remove()\n\n    @app.before_request\n    def setup_g():\n        \"\"\"Store commonly used values in Flask's special g object\"\"\"\n        if 'expires' in session and datetime.utcnow() >= session['expires']:\n            session.clear()\n            flash(gettext('You have been logged out due to inactivity'),\n                  'error')\n\n        session['expires'] = datetime.utcnow() + \\\n            timedelta(minutes=getattr(config,\n                                      'SESSION_EXPIRATION_MINUTES',\n                                      30))\n\n        uid = session.get('uid', None)\n        if uid:\n            g.user = Journalist.query.get(uid)\n\n        g.locale = i18n.get_locale()\n        g.text_direction = i18n.get_text_direction(g.locale)\n        g.html_lang = i18n.locale_to_rfc_5646(g.locale)\n        g.locales = i18n.get_locale2name()\n\n        if request.method == 'POST':\n            filesystem_id = request.form.get('filesystem_id')\n            if filesystem_id:\n                g.filesystem_id = filesystem_id\n                g.source = get_source(filesystem_id)\n\n    app.register_blueprint(main.make_blueprint(config))\n    app.register_blueprint(account.make_blueprint(config),\n                           url_prefix='/account')\n    app.register_blueprint(admin.make_blueprint(config), url_prefix='/admin')\n    app.register_blueprint(col.make_blueprint(config), url_prefix='/col')\n\n    return app\n", "path": "securedrop/journalist_app/__init__.py"}], "after_files": [{"content": "from datetime import datetime, timedelta\nfrom flask import (Flask, render_template, flash, Markup, request, g, session,\n                   url_for, redirect)\nfrom flask_babel import gettext\nfrom flask_assets import Environment\nfrom flask_wtf.csrf import CSRFProtect, CSRFError\nfrom jinja2 import evalcontextfilter\nfrom os import path\nfrom sqlalchemy.orm.exc import NoResultFound\n\nimport crypto_util\nimport i18n\nimport store\nimport template_filters\nimport version\n\nfrom db import Source, db_session\nfrom request_that_secures_file_uploads import RequestThatSecuresFileUploads\nfrom source_app import main, info, api\nfrom source_app.decorators import ignore_static\nfrom source_app.utils import logged_in\n\n\ndef create_app(config):\n    app = Flask(__name__,\n                template_folder=config.SOURCE_TEMPLATES_DIR,\n                static_folder=path.join(config.SECUREDROP_ROOT, 'static'))\n    app.request_class = RequestThatSecuresFileUploads\n    app.config.from_object(config.SourceInterfaceFlaskConfig)\n\n    # The default CSRF token expiration is 1 hour. Since large uploads can\n    # take longer than an hour over Tor, we increase the valid window to 24h.\n    app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24\n\n    CSRFProtect(app)\n\n    @app.errorhandler(CSRFError)\n    def handle_csrf_error(e):\n        msg = render_template('session_timeout.html')\n        session.clear()\n        flash(Markup(msg), \"important\")\n        return redirect(url_for('main.index'))\n\n    assets = Environment(app)\n    app.config['assets'] = assets\n\n    i18n.setup_app(app)\n\n    app.jinja_env.trim_blocks = True\n    app.jinja_env.lstrip_blocks = True\n    app.jinja_env.globals['version'] = version.__version__\n    if getattr(config, 'CUSTOM_HEADER_IMAGE', None):\n        app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE\n        app.jinja_env.globals['use_custom_header_image'] = True\n    else:\n        app.jinja_env.globals['header_image'] = 'logo.png'\n        app.jinja_env.globals['use_custom_header_image'] = False\n\n    app.jinja_env.filters['rel_datetime_format'] = \\\n        template_filters.rel_datetime_format\n    app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br)\n    app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat\n\n    for module in [main, info, api]:\n        app.register_blueprint(module.make_blueprint(config))\n\n    @app.before_request\n    @ignore_static\n    def check_tor2web():\n        # ignore_static here so we only flash a single message warning\n        # about Tor2Web, corresponding to the initial page load.\n        if 'X-tor2web' in request.headers:\n            flash(Markup(gettext(\n                '<strong>WARNING:</strong> You appear to be using Tor2Web. '\n                'This <strong>does not</strong> provide anonymity. '\n                '<a href=\"{url}\">Why is this dangerous?</a>')\n                .format(url=url_for('info.tor2web_warning'))),\n                  \"banner-warning\")\n\n    @app.before_request\n    @ignore_static\n    def setup_g():\n        \"\"\"Store commonly used values in Flask's special g object\"\"\"\n        g.locale = i18n.get_locale()\n        g.text_direction = i18n.get_text_direction(g.locale)\n        g.html_lang = i18n.locale_to_rfc_5646(g.locale)\n        g.locales = i18n.get_locale2name()\n\n        if 'expires' in session and datetime.utcnow() >= session['expires']:\n            msg = render_template('session_timeout.html')\n\n            # clear the session after we render the message so it's localized\n            session.clear()\n\n            flash(Markup(msg), \"important\")\n\n        session['expires'] = datetime.utcnow() + \\\n            timedelta(minutes=getattr(config,\n                                      'SESSION_EXPIRATION_MINUTES',\n                                      120))\n\n        # ignore_static here because `crypto_util.hash_codename` is scrypt\n        # (very time consuming), and we don't need to waste time running if\n        # we're just serving a static resource that won't need to access\n        # these common values.\n        if logged_in():\n            g.codename = session['codename']\n            g.filesystem_id = crypto_util.hash_codename(g.codename)\n            try:\n                g.source = Source.query \\\n                            .filter(Source.filesystem_id == g.filesystem_id) \\\n                            .one()\n            except NoResultFound as e:\n                app.logger.error(\n                    \"Found no Sources when one was expected: %s\" %\n                    (e,))\n                del session['logged_in']\n                del session['codename']\n                return redirect(url_for('main.index'))\n            g.loc = store.path(g.filesystem_id)\n\n    @app.teardown_appcontext\n    def shutdown_session(exception=None):\n        \"\"\"Automatically remove database sessions at the end of the request, or\n        when the application shuts down\"\"\"\n        db_session.remove()\n\n    @app.errorhandler(404)\n    def page_not_found(error):\n        return render_template('notfound.html'), 404\n\n    @app.errorhandler(500)\n    def internal_error(error):\n        return render_template('error.html'), 500\n\n    return app\n", "path": "securedrop/source_app/__init__.py"}, {"content": "# -*- coding: utf-8 -*-\n\nfrom datetime import datetime, timedelta\nfrom flask import Flask, session, redirect, url_for, flash, g, request\nfrom flask_assets import Environment\nfrom flask_babel import gettext\nfrom flask_wtf.csrf import CSRFProtect, CSRFError\nfrom os import path\n\nimport i18n\nimport template_filters\nimport version\n\nfrom db import db_session, Journalist\nfrom journalist_app import account, admin, main, col\nfrom journalist_app.utils import get_source\n\n\ndef create_app(config):\n    app = Flask(__name__,\n                template_folder=config.JOURNALIST_TEMPLATES_DIR,\n                static_folder=path.join(config.SECUREDROP_ROOT, 'static'))\n\n    app.config.from_object(config.JournalistInterfaceFlaskConfig)\n\n    CSRFProtect(app)\n    Environment(app)\n\n    @app.errorhandler(CSRFError)\n    def handle_csrf_error(e):\n        # render the message first to ensure it's localized.\n        msg = gettext('You have been logged out due to inactivity')\n        session.clear()\n        flash(msg, 'error')\n        return redirect(url_for('main.login'))\n\n    i18n.setup_app(app)\n\n    app.jinja_env.trim_blocks = True\n    app.jinja_env.lstrip_blocks = True\n    app.jinja_env.globals['version'] = version.__version__\n    if hasattr(config, 'CUSTOM_HEADER_IMAGE'):\n        app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE\n        app.jinja_env.globals['use_custom_header_image'] = True\n    else:\n        app.jinja_env.globals['header_image'] = 'logo.png'\n        app.jinja_env.globals['use_custom_header_image'] = False\n\n    app.jinja_env.filters['rel_datetime_format'] = \\\n        template_filters.rel_datetime_format\n    app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat\n\n    @app.teardown_appcontext\n    def shutdown_session(exception=None):\n        \"\"\"Automatically remove database sessions at the end of the request, or\n        when the application shuts down\"\"\"\n        db_session.remove()\n\n    @app.before_request\n    def setup_g():\n        \"\"\"Store commonly used values in Flask's special g object\"\"\"\n        if 'expires' in session and datetime.utcnow() >= session['expires']:\n            session.clear()\n            flash(gettext('You have been logged out due to inactivity'),\n                  'error')\n\n        session['expires'] = datetime.utcnow() + \\\n            timedelta(minutes=getattr(config,\n                                      'SESSION_EXPIRATION_MINUTES',\n                                      120))\n\n        uid = session.get('uid', None)\n        if uid:\n            g.user = Journalist.query.get(uid)\n\n        g.locale = i18n.get_locale()\n        g.text_direction = i18n.get_text_direction(g.locale)\n        g.html_lang = i18n.locale_to_rfc_5646(g.locale)\n        g.locales = i18n.get_locale2name()\n\n        if request.method == 'POST':\n            filesystem_id = request.form.get('filesystem_id')\n            if filesystem_id:\n                g.filesystem_id = filesystem_id\n                g.source = get_source(filesystem_id)\n\n    app.register_blueprint(main.make_blueprint(config))\n    app.register_blueprint(account.make_blueprint(config),\n                           url_prefix='/account')\n    app.register_blueprint(admin.make_blueprint(config), url_prefix='/admin')\n    app.register_blueprint(col.make_blueprint(config), url_prefix='/col')\n\n    return app\n", "path": "securedrop/journalist_app/__init__.py"}]}