-
Notifications
You must be signed in to change notification settings - Fork 688
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upgrade Flask dependency to 2.0.2 and refactor applications to improve static type checks #6217
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
454febd
Reordered requirements installation in Docker env.
zenmonkeykstop 4829953
Updated application dependencies to use Flask 2.0.2
zenmonkeykstop 2072989
Updated Flask version in testinfra test variables
zenmonkeykstop 1633566
Replaced naive datetime.utcnow() calls with tz-aware equivalent.
zenmonkeykstop 43d4cb7
Disabled pylint:E0237 false positives for g attributes
zenmonkeykstop 4a09a16
Replaced flask app.instance_config attribute with global InstanceConf…
zenmonkeykstop f2b35bf
Replaced Flask app.storage attribute with global Storage object
zenmonkeykstop 6a0dbc2
Added typing fixes
zenmonkeykstop 01801e4
Removed Storage.get_default() refs from db model and store utility fu…
zenmonkeykstop 0d21eb6
Added app_storage test fixture, updated tests to use it
zenmonkeykstop 4ce6588
Added option to refresh the global InstanceConfig.
zenmonkeykstop 057d18f
Readability fixes based on PR review.
zenmonkeykstop 183afe8
Simplified InstanceConfig constructor as per PR review
zenmonkeykstop dd79d8f
removed unnecessary journalist_app and config fixtures in store tests…
zenmonkeykstop 39eb634
removed superfluous source_app fixture from test as per PR review
zenmonkeykstop File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,7 @@ app_ip: 10.0.1.2 | |
|
||
pip_deps: | ||
- name: 'Flask' | ||
version: '1.0.2' | ||
version: '2.0.2' | ||
|
||
apparmor_complain: [] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,7 @@ app_ip: 10.20.2.2 | |
|
||
pip_deps: | ||
- name: 'Flask' | ||
version: '1.0.2' | ||
version: '2.0.2' | ||
|
||
apparmor_complain: [] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ app_ip: 10.0.1.4 | |
|
||
pip_deps: | ||
- name: 'Flask' | ||
version: '1.0.2' | ||
version: '2.0.2' | ||
|
||
apparmor_complain: [] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ app_ip: 10.0.1.2 | |
|
||
pip_deps: | ||
- name: 'Flask' | ||
version: '1.0.2' | ||
version: '2.0.2' | ||
|
||
apparmor_complain: [] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from datetime import datetime, timedelta | ||
from datetime import datetime, timedelta, timezone | ||
from pathlib import Path | ||
|
||
from flask import (Flask, session, redirect, url_for, flash, g, request, | ||
|
@@ -21,7 +21,6 @@ | |
JournalistInterfaceSessionInterface, | ||
cleanup_expired_revoked_tokens) | ||
from models import InstanceConfig, Journalist | ||
from store import Storage | ||
|
||
import typing | ||
# https://www.python.org/dev/peps/pep-0484/#runtime-or-type-checking | ||
|
@@ -69,11 +68,9 @@ def create_app(config: 'SDConfig') -> Flask: | |
app.config['SQLALCHEMY_DATABASE_URI'] = config.DATABASE_URI | ||
db.init_app(app) | ||
|
||
# TODO: Attaching a Storage dynamically like this disables all type checking (and | ||
# breaks code analysis tools) for code that uses current_app.storage; it should be refactored | ||
app.storage = Storage(config.STORE_DIR, config.TEMP_DIR) | ||
|
||
@app.errorhandler(CSRFError) | ||
# TODO: enable type checking once upstream Flask fix is available. See: | ||
# https://github.com/pallets/flask/issues/4295 | ||
@app.errorhandler(CSRFError) # type: ignore | ||
def handle_csrf_error(e: CSRFError) -> 'Response': | ||
app.logger.error("The CSRF token is invalid.") | ||
session.clear() | ||
|
@@ -86,9 +83,12 @@ def _handle_http_exception( | |
) -> 'Tuple[Union[Response, str], Optional[int]]': | ||
# Workaround for no blueprint-level 404/5 error handlers, see: | ||
# https://github.com/pallets/flask/issues/503#issuecomment-71383286 | ||
# TODO: clean up API error handling such that all except 404/5s are | ||
# registered in the blueprint and 404/5s are handled at the application | ||
# level. | ||
handler = list(app.error_handler_spec['api'][error.code].values())[0] | ||
if request.path.startswith('/api/') and handler: | ||
return handler(error) | ||
return handler(error) # type: ignore | ||
|
||
return render_template('error.html', error=error), error.code | ||
|
||
|
@@ -111,13 +111,13 @@ def expire_blacklisted_tokens() -> None: | |
cleanup_expired_revoked_tokens() | ||
|
||
@app.before_request | ||
def load_instance_config() -> None: | ||
app.instance_config = InstanceConfig.get_current() | ||
def update_instance_config() -> None: | ||
InstanceConfig.get_default(refresh=True) | ||
|
||
@app.before_request | ||
def setup_g() -> 'Optional[Response]': | ||
"""Store commonly used values in Flask's special g object""" | ||
if 'expires' in session and datetime.utcnow() >= session['expires']: | ||
if 'expires' in session and datetime.now(timezone.utc) >= session['expires']: | ||
session.clear() | ||
flash(gettext('You have been logged out due to inactivity.'), | ||
'error') | ||
|
@@ -131,24 +131,25 @@ def setup_g() -> 'Optional[Response]': | |
flash(gettext('You have been logged out due to password change'), | ||
'error') | ||
|
||
session['expires'] = datetime.utcnow() + \ | ||
session['expires'] = datetime.now(timezone.utc) + \ | ||
timedelta(minutes=getattr(config, | ||
'SESSION_EXPIRATION_MINUTES', | ||
120)) | ||
|
||
uid = session.get('uid', None) | ||
if uid: | ||
g.user = Journalist.query.get(uid) | ||
g.user = Journalist.query.get(uid) # pylint: disable=assigning-non-slot | ||
|
||
i18n.set_locale(config) | ||
|
||
if app.instance_config.organization_name: | ||
g.organization_name = app.instance_config.organization_name | ||
if InstanceConfig.get_default().organization_name: | ||
g.organization_name = \ | ||
InstanceConfig.get_default().organization_name # pylint: disable=assigning-non-slot | ||
else: | ||
g.organization_name = gettext('SecureDrop') | ||
g.organization_name = gettext('SecureDrop') # pylint: disable=assigning-non-slot | ||
Comment on lines
-145
to
+149
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit in passing: I wondered if this could be simplified, since |
||
|
||
try: | ||
g.logo = get_logo_url(app) | ||
g.logo = get_logo_url(app) # pylint: disable=assigning-non-slot | ||
except FileNotFoundError: | ||
app.logger.error("Site logo not found.") | ||
|
||
|
@@ -161,8 +162,8 @@ def setup_g() -> 'Optional[Response]': | |
if request.method == 'POST': | ||
filesystem_id = request.form.get('filesystem_id') | ||
if filesystem_id: | ||
g.filesystem_id = filesystem_id | ||
g.source = get_source(filesystem_id) | ||
g.filesystem_id = filesystem_id # pylint: disable=assigning-non-slot | ||
g.source = get_source(filesystem_id) # pylint: disable=assigning-non-slot | ||
|
||
return None | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm understanding this correctly, this is a behavior shift now in that InstanceConfig is just initialized once at startup rather than on each request. Is that intentional? I haven't figured out how that works with the "valid_until" field yet...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the instance config is now retrieved every time InstanceConfig.get_default() is called, so it's actually hitting the DB as much as before (or potentially more often if a single request has multiple .get_default()s) This reduces the benefit of a global object, so there's probably some opportunity for optimization there. The trick would be to detect configuration changes when they're made in the journalist interface, as we want those to be reflected immediately in the source app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the InstanceConfig get_default() method to be lazier - it will now only hit the db if explicitly requested or if the global is
None
. With some tweaks to@app.before_request
-decorate functions, changes should show up immediately in both apps without extra DB overhead.Also, re
valid_until
- it might be a bit counter-intuitive. It records the historical info about previous configs, and when they were invalidated. (TBH I'm not sure we need to store said previous configs, but it does provide an audit trail for instance_config changes.)