예제 #1
0
def test_MessageDownloadJob_with_crypto_error(mocker, homedir, session,
                                              session_maker):
    """
    Test when a message successfully downloads, but does not successfully decrypt. Use the `homedir`
    fixture to get a GPG keyring.
    """
    message = factory.Message(source=factory.Source(),
                              is_downloaded=False,
                              is_decrypted=None,
                              content=None)
    session.add(message)
    session.commit()
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job = MessageDownloadJob(message.uuid, homedir, gpg)
    mocker.patch.object(job.gpg,
                        'decrypt_submission_or_reply',
                        side_effect=CryptoError)
    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()
    path = os.path.join(homedir, 'data')
    api_client.download_submission = mocker.MagicMock(return_value=('', path))

    with pytest.raises(DownloadDecryptionException):
        job.call_api(api_client, session)

    assert message.content is None
    assert message.is_downloaded is True
    assert message.is_decrypted is False
예제 #2
0
def test_MessageDownloadJob_happiest_path(mocker, homedir, session,
                                          session_maker):
    """
    Test when a message successfully downloads and decrypts. Use the `homedir` fixture to get a GPG
    keyring.
    """
    message = factory.Message(source=factory.Source(),
                              is_downloaded=False,
                              is_decrypted=None,
                              content=None)
    session.add(message)
    session.commit()
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job = MessageDownloadJob(message.uuid, homedir, gpg)
    mocker.patch.object(job.gpg, 'decrypt_submission_or_reply')
    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()
    data_dir = os.path.join(homedir, 'data')
    api_client.download_submission = mocker.MagicMock(return_value=('',
                                                                    data_dir))

    job.call_api(api_client, session)

    assert message.content is not None
    assert message.is_downloaded is True
    assert message.is_decrypted is True
예제 #3
0
def test_MessageDownloadJob_with_base_error(mocker, homedir, session,
                                            session_maker):
    """
    Test when a message does not successfully download.
    """
    message = factory.Message(source=factory.Source(),
                              is_downloaded=False,
                              is_decrypted=None,
                              content=None)
    session.add(message)
    session.commit()
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job = MessageDownloadJob(message.uuid, homedir, gpg)
    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()
    mocker.patch.object(api_client,
                        'download_submission',
                        side_effect=BaseError)
    decrypt_fn = mocker.patch.object(job.gpg, 'decrypt_submission_or_reply')

    with pytest.raises(BaseError):
        job.call_api(api_client, session)

    assert message.content is None
    assert message.is_downloaded is False
    assert message.is_decrypted is None
    decrypt_fn.assert_not_called()
예제 #4
0
def test_MessageDownloadJob_no_download_or_decrypt(mocker, homedir, session,
                                                   session_maker):
    """
    Test that an already-downloaded message successfully decrypts. Use the `homedir` fixture to get
    a GPG keyring.
    """
    message_is_decrypted_false = factory.Message(source=factory.Source(),
                                                 is_downloaded=True,
                                                 is_decrypted=False,
                                                 content=None)
    message_is_decrypted_none = factory.Message(source=factory.Source(),
                                                is_downloaded=True,
                                                is_decrypted=None,
                                                content=None)
    session.add(message_is_decrypted_false)
    session.add(message_is_decrypted_none)
    session.commit()
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job_1 = MessageDownloadJob(message_is_decrypted_false.uuid, homedir, gpg)
    job_2 = MessageDownloadJob(message_is_decrypted_none.uuid, homedir, gpg)
    mocker.patch.object(job_1.gpg, 'decrypt_submission_or_reply')
    mocker.patch.object(job_2.gpg, 'decrypt_submission_or_reply')
    api_client = mocker.MagicMock()
    path = os.path.join(homedir, 'data')
    api_client.download_submission = mocker.MagicMock(return_value=('', path))

    job_1.call_api(api_client, session)
    job_2.call_api(api_client, session)

    assert message_is_decrypted_false.content is not None
    assert message_is_decrypted_false.is_downloaded is True
    assert message_is_decrypted_false.is_decrypted is True
    assert message_is_decrypted_none.content is not None
    assert message_is_decrypted_none.is_downloaded is True
    assert message_is_decrypted_none.is_decrypted is True
예제 #5
0
def test_RunnableQueue_duplicate_jobs(mocker):
    """
    Verify that duplicate jobs are not added to the queue.
    """
    mock_api_client = mocker.MagicMock()
    mock_session = mocker.MagicMock()
    mock_session_maker = mocker.MagicMock(return_value=mock_session)

    dl_job = FileDownloadJob("mock", "mock", "mock")
    msg_dl_job = MessageDownloadJob("mock", "mock", "mock")
    queue = RunnableQueue(mock_api_client, mock_session_maker)
    debug_logger = mocker.patch("securedrop_client.queue.logger.debug")

    # Queue begins empty (0 entries).
    assert len(queue.queue.queue) == 0

    queue.add_job(dl_job)
    assert len(queue.queue.queue) == 1

    # Now add the same job again.
    queue.add_job(dl_job)
    assert len(queue.queue.queue) == 1

    log_msg = "Duplicate job {}, skipping".format(dl_job)
    debug_logger.call_args[1] == log_msg

    # Now add a _different_ job with the same arguments (same uuid).
    queue.add_job(msg_dl_job)
    assert len(queue.queue.queue) == 2

    # Ensure that using _re_add_job in the case of a timeout won't allow duplicate
    # jobs to be added.
    with queue.condition_add_or_remove_job:
        queue._re_add_job(msg_dl_job)
    assert len(queue.queue.queue) == 2
예제 #6
0
    def _submit_download_job(self, object_type: Union[Type[db.Reply],
                                                      Type[db.Message],
                                                      Type[db.File]],
                             uuid: str) -> None:

        if object_type == db.Reply:
            job = ReplyDownloadJob(
                uuid, self.data_dir, self.gpg
            )  # type: Union[ReplyDownloadJob, MessageDownloadJob, FileDownloadJob]
            job.success_signal.connect(self.on_reply_download_success,
                                       type=Qt.QueuedConnection)
            job.failure_signal.connect(self.on_reply_download_failure,
                                       type=Qt.QueuedConnection)
        elif object_type == db.Message:
            job = MessageDownloadJob(uuid, self.data_dir, self.gpg)
            job.success_signal.connect(self.on_message_download_success,
                                       type=Qt.QueuedConnection)
            job.failure_signal.connect(self.on_message_download_failure,
                                       type=Qt.QueuedConnection)
        elif object_type == db.File:
            job = FileDownloadJob(uuid, self.data_dir, self.gpg)
            job.success_signal.connect(self.on_file_download_success,
                                       type=Qt.QueuedConnection)
            job.failure_signal.connect(self.on_file_download_failure,
                                       type=Qt.QueuedConnection)

        self.api_job_queue.enqueue(job)
예제 #7
0
def test_MessageDownloadJob_message_already_downloaded(mocker, homedir,
                                                       session, session_maker):
    """
    Test that call_api just decrypts and returns uuid if already downloaded.
    """
    message = factory.Message(source=factory.Source(),
                              is_downloaded=True,
                              is_decrypted=None)
    session.add(message)
    session.commit()
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job = MessageDownloadJob(message.uuid, homedir, gpg)
    mocker.patch.object(job.gpg, 'decrypt_submission_or_reply')
    api_client = mocker.MagicMock()
    download_fn = mocker.patch.object(api_client, 'download_submission')

    return_uuid = job.call_api(api_client, session)

    assert message.uuid == return_uuid
    assert message.is_decrypted is True
    download_fn.assert_not_called()
예제 #8
0
def test_MessageDownloadJob_message_already_decrypted(mocker, homedir, session,
                                                      session_maker,
                                                      download_error_codes):
    """
    Test that call_api just returns uuid if already decrypted.
    """
    message = factory.Message(source=factory.Source(),
                              is_downloaded=True,
                              is_decrypted=True)
    session.add(message)
    session.commit()
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job = MessageDownloadJob(message.uuid, homedir, gpg)
    decrypt_fn = mocker.patch.object(job.gpg, "decrypt_submission_or_reply")
    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()
    download_fn = mocker.patch.object(api_client, "download_submission")

    return_uuid = job.call_api(api_client, session)

    assert message.uuid == return_uuid
    decrypt_fn.assert_not_called()
    download_fn.assert_not_called()