コード例 #1
0
def test_workspacestatusapi_success(api_rf):
    request = api_rf.get("/")

    project1 = ProjectFactory()
    workspace1 = WorkspaceFactory(project=project1, uses_new_release_flow=True)

    response = WorkspaceStatusAPI.as_view()(request, workspace_id=workspace1.name)
    assert response.status_code == 200
    assert response.data["uses_new_release_flow"]

    project2 = ProjectFactory()
    workspace2 = WorkspaceFactory(project=project2, uses_new_release_flow=False)
    response = WorkspaceStatusAPI.as_view()(request, workspace_id=workspace2.name)
    assert response.status_code == 200
    assert not response.data["uses_new_release_flow"]
コード例 #2
0
def test_create_release_success():
    backend = BackendFactory()
    workspace = WorkspaceFactory()
    user = UserFactory()
    files = {"file1.txt": "hash"}
    release = releases.create_release(workspace, backend, user, files)
    assert release.requested_files == files
コード例 #3
0
def test_jobrequestapicreate_success(api_rf, pipeline_config):
    backend = BackendFactory()
    workspace = WorkspaceFactory()
    user = UserFactory()
    token = user.rotate_token()

    assert not JobRequest.objects.exists()

    data = {
        "workspace": workspace.name,
        "backend": backend.slug,
        "sha": "123",
        "project_definition": pipeline_config,
        "requested_actions": ["test"],
    }
    request = api_rf.post("/",
                          HTTP_AUTHORIZATION=f"{user.username}:{token}",
                          data=data)

    response = JobRequestAPICreate.as_view()(request)

    assert response.status_code == 201, response.data
    assert JobRequest.objects.count() == 1

    job_request = JobRequest.objects.first()
    assert job_request.workspace == workspace
コード例 #4
0
def test_jobapiupdate_notifications_on_with_move_to_completed(api_rf, mocker):
    workspace = WorkspaceFactory()
    job_request = JobRequestFactory(workspace=workspace, will_notify=True)
    job = JobFactory(job_request=job_request, status="running")

    now = timezone.now()

    mocked_send = mocker.patch("jobserver.api.jobs.send_finished_notification",
                               autospec=True)

    data = [
        {
            "identifier": job.identifier,
            "job_request_id": job_request.identifier,
            "action": "test",
            "status": "succeeded",
            "status_code": "",
            "status_message": "",
            "created_at": minutes_ago(now, 2),
            "started_at": minutes_ago(now, 1),
            "updated_at": now,
            "completed_at": seconds_ago(now, 30),
        },
    ]
    request = api_rf.post(
        "/",
        HTTP_AUTHORIZATION=job_request.backend.auth_token,
        data=data,
        format="json",
    )

    response = JobAPIUpdate.as_view()(request)

    mocked_send.assert_called_once()
    assert response.status_code == 200
コード例 #5
0
def test_releaseworkspaceapi_post_without_backend_token(api_rf):
    workspace = WorkspaceFactory()

    request = api_rf.post("/")

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

    assert response.status_code == 403
コード例 #6
0
def test_releaseworkspaceapi_get_with_anonymous_user(api_rf):
    workspace = WorkspaceFactory()

    request = api_rf.get("/")

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

    assert response.status_code == 403
コード例 #7
0
def test_releaseworkspaceapi_get_without_permission(api_rf):
    workspace = WorkspaceFactory()

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

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

    assert response.status_code == 403
コード例 #8
0
def test_releaseworkspaceapi_post_with_bad_backend_token(api_rf):
    workspace = WorkspaceFactory()
    BackendFactory(auth_token="test")

    request = api_rf.post("/", HTTP_AUTHORIZATION="invalid")

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

    assert response.status_code == 403
コード例 #9
0
def test_snapshotcreate_without_permission(api_rf):
    workspace = WorkspaceFactory()

    request = api_rf.post("/", data={"file_ids": ["test"]})
    request.user = UserFactory()

    response = SnapshotCreateAPI.as_view()(request, workspace_id=workspace.name)

    assert response.status_code == 403, response.data
コード例 #10
0
def test_validate_upload_access_unknown_user(rf):
    backend = BackendFactory()
    workspace = WorkspaceFactory()

    BackendMembershipFactory(backend=backend)

    request = rf.get("/", HTTP_AUTHORIZATION=backend.auth_token, HTTP_OS_USER="******")

    with pytest.raises(NotAuthenticated):
        validate_upload_access(request, workspace)
コード例 #11
0
def test_validate_release_access_with_auth_header_success(rf):
    user = UserFactory()
    workspace = WorkspaceFactory()

    token = user.rotate_token()

    request = rf.get("/", HTTP_AUTHORIZATION=f"{user.username}:{token}")
    request.user = AnonymousUser()

    assert validate_release_access(request, workspace) is None
コード例 #12
0
def test_workspacestatusesapi_success(api_rf):
    workspace = WorkspaceFactory()
    job_request = JobRequestFactory(workspace=workspace)
    JobFactory(job_request=job_request, action="run_all", status="failed")

    request = api_rf.get("/")
    response = WorkspaceStatusesAPI.as_view()(request, name=workspace.name)

    assert response.status_code == 200
    assert response.data["run_all"] == "failed"
コード例 #13
0
def test_build_hatch_token_and_url_default():
    backend = BackendFactory()
    user = UserFactory()
    workspace = WorkspaceFactory()

    releases.build_hatch_token_and_url(
        backend=backend,
        workspace=workspace,
        user=user,
    )
コード例 #14
0
def test_releaseworkspaceapi_get_with_permission(api_rf, build_release_with_files):
    workspace = WorkspaceFactory()
    backend1 = BackendFactory(slug="backend1")
    backend2 = BackendFactory(slug="backend2")
    user = UserFactory()
    ProjectMembershipFactory(
        user=user, project=workspace.project, roles=[ProjectCollaborator]
    )

    # two release for same filename but different content
    release1 = build_release_with_files(
        ["file1.txt"], workspace=workspace, backend=backend1, created_by=user
    )
    rfile1 = release1.files.first()
    release2 = build_release_with_files(
        ["file1.txt"], workspace=workspace, backend=backend2, created_by=user
    )
    rfile2 = release2.files.first()

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

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

    assert response.status_code == 200
    assert response.data == {
        "files": [
            {
                "name": "backend2/file1.txt",
                "id": rfile2.pk,
                "url": f"/api/v2/releases/file/{rfile2.id}",
                "user": rfile2.created_by.username,
                "date": rfile2.created_at.isoformat(),
                "size": rfile2.size,
                "sha256": rfile2.filehash,
                "is_deleted": False,
                "backend": release2.backend.name,
                "metadata": None,
                "review": None,
            },
            {
                "name": "backend1/file1.txt",
                "id": rfile1.pk,
                "url": f"/api/v2/releases/file/{rfile1.id}",
                "user": rfile1.created_by.username,
                "date": rfile1.created_at.isoformat(),
                "size": rfile1.size,
                "sha256": rfile1.filehash,
                "is_deleted": False,
                "backend": release1.backend.name,
                "metadata": None,
                "review": None,
            },
        ],
    }
コード例 #15
0
def test_validate_release_access_with_auth_header_and_unknown_user(rf):
    user = UserFactory()
    workspace = WorkspaceFactory()

    token = user.rotate_token()

    request = rf.get("/", HTTP_AUTHORIZATION=f"0:{token}")
    request.user = AnonymousUser()

    with pytest.raises(NotAuthenticated):
        validate_release_access(request, workspace)
コード例 #16
0
def test_build_hatch_token_and_url_with_custom_expires():
    backend = BackendFactory()
    user = UserFactory()
    workspace = WorkspaceFactory()

    releases.build_hatch_token_and_url(
        backend=backend,
        workspace=workspace,
        user=user,
        expiry=timezone.now() + timedelta(minutes=3),
    )
コード例 #17
0
def test_workspace_files_many_releases(freezer, build_release_with_files):
    now = timezone.now()

    backend1 = BackendFactory(slug="backend1")
    backend2 = BackendFactory(slug="backend2")
    workspace = WorkspaceFactory()

    build_release_with_files(
        ["test1", "test2", "test3"],
        workspace=workspace,
        backend=backend1,
        created_at=minutes_ago(now, 10),
    )
    build_release_with_files(
        ["test2", "test3"],
        workspace=workspace,
        backend=backend1,
        created_at=minutes_ago(now, 8),
    )
    release3 = build_release_with_files(
        ["test2"],
        workspace=workspace,
        backend=backend1,
        created_at=minutes_ago(now, 6),
    )
    release4 = build_release_with_files(
        ["test1", "test3"],
        workspace=workspace,
        backend=backend1,
        created_at=minutes_ago(now, 4),
    )
    release5 = build_release_with_files(
        ["test1"],
        workspace=workspace,
        backend=backend1,
        created_at=minutes_ago(now, 2),
    )
    # different backend, same file name, more recent
    release6 = build_release_with_files(
        ["test1"],
        workspace=workspace,
        backend=backend2,
        created_at=minutes_ago(now, 1),
    )

    output = releases.workspace_files(workspace)

    assert output == {
        "backend1/test1": release5.files.get(name="test1"),
        "backend1/test3": release4.files.get(name="test3"),
        "backend1/test2": release3.files.get(name="test2"),
        "backend2/test1": release6.files.get(name="test1"),
    }
コード例 #18
0
def test_validate_release_access_with_auth_header_and_invalid_token(rf):
    user = UserFactory()
    workspace = WorkspaceFactory()

    # set a token so the user is considered a bot
    user.rotate_token()

    request = rf.get("/", HTTP_AUTHORIZATION=f"{user.username}:invalid")
    request.user = AnonymousUser()

    with pytest.raises(PermissionDenied):
        validate_release_access(request, workspace)
コード例 #19
0
def test_snapshotpublishapi_unknown_snapshot(api_rf):
    workspace = WorkspaceFactory()

    request = api_rf.post("/")
    request.user = UserFactory(roles=[OutputPublisher])

    response = SnapshotPublishAPI.as_view()(
        request,
        workspace_id=workspace.name,
        snapshot_id=0,
    )

    assert response.status_code == 404
コード例 #20
0
def test_validate_upload_access_not_a_backend_member(rf):
    backend = BackendFactory()
    user = UserFactory(roles=[OutputChecker])
    workspace = WorkspaceFactory()

    request = rf.get(
        "/",
        HTTP_AUTHORIZATION=backend.auth_token,
        HTTP_OS_USER=user.username,
    )

    with pytest.raises(NotAuthenticated):
        validate_upload_access(request, workspace)
コード例 #21
0
def test_snapshotcreate_unknown_files(api_rf):
    workspace = WorkspaceFactory()
    user = UserFactory()
    ProjectMembershipFactory(
        project=workspace.project, user=user, roles=[ProjectDeveloper]
    )

    request = api_rf.post("/", data={"file_ids": ["test"]})
    request.user = user

    response = SnapshotCreateAPI.as_view()(request, workspace_id=workspace.name)

    assert response.status_code == 400, response.data
    assert "Unknown file IDs" in response.data["detail"], response.data
コード例 #22
0
def test_releaseworkspaceapi_post_create_release(api_rf, slack_messages):
    user = UserFactory(roles=[OutputChecker])
    workspace = WorkspaceFactory()
    ProjectMembershipFactory(user=user, project=workspace.project)

    backend = BackendFactory(auth_token="test", name="test-backend")
    BackendMembershipFactory(backend=backend, user=user)

    assert Release.objects.count() == 0

    data = {
        "files": [
            {
                "name": "file1.txt",
                "url": "url",
                "size": 7,
                "sha256": "hash",
                "date": timezone.now(),
                "metadata": {},
                "review": None,
            }
        ],
        "metadata": {},
        "review": None,
    }
    request = api_rf.post(
        "/",
        data=data,
        format="json",
        HTTP_AUTHORIZATION="test",
        HTTP_OS_USER=user.username,
    )

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

    assert response.status_code == 201, response.data
    assert Release.objects.count() == 1

    release = Release.objects.first()
    assert response["Release-Id"] == str(release.id)
    assert response["Location"] == f"http://testserver{release.get_api_url()}"

    assert len(slack_messages) == 1
    text, channel = slack_messages[0]

    assert channel == "opensafely-releases"
    assert f"{user.get_staff_url()}|{user.name}>" in text
    assert f"{release.get_absolute_url()}|release>" in text
    assert f"{workspace.get_absolute_url()}|{workspace.name}>" in text
    assert backend.name in text
コード例 #23
0
def test_validate_upload_access_no_permission(rf):
    backend = BackendFactory()
    user = UserFactory()
    workspace = WorkspaceFactory()

    BackendMembershipFactory(backend=backend, user=user)

    request = rf.get(
        "/",
        HTTP_AUTHORIZATION=backend.auth_token,
        HTTP_OS_USER=user.username,
    )

    with pytest.raises(NotAuthenticated):
        validate_upload_access(request, workspace)
コード例 #24
0
def test_snapshotcreate_with_existing_snapshot(api_rf, build_release_with_files):
    workspace = WorkspaceFactory()
    release = build_release_with_files(["file1.txt"])
    snapshot = SnapshotFactory(workspace=workspace)
    snapshot.files.set(release.files.all())

    user = UserFactory()
    ProjectMembershipFactory(
        project=workspace.project, user=user, roles=[ProjectDeveloper]
    )

    request = api_rf.post("/", data={"file_ids": [release.files.first().pk]})
    request.user = user

    response = SnapshotCreateAPI.as_view()(request, workspace_id=workspace.name)

    assert response.status_code == 400, response.data

    msg = "A release with the current files already exists"
    assert msg in response.data["detail"], response.data
コード例 #25
0
def test_releaseworkspaceapi_post_with_bad_json(api_rf):
    user = UserFactory(roles=[OutputChecker])
    workspace = WorkspaceFactory()
    ProjectMembershipFactory(user=user, project=workspace.project)

    backend = BackendFactory(auth_token="test")
    BackendMembershipFactory(backend=backend, user=user)

    request = api_rf.post(
        "/",
        content_type="application/json",
        data=json.dumps({}),
        HTTP_CONTENT_DISPOSITION="attachment; filename=release.zip",
        HTTP_AUTHORIZATION="test",
        HTTP_OS_USER=user.username,
    )

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

    assert response.status_code == 400
コード例 #26
0
def test_create_release_new_style_success():
    backend = BackendFactory()
    workspace = WorkspaceFactory()
    user = UserFactory()
    files = [{
        "name": "file1.txt",
        "path": "path/to/file1.txt",
        "url": "",
        "size": 7,
        "sha256": "hash",
        "date": "2022-08-17T13:37Z",
        "metadata": {},
    }]

    release = releases.create_release(workspace, backend, user, files)

    assert release.requested_files == files
    assert release.files.count() == 1

    rfile = release.files.first()
    rfile.filehash == "hash"
    rfile.size == 7
コード例 #27
0
def test_snapshotcreate_with_permission(api_rf, build_release_with_files):
    workspace = WorkspaceFactory()
    release = build_release_with_files(
        [
            "file1.txt",
            "file2.txt",
            "file3.txt",
            "file4.txt",
            "file5.txt",
        ],
        workspace=workspace,
    )

    user = UserFactory()
    ProjectMembershipFactory(
        project=workspace.project, user=user, roles=[ProjectDeveloper]
    )

    data = {
        "file_ids": [
            release.files.get(name="file1.txt").pk,
            release.files.get(name="file3.txt").pk,
            release.files.get(name="file5.txt").pk,
        ],
    }
    request = api_rf.post("/", data)
    request.user = user

    response = SnapshotCreateAPI.as_view()(request, workspace_id=workspace.name)

    assert response.status_code == 201

    workspace.refresh_from_db()

    assert workspace.snapshots.count() == 1

    snapshot_file_ids = set_from_qs(workspace.snapshots.first().files.all())
    current_file_ids = set_from_qs(workspace.files.all())
    assert snapshot_file_ids <= current_file_ids
コード例 #28
0
def test_jobrequestapilist_success(api_rf):
    workspace = WorkspaceFactory()

    # all completed
    job_request1 = JobRequestFactory(workspace=workspace)
    JobFactory.create_batch(2,
                            job_request=job_request1,
                            completed_at=timezone.now())

    # some completed
    job_request2 = JobRequestFactory(workspace=workspace)
    JobFactory(job_request=job_request2, completed_at=timezone.now())
    JobFactory(job_request=job_request2, completed_at=None)

    # none completed
    job_request3 = JobRequestFactory(workspace=workspace)
    JobFactory.create_batch(2, job_request=job_request3, completed_at=None)

    #  no jobs
    job_request4 = JobRequestFactory(workspace=workspace)

    assert JobRequest.objects.count() == 4

    request = api_rf.get("/")
    response = JobRequestAPIList.as_view()(request)

    assert response.status_code == 200
    assert response.data["count"] == 3
    assert len(response.data["results"]) == 3

    identifiers = {j["identifier"] for j in response.data["results"]}
    assert identifiers == {
        job_request2.identifier,
        job_request3.identifier,
        job_request4.identifier,
    }
コード例 #29
0
def test_workspace_files_no_releases():
    workspace = WorkspaceFactory()

    assert releases.workspace_files(workspace) == {}