def init(app): app.jinja_env.filters['elapsed_time'] = time_difference_UTC app.jinja_env.filters['datetime_string'] = get_datetime_string app.jinja_env.filters['beautify_platform'] = beautify_platform app.jinja_env.filters['none2blank'] = convert_none_to_blank # The nl2br filter uses the Jinja environment's context to determine # whether to autoescape app.jinja_env.filters['nl2br'] = evalcontextfilter(nl2br) app.jinja_env.filters['comma2br'] = evalcontextfilter(comma2br)
def init(app): app.jinja_env.filters["elapsed_time"] = time_difference_UTC app.jinja_env.filters["datetime_string"] = get_datetime_string app.jinja_env.filters["beautify_platform"] = beautify_platform app.jinja_env.filters["none2blank"] = convert_none_to_blank # The nl2br filter uses the Jinja environment's context to determine # whether to autoescape app.jinja_env.filters["nl2br"] = evalcontextfilter(nl2br) app.jinja_env.filters["comma2br"] = evalcontextfilter(comma2br)
def init(app): app.jinja_env.filters['elapsed_time'] = time_difference_UTC app.jinja_env.filters['datetime_string'] = get_datetime_string app.jinja_env.filters['beautify_platform'] = beautify_platform app.jinja_env.filters['none2blank'] = convert_none_to_blank app.jinja_env.filters['match_string'] = match_string # The nl2br filter uses the Jinja environment's context to determine # whether to autoescape app.jinja_env.filters['nl2br'] = evalcontextfilter(nl2br) app.jinja_env.filters['comma2br'] = evalcontextfilter(comma2br)
def init_app(app): app.jinja_env.filters['date'] = do_date app.jinja_env.filters['datetime'] = do_datetime app.jinja_env.filters['duration'] = do_duration # The nl2br filter uses the Jinja environment's context to determine # whether to autoescape app.jinja_env.filters['nl2br'] = evalcontextfilter(do_nl2br)
def init_app(app): """Initialize a Flask application with custom filters.""" app.jinja_env.filters['date'] = do_date app.jinja_env.filters['datetime'] = do_datetime app.jinja_env.filters['duration'] = do_duration # The nl2br filter uses the Jinja environment's context to determine # whether to autoescape app.jinja_env.filters['nl2br'] = evalcontextfilter(do_nl2br)
def init_app(app): """Initialize a Flask application with filters defined in this module.""" app.jinja_env.filters['date'] = do_date app.jinja_env.filters['datetime'] = do_datetime app.jinja_env.filters['duration'] = do_duration # The nl2br filter uses the Jinja environment's context to determine # whether to autoescape app.jinja_env.filters['nl2br'] = evalcontextfilter(do_nl2br)
# The default CSRF token expiration is 1 hour. Since large uploads can # take longer than an hour over Tor, we increase the valid window to 24h. app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24 CSRFProtect(app) app.jinja_env.globals['version'] = version.__version__ if getattr(config, 'CUSTOM_HEADER_IMAGE', None): app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE app.jinja_env.globals['use_custom_header_image'] = True else: app.jinja_env.globals['header_image'] = 'logo.png' app.jinja_env.globals['use_custom_header_image'] = False app.jinja_env.filters['datetimeformat'] = template_filters.datetimeformat app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br) @app.teardown_appcontext def shutdown_session(exception=None): """Automatically remove database sessions at the end of the request, or when the application shuts down""" db_session.remove() def logged_in(): return 'logged_in' in session def login_required(f): @wraps(f)
def create_app(config): # type: (SDConfig) -> Flask app = Flask(__name__, template_folder=config.SOURCE_TEMPLATES_DIR, static_folder=path.join(config.SECUREDROP_ROOT, 'static')) app.request_class = RequestThatSecuresFileUploads app.config.from_object(config.SourceInterfaceFlaskConfig) # type: ignore app.sdconfig = config # The default CSRF token expiration is 1 hour. Since large uploads can # take longer than an hour over Tor, we increase the valid window to 24h. app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24 CSRFProtect(app) if config.DATABASE_ENGINE == "sqlite": db_uri = (config.DATABASE_ENGINE + ":///" + config.DATABASE_FILE) else: db_uri = (config.DATABASE_ENGINE + '://' + config.DATABASE_USERNAME + ':' + config.DATABASE_PASSWORD + '@' + config.DATABASE_HOST + '/' + config.DATABASE_NAME) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_DATABASE_URI'] = db_uri db.init_app(app) app.storage = Storage(config.STORE_DIR, config.TEMP_DIR, config.JOURNALIST_KEY) app.crypto_util = CryptoUtil( scrypt_params=config.SCRYPT_PARAMS, scrypt_id_pepper=config.SCRYPT_ID_PEPPER, scrypt_gpg_pepper=config.SCRYPT_GPG_PEPPER, securedrop_root=config.SECUREDROP_ROOT, word_list=config.WORD_LIST, nouns_file=config.NOUNS, adjectives_file=config.ADJECTIVES, gpg_key_dir=config.GPG_KEY_DIR, ) @app.errorhandler(CSRFError) def handle_csrf_error(e): msg = render_template('session_timeout.html') session.clear() flash(Markup(msg), "important") return redirect(url_for('main.index')) assets = Environment(app) app.config['assets'] = assets i18n.setup_app(config, app) app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True app.jinja_env.globals['version'] = version.__version__ if getattr(config, 'CUSTOM_HEADER_IMAGE', None): app.jinja_env.globals['header_image'] = \ config.CUSTOM_HEADER_IMAGE # type: ignore app.jinja_env.globals['use_custom_header_image'] = True else: app.jinja_env.globals['header_image'] = 'logo.png' app.jinja_env.globals['use_custom_header_image'] = False app.jinja_env.filters['rel_datetime_format'] = \ template_filters.rel_datetime_format app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br) app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat for module in [main, info, api]: app.register_blueprint(module.make_blueprint(config)) # type: ignore @app.before_request @ignore_static def setup_i18n(): """Store i18n-related values in Flask's special g object""" g.locale = i18n.get_locale(config) g.text_direction = i18n.get_text_direction(g.locale) g.html_lang = i18n.locale_to_rfc_5646(g.locale) g.locales = i18n.get_locale2name() @app.before_request @ignore_static def check_tor2web(): # ignore_static here so we only flash a single message warning # about Tor2Web, corresponding to the initial page load. if 'X-tor2web' in request.headers: flash( Markup( gettext( '<strong>WARNING: </strong> ' 'You appear to be using Tor2Web. ' 'This <strong> does not </strong> ' 'provide anonymity. ' '<a href="{url}">Why is this dangerous?</a>').format( url=url_for('info.tor2web_warning'))), "banner-warning") @app.before_request @ignore_static def load_instance_config(): app.instance_config = InstanceConfig.get_current() @app.before_request @ignore_static def setup_g(): """Store commonly used values in Flask's special g object""" if 'expires' in session and datetime.utcnow() >= session['expires']: msg = render_template('session_timeout.html') # 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, 'SESSION_EXPIRATION_MINUTES', 120)) # ignore_static here because `crypto_util.hash_codename` is scrypt # (very time consuming), and we don't need to waste time running if # we're just serving a static resource that won't need to access # these common values. if logged_in(): g.codename = session['codename'] g.filesystem_id = app.crypto_util.hash_codename(g.codename) try: g.source = Source.query \ .filter(Source.filesystem_id == g.filesystem_id) \ .one() except NoResultFound as e: app.logger.error("Found no Sources when one was expected: %s" % (e, )) del session['logged_in'] del session['codename'] return redirect(url_for('main.index')) g.loc = app.storage.path(g.filesystem_id) @app.errorhandler(404) def page_not_found(error): return render_template('notfound.html'), 404 @app.errorhandler(500) def internal_error(error): return render_template('error.html'), 500 return app
def init_app(app): app.jinja_env.filters['date'] = do_date app.jinja_env.filters['datetime'] = do_datetime app.jinja_env.filters['duration'] = do_duration app.jinja_env.filters['nl2br'] = evalcontextfilter(do_nl2br)
def create_app(config): app = Flask(__name__, template_folder=config.SOURCE_TEMPLATES_DIR, static_folder=path.join(config.SECUREDROP_ROOT, 'static')) app.request_class = RequestThatSecuresFileUploads app.config.from_object(config.SourceInterfaceFlaskConfig) # The default CSRF token expiration is 1 hour. Since large uploads can # take longer than an hour over Tor, we increase the valid window to 24h. app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24 CSRFProtect(app) @app.errorhandler(CSRFError) def handle_csrf_error(e): msg = render_template('session_timeout.html') session.clear() flash(Markup(msg), "important") return redirect(url_for('main.index')) assets = Environment(app) app.config['assets'] = assets i18n.setup_app(config, app) app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True app.jinja_env.globals['version'] = version.__version__ if getattr(config, 'CUSTOM_HEADER_IMAGE', None): app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE app.jinja_env.globals['use_custom_header_image'] = True else: app.jinja_env.globals['header_image'] = 'logo.png' app.jinja_env.globals['use_custom_header_image'] = False app.jinja_env.filters['rel_datetime_format'] = \ template_filters.rel_datetime_format app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br) app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat for module in [main, info, api]: app.register_blueprint(module.make_blueprint(config)) @app.before_request @ignore_static def check_tor2web(): # ignore_static here so we only flash a single message warning # about Tor2Web, corresponding to the initial page load. if 'X-tor2web' in request.headers: flash( Markup( gettext( '<strong>WARNING: </strong> ' 'You appear to be using Tor2Web. ' 'This <strong> does not </strong> ' 'provide anonymity. ' '<a href="{url}">Why is this dangerous?</a>').format( url=url_for('info.tor2web_warning'))), "banner-warning") @app.before_request @ignore_static def setup_g(): """Store commonly used values in Flask's special g object""" g.locale = i18n.get_locale(config) g.text_direction = i18n.get_text_direction(g.locale) g.html_lang = i18n.locale_to_rfc_5646(g.locale) g.locales = i18n.get_locale2name() if 'expires' in session and datetime.utcnow() >= session['expires']: msg = render_template('session_timeout.html') # clear the session after we render the message so it's localized session.clear() flash(Markup(msg), "important") session['expires'] = datetime.utcnow() + \ timedelta(minutes=getattr(config, 'SESSION_EXPIRATION_MINUTES', 120)) # ignore_static here because `crypto_util.hash_codename` is scrypt # (very time consuming), and we don't need to waste time running if # we're just serving a static resource that won't need to access # these common values. if logged_in(): g.codename = session['codename'] g.filesystem_id = crypto_util.hash_codename(g.codename) try: g.source = Source.query \ .filter(Source.filesystem_id == g.filesystem_id) \ .one() except NoResultFound as e: app.logger.error("Found no Sources when one was expected: %s" % (e, )) del session['logged_in'] del session['codename'] return redirect(url_for('main.index')) g.loc = store.path(g.filesystem_id) @app.teardown_appcontext def shutdown_session(exception=None): """Automatically remove database sessions at the end of the request, or when the application shuts down""" db_session.remove() @app.errorhandler(404) def page_not_found(error): return render_template('notfound.html'), 404 @app.errorhandler(500) def internal_error(error): return render_template('error.html'), 500 return app
def create_app(config: SDConfig) -> Flask: app = Flask(__name__, template_folder=config.SOURCE_TEMPLATES_DIR, static_folder=path.join(config.SECUREDROP_ROOT, 'static')) app.request_class = RequestThatSecuresFileUploads app.config.from_object(config.SOURCE_APP_FLASK_CONFIG_CLS) # The default CSRF token expiration is 1 hour. Since large uploads can # take longer than an hour over Tor, we increase the valid window to 24h. app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24 CSRFProtect(app) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 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, config.JOURNALIST_KEY) # TODO: Attaching a CryptoUtil dynamically like this disables all type checking (and # breaks code analysis tools) for code that uses current_app.storage; it should be refactored app.crypto_util = CryptoUtil( scrypt_params=config.SCRYPT_PARAMS, scrypt_id_pepper=config.SCRYPT_ID_PEPPER, scrypt_gpg_pepper=config.SCRYPT_GPG_PEPPER, securedrop_root=config.SECUREDROP_ROOT, word_list=config.WORD_LIST, nouns_file=config.NOUNS, adjectives_file=config.ADJECTIVES, gpg_key_dir=config.GPG_KEY_DIR, ) @app.errorhandler(CSRFError) def handle_csrf_error(e: CSRFError) -> werkzeug.Response: msg = render_template('session_timeout.html') session.clear() flash(Markup(msg), "important") return redirect(url_for('main.index')) assets = Environment(app) app.config['assets'] = assets i18n.setup_app(config, app) app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True app.jinja_env.globals['version'] = version.__version__ # Exported to source templates for being included in instructions app.jinja_env.globals['submission_key_fpr'] = config.JOURNALIST_KEY app.jinja_env.filters['rel_datetime_format'] = \ template_filters.rel_datetime_format app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br) app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat for module in [main, info, api]: app.register_blueprint(module.make_blueprint(config)) # type: ignore @app.before_request @ignore_static def setup_i18n() -> None: """Store i18n-related values in Flask's special g object""" g.locale = i18n.get_locale(config) g.text_direction = i18n.get_text_direction(g.locale) g.html_lang = i18n.locale_to_rfc_5646(g.locale) g.locales = i18n.get_locale2name() @app.before_request @ignore_static def check_tor2web() -> None: # ignore_static here so we only flash a single message warning # about Tor2Web, corresponding to the initial page load. if 'X-tor2web' in request.headers: flash(Markup(gettext( '<strong>WARNING: </strong> ' 'You appear to be using Tor2Web. ' 'This <strong> does not </strong> ' 'provide anonymity. ' '<a href="{url}">Why is this dangerous?</a>') .format(url=url_for('info.tor2web_warning'))), "banner-warning") @app.before_request @ignore_static def load_instance_config() -> None: app.instance_config = InstanceConfig.get_current() @app.before_request @ignore_static def setup_g() -> Optional[werkzeug.Response]: """Store commonly used values in Flask's special g object""" if 'expires' in session and datetime.utcnow() >= session['expires']: msg = render_template('session_timeout.html') # Show expiration message only if the user was # either in the codename generation flow or logged in show_expiration_message = any([ session.get('show_expiration_message'), logged_in(), was_in_generate_flow(), ]) # clear the session after we render the message so it's localized session.clear() # Persist this properety across sessions to distinguish users whose sessions expired # from users who never logged in or generated a codename session['show_expiration_message'] = show_expiration_message # Redirect to index with flashed message if session['show_expiration_message']: flash(Markup(msg), "important") return redirect(url_for('main.index')) session['expires'] = datetime.utcnow() + \ timedelta(minutes=getattr(config, 'SESSION_EXPIRATION_MINUTES', 120)) # ignore_static here because `crypto_util.hash_codename` is scrypt # (very time consuming), and we don't need to waste time running if # we're just serving a static resource that won't need to access # these common values. if logged_in(): g.codename = session['codename'] g.filesystem_id = app.crypto_util.hash_codename(g.codename) try: g.source = Source.query \ .filter(Source.filesystem_id == g.filesystem_id) \ .filter_by(deleted_at=None) \ .one() except NoResultFound as e: app.logger.error( "Found no Sources when one was expected: %s" % (e,)) del session['logged_in'] del session['codename'] return redirect(url_for('main.index')) g.loc = app.storage.path(g.filesystem_id) return None @app.errorhandler(404) def page_not_found(error: werkzeug.exceptions.HTTPException) -> Tuple[str, int]: return render_template('notfound.html'), 404 @app.errorhandler(500) def internal_error(error: werkzeug.exceptions.HTTPException) -> Tuple[str, int]: return render_template('error.html'), 500 return app
def create_app(config): app = Flask(__name__, template_folder=config.SOURCE_TEMPLATES_DIR, static_folder=path.join(config.SECUREDROP_ROOT, 'static')) app.request_class = RequestThatSecuresFileUploads app.config.from_object(config.SourceInterfaceFlaskConfig) # The default CSRF token expiration is 1 hour. Since large uploads can # take longer than an hour over Tor, we increase the valid window to 24h. app.config['WTF_CSRF_TIME_LIMIT'] = 60 * 60 * 24 CSRFProtect(app) @app.errorhandler(CSRFError) def handle_csrf_error(e): msg = render_template('session_timeout.html') session.clear() flash(Markup(msg), "important") return redirect(url_for('main.index')) assets = Environment(app) app.config['assets'] = assets i18n.setup_app(config, app) app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True app.jinja_env.globals['version'] = version.__version__ if getattr(config, 'CUSTOM_HEADER_IMAGE', None): app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE app.jinja_env.globals['use_custom_header_image'] = True else: app.jinja_env.globals['header_image'] = 'logo.png' app.jinja_env.globals['use_custom_header_image'] = False app.jinja_env.filters['rel_datetime_format'] = \ template_filters.rel_datetime_format app.jinja_env.filters['nl2br'] = evalcontextfilter(template_filters.nl2br) app.jinja_env.filters['filesizeformat'] = template_filters.filesizeformat for module in [main, info, api]: app.register_blueprint(module.make_blueprint(config)) @app.before_request @ignore_static def check_tor2web(): # ignore_static here so we only flash a single message warning # about Tor2Web, corresponding to the initial page load. if 'X-tor2web' in request.headers: flash(Markup(gettext( '<strong>WARNING: </strong> ' 'You appear to be using Tor2Web. ' 'This <strong> does not </strong> ' 'provide anonymity. ' '<a href="{url}">Why is this dangerous?</a>') .format(url=url_for('info.tor2web_warning'))), "banner-warning") @app.before_request @ignore_static def setup_g(): """Store commonly used values in Flask's special g object""" g.locale = i18n.get_locale(config) g.text_direction = i18n.get_text_direction(g.locale) g.html_lang = i18n.locale_to_rfc_5646(g.locale) g.locales = i18n.get_locale2name() if 'expires' in session and datetime.utcnow() >= session['expires']: msg = render_template('session_timeout.html') # clear the session after we render the message so it's localized session.clear() flash(Markup(msg), "important") session['expires'] = datetime.utcnow() + \ timedelta(minutes=getattr(config, 'SESSION_EXPIRATION_MINUTES', 120)) # ignore_static here because `crypto_util.hash_codename` is scrypt # (very time consuming), and we don't need to waste time running if # we're just serving a static resource that won't need to access # these common values. if logged_in(): g.codename = session['codename'] g.filesystem_id = crypto_util.hash_codename(g.codename) try: g.source = Source.query \ .filter(Source.filesystem_id == g.filesystem_id) \ .one() except NoResultFound as e: app.logger.error( "Found no Sources when one was expected: %s" % (e,)) del session['logged_in'] del session['codename'] return redirect(url_for('main.index')) g.loc = store.path(g.filesystem_id) @app.teardown_appcontext def shutdown_session(exception=None): """Automatically remove database sessions at the end of the request, or when the application shuts down""" db_session.remove() @app.errorhandler(404) def page_not_found(error): return render_template('notfound.html'), 404 @app.errorhandler(500) def internal_error(error): return render_template('error.html'), 500 return app