def test_invalid_locales(config): """ An invalid locale raises an error during app configuration. """ fake_config = SDConfig() fake_config.SUPPORTED_LOCALES = [FALLBACK_LOCALE, "yy_ZZ"] fake_config.TRANSLATION_DIRS = Path(config.TEMP_DIR) with pytest.raises(UnknownLocaleError): journalist_app_module.create_app(fake_config) with pytest.raises(UnknownLocaleError): source_app.create_app(fake_config)
def test_schema_unchanged_after_up_then_downgrade(alembic_config, config, migration): # Create the app here. Using a fixture will init the database. app = create_app(config) migrations = list_migrations(alembic_config, migration) if len(migrations) > 1: target = migrations[-2] upgrade(alembic_config, target) else: # The first migration is the degenerate case where we don't need to # get the database to some base state. pass original_schema = get_schema(app) upgrade(alembic_config, '+1') downgrade(alembic_config, '-1') reverted_schema = get_schema(app) # The initial migration is a degenerate case because it creates the table # 'alembic_version', but rolling back the migration doesn't clear it. if len(migrations) == 1: reverted_schema = {k: v for k, v in list(reverted_schema.items()) if k[2] != 'alembic_version'} assert_schemas_equal(reverted_schema, original_schema)
def test_html_attributes(journalist_app, config): """Check that HTML lang and dir attributes respect locale.""" # Then delete it because using it won't test what we want del journalist_app config.SUPPORTED_LOCALES = ["ar", "en_US"] app = journalist_app_module.create_app(config).test_client() resp = app.get("/?l=ar", follow_redirects=True) html = resp.data.decode("utf-8") assert '<html lang="ar" dir="rtl">' in html resp = app.get("/?l=en_US", follow_redirects=True) html = resp.data.decode("utf-8") assert '<html lang="en-US" dir="ltr">' in html app = source_app.create_app(config).test_client() resp = app.get("/?l=ar", follow_redirects=True) html = resp.data.decode("utf-8") assert '<html lang="ar" dir="rtl">' in html resp = app.get("/?l=en_US", follow_redirects=True) html = resp.data.decode("utf-8") assert '<html lang="en-US" dir="ltr">' in html # check '/generate' too because '/' uses a different template resp = app.post("/generate?l=ar", data={"tor2web_check": 'href="fake.onion"'}, follow_redirects=True) html = resp.data.decode("utf-8") assert '<html lang="ar" dir="rtl">' in html resp = app.post("/generate?l=en_US", data={"tor2web_check": 'href="fake.onion"'}, follow_redirects=True) html = resp.data.decode("utf-8") assert '<html lang="en-US" dir="ltr">' in html
def test_no_usable_fallback_locale(journalist_app, config): """ The apps fail if neither the default nor the fallback locale is usable. """ fake_config = SDConfig() fake_config.DEFAULT_LOCALE = NEVER_LOCALE fake_config.SUPPORTED_LOCALES = [NEVER_LOCALE] fake_config.TRANSLATION_DIRS = Path(config.TEMP_DIR) i18n.USABLE_LOCALES = set() with pytest.raises(ValueError, match="in the set of usable locales"): journalist_app_module.create_app(fake_config) with pytest.raises(ValueError, match="in the set of usable locales"): source_app.create_app(fake_config)
def test_filters(self): sources = [ 'tests/i18n/code.py', ] kwargs = { 'translations_dir': config.TEMP_DIR, 'mapping': 'tests/i18n/babel.cfg', 'source': sources, 'extract_update': True, 'compile': True, 'verbose': logging.DEBUG, 'version': version.__version__, } args = argparse.Namespace(**kwargs) manage.setup_verbosity(args) manage.translate_messages(args) manage.sh(""" pybabel init -i {d}/messages.pot -d {d} -l en_US pybabel init -i {d}/messages.pot -d {d} -l fr_FR """.format(d=config.TEMP_DIR)) fake_config = self.get_fake_config() fake_config.SUPPORTED_LOCALES = ['en_US', 'fr_FR'] fake_config.TRANSLATION_DIRS = config.TEMP_DIR for app in (journalist_app.create_app(fake_config), source_app.create_app(fake_config)): assert i18n.LOCALES == fake_config.SUPPORTED_LOCALES self.verify_filesizeformat(app) self.verify_rel_datetime_format(app)
def test_filters(self): sources = [ 'tests/i18n/code.py', ] kwargs = { 'translations_dir': config.TEMP_DIR, 'mapping': 'tests/i18n/babel.cfg', 'source': sources, 'extract_update': True, 'compile': True, 'verbose': logging.DEBUG, 'version': version.__version__, } args = argparse.Namespace(**kwargs) manage.setup_verbosity(args) manage.translate_messages(args) manage.sh(""" pybabel init -i {d}/messages.pot -d {d} -l en_US pybabel init -i {d}/messages.pot -d {d} -l fr_FR """.format(d=config.TEMP_DIR)) fake_config = self.get_fake_config() fake_config.SUPPORTED_LOCALES = ['en_US', 'fr_FR'] fake_config.TRANSLATION_DIRS = config.TEMP_DIR for app in (journalist_app.create_app(fake_config), source_app.create_app(fake_config)): assert i18n.LOCALES == fake_config.SUPPORTED_LOCALES self.verify_filesizeformat(app) self.verify_rel_datetime_format(app)
def test_alembic_head_matches_db_models(journalist_app, alembic_config, config): """This test is to make sure that our database models in `models.py` are always in sync with the schema generated by `alembic upgrade head`. """ models_schema = get_schema(journalist_app) os.remove(config.DATABASE_FILE) # Create database file subprocess.check_call(["sqlite3", config.DATABASE_FILE, ".databases"]) upgrade(alembic_config, "head") # Recreate the app to get a new SQLALCHEMY_DATABASE_URI app = create_app(config) alembic_schema = get_schema(app) # The initial migration creates the table 'alembic_version', but this is # not present in the schema created by `db.create_all()`. alembic_schema = { k: v for k, v in list(alembic_schema.items()) if k[2] != "alembic_version" } assert_schemas_equal(alembic_schema, models_schema)
def __init__(self, config): """This function MUST accept an argument named `config`. You will likely want to save a reference to the config in your class, so you can access the database later. """ self.config = config self.app = create_app(config)
def __init__( self, config: SDConfig, journalist_count: int = 10, source_count: int = 50, submissions_per_source: int = 1, replies_per_source: int = 1, source_star_fraction: float = 0.1, source_reply_fraction: float = 0.5, ) -> None: """ source_star_fraction and source_reply_fraction are simply the fraction of sources starred or replied to. """ self.config = config self.app = create_app(config) self.journalist_count = journalist_count self.source_count = source_count self.submissions_per_source = submissions_per_source self.replies_per_source = replies_per_source self.source_star_fraction = source_star_fraction self.source_reply_fraction = source_reply_fraction self.journalists = [] # type: List[int] self.sources = [] # type: List[int]
def upgrade() -> None: with op.batch_alter_table("replies", schema=None) as batch_op: batch_op.add_column( sa.Column("checksum", sa.String(length=255), nullable=True)) with op.batch_alter_table("submissions", schema=None) as batch_op: batch_op.add_column( sa.Column("checksum", sa.String(length=255), nullable=True)) op.create_table( "revoked_tokens", sa.Column("id", sa.Integer(), nullable=False), sa.Column("journalist_id", sa.Integer(), nullable=True), sa.Column("token", sa.Text(), nullable=False), sa.ForeignKeyConstraint(["journalist_id"], ["journalists.id"]), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("token"), ) try: app = create_app(config) # we need an app context for the rq worker extension to work properly with app.app_context(): conn = op.get_bind() query = sa.text( """SELECT submissions.id, sources.filesystem_id, submissions.filename FROM submissions INNER JOIN sources ON submissions.source_id = sources.id """) for (sub_id, filesystem_id, filename) in conn.execute(query): full_path = Storage.get_default().path(filesystem_id, filename) create_queue().enqueue( queued_add_checksum_for_file, Submission, int(sub_id), full_path, app.config["SQLALCHEMY_DATABASE_URI"], ) query = sa.text( """SELECT replies.id, sources.filesystem_id, replies.filename FROM replies INNER JOIN sources ON replies.source_id = sources.id """) for (rep_id, filesystem_id, filename) in conn.execute(query): full_path = Storage.get_default().path(filesystem_id, filename) create_queue().enqueue( queued_add_checksum_for_file, Reply, int(rep_id), full_path, app.config["SQLALCHEMY_DATABASE_URI"], ) except: # noqa if raise_errors: raise
def __init__(self, config): Helper.__init__(self) self.config = config self.app = create_app(config) # as this class requires access to the Storage object, which is no longer # attached to app, we create it here and mock the call to return it below. self.storage = Storage(config.STORE_DIR, config.TEMP_DIR)
def __init__(self, config, multiplier): self.config = config self.app = create_app(config) self.multiplier = multiplier self.journalists = [] self.sources = [] self.submissions = []
def test_i18n(journalist_app, config): # Then delete it because using it won't test what we want del journalist_app sources = [ os.path.join(TESTS_DIR, "i18n/code.py"), os.path.join(TESTS_DIR, "i18n/template.html"), ] i18n_tool.I18NTool().main([ "--verbose", "translate-messages", "--mapping", os.path.join(TESTS_DIR, "i18n/babel.cfg"), "--translations-dir", config.TEMP_DIR, "--sources", ",".join(sources), "--extract-update", ]) pot = os.path.join(config.TEMP_DIR, "messages.pot") pybabel("init", "-i", pot, "-d", config.TEMP_DIR, "-l", "en_US") for (l, s) in ( ("fr_FR", "code bonjour"), ("zh_Hans", "code chinese"), ("ar", "code arabic"), ("nb_NO", "code norwegian"), ("es_ES", "code spanish"), ): pybabel("init", "-i", pot, "-d", config.TEMP_DIR, "-l", l) po = os.path.join(config.TEMP_DIR, l, "LC_MESSAGES/messages.po") sed("-i", "-e", '/code hello i18n/,+1s/msgstr ""/msgstr "{}"/'.format(s), po) i18n_tool.I18NTool().main([ "--verbose", "translate-messages", "--translations-dir", config.TEMP_DIR, "--compile", ]) fake_config = SDConfig() fake_config.SUPPORTED_LOCALES = [ "ar", "en_US", "fr_FR", "nb_NO", "zh_Hans" ] fake_config.TRANSLATION_DIRS = Path(config.TEMP_DIR) # Use our config (and not an app fixture) because the i18n module # grabs values at init time and we can't inject them later. for app in (journalist_app_module.create_app(fake_config), source_app.create_app(fake_config)): with app.app_context(): db.create_all() assert list(i18n.LOCALES.keys()) == fake_config.SUPPORTED_LOCALES verify_i18n(app)
def upgrade(): conn = op.get_bind() submissions = conn.execute( sa.text(raw_sql_grab_orphaned_objects('submissions'))).fetchall() replies = conn.execute(sa.text( raw_sql_grab_orphaned_objects('replies'))).fetchall() try: app = create_app(config) with app.app_context(): for submission in submissions: try: conn.execute( sa.text(""" DELETE FROM submissions WHERE id=:id """).bindparams(id=submission.id)) path = app.storage.path_without_filesystem_id( submission.filename) app.storage.move_to_shredder(path) except NoFileFoundException: # The file must have been deleted by the admin, remove the row conn.execute( sa.text(""" DELETE FROM submissions WHERE id=:id """).bindparams(id=submission.id)) except TooManyFilesException: pass for reply in replies: try: conn.execute( sa.text(""" DELETE FROM replies WHERE id=:id """).bindparams(id=reply.id)) path = app.storage.path_without_filesystem_id( reply.filename) app.storage.move_to_shredder(path) except NoFileFoundException: # The file must have been deleted by the admin, remove the row conn.execute( sa.text(""" DELETE FROM replies WHERE id=:id """).bindparams(id=reply.id)) except TooManyFilesException: pass except: # noqa if raise_errors: raise
def test_i18n(journalist_app, config): # Then delete it because using it won't test what we want del journalist_app sources = [ os.path.join(TESTS_DIR, 'i18n/code.py'), os.path.join(TESTS_DIR, 'i18n/template.html'), ] i18n_tool.I18NTool().main([ '--verbose', 'translate-messages', '--mapping', os.path.join(TESTS_DIR, 'i18n/babel.cfg'), '--translations-dir', config.TEMP_DIR, '--sources', ",".join(sources), '--extract-update', ]) pot = os.path.join(config.TEMP_DIR, 'messages.pot') pybabel('init', '-i', pot, '-d', config.TEMP_DIR, '-l', 'en_US') for (l, s) in (('fr_FR', 'code bonjour'), ('zh_Hans_CN', 'code chinese'), ('ar', 'code arabic'), ('nb_NO', 'code norwegian'), ('es_ES', 'code spanish')): pybabel('init', '-i', pot, '-d', config.TEMP_DIR, '-l', l) po = os.path.join(config.TEMP_DIR, l, 'LC_MESSAGES/messages.po') sed('-i', '-e', '/code hello i18n/,+1s/msgstr ""/msgstr "{}"/'.format(s), po) i18n_tool.I18NTool().main([ '--verbose', 'translate-messages', '--translations-dir', config.TEMP_DIR, '--compile', ]) fake_config = SDConfig() fake_config.SUPPORTED_LOCALES = [ 'en_US', 'fr_FR', 'zh_Hans_CN', 'ar', 'nb_NO' ] fake_config.TRANSLATION_DIRS = config.TEMP_DIR # Use our config (and not an app fixture) because the i18n module # grabs values at init time and we can't inject them later. for app in (journalist_app_module.create_app(fake_config), source_app.create_app(fake_config)): with app.app_context(): db.create_all() assert i18n.LOCALES == fake_config.SUPPORTED_LOCALES verify_i18n(app)
def test_i18n(self): sources = [ 'tests/i18n/code.py', 'tests/i18n/template.html', ] kwargs = { 'translations_dir': config.TEMP_DIR, 'mapping': 'tests/i18n/babel.cfg', 'source': sources, 'extract_update': True, 'compile': True, 'verbose': logging.DEBUG, 'version': version.__version__, } args = argparse.Namespace(**kwargs) manage.setup_verbosity(args) manage.translate_messages(args) manage.sh(""" pybabel init -i {d}/messages.pot -d {d} -l en_US pybabel init -i {d}/messages.pot -d {d} -l fr_FR sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code bonjour"/' \ {d}/fr_FR/LC_MESSAGES/messages.po pybabel init -i {d}/messages.pot -d {d} -l zh_Hans_CN sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code chinese"/' \ {d}/zh_Hans_CN/LC_MESSAGES/messages.po pybabel init -i {d}/messages.pot -d {d} -l ar sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code arabic"/' \ {d}/ar/LC_MESSAGES/messages.po pybabel init -i {d}/messages.pot -d {d} -l nb_NO sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code norwegian"/' \ {d}/nb_NO/LC_MESSAGES/messages.po pybabel init -i {d}/messages.pot -d {d} -l es_ES sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code spanish"/' \ {d}/es_ES/LC_MESSAGES/messages.po """.format(d=config.TEMP_DIR)) manage.translate_messages(args) fake_config = self.get_fake_config() fake_config.SUPPORTED_LOCALES = [ 'en_US', 'fr_FR', 'zh_Hans_CN', 'ar', 'nb_NO' ] fake_config.TRANSLATION_DIRS = config.TEMP_DIR for app in (journalist_app.create_app(fake_config), source_app.create_app(fake_config)): assert i18n.LOCALES == fake_config.SUPPORTED_LOCALES self.verify_i18n(app)
def main(staging: bool = False) -> None: app = journalist_app.create_app(config) with app.app_context(): # Add two test users test_password = "******" test_otp_secret = "JHCOGO7VCER3EJ4L" journalist_who_saw = add_test_user( "journalist", test_password, test_otp_secret, is_admin=True ) if staging: return dellsberg = add_test_user( "dellsberg", test_password, test_otp_secret, is_admin=False ) journalist_tobe_deleted = add_test_user("clarkkent", test_password, test_otp_secret, is_admin=False, first_name="Clark", last_name="Kent") NUM_SOURCES = os.getenv('NUM_SOURCES', 3) if NUM_SOURCES == "ALL": # We ingest two strings per source, so this will create the required # number of sources to include all special strings NUM_SOURCES = math.ceil(len(strings) / 2) # Create source data num_sources = int(NUM_SOURCES) for i in range(num_sources): # For the first source, the journalist who replied will be deleted, otherwise dellsberg journalist_who_replied = journalist_tobe_deleted if i == 0 else dellsberg create_source_data( i, num_sources, journalist_who_replied, journalist_who_saw ) # Now let us delete one journalist db.session.delete(journalist_tobe_deleted) db.session.commit()
def test_i18n(self): sources = [ 'tests/i18n/code.py', 'tests/i18n/template.html', ] kwargs = { 'translations_dir': config.TEMP_DIR, 'mapping': 'tests/i18n/babel.cfg', 'source': sources, 'extract_update': True, 'compile': True, 'verbose': logging.DEBUG, 'version': version.__version__, } args = argparse.Namespace(**kwargs) manage.setup_verbosity(args) manage.translate_messages(args) manage.sh(""" pybabel init -i {d}/messages.pot -d {d} -l en_US pybabel init -i {d}/messages.pot -d {d} -l fr_FR sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code bonjour"/' \ {d}/fr_FR/LC_MESSAGES/messages.po pybabel init -i {d}/messages.pot -d {d} -l zh_Hans_CN sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code chinese"/' \ {d}/zh_Hans_CN/LC_MESSAGES/messages.po pybabel init -i {d}/messages.pot -d {d} -l ar sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code arabic"/' \ {d}/ar/LC_MESSAGES/messages.po pybabel init -i {d}/messages.pot -d {d} -l nb_NO sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code norwegian"/' \ {d}/nb_NO/LC_MESSAGES/messages.po pybabel init -i {d}/messages.pot -d {d} -l es_ES sed -i -e '/code hello i18n/,+1s/msgstr ""/msgstr "code spanish"/' \ {d}/es_ES/LC_MESSAGES/messages.po """.format(d=config.TEMP_DIR)) manage.translate_messages(args) fake_config = self.get_fake_config() fake_config.SUPPORTED_LOCALES = [ 'en_US', 'fr_FR', 'zh_Hans_CN', 'ar', 'nb_NO'] fake_config.TRANSLATION_DIRS = config.TEMP_DIR for app in (journalist_app.create_app(fake_config), source_app.create_app(fake_config)): assert i18n.LOCALES == fake_config.SUPPORTED_LOCALES self.verify_i18n(app)
def test_supported_locales(config): fake_config = SDConfig() # Check that an invalid locale raises an error during app # configuration. fake_config.SUPPORTED_LOCALES = ['en_US', 'yy_ZZ'] fake_config.TRANSLATION_DIRS = Path(config.TEMP_DIR) with pytest.raises(UnknownLocaleError): journalist_app_module.create_app(fake_config) with pytest.raises(UnknownLocaleError): source_app.create_app(fake_config) # Check that a valid but unsupported locale raises an error during # app configuration. fake_config.SUPPORTED_LOCALES = ['en_US', 'wae_CH'] fake_config.TRANSLATION_DIRS = Path(config.TEMP_DIR) with pytest.raises(ValueError, match="not in the set of translated locales"): journalist_app_module.create_app(fake_config) with pytest.raises(ValueError, match="not in the set of translated locales"): source_app.create_app(fake_config)
def test_unusable_default_but_usable_fallback_locale(config, caplog): """ The apps start even if the default locale is unusable, as along as the fallback locale is usable, but log an error for OSSEC to pick up. """ fake_config = SDConfig() fake_config.DEFAULT_LOCALE = NEVER_LOCALE fake_config.SUPPORTED_LOCALES = [NEVER_LOCALE, FALLBACK_LOCALE] fake_config.TRANSLATION_DIRS = Path(config.TEMP_DIR) for app in (journalist_app_module.create_app(fake_config), source_app.create_app(fake_config)): with app.app_context(): assert NEVER_LOCALE in caplog.text assert "not in the set of usable locales" in caplog.text
def test_valid_but_unusable_locales(config, caplog): """ The apps start with one or more unusable, but still valid, locales, but log an error for OSSEC to pick up. """ fake_config = SDConfig() fake_config.SUPPORTED_LOCALES = [FALLBACK_LOCALE, "wae_CH"] fake_config.TRANSLATION_DIRS = Path(config.TEMP_DIR) for app in (journalist_app_module.create_app(fake_config), source_app.create_app(fake_config)): with app.app_context(): assert "wae" in caplog.text assert "not in the set of usable locales" in caplog.text
def test_html_en_lang_correct(self): fake_config = self.get_fake_config() app = journalist_app.create_app(fake_config).test_client() resp = app.get('/', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html app = source_app.create_app(fake_config).test_client() resp = app.get('/', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html # check '/generate' too because '/' uses a different template resp = app.get('/generate', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html
def test_html_en_lang_correct(self): fake_config = self.get_fake_config() app = journalist_app.create_app(fake_config).test_client() resp = app.get('/', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html app = source_app.create_app(fake_config).test_client() resp = app.get('/', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html # check '/generate' too because '/' uses a different template resp = app.get('/generate', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html
def test_add_checksum_for_file(config, app_storage, db_model): """ Check that when we execute the `add_checksum_for_file` function, the database object is correctly updated with the actual hash of the file. We have to create our own app in order to have more control over the SQLAlchemy sessions. The fixture pushes a single app context that forces us to work within a single transaction. """ app = create_app(config) test_storage = app_storage with app.app_context(): db.create_all() source_user = create_source_user( db_session=db.session, source_passphrase=PassphraseGenerator.get_default(). generate_passphrase(), source_app_storage=test_storage, ) source = source_user.get_db_record() target_file_path = test_storage.path(source.filesystem_id, "1-foo-msg.gpg") test_message = b"hash me!" expected_hash = "f1df4a6d8659471333f7f6470d593e0911b4d487856d88c83d2d187afa195927" with open(target_file_path, "wb") as f: f.write(test_message) if db_model == Submission: db_obj = Submission(source, target_file_path, app_storage) else: journalist, _ = utils.db_helper.init_journalist() db_obj = Reply(journalist, source, target_file_path, app_storage) db.session.add(db_obj) db.session.commit() db_obj_id = db_obj.id queued_add_checksum_for_file(db_model, db_obj_id, target_file_path, app.config["SQLALCHEMY_DATABASE_URI"]) with app.app_context(): # requery to get a new object db_obj = db_model.query.filter_by(id=db_obj_id).one() assert db_obj.checksum == "sha256:" + expected_hash
def test_html_fr_lang_correct(self): """Check that when the locale is fr_FR the lang property is correct""" fake_config = self.get_fake_config() fake_config.SUPPORTED_LOCALES = ['fr_FR', 'en_US'] app = journalist_app.create_app(fake_config).test_client() resp = app.get('/?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html app = source_app.create_app(fake_config).test_client() resp = app.get('/?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html # check '/generate' too because '/' uses a different template resp = app.get('/generate?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html
def test_html_en_lang_correct(journalist_app, config): # Then delete it because using it won't test what we want del journalist_app app = journalist_app_module.create_app(config).test_client() resp = app.get('/', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html app = source_app.create_app(config).test_client() resp = app.get('/', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html # check '/generate' too because '/' uses a different template resp = app.get('/generate', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="en".*>').search(html), html
def test_html_fr_lang_correct(self): """Check that when the locale is fr_FR the lang property is correct""" fake_config = self.get_fake_config() fake_config.SUPPORTED_LOCALES = ['fr_FR', 'en_US'] app = journalist_app.create_app(fake_config).test_client() resp = app.get('/?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html app = source_app.create_app(fake_config).test_client() resp = app.get('/?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html # check '/generate' too because '/' uses a different template resp = app.get('/generate?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html
def test_html_en_lang_correct(journalist_app, config): # Then delete it because using it won't test what we want del journalist_app app = journalist_app_module.create_app(config).test_client() resp = app.get("/", follow_redirects=True) html = resp.data.decode("utf-8") assert re.compile('<html lang="en-US".*>').search(html), html app = source_app.create_app(config).test_client() resp = app.get("/", follow_redirects=True) html = resp.data.decode("utf-8") assert re.compile('<html lang="en-US".*>').search(html), html # check '/generate' too because '/' uses a different template resp = app.post("/generate", data={"tor2web_check": 'href="fake.onion"'}, follow_redirects=True) html = resp.data.decode("utf-8") assert re.compile('<html lang="en-US".*>').search(html), html
def test_html_fr_lang_correct(journalist_app, config): """Check that when the locale is fr_FR the lang property is correct""" # Then delete it because using it won't test what we want del journalist_app config.SUPPORTED_LOCALES = ['fr_FR', 'en_US'] app = journalist_app_module.create_app(config).test_client() resp = app.get('/?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html app = source_app.create_app(config).test_client() resp = app.get('/?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html # check '/generate' too because '/' uses a different template resp = app.get('/generate?l=fr_FR', follow_redirects=True) html = resp.data.decode('utf-8') assert re.compile('<html .*lang="fr".*>').search(html), html
def load(args: argparse.Namespace) -> None: """ Populate the database. """ if args.seed: random.seed(args.seed) if not os.environ.get("SECUREDROP_ENV"): os.environ["SECUREDROP_ENV"] = "dev" app = journalist_app.create_app(config) with app.app_context(): journalists = create_default_journalists() add_journalists(args) add_sources(args, journalists) # delete one journalist _, _, journalist_to_be_deleted = journalists journalist_to_be_deleted.delete() db.session.commit()
def test_add_checksum_for_file(config, db_model): ''' Check that when we execute the `add_checksum_for_file` function, the database object is correctly updated with the actual hash of the file. We have to create our own app in order to have more control over the SQLAlchemy sessions. The fixture pushes a single app context that forces us to work within a single transaction. ''' app = create_app(config) with app.app_context(): db.create_all() source, _ = utils.db_helper.init_source_without_keypair() target_file_path = app.storage.path(source.filesystem_id, '1-foo-msg.gpg') test_message = b'hash me!' expected_hash = 'f1df4a6d8659471333f7f6470d593e0911b4d487856d88c83d2d187afa195927' with open(target_file_path, 'wb') as f: f.write(test_message) if db_model == Submission: db_obj = Submission(source, target_file_path) else: journalist, _ = utils.db_helper.init_journalist() db_obj = Reply(journalist, source, target_file_path) db.session.add(db_obj) db.session.commit() db_obj_id = db_obj.id queued_add_checksum_for_file(db_model, db_obj_id, target_file_path, app.config['SQLALCHEMY_DATABASE_URI']) with app.app_context(): # requery to get a new object db_obj = db_model.query.filter_by(id=db_obj_id).one() assert db_obj.checksum == 'sha256:' + expected_hash
def test_html_fr_lang_correct(journalist_app, config): """Check that when the locale is fr_FR the lang property is correct""" # Then delete it because using it won't test what we want del journalist_app config.SUPPORTED_LOCALES = ["fr_FR", "en_US"] app = journalist_app_module.create_app(config).test_client() resp = app.get("/?l=fr_FR", follow_redirects=True) html = resp.data.decode("utf-8") assert re.compile('<html lang="fr-FR".*>').search(html), html app = source_app.create_app(config).test_client() resp = app.get("/?l=fr_FR", follow_redirects=True) html = resp.data.decode("utf-8") assert re.compile('<html lang="fr-FR".*>').search(html), html # check '/generate' too because '/' uses a different template resp = app.post("/generate?l=fr_FR", data={"tor2web_check": 'href="fake.onion"'}, follow_redirects=True) html = resp.data.decode("utf-8") assert re.compile('<html lang="fr-FR".*>').search(html), html
def main(staging=False): app = journalist_app.create_app(config) with app.app_context(): # Add two test users test_password = "******" test_otp_secret = "JHCOGO7VCER3EJ4L" add_test_user("journalist", test_password, test_otp_secret, is_admin=True) if staging: return add_test_user("dellsberg", test_password, test_otp_secret, is_admin=False) # Add test sources and submissions num_sources = int(os.getenv('NUM_SOURCES', 2)) for _ in range(num_sources): create_source_and_submissions()
def __init__(self, config): self.config = config self.app = create_app(config)
# -*- coding: utf-8 -*- import config from journalist_app import create_app app = create_app(config) if __name__ == "__main__": # pragma: no cover debug = getattr(config, 'env', 'prod') != 'prod' app.run(debug=debug, host='0.0.0.0', port=8081)