def evernote_login_password(
    auth_user: Optional[str],
    auth_password: Optional[str],
    backend: str,
    network_retry_count: int,
) -> str:
    auth_user, auth_password = prompt_credentials(auth_user, auth_password)

    auth_client = get_auth_client(
        backend=backend, network_retry_count=network_retry_count
    )

    try:
        auth_res = auth_client.login(auth_user, auth_password)
    except EvernoteAuthError as e:
        raise ProgramTerminatedError(e)

    if auth_res.secondFactorRequired:
        auth_res = handle_two_factor_auth(
            auth_client,
            auth_res.authenticationToken,
            auth_res.secondFactorDeliveryHint,
        )

    return str(auth_res.authenticationToken)
Пример #2
0
def sync(
    database: str,
    max_chunk_results: int,
    max_download_workers: int,
    network_retry_count: int,
) -> None:
    storage = get_storage(database)

    raise_on_old_database_version(storage)

    backend = storage.config.get_config_value("backend")
    auth_token = storage.config.get_config_value("auth_token")

    note_client = get_sync_client(auth_token, backend, network_retry_count,
                                  max_chunk_results)

    note_synchronizer = NoteSynchronizer(note_client, storage,
                                         max_download_workers)

    try:
        note_synchronizer.sync()
    except WrongAuthUserError as e:
        raise ProgramTerminatedError(
            f"Current user of this database is {e.local_user}, not {e.remote_user}!"
            " Each user must use a different database file.")

    logger.info("Synchronization completed!")
Пример #3
0
def get_sync_client(
    auth_token: str,
    backend: str,
    network_error_retry_count: int,
    max_chunk_results: int,
) -> EvernoteClientSync:
    logger.info(f"Authorizing auth token, {backend} backend...")

    client = EvernoteClientSync(
        token=auth_token,
        backend=backend,
        network_error_retry_count=network_error_retry_count,
        max_chunk_results=max_chunk_results,
    )

    try:
        client.verify_token()
    except EvernoteAuthError as e:
        raise ProgramTerminatedError(e)

    token_expiration = get_token_expiration_date(auth_token)

    logger.info(f"Successfully authenticated as {client.user}!")
    logger.info(f"Current login will expire at {token_expiration}.")

    return client
Пример #4
0
def test_cli_program_error(mocker, caplog):
    cli_mock = mocker.patch("evernote_backup.cli.cli")
    cli_mock.side_effect = ProgramTerminatedError("test")

    with pytest.raises(SystemExit):
        cli_module.main()

    assert caplog.messages[0] == "test"
Пример #5
0
def handle_two_factor_auth(auth_client: EvernoteClientAuth, token: str,
                           delivery_hint: str) -> AuthenticationResult:
    ota_code = prompt_ota(delivery_hint)

    try:
        return auth_client.two_factor_auth(token, ota_code)
    except EvernoteAuthError as e:
        raise ProgramTerminatedError(e)
Пример #6
0
def get_storage(database_path: Path) -> SqliteStorage:
    logger.info("Reading database {0}...".format(database_path.name))

    try:
        return SqliteStorage(database_path)
    except FileNotFoundError:
        raise ProgramTerminatedError(
            f"Database file {database_path} does not exist."
            f" Initialize database first!"
        )
Пример #7
0
def prompt_ota(delivery_hint: str) -> str:
    if not is_output_to_terminal():
        raise ProgramTerminatedError(
            "Two-factor authentication requires user input!")

    one_time_hint = ""
    if delivery_hint:
        one_time_hint = " ({0})".format(delivery_hint)

    return str(click.prompt(f"Enter one-time code{one_time_hint}"))
def prompt_credentials(
    user: Optional[str],
    password: Optional[str],
) -> Tuple[str, str]:
    if not is_output_to_terminal() and not all([user, password]):
        raise ProgramTerminatedError("--user and --password are required!")

    if not user:
        user = str(click.prompt("Username or Email"))
    if not password:
        password = str(click.prompt("Password", hide_input=True))

    return user, password
Пример #9
0
def export(
    database: str,
    single_notes: bool,
    include_trash: bool,
    output_path: str,
) -> None:
    storage = get_storage(database)

    raise_on_old_database_version(storage)

    exporter = NoteExporter(storage, output_path)

    try:
        exporter.export_notebooks(single_notes, include_trash)
    except NothingToExportError:
        raise ProgramTerminatedError(
            "Database is empty, nothing to export."
            " Execute sync command to populate database first!")

    logger.info("All notes have been exported!")
Пример #10
0
def reauth(
    database: Path,
    auth_user: Optional[str],
    auth_password: Optional[str],
    auth_is_oauth: bool,
    auth_oauth_port: int,
    auth_oauth_host: str,
    auth_token: Optional[str],
    network_retry_count: int,
) -> None:
    storage = get_storage(database)

    raise_on_old_database_version(storage)

    backend = storage.config.get_config_value("backend")

    if not auth_token:
        auth_token = get_auth_token(
            auth_user,
            auth_password,
            auth_is_oauth,
            auth_oauth_port,
            auth_oauth_host,
            backend,
            network_retry_count,
        )

    note_client = get_sync_client(auth_token, backend, network_retry_count, 1)

    local_user = storage.config.get_config_value("user")

    if local_user != note_client.user:
        raise ProgramTerminatedError(
            f"Current user of this database is {local_user}, not {note_client.user}!"
            " Each user must use a different database file.")

    storage.config.set_config_value("auth_token", auth_token)

    logger.info(f"Successfully refreshed auth token for {local_user}!")
Пример #11
0
def raise_on_existing_database(database_path: Path) -> None:
    if database_path.exists():
        raise ProgramTerminatedError(
            "Database already exists."
            " Use --force option to overwrite existing database file."
        )
Пример #12
0
def raise_on_old_database_version(storage: SqliteStorage) -> None:
    try:
        storage.check_version()
    except DatabaseResyncRequiredError:
        raise ProgramTerminatedError(
            "The database version has been updated. Full resync is required.")