Esempio n. 1
0
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)
Esempio n. 2
0
def config(
    setup_journalist_key_and_gpg_folder: Tuple[str, Path]
) -> Generator[SDConfig, None, None]:
    config = SDConfig()
    journalist_key_fingerprint, gpg_key_dir = setup_journalist_key_and_gpg_folder
    config.GPG_KEY_DIR = str(gpg_key_dir)
    config.JOURNALIST_KEY = journalist_key_fingerprint

    # Setup the filesystem for the application
    with TemporaryDirectory() as data_dir_name:
        data_dir = Path(data_dir_name)
        config.SECUREDROP_DATA_ROOT = str(data_dir)

        store_dir = data_dir / "store"
        store_dir.mkdir()
        config.STORE_DIR = str(store_dir)

        tmp_dir = data_dir / "tmp"
        tmp_dir.mkdir()
        config.TEMP_DIR = str(tmp_dir)

        # Create the db file
        sqlite_db_path = data_dir / "db.sqlite"
        config.DATABASE_FILE = str(sqlite_db_path)
        subprocess.check_call(["sqlite3", config.DATABASE_FILE, ".databases"])

        config.SUPPORTED_LOCALES = i18n.get_test_locales()

        # Set this newly-created config as the "global" config
        with mock.patch.object(sdconfig, "config", config):

            yield config
Esempio n. 3
0
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)
Esempio n. 4
0
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)
Esempio n. 5
0
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
Esempio n. 6
0
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
Esempio n. 7
0
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)
Esempio n. 8
0
def config(tmpdir):
    '''Clone the module so we can modify it per test.'''

    cnf = SDConfig()

    data = tmpdir.mkdir('data')
    keys = data.mkdir('keys')
    os.chmod(str(keys), 0o700)
    store = data.mkdir('store')
    tmp = data.mkdir('tmp')
    sqlite = data.join('db.sqlite')

    # gpg 2.1+ requires gpg-agent, see #4013
    gpg_agent_config = str(keys.join('gpg-agent.conf'))
    with open(gpg_agent_config, 'w+') as f:
        f.write('allow-loopback-pinentry')

    gpg = gnupg.GPG('gpg2', homedir=str(keys))
    for ext in ['sec', 'pub']:
        with io.open(
                path.join(path.dirname(__file__), 'files',
                          'test_journalist_key.{}'.format(ext))) as f:
            gpg.import_keys(f.read())

    cnf.SECUREDROP_DATA_ROOT = str(data)
    cnf.GPG_KEY_DIR = str(keys)
    cnf.STORE_DIR = str(store)
    cnf.TEMP_DIR = str(tmp)
    cnf.DATABASE_FILE = str(sqlite)

    # create the db file
    subprocess.check_call(['sqlite3', cnf.DATABASE_FILE, '.databases'])

    return cnf
Esempio n. 9
0
def test_missing_config_attribute_is_handled():
    """
    Test handling of incomplete configurations.

    Long-running SecureDrop instances might not have ever updated
    config.py, so could be missing newer settings. This tests that
    sdconfig.SDConfig can be initialized without error with such a
    configuration.
    """
    attributes_to_test = (
        "JournalistInterfaceFlaskConfig",
        "SourceInterfaceFlaskConfig",
        "DATABASE_ENGINE",
        "DATABASE_FILE",
        "ADJECTIVES",
        "NOUNS",
        "GPG_KEY_DIR",
        "JOURNALIST_KEY",
        "JOURNALIST_TEMPLATES_DIR",
        "SCRYPT_GPG_PEPPER",
        "SCRYPT_ID_PEPPER",
        "SCRYPT_PARAMS",
        "SECUREDROP_DATA_ROOT",
        "SECUREDROP_ROOT",
        "SESSION_EXPIRATION_MINUTES",
        "SOURCE_TEMPLATES_DIR",
        "TEMP_DIR",
        "STORE_DIR",
        "WORKER_PIDFILE",
    )

    try:
        importlib.reload(_config)

        for a in attributes_to_test:
            delattr(_config, a)

        from sdconfig import SDConfig

        SDConfig()
    finally:
        importlib.reload(_config)
Esempio n. 10
0
def config(gpg_key_dir: Path) -> Generator[SDConfig, None, None]:
    config = SDConfig()
    config.GPG_KEY_DIR = str(gpg_key_dir)

    # Setup the filesystem for the application
    with TemporaryDirectory() as data_dir_name:
        data_dir = Path(data_dir_name)
        config.SECUREDROP_DATA_ROOT = str(data_dir)

        store_dir = data_dir / "store"
        store_dir.mkdir()
        config.STORE_DIR = str(store_dir)

        tmp_dir = data_dir / "tmp"
        tmp_dir.mkdir()
        config.TEMP_DIR = str(tmp_dir)

        # Create the db file
        sqlite_db_path = data_dir / "db.sqlite"
        config.DATABASE_FILE = str(sqlite_db_path)
        subprocess.check_call(["sqlite3", config.DATABASE_FILE, ".databases"])

        yield config
Esempio n. 11
0
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)