Beispiel #1
0
def test_handle_release_upload_exists_in_db_and_not_on_disk(file_content):
    filehash = hashlib.sha256(file_content).hexdigest()
    stream = io.BytesIO(file_content)

    existing = ReleaseFileFactory(
        name="file1.txt",
        path="foo/file1.txt",
        filehash=filehash,
        uploaded_at=None,
    )

    # check out test setup is correct
    assert existing.filehash == filehash

    # upload same files
    releases.handle_file_upload(
        existing.release,
        existing.release.backend,
        existing.created_by,
        stream,
        "file1.txt",
    )

    existing.refresh_from_db()

    assert existing.uploaded_at
    assert existing.absolute_path().exists()
Beispiel #2
0
def test_releasefile_format():
    rfile = ReleaseFileFactory()
    rfile.size = 3.2 * 1024 * 1024  # 3.2Mb
    rfile.save()

    assert f"{rfile:b}" == "3,355,443.2b"
    assert f"{rfile:Kb}" == "3,276.8Kb"
    assert f"{rfile:Mb}" == "3.2Mb"
    assert f"{rfile}".startswith("ReleaseFile object")
Beispiel #3
0
def test_reviewapi_success(api_rf):
    release = ReleaseFactory()
    ReleaseFileFactory(release=release, name="test1", filehash="test1")
    ReleaseFileFactory(release=release, name="test2", filehash="test2")

    data = {
        "files": [
            {
                "name": "test1",
                "url": "url",
                "size": 7,
                "sha256": "test1",
                "date": timezone.now(),
                "metadata": {},
                "review": {
                    "status": "APPROVED",
                    "comments": {"test": "foo"},
                },
            },
            {
                "name": "test2",
                "url": "url",
                "size": 7,
                "sha256": "test2",
                "date": timezone.now(),
                "metadata": {},
                "review": {
                    "status": "REJECTED",
                    "comments": {"test": "bar"},
                },
            },
        ],
        "metadata": {},
        "review": {"foo": "bar"},
    }

    request = api_rf.post("/", data=data, format="json")
    request.user = UserFactory(roles=[OutputChecker])

    response = ReviewAPI.as_view()(request, release_id=release.pk)

    assert response.status_code == 200, response.data

    release.refresh_from_db()
    assert release.review == {"foo": "bar"}

    review1, review2 = ReleaseFileReview.objects.filter(
        release_file__release=release
    ).order_by("release_file__name")

    assert review1.status == "APPROVED"
    assert review1.comments == {"test": "foo"}

    assert review2.status == "REJECTED"
    assert review2.comments == {"test": "bar"}
Beispiel #4
0
def test_releasefile_get_latest_url():
    rfile = ReleaseFileFactory(name="file1.txt")

    url = rfile.get_latest_url()

    assert url == reverse(
        "workspace-latest-outputs-detail",
        kwargs={
            "org_slug": rfile.release.workspace.project.org.slug,
            "project_slug": rfile.release.workspace.project.slug,
            "workspace_slug": rfile.release.workspace.name,
            "path": f"{rfile.release.backend.slug}/{rfile.name}",
        },
    )
Beispiel #5
0
def test_releasefile_get_delete_url():
    rfile = ReleaseFileFactory()

    url = rfile.get_delete_url()

    assert url == reverse(
        "release-file-delete",
        kwargs={
            "org_slug": rfile.release.workspace.project.org.slug,
            "project_slug": rfile.release.workspace.project.slug,
            "workspace_slug": rfile.release.workspace.name,
            "pk": rfile.release.id,
            "release_file_id": rfile.pk,
        },
    )
Beispiel #6
0
def test_releasefile_get_absolute_url():
    rfile = ReleaseFileFactory(name="file1.txt")

    url = rfile.get_absolute_url()

    assert url == reverse(
        "release-detail",
        kwargs={
            "org_slug": rfile.release.workspace.project.org.slug,
            "project_slug": rfile.release.workspace.project.slug,
            "workspace_slug": rfile.release.workspace.name,
            "pk": rfile.release.id,
            "path": rfile.name,
        },
    )
Beispiel #7
0
def test_release_with_a_missing_file(download_file_mock, repository, rf):
    """
    If a local ReleaseFile had a missing file we must set local as False,
    redirect to the PyPI, requeue the download_file task.
    """
    release_file = ReleaseFileFactory(release__package__repository=repository)
    os.remove(release_file.distribution.path)

    url_kwargs = {
        'repo': repository.slug,
        'name': release_file.release.package.name,
        'pk': release_file.pk,
        'filename': release_file.filename
    }

    request = rf.get(reverse('packages:download', kwargs=url_kwargs))
    response = views.DownloadReleaseFile.as_view()(request, **url_kwargs)

    # The request is redirected to PyPI
    assert response.status_code == 302
    assert response.url == release_file.url

    # The download file task must the queued
    assert download_file_mock.delay.call_count == 1
    assert download_file_mock.delay.call_args[1] == {'pk': release_file.pk}
Beispiel #8
0
def test_releasefile_get_api_url_with_is_published():
    rfile = ReleaseFileFactory()

    # mirror the SnapshotAPI view setting this value on the ReleaseFile object.
    setattr(rfile, "is_published", True)

    url = rfile.get_api_url()

    assert url == reverse(
        "published-file",
        kwargs={
            "org_slug": rfile.workspace.project.org.slug,
            "project_slug": rfile.workspace.project.slug,
            "workspace_slug": rfile.workspace.name,
            "file_id": rfile.id,
        },
    )
Beispiel #9
0
def test_releasefileapi_with_anonymous_user(api_rf):
    rfile = ReleaseFileFactory()

    request = api_rf.get("/")

    response = ReleaseFileAPI.as_view()(request, file_id=rfile.id)

    assert response.status_code == 403
Beispiel #10
0
def test_releasefileapi_without_permission(api_rf):
    rfile = ReleaseFileFactory()

    request = api_rf.get("/")
    request.user = UserFactory()  # logged in, but no permission

    response = ReleaseFileAPI.as_view()(request, file_id=rfile.id)

    assert response.status_code == 403
Beispiel #11
0
def test_build_outputs_zip_with_missing_files(build_release_with_files):
    release = build_release_with_files(["test1", "test3", "test5"])

    # create a couple of deleted files
    user = UserFactory()
    ReleaseFileFactory(release=release,
                       name="test2",
                       deleted_at=timezone.now(),
                       deleted_by=user)
    ReleaseFileFactory(release=release,
                       name="test4",
                       deleted_at=timezone.now(),
                       deleted_by=user)

    release.requested_files.append([{"name": "test2"}, {"name": "test4"}])
    files = release.files.order_by("name")

    zf = releases.build_outputs_zip(files, lambda u: u)

    with zipfile.ZipFile(zf, "r") as zip_obj:
        assert zip_obj.testzip() is None

        assert zip_obj.namelist() == [
            "test1", "test2", "test3", "test4", "test5"
        ]

        # check ReleaseFile on-disk contents matches their zipped contents
        for name in ["test1", "test3", "test5"]:
            with open(files.get(name=name).absolute_path(), "rb") as f:
                original_contents = f.read()

            with zip_obj.open(name) as f:
                zipped_contents = f.read()

            assert zipped_contents == original_contents

        for name in ["test2", "test4"]:
            with zip_obj.open(name) as f:
                zipped_contents = f.read().decode()

            rfile = files.get(name=name)
            assert rfile.get_absolute_url() in zipped_contents, zipped_contents
            assert "This file was redacted by" in zipped_contents, zipped_contents
Beispiel #12
0
def test_create_release_reupload():
    rfile = ReleaseFileFactory(name="file1.txt", filehash="hash")
    files = {"file1.txt": "hash"}
    with pytest.raises(releases.ReleaseFileAlreadyExists):
        releases.create_release(
            rfile.release.workspace,
            rfile.release.backend,
            rfile.release.created_by,
            files,
        )
Beispiel #13
0
def test_reviewapi_unknown_filename_or_content(api_rf):
    release = ReleaseFactory()
    ReleaseFileFactory(release=release, name="test1", filehash="test1")
    ReleaseFileFactory(release=release, name="test2", filehash="test2")

    data = {
        "files": [
            {
                "name": "unknown",
                "url": "url",
                "size": 7,
                "sha256": "test1",
                "date": timezone.now(),
                "metadata": {},
                "review": {
                    "status": "APPROVED",
                    "comments": {"test": "foo"},
                },
            },
            {
                "name": "test2",
                "url": "url",
                "size": 7,
                "sha256": "unknown",
                "date": timezone.now(),
                "metadata": {},
                "review": {
                    "status": "REJECTED",
                    "comments": {"test": "bar"},
                },
            },
        ],
        "metadata": {},
        "review": {},
    }

    request = api_rf.post("/", data=data, format="json")
    request.user = UserFactory(roles=[OutputChecker])

    response = ReviewAPI.as_view()(request, release_id=release.pk)

    assert response.status_code == 400, response.data
Beispiel #14
0
def test_upload_should_not_overwrite_pypi_package(app, repository, admin_user):
    ReleaseFileFactory(
        release__package__repository=repository,
        release__package__name='localshop')

    headers = {
        'Content-type': tostr('multipart/form-data; boundary=--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'),
        'Authorization': basic_auth_header('admin', 'password'),
    }

    response = app.post(
        '/repo/%s/' % repository.slug, REGISTER_POST, headers=headers,
        status=400)

    assert response.unicode_body == 'localshop is a pypi package!'
Beispiel #15
0
def test_wrong_package_name_case(app, admin_user, repository, pypi_stub):
    repository.upstream_pypi_url = pypi_stub.url
    repository.save()

    ReleaseFileFactory(
        release__package__repository=repository,
        release__package__name='minibar')

    response = app.get(
        reverse('packages:simple_detail', kwargs={
            'slug': 'Minibar',
            'repo': 'default'
        }))

    assert response.status_code == 302
    assert response.url == 'http://testserver/repo/default/minibar/'
Beispiel #16
0
def test_releasefileapi_with_deleted_file(api_rf):
    rfile = ReleaseFileFactory(deleted_at=timezone.now(), deleted_by=UserFactory())
    user = UserFactory()

    ProjectMembershipFactory(
        user=user,
        project=rfile.release.workspace.project,
        roles=[ProjectCollaborator],
    )

    request = api_rf.get("/")
    request.user = user

    response = ReleaseFileAPI.as_view()(request, file_id=rfile.id)

    assert response.status_code == 404, response.data
Beispiel #17
0
def test_download_file_incorrect_md5_sum(requests_mock):
    file_data = six.b('My cool package')
    release_file = ReleaseFileFactory(distribution=None, md5_digest='arcoiro')

    requests_mock.return_value = mock.Mock(**{
            'headers': {
                'content-length': len(file_data),
                'content-type': 'application/octet-stream',
            },
            'content': file_data,
        })

    tasks.download_file.run(release_file.pk)

    release_file = models.ReleaseFile.objects.get(pk=release_file.pk)

    assert not release_file.distribution
Beispiel #18
0
def test_workspace_files_one_release(build_release):
    backend = BackendFactory(slug="backend")
    names = ["test1", "test2", "test3"]
    release = build_release(names, backend=backend)
    for name in names:
        ReleaseFileFactory(
            release=release,
            workspace=release.workspace,
            name=name,
        )

    output = releases.workspace_files(release.workspace)

    assert output == {
        "backend/test1": release.files.get(name="test1"),
        "backend/test2": release.files.get(name="test2"),
        "backend/test3": release.files.get(name="test3"),
    }
Beispiel #19
0
def test_handle_release_upload_exists_with_incorrect_filehash(file_content):
    stream = io.BytesIO(file_content)

    existing = ReleaseFileFactory(
        name="file1.txt",
        path="foo/file1.txt",
        filehash="hash",
        uploaded_at=None,
    )

    with pytest.raises(Exception, match="^Contents of uploaded"):
        releases.handle_file_upload(
            existing.release,
            existing.release.backend,
            existing.created_by,
            stream,
            "file1.txt",
        )
Beispiel #20
0
def test_releaseworkspaceapi_post_release_already_exists(api_rf):
    user = UserFactory(roles=[OutputChecker])

    release = ReleaseFactory()
    rfile = ReleaseFileFactory(
        release=release,
        created_by=user,
        name="file.txt",
        filehash="hash",
    )

    BackendMembershipFactory(backend=release.backend, user=user)
    ProjectMembershipFactory(project=release.workspace.project, user=user)

    data = {
        "files": [
            {
                "name": rfile.name,
                "url": "url",
                "size": 7,
                "sha256": rfile.filehash,
                "date": timezone.now(),
                "metadata": {},
                "review": None,
            }
        ],
        "metadata": {},
        "review": {},
    }
    request = api_rf.post(
        "/",
        data=data,
        format="json",
        HTTP_AUTHORIZATION=release.backend.auth_token,
        HTTP_OS_USER=user.username,
    )

    response = ReleaseWorkspaceAPI.as_view()(
        request, workspace_name=release.workspace.name
    )

    assert response.status_code == 400
    assert "file.txt" in response.data["detail"]
    assert "already been uploaded" in response.data["detail"]
Beispiel #21
0
def test_create_release_new_style_reupload():
    rfile = ReleaseFileFactory(name="file1.txt", filehash="hash")

    files = [{
        "name": "file1.txt",
        "path": "path/to/file1.txt",
        "url": "",
        "size": 4,
        "sha256": "hash",
        "mtime": "2022-08-17T13:37Z",
        "metadata": {},
    }]

    with pytest.raises(releases.ReleaseFileAlreadyExists):
        releases.create_release(
            rfile.release.workspace,
            rfile.release.backend,
            rfile.release.created_by,
            files,
        )
Beispiel #22
0
def test_download_pypi_release(download_file_mock, repository, rf):
    release_file = ReleaseFileFactory(release__package__repository=repository,
                                      distribution=None)

    url_kwargs = {
        'repo': repository.slug,
        'name': release_file.release.package.name,
        'pk': release_file.pk,
        'filename': release_file.filename
    }
    request = rf.get(reverse('packages:download', kwargs=url_kwargs))
    response = views.DownloadReleaseFile.as_view()(request, **url_kwargs)

    # The request is redirected to PyPI
    assert response.status_code == 302
    assert response.url == release_file.url

    # The download file task must the queued
    assert download_file_mock.delay.call_count == 1
    assert download_file_mock.delay.call_args[1] == {'pk': release_file.pk}
def test_upload_should_not_overwrite_pypi_package(
    django_app, repository, admin_user, upload_post_data
):
    ReleaseFileFactory(
        release__package__repository=repository,
        release__package__name='localshop')

    key = admin_user.access_keys.create(comment='For testing')
    headers = {
        'Content-type': upload_post_data.content_type,
        'Authorization': basic_auth_header(key.access_key, key.secret_key)
    }

    response = django_app.post(
        '/repo/%s/' % repository.slug,
        params=upload_post_data.to_string(),
        headers=headers,
        status=400)

    assert response.unicode_body == 'localshop is a pypi package!'
Beispiel #24
0
def test_success(app, admin_user, repository, pypi_stub):
    repository.upstream_pypi_url = pypi_stub.url
    repository.save()
    release_file = ReleaseFileFactory(release__package__repository=repository)

    response = app.get(
        reverse('packages:simple_detail', kwargs={
            'slug': release_file.release.package.name,
            'repo': release_file.release.package.repository.slug
        }))

    assert response.status_code == 200
    assert 'Links for test-package' in response.unicode_body

    a_elms = response.html.select('a')
    assert len(a_elms) == 1
    assert a_elms[0]['href'] == (
        '/repo/default/download/test-package/1/test-1.0.0-sdist.zip' +
        '#md5=62ecd3ee980023db87945470aa2b347b')
    assert a_elms[0]['rel'][0] == 'package'
Beispiel #25
0
def test_download_file_missing_content_length(requests_mock, settings, tmpdir):
    settings.MEDIA_ROOT = tmpdir
    file_data = six.b('My cool package')
    release_file = ReleaseFileFactory(distribution=None,
                                      md5_digest=md5(file_data).hexdigest())

    requests_mock.return_value = mock.Mock(**{
            'headers': {
                'content-type': 'application/octet-stream',
            },
            'content': file_data,
        })

    tasks.download_file.run(release_file.pk)

    release_file = models.ReleaseFile.objects.get(pk=release_file.pk)

    assert release_file.distribution.read() == file_data
    assert release_file.distribution.size == len(file_data)
    assert release_file.distribution.name == (
        'default/2.7/t/test-package/test-1.0.0-sdist.zip')
Beispiel #26
0
def test_download_local_release(rf, isolated, repository, settings):
    settings.LOCALSHOP_ISOLATED = isolated

    release_file = ReleaseFileFactory(release__package__repository=repository)

    url_kwargs = {
        'repo': repository.slug,
        'name': release_file.release.package.name,
        'pk': release_file.pk,
        'filename': release_file.filename
    }

    request = rf.get(reverse('packages:download', kwargs=url_kwargs))
    response = views.DownloadReleaseFile.as_view()(request, **url_kwargs)

    # Localshop must return the release file
    assert response.status_code == 200
    assert response.content == six.b('the file data')
    assert response.get('Content-Length') == '13'
    assert response.get(
        'Content-Disposition') == 'attachment; filename=test-1.0.0-sdist.zip'
Beispiel #27
0
def test_download_file_with_proxy_enabled(requests_mock, settings):
    settings.LOCALSHOP_HTTP_PROXY = {
        "http": "http://10.10.1.10:3128/",
    }
    file_data = six.b('My cool package')
    release_file = ReleaseFileFactory(distribution=None,
                                      md5_digest=md5(file_data).hexdigest())

    requests_mock.return_value = mock.Mock(**{
            'headers': {
                'content-length': len(file_data),
                'content-type': 'application/octet-stream',
            },
            'content': file_data,
        })

    tasks.download_file.run(release_file.pk)

    requests_mock.assert_called_once_with(
        'http://www.example.org/download/test-1.0.0-sdist.zip',
        proxies=settings.LOCALSHOP_HTTP_PROXY,
        stream=True)
Beispiel #28
0
def test_releasefileapi_with_no_file_on_disk(api_rf, build_release):
    release = build_release(["file1.txt"])
    rfile = ReleaseFileFactory(
        release=release,
        workspace=release.workspace,
        name="file1.txt",
        uploaded_at=None,
    )
    user = UserFactory()

    ProjectMembershipFactory(
        user=user,
        project=release.workspace.project,
        roles=[ProjectCollaborator],
    )

    request = api_rf.get("/")
    request.user = user

    response = ReleaseFileAPI.as_view()(request, file_id=rfile.id)

    assert response.status_code == 404, response.data
Beispiel #29
0
def test_download_pypi_release_when_isolated_is_on(requests_mock, rf,
                                                   repository, settings):
    file_data = six.b('Hello from PyPI')
    md5_digest = md5(file_data).hexdigest()

    settings.LOCALSHOP_ISOLATED = True

    release_file = ReleaseFileFactory(release__package__repository=repository,
                                      distribution=None,
                                      md5_digest=md5_digest)

    url_kwargs = {
        'repo': repository.slug,
        'name': release_file.release.package.name,
        'pk': release_file.pk,
        'filename': release_file.filename
    }

    requests_mock.return_value = Mock(
        **{
            'headers': {
                'content-length': len(file_data),
                'content-type': 'application/octet-stream',
            },
            'content': file_data,
        })

    request = rf.get(reverse('packages:download', kwargs=url_kwargs))
    response = views.DownloadReleaseFile.as_view()(request, **url_kwargs)

    assert response.status_code == 200
    assert response.content == file_data
    requests_mock.assert_called_with(
        u'http://www.example.org/download/test-1.0.0-sdist.zip',
        proxies=None,
        stream=True)
Beispiel #30
0
def test_releasefile_constraints_missing_deleted_at_or_deleted_by():
    with pytest.raises(IntegrityError):
        ReleaseFileFactory(deleted_at=None, deleted_by=UserFactory())

    with pytest.raises(IntegrityError):
        ReleaseFileFactory(deleted_at=timezone.now(), deleted_by=None)