We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Expired Source Interface session causes server error on new session
## Description

Creating a new codename after a session has expired causes a server error.

## Steps to Reproduce

1. Visit the codename generation page (`/generate`) but do not press 'Submit Documents'
2. Wait for the session to expire
3. Press 'Submit Documents'

Diff to force session expiry at 1 minute:

```diff
diff --git a/securedrop/source_app/__init__.py b/securedrop/source_app/__init__.py
index d2679b737..60df38ece 100644
--- a/securedrop/source_app/__init__.py
+++ b/securedrop/source_app/__init__.py
@@ -148,9 +148,7 @@ def create_app(config):
             flash(Markup(msg), "important")
 
         session['expires'] = datetime.utcnow() + \
-            timedelta(minutes=getattr(config,
-                                      'SESSION_EXPIRATION_MINUTES',
-                                      120))
+            timedelta(minutes=1)
 
         # ignore_static here because `crypto_util.hash_codename` is scrypt
         # (very time consuming), and we don't need to waste time running if
```

## Expected Behavior

A new codename is generated or an appropriate error message is shown.

## Actual Behavior

The Source Interface displays:

> Server error
> Sorry, the website encountered an error and was unable to complete your request.

--- 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 i18n
12 import template_filters
13 import version
14 
15 from crypto_util import CryptoUtil
16 from db import db
17 from models import Source
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 from store import Storage
23 from worker import rq_worker_queue
24 
25 import typing
26 # https://www.python.org/dev/peps/pep-0484/#runtime-or-type-checking
27 if typing.TYPE_CHECKING:
28     # flake8 can not understand type annotation yet.
29     # That is why all type annotation relative import
30     # statements has to be marked as noqa.
31     # http://flake8.pycqa.org/en/latest/user/error-codes.html?highlight=f401
32     from sdconfig import SDConfig  # noqa: F401
33 
34 
35 def create_app(config):
36     # type: (SDConfig) -> Flask
37     app = Flask(__name__,
38                 template_folder=config.SOURCE_TEMPLATES_DIR,
39                 static_folder=path.join(config.SECUREDROP_ROOT, 'static'))
40     app.request_class = RequestThatSecuresFileUploads
41     app.config.from_object(config.SourceInterfaceFlaskConfig)  # type: ignore
42     app.sdconfig = config
43 
44     # The default CSRF token expiration is 1 hour. Since large uploads can
45     # take longer than an hour over Tor, we increase the valid window to 24h.
46     app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24
47     CSRFProtect(app)
48 
49     if config.DATABASE_ENGINE == "sqlite":
50         db_uri = (config.DATABASE_ENGINE + ":///" +
51                   config.DATABASE_FILE)
52     else:
53         db_uri = (
54             config.DATABASE_ENGINE + '://' +
55             config.DATABASE_USERNAME + ':' +
56             config.DATABASE_PASSWORD + '@' +
57             config.DATABASE_HOST + '/' +
58             config.DATABASE_NAME
59         )
60     app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
61     app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
62     db.init_app(app)
63 
64     app.storage = Storage(config.STORE_DIR,
65                           config.TEMP_DIR,
66                           config.JOURNALIST_KEY)
67 
68     app.crypto_util = CryptoUtil(
69         scrypt_params=config.SCRYPT_PARAMS,
70         scrypt_id_pepper=config.SCRYPT_ID_PEPPER,
71         scrypt_gpg_pepper=config.SCRYPT_GPG_PEPPER,
72         securedrop_root=config.SECUREDROP_ROOT,
73         word_list=config.WORD_LIST,
74         nouns_file=config.NOUNS,
75         adjectives_file=config.ADJECTIVES,
76         gpg_key_dir=config.GPG_KEY_DIR,
77     )
78 
79     app.config['RQ_WORKER_NAME'] = config.RQ_WORKER_NAME
80     rq_worker_queue.init_app(app)
81 
82     @app.errorhandler(CSRFError)
83     def handle_csrf_error(e):
84         msg = render_template('session_timeout.html')
85         session.clear()
86         flash(Markup(msg), "important")
87         return redirect(url_for('main.index'))
88 
89     assets = Environment(app)
90     app.config['assets'] = assets
91 
92     i18n.setup_app(config, app)
93 
94     app.jinja_env.trim_blocks = True
95     app.jinja_env.lstrip_blocks = True
96     app.jinja_env.globals['version'] = version.__version__
97     if getattr(config, 'CUSTOM_HEADER_IMAGE', None):
98         app.jinja_env.globals['header_image'] = \
99             config.CUSTOM_HEADER_IMAGE  # type: ignore
100         app.jinja_env.globals['use_custom_header_image'] = True
101     else:
102         app.jinja_env.globals['header_image'] = 'logo.png'
103         app.jinja_env.globals['use_custom_header_image'] = False
104 
105     app.jinja_env.filters['rel_datetime_format'] = \
106         template_filters.rel_datetime_format
107     app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br)
108     app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat
109 
110     for module in [main, info, api]:
111         app.register_blueprint(module.make_blueprint(config))  # type: ignore
112 
113     @app.before_request
114     @ignore_static
115     def setup_i18n():
116         """Store i18n-related values in Flask's special g object"""
117         g.locale = i18n.get_locale(config)
118         g.text_direction = i18n.get_text_direction(g.locale)
119         g.html_lang = i18n.locale_to_rfc_5646(g.locale)
120         g.locales = i18n.get_locale2name()
121 
122     @app.before_request
123     @ignore_static
124     def check_tor2web():
125         # ignore_static here so we only flash a single message warning
126         # about Tor2Web, corresponding to the initial page load.
127         if 'X-tor2web' in request.headers:
128             flash(Markup(gettext(
129                 '<strong>WARNING:&nbsp;</strong> '
130                 'You appear to be using Tor2Web. '
131                 'This <strong>&nbsp;does not&nbsp;</strong> '
132                 'provide anonymity. '
133                 '<a href="{url}">Why is this dangerous?</a>')
134                 .format(url=url_for('info.tor2web_warning'))),
135                   "banner-warning")
136 
137     @app.before_request
138     @ignore_static
139     def setup_g():
140         """Store commonly used values in Flask's special g object"""
141 
142         if 'expires' in session and datetime.utcnow() >= session['expires']:
143             msg = render_template('session_timeout.html')
144 
145             # clear the session after we render the message so it's localized
146             session.clear()
147 
148             flash(Markup(msg), "important")
149 
150         session['expires'] = datetime.utcnow() + \
151             timedelta(minutes=getattr(config,
152                                       'SESSION_EXPIRATION_MINUTES',
153                                       120))
154 
155         # ignore_static here because `crypto_util.hash_codename` is scrypt
156         # (very time consuming), and we don't need to waste time running if
157         # we're just serving a static resource that won't need to access
158         # these common values.
159         if logged_in():
160             g.codename = session['codename']
161             g.filesystem_id = app.crypto_util.hash_codename(g.codename)
162             try:
163                 g.source = Source.query \
164                             .filter(Source.filesystem_id == g.filesystem_id) \
165                             .one()
166             except NoResultFound as e:
167                 app.logger.error(
168                     "Found no Sources when one was expected: %s" %
169                     (e,))
170                 del session['logged_in']
171                 del session['codename']
172                 return redirect(url_for('main.index'))
173             g.loc = app.storage.path(g.filesystem_id)
174 
175     @app.errorhandler(404)
176     def page_not_found(error):
177         return render_template('notfound.html'), 404
178 
179     @app.errorhandler(500)
180     def internal_error(error):
181         return render_template('error.html'), 500
182 
183     return app
184
```
--- 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/source_app/__init__.py b/securedrop/source_app/__init__.py
--- a/securedrop/source_app/__init__.py
+++ b/securedrop/source_app/__init__.py
@@ -145,7 +145,9 @@
             # clear the session after we render the message so it's localized
             session.clear()
 
+            # Redirect to index with flashed message
             flash(Markup(msg), "important")
+            return redirect(url_for('main.index'))
 
         session['expires'] = datetime.utcnow() + \
             timedelta(minutes=getattr(config,

{"golden_diff": "diff --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@@ -145,7 +145,9 @@\n             # clear the session after we render the message so it's localized\n             session.clear()\n \n+            # Redirect to index with flashed message\n             flash(Markup(msg), \"important\")\n+            return redirect(url_for('main.index'))\n \n         session['expires'] = datetime.utcnow() + \\\n             timedelta(minutes=getattr(config,\n", "issue": "Expired Source Interface session causes server error on new session\n## Description\r\n\r\nCreating a new codename after a session has expired causes a server error.\r\n\r\n## Steps to Reproduce\r\n\r\n1. Visit the codename generation page (`/generate`) but do not press 'Submit Documents'\r\n2. Wait for the session to expire\r\n3. Press 'Submit Documents'\r\n\r\nDiff to force session expiry at 1 minute:\r\n\r\n```diff\r\ndiff --git a/securedrop/source_app/__init__.py b/securedrop/source_app/__init__.py\r\nindex d2679b737..60df38ece 100644\r\n--- a/securedrop/source_app/__init__.py\r\n+++ b/securedrop/source_app/__init__.py\r\n@@ -148,9 +148,7 @@ def create_app(config):\r\n             flash(Markup(msg), \"important\")\r\n \r\n         session['expires'] = datetime.utcnow() + \\\r\n-            timedelta(minutes=getattr(config,\r\n-                                      'SESSION_EXPIRATION_MINUTES',\r\n-                                      120))\r\n+            timedelta(minutes=1)\r\n \r\n         # ignore_static here because `crypto_util.hash_codename` is scrypt\r\n         # (very time consuming), and we don't need to waste time running if\r\n```\r\n\r\n## Expected Behavior\r\n\r\nA new codename is generated or an appropriate error message is shown.\r\n\r\n## Actual Behavior\r\n\r\nThe Source Interface displays:\r\n\r\n> Server error\r\n> Sorry, the website encountered an error and was unable to complete your request.\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 i18n\nimport template_filters\nimport version\n\nfrom crypto_util import CryptoUtil\nfrom db import db\nfrom models import Source\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\nfrom store import Storage\nfrom worker import rq_worker_queue\n\nimport typing\n# https://www.python.org/dev/peps/pep-0484/#runtime-or-type-checking\nif typing.TYPE_CHECKING:\n    # flake8 can not understand type annotation yet.\n    # That is why all type annotation relative import\n    # statements has to be marked as noqa.\n    # http://flake8.pycqa.org/en/latest/user/error-codes.html?highlight=f401\n    from sdconfig import SDConfig  # noqa: F401\n\n\ndef create_app(config):\n    # type: (SDConfig) -> Flask\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)  # type: ignore\n    app.sdconfig = config\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    CSRFProtect(app)\n\n    if config.DATABASE_ENGINE == \"sqlite\":\n        db_uri = (config.DATABASE_ENGINE + \":///\" +\n                  config.DATABASE_FILE)\n    else:\n        db_uri = (\n            config.DATABASE_ENGINE + '://' +\n            config.DATABASE_USERNAME + ':' +\n            config.DATABASE_PASSWORD + '@' +\n            config.DATABASE_HOST + '/' +\n            config.DATABASE_NAME\n        )\n    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\n    app.config['SQLALCHEMY_DATABASE_URI'] = db_uri\n    db.init_app(app)\n\n    app.storage = Storage(config.STORE_DIR,\n                          config.TEMP_DIR,\n                          config.JOURNALIST_KEY)\n\n    app.crypto_util = CryptoUtil(\n        scrypt_params=config.SCRYPT_PARAMS,\n        scrypt_id_pepper=config.SCRYPT_ID_PEPPER,\n        scrypt_gpg_pepper=config.SCRYPT_GPG_PEPPER,\n        securedrop_root=config.SECUREDROP_ROOT,\n        word_list=config.WORD_LIST,\n        nouns_file=config.NOUNS,\n        adjectives_file=config.ADJECTIVES,\n        gpg_key_dir=config.GPG_KEY_DIR,\n    )\n\n    app.config['RQ_WORKER_NAME'] = config.RQ_WORKER_NAME\n    rq_worker_queue.init_app(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(config, 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'] = \\\n            config.CUSTOM_HEADER_IMAGE  # type: ignore\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))  # type: ignore\n\n    @app.before_request\n    @ignore_static\n    def setup_i18n():\n        \"\"\"Store i18n-related values in Flask's special g object\"\"\"\n        g.locale = i18n.get_locale(config)\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    @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:&nbsp;</strong> '\n                'You appear to be using Tor2Web. '\n                'This <strong>&nbsp;does not&nbsp;</strong> '\n                '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\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 = app.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 = app.storage.path(g.filesystem_id)\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"}], "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 i18n\nimport template_filters\nimport version\n\nfrom crypto_util import CryptoUtil\nfrom db import db\nfrom models import Source\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\nfrom store import Storage\nfrom worker import rq_worker_queue\n\nimport typing\n# https://www.python.org/dev/peps/pep-0484/#runtime-or-type-checking\nif typing.TYPE_CHECKING:\n    # flake8 can not understand type annotation yet.\n    # That is why all type annotation relative import\n    # statements has to be marked as noqa.\n    # http://flake8.pycqa.org/en/latest/user/error-codes.html?highlight=f401\n    from sdconfig import SDConfig  # noqa: F401\n\n\ndef create_app(config):\n    # type: (SDConfig) -> Flask\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)  # type: ignore\n    app.sdconfig = config\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    CSRFProtect(app)\n\n    if config.DATABASE_ENGINE == \"sqlite\":\n        db_uri = (config.DATABASE_ENGINE + \":///\" +\n                  config.DATABASE_FILE)\n    else:\n        db_uri = (\n            config.DATABASE_ENGINE + '://' +\n            config.DATABASE_USERNAME + ':' +\n            config.DATABASE_PASSWORD + '@' +\n            config.DATABASE_HOST + '/' +\n            config.DATABASE_NAME\n        )\n    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\n    app.config['SQLALCHEMY_DATABASE_URI'] = db_uri\n    db.init_app(app)\n\n    app.storage = Storage(config.STORE_DIR,\n                          config.TEMP_DIR,\n                          config.JOURNALIST_KEY)\n\n    app.crypto_util = CryptoUtil(\n        scrypt_params=config.SCRYPT_PARAMS,\n        scrypt_id_pepper=config.SCRYPT_ID_PEPPER,\n        scrypt_gpg_pepper=config.SCRYPT_GPG_PEPPER,\n        securedrop_root=config.SECUREDROP_ROOT,\n        word_list=config.WORD_LIST,\n        nouns_file=config.NOUNS,\n        adjectives_file=config.ADJECTIVES,\n        gpg_key_dir=config.GPG_KEY_DIR,\n    )\n\n    app.config['RQ_WORKER_NAME'] = config.RQ_WORKER_NAME\n    rq_worker_queue.init_app(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(config, 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'] = \\\n            config.CUSTOM_HEADER_IMAGE  # type: ignore\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))  # type: ignore\n\n    @app.before_request\n    @ignore_static\n    def setup_i18n():\n        \"\"\"Store i18n-related values in Flask's special g object\"\"\"\n        g.locale = i18n.get_locale(config)\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    @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:&nbsp;</strong> '\n                'You appear to be using Tor2Web. '\n                'This <strong>&nbsp;does not&nbsp;</strong> '\n                '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\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            # Redirect to index with flashed message\n            flash(Markup(msg), \"important\")\n            return redirect(url_for('main.index'))\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 = app.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 = app.storage.path(g.filesystem_id)\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"}]}