示例#1
0
def test_badge_endpoints_have_cors_header(client, origin, release):
    url = reverse("swh-badge",
                  url_args={
                      "object_type": "origin",
                      "object_id": origin["url"]
                  })

    resp = check_http_get_response(
        client,
        url,
        status_code=200,
        content_type="image/svg+xml",
        http_origin="https://example.org",
    )
    assert ACCESS_CONTROL_ALLOW_ORIGIN in resp

    release_swhid = str(
        QualifiedSWHID(object_type=ObjectType.RELEASE,
                       object_id=hash_to_bytes(release)))
    url = reverse("swh-badge-swhid", url_args={"object_swhid": release_swhid})
    resp = check_http_get_response(
        client,
        url,
        status_code=200,
        content_type="image/svg+xml",
        http_origin="https://example.org",
    )
    assert ACCESS_CONTROL_ALLOW_ORIGIN in resp
示例#2
0
def test_content_raw_text(client, archive_data, content):
    url = reverse("browse-content-raw",
                  url_args={"query_string": content["sha1"]})

    resp = check_http_get_response(client,
                                   url,
                                   status_code=200,
                                   content_type="text/plain")

    content_data = archive_data.content_get_data(content["sha1"])["data"]

    assert resp["Content-Type"] == "text/plain"
    assert resp["Content-disposition"] == ("filename=%s_%s" %
                                           ("sha1", content["sha1"]))
    assert resp.content == content_data

    filename = content["path"].split("/")[-1]

    url = reverse(
        "browse-content-raw",
        url_args={"query_string": content["sha1"]},
        query_params={"filename": filename},
    )

    resp = check_http_get_response(client,
                                   url,
                                   status_code=200,
                                   content_type="text/plain")

    assert resp["Content-Type"] == "text/plain"
    assert resp["Content-disposition"] == "filename=%s" % filename
    assert resp.content == content_data
示例#3
0
def test_content_raw_bin(client, archive_data, content):
    url = reverse("browse-content-raw",
                  url_args={"query_string": content["sha1"]})

    resp = check_http_get_response(client,
                                   url,
                                   status_code=200,
                                   content_type="application/octet-stream")

    filename = content["path"].split("/")[-1]
    content_data = archive_data.content_get_data(content["sha1"])["data"]

    assert resp["Content-Type"] == "application/octet-stream"
    assert resp["Content-disposition"] == "attachment; filename=%s_%s" % (
        "sha1",
        content["sha1"],
    )
    assert resp.content == content_data

    url = reverse(
        "browse-content-raw",
        url_args={"query_string": content["sha1"]},
        query_params={"filename": filename},
    )

    resp = check_http_get_response(client,
                                   url,
                                   status_code=200,
                                   content_type="application/octet-stream")

    assert resp["Content-Type"] == "application/octet-stream"
    assert resp["Content-disposition"] == "attachment; filename=%s" % filename
    assert resp.content == content_data
示例#4
0
def test_oidc_list_bearer_tokens_anonymous_user(client):
    """
    Anonymous user should be refused access with forbidden response.
    """
    url = reverse("oidc-list-bearer-tokens",
                  query_params={
                      "draw": 1,
                      "start": 0,
                      "length": 10
                  })
    check_http_get_response(client, url, status_code=403)
示例#5
0
def test_badge_errors(
    client,
    unknown_content,
    unknown_directory,
    new_origin,
    unknown_release,
    unknown_revision,
    unknown_snapshot,
    invalid_sha1,
):
    for object_type, object_id in (
        ("content", unknown_content["sha1_git"]),
        ("directory", unknown_directory),
        ("origin", new_origin),
        ("release", unknown_release),
        ("revision", unknown_revision),
        ("snapshot", unknown_snapshot),
    ):
        url_args = {"object_type": object_type, "object_id": object_id}
        url = reverse("swh-badge", url_args=url_args)
        resp = check_http_get_response(client,
                                       url,
                                       status_code=200,
                                       content_type="image/svg+xml")
        _check_generated_badge(resp, **url_args, error="not found")

    for object_type, object_id in (
        (ObjectType.CONTENT, invalid_sha1),
        (ObjectType.DIRECTORY, invalid_sha1),
        (ObjectType.RELEASE, invalid_sha1),
        (ObjectType.REVISION, invalid_sha1),
        (ObjectType.SNAPSHOT, invalid_sha1),
    ):
        url_args = {
            "object_type": object_type.name.lower(),
            "object_id": object_id
        }
        url = reverse("swh-badge", url_args=url_args)

        resp = check_http_get_response(client,
                                       url,
                                       status_code=200,
                                       content_type="image/svg+xml")
        _check_generated_badge(resp, **url_args, error="invalid id")

        object_swhid = f"swh:1:{object_type.value}:{object_id}"
        url = reverse("swh-badge-swhid",
                      url_args={"object_swhid": object_swhid})
        resp = check_http_get_response(client,
                                       url,
                                       status_code=200,
                                       content_type="image/svg+xml")
        _check_generated_badge(resp, "", "", error="invalid id")
示例#6
0
def test_graph_endpoint_no_authentication_for_vpn_users(
        api_client, requests_mock):
    graph_query = "stats"
    url = reverse("api-1-graph", url_args={"graph_query": graph_query})
    requests_mock.get(
        get_config()["graph"]["server_url"] + graph_query,
        json={},
        headers={"Content-Type": "application/json"},
    )
    check_http_get_response(api_client,
                            url,
                            status_code=200,
                            server_name=SWH_WEB_INTERNAL_SERVER_NAME)
示例#7
0
def test_api_content_uppercase(api_client, content):
    url = reverse("api-1-content-uppercase-checksum",
                  url_args={"q": content["sha1"].upper()})

    rv = check_http_get_response(api_client, url, status_code=302)
    redirect_url = reverse("api-1-content", url_args={"q": content["sha1"]})
    assert rv["location"] == redirect_url
示例#8
0
def test_graph_ndjson_response(api_client, keycloak_mock, requests_mock):
    _authenticate_graph_user(api_client, keycloak_mock)

    graph_query = "visit/paths/swh:1:dir:644dd466d8ad527ea3a609bfd588a3244e6dafcb"

    response_ndjson = textwrap.dedent("""\
        ["swh:1:dir:644dd466d8ad527ea3a609bfd588a3244e6dafcb",\
         "swh:1:cnt:acfb7cabd63b368a03a9df87670ece1488c8bce0"]
        ["swh:1:dir:644dd466d8ad527ea3a609bfd588a3244e6dafcb",\
         "swh:1:cnt:2a0837708151d76edf28fdbb90dc3eabc676cff3"]
        ["swh:1:dir:644dd466d8ad527ea3a609bfd588a3244e6dafcb",\
         "swh:1:cnt:eaf025ad54b94b2fdda26af75594cfae3491ec75"]
        """)

    requests_mock.get(
        get_config()["graph"]["server_url"] + graph_query,
        text=response_ndjson,
        headers={
            "Content-Type": "application/x-ndjson",
            "Transfer-Encoding": "chunked",
        },
    )

    url = reverse("api-1-graph", url_args={"graph_query": graph_query})

    resp = check_http_get_response(api_client, url, status_code=200)
    assert isinstance(resp, StreamingHttpResponse)
    assert resp["Content-Type"] == "application/x-ndjson"
    assert b"".join(resp.streaming_content) == response_ndjson.encode()
示例#9
0
def test_api_vault_cook_uppercase_hash(api_client, directory, revision):

    for obj_type, obj_id in (
        ("directory", directory),
        ("revision_gitfast", revision),
    ):

        url = reverse(
            f"api-1-vault-cook-{obj_type}-uppercase-checksum",
            url_args={f"{obj_type[:3]}_id": obj_id.upper()},
        )
        rv = check_http_post_response(api_client,
                                      url,
                                      data={"email": "*****@*****.**"},
                                      status_code=302)

        redirect_url = reverse(f"api-1-vault-cook-{obj_type}",
                               url_args={f"{obj_type[:3]}_id": obj_id})

        assert rv["location"] == redirect_url

        fetch_url = reverse(
            f"api-1-vault-fetch-{obj_type}-uppercase-checksum",
            url_args={f"{obj_type[:3]}_id": obj_id.upper()},
        )

        rv = check_http_get_response(api_client, fetch_url, status_code=302)

        redirect_url = reverse(
            f"api-1-vault-fetch-{obj_type}",
            url_args={f"{obj_type[:3]}_id": obj_id},
        )

        assert rv["location"] == redirect_url
示例#10
0
def test_graph_endpoint_needs_permission(api_client, keycloak_mock,
                                         requests_mock):
    graph_query = "stats"
    url = reverse("api-1-graph", url_args={"graph_query": graph_query})
    oidc_profile = keycloak_mock.login()
    api_client.credentials(
        HTTP_AUTHORIZATION=f"Bearer {oidc_profile['refresh_token']}")

    check_http_get_response(api_client, url, status_code=403)

    _authenticate_graph_user(api_client, keycloak_mock)
    requests_mock.get(
        get_config()["graph"]["server_url"] + graph_query,
        json={},
        headers={"Content-Type": "application/json"},
    )
    check_http_get_response(api_client, url, status_code=200)
示例#11
0
def _generate_and_test_bearer_token(client, kc_oidc_mock):
    # user authenticates
    client.login(code="code",
                 code_verifier="code-verifier",
                 redirect_uri="redirect-uri")
    # user initiates bearer token generation flow
    url = reverse("oidc-generate-bearer-token")
    response = check_http_get_response(client, url, status_code=302)
    request = response.wsgi_request
    redirect_uri = reverse("oidc-generate-bearer-token-complete",
                           request=request)
    # check login data and redirection to Keycloak is valid
    login_data = _check_oidc_login_code_flow_data(
        request,
        response,
        kc_oidc_mock,
        redirect_uri=redirect_uri,
        scope="openid offline_access",
    )

    # once a user has identified himself in Keycloak, he is
    # redirected to the 'oidc-generate-bearer-token-complete' view
    # to get and save bearer token

    # generate authorization code / session state in the same
    # manner as Keycloak
    code = f"{str(uuid.uuid4())}.{str(uuid.uuid4())}.{str(uuid.uuid4())}"
    session_state = str(uuid.uuid4())

    token_complete_url = reverse(
        "oidc-generate-bearer-token-complete",
        query_params={
            "code": code,
            "state": login_data["state"],
            "session_state": session_state,
        },
    )

    nb_tokens = len(OIDCUserOfflineTokens.objects.all())
    response = check_html_get_response(client,
                                       token_complete_url,
                                       status_code=302)
    request = response.wsgi_request

    # check token has been generated and saved encrypted to database
    assert len(OIDCUserOfflineTokens.objects.all()) == nb_tokens + 1
    encrypted_token = OIDCUserOfflineTokens.objects.last().offline_token
    secret = get_config()["secret_key"].encode()
    salt = request.user.sub.encode()
    decrypted_token = decrypt_data(encrypted_token, secret, salt)
    oidc_profile = kc_oidc_mock.authorization_code(code=code,
                                                   redirect_uri=redirect_uri)
    assert decrypted_token.decode("ascii") == oidc_profile["refresh_token"]

    # should redirect to tokens management Web UI
    assert response["location"] == reverse("oidc-profile") + "#tokens"

    return decrypted_token
示例#12
0
def test_api_revision_uppercase(api_client, revision):
    url = reverse("api-1-revision-uppercase-checksum",
                  url_args={"sha1_git": revision.upper()})

    resp = check_http_get_response(api_client, url, status_code=302)

    redirect_url = reverse("api-1-revision", url_args={"sha1_git": revision})

    assert resp["location"] == redirect_url
示例#13
0
def test_api_revision_raw_ok(api_client, archive_data, revision):
    url = reverse("api-1-revision-raw-message",
                  url_args={"sha1_git": revision})

    expected_message = archive_data.revision_get(revision)["message"]

    rv = check_http_get_response(api_client, url, status_code=200)
    assert rv["Content-Type"] == "application/octet-stream"
    assert rv.content == expected_message.encode()
示例#14
0
def test_layout_without_oidc_auth_enabled(client, mocker):
    config = deepcopy(get_config())
    config["keycloak"]["server_url"] = ""
    mock_get_config = mocker.patch("swh.web.common.utils.get_config")
    mock_get_config.return_value = config

    url = reverse("swh-web-homepage")
    resp = check_http_get_response(client, url, status_code=200)
    assert_contains(resp, reverse("login"))
示例#15
0
def test_api_directory_uppercase(api_client, directory):
    url = reverse(
        "api-1-directory-uppercase-checksum", url_args={"sha1_git": directory.upper()}
    )

    resp = check_http_get_response(api_client, url, status_code=302)

    redirect_url = reverse("api-1-directory", url_args={"sha1_git": directory})

    assert resp["location"] == redirect_url
示例#16
0
def test_api_content_raw_text(api_client, archive_data, content):
    url = reverse("api-1-content-raw",
                  url_args={"q": "sha1:%s" % content["sha1"]})

    rv = check_http_get_response(api_client, url, status_code=200)
    assert rv["Content-Type"] == "application/octet-stream"
    assert (rv["Content-disposition"] ==
            "attachment; filename=content_sha1_%s_raw" % content["sha1"])
    expected_data = archive_data.content_get_data(content["sha1"])
    assert rv.content == expected_data["data"]
示例#17
0
def test_api_snapshot_uppercase(api_client, snapshot):
    url = reverse("api-1-snapshot-uppercase-checksum",
                  url_args={"snapshot_id": snapshot.upper()})

    resp = check_http_get_response(api_client, url, status_code=302)

    redirect_url = reverse("api-1-snapshot-uppercase-checksum",
                           url_args={"snapshot_id": snapshot})

    assert resp["location"] == redirect_url
示例#18
0
def test_content_raw_no_utf8_text(client, content):
    url = reverse("browse-content-raw",
                  url_args={"query_string": content["sha1"]})

    resp = check_http_get_response(client,
                                   url,
                                   status_code=200,
                                   content_type="text/plain")
    _, encoding = get_mimetype_and_encoding_for_content(resp.content)
    assert encoding == content["encoding"]
示例#19
0
def _test_badge_endpoints(client, object_type: str, object_id: str):
    url_args = {"object_type": object_type, "object_id": object_id}
    url = reverse("swh-badge", url_args=url_args)
    resp = check_http_get_response(client,
                                   url,
                                   status_code=200,
                                   content_type="image/svg+xml")
    _check_generated_badge(resp, **url_args)

    if object_type != "origin":
        obj_swhid = str(
            QualifiedSWHID(
                object_type=ObjectType[object_type.upper()],
                object_id=hash_to_bytes(object_id),
            ))
        url = reverse("swh-badge-swhid", url_args={"object_swhid": obj_swhid})
        resp = check_http_get_response(client,
                                       url,
                                       status_code=200,
                                       content_type="image/svg+xml")
        _check_generated_badge(resp, **url_args)
示例#20
0
def test_reject_pending_save_request(client, mocker):
    mock_scheduler = mocker.patch("swh.web.common.origin_save.scheduler")
    visit_type = "git"
    origin_url = "https://wikipedia.com"
    save_request_url = reverse(
        "api-1-save-origin",
        url_args={
            "visit_type": visit_type,
            "origin_url": origin_url
        },
    )

    response = check_http_post_response(client,
                                        save_request_url,
                                        status_code=200)
    assert response.data["save_request_status"] == SAVE_REQUEST_PENDING

    reject_request_url = reverse(
        "admin-origin-save-request-reject",
        url_args={
            "visit_type": visit_type,
            "origin_url": origin_url
        },
    )

    check_not_login(client, reject_request_url)

    client.login(username=_user_name, password=_user_password)
    response = check_http_post_response(client,
                                        reject_request_url,
                                        status_code=200)

    tasks_data = [{
        "priority": "high",
        "policy": "oneshot",
        "type": "load-git",
        "arguments": {
            "kwargs": {
                "repo_url": origin_url
            },
            "args": []
        },
        "status": "next_run_not_scheduled",
        "id": 1,
    }]

    mock_scheduler.create_tasks.return_value = tasks_data
    mock_scheduler.get_tasks.return_value = tasks_data

    response = check_http_get_response(client,
                                       save_request_url,
                                       status_code=200)
    assert response.data[0]["save_request_status"] == SAVE_REQUEST_REJECTED
示例#21
0
def test_api_vault_cook(api_client, mocker, directory, revision):
    mock_archive = mocker.patch("swh.web.api.views.vault.archive")

    for obj_type, obj_id in (
        ("directory", directory),
        ("revision_gitfast", revision),
    ):

        fetch_url = reverse(
            f"api-1-vault-fetch-{obj_type}",
            url_args={f"{obj_type[:3]}_id": obj_id},
        )
        stub_cook = {
            "type": obj_type,
            "progress_msg": None,
            "task_id": 1,
            "task_status": "done",
            "object_id": obj_id,
        }
        stub_fetch = b"content"

        mock_archive.vault_cook.return_value = stub_cook
        mock_archive.vault_fetch.return_value = stub_fetch

        email = "*****@*****.**"
        url = reverse(
            f"api-1-vault-cook-{obj_type}",
            url_args={f"{obj_type[:3]}_id": obj_id},
            query_params={"email": email},
        )

        rv = check_api_post_responses(api_client,
                                      url,
                                      data=None,
                                      status_code=200)
        assert rv.data == {
            "fetch_url": rv.wsgi_request.build_absolute_uri(fetch_url),
            "obj_type": obj_type,
            "progress_message": None,
            "id": 1,
            "status": "done",
            "obj_id": obj_id,
        }
        mock_archive.vault_cook.assert_called_with(
            obj_type, hashutil.hash_to_bytes(obj_id), email)

        rv = check_http_get_response(api_client, fetch_url, status_code=200)
        assert rv["Content-Type"] == "application/gzip"
        assert rv.content == stub_fetch
        mock_archive.vault_fetch.assert_called_with(
            obj_type, hashutil.hash_to_bytes(obj_id))
示例#22
0
def test_graph_json_response(api_client, keycloak_mock, requests_mock):
    _authenticate_graph_user(api_client, keycloak_mock)

    graph_query = "stats"

    requests_mock.get(
        get_config()["graph"]["server_url"] + graph_query,
        json=_response_json,
        headers={"Content-Type": "application/json"},
    )

    url = reverse("api-1-graph", url_args={"graph_query": graph_query})

    resp = check_http_get_response(api_client, url, status_code=200)
    assert resp.content_type == "application/json"
    assert resp.content == json.dumps(_response_json).encode()
示例#23
0
def test_drf_django_session_auth_success(keycloak_mock, client):
    """
    Check user gets authenticated when querying the web api
    through a web browser.
    """
    url = reverse("api-1-stat-counters")

    client.login(code="", code_verifier="", redirect_uri="")

    response = check_http_get_response(client, url, status_code=200)
    request = response.wsgi_request

    # user should be authenticated
    assert isinstance(request.user, OIDCUser)

    # check remoter used has not been saved to Django database
    with pytest.raises(User.DoesNotExist):
        User.objects.get(username=request.user.username)
示例#24
0
def test_graph_text_plain_response(api_client, keycloak_mock, requests_mock):
    _authenticate_graph_user(api_client, keycloak_mock)

    graph_query = "leaves/swh:1:dir:432d1b21c1256f7408a07c577b6974bbdbcc1323"

    response_text = textwrap.dedent("""\
        swh:1:cnt:1d3dace0a825b0535c37c53ed669ef817e9c1b47
        swh:1:cnt:6d5b280f4e33589ae967a7912a587dd5cb8dedaa
        swh:1:cnt:91bef238bf01356a550d416d14bb464c576ac6f4
        swh:1:cnt:58a8b925a463b87d49639fda282b8f836546e396
        swh:1:cnt:fd32ee0a87e16ccc853dfbeb7018674f9ce008c0
        swh:1:cnt:ab7c39871872589a4fc9e249ebc927fb1042c90d
        swh:1:cnt:93073c02bf3869845977527de16af4d54765838d
        swh:1:cnt:4251f795b52c54c447a97c9fe904d8b1f993b1e0
        swh:1:cnt:c6e7055424332006d07876ffeba684e7e284b383
        swh:1:cnt:8459d8867dc3b15ef7ae9683e21cccc9ab2ec887
        swh:1:cnt:5f9981d52202815aa947f85b9dfa191b66f51138
        swh:1:cnt:00a685ec51bcdf398c15d588ecdedb611dbbab4b
        swh:1:cnt:e1cf1ea335106a0197a2f92f7804046425a7d3eb
        swh:1:cnt:07069b38087f88ec192d2c9aff75a502476fd17d
        swh:1:cnt:f045ee845c7f14d903a2c035b2691a7c400c01f0
        """)

    requests_mock.get(
        get_config()["graph"]["server_url"] + graph_query,
        text=response_text,
        headers={
            "Content-Type": "text/plain",
            "Transfer-Encoding": "chunked"
        },
    )

    url = reverse("api-1-graph", url_args={"graph_query": graph_query})

    resp = check_http_get_response(api_client,
                                   url,
                                   status_code=200,
                                   content_type="text/plain")
    assert isinstance(resp, StreamingHttpResponse)
    assert b"".join(resp.streaming_content) == response_text.encode()
示例#25
0
def test_oidc_list_bearer_tokens(client, keycloak_mock):
    """
    User with correct credentials should be allowed to list his tokens.
    """
    nb_tokens = 3

    for _ in range(nb_tokens):
        _generate_and_test_bearer_token(client, keycloak_mock)

    url = reverse("oidc-list-bearer-tokens",
                  query_params={
                      "draw": 1,
                      "start": 0,
                      "length": 10
                  })

    response = check_http_get_response(client, url, status_code=200)
    tokens_data = list(
        reversed(json.loads(response.content.decode("utf-8"))["data"]))

    for oidc_token in OIDCUserOfflineTokens.objects.all():
        assert (oidc_token.creation_date.isoformat() == tokens_data[
            oidc_token.id - 1]["creation_date"])
示例#26
0
def test_api_endpoints_have_cors_headers(client, content, directory, revision):
    url = reverse("api-1-stat-counters")

    resp = check_http_get_response(client,
                                   url,
                                   status_code=200,
                                   http_origin="https://example.org")
    assert ACCESS_CONTROL_ALLOW_ORIGIN in resp

    swhids = [
        gen_swhid(CONTENT, content["sha1_git"]),
        gen_swhid(DIRECTORY, directory),
        gen_swhid(REVISION, revision),
    ]
    url = reverse("api-1-known")
    ac_request_method = "POST"
    ac_request_headers = "Content-Type"
    resp = client.options(
        url,
        HTTP_ORIGIN="https://example.org",
        HTTP_ACCESS_CONTROL_REQUEST_METHOD=ac_request_method,
        HTTP_ACCESS_CONTROL_REQUEST_HEADERS=ac_request_headers,
    )

    assert resp.status_code == 200
    assert ACCESS_CONTROL_ALLOW_ORIGIN in resp
    assert ACCESS_CONTROL_ALLOW_METHODS in resp
    assert ac_request_method in resp[ACCESS_CONTROL_ALLOW_METHODS]
    assert ACCESS_CONTROL_ALLOW_HEADERS in resp
    assert ac_request_headers.lower() in resp[ACCESS_CONTROL_ALLOW_HEADERS]

    resp = resp = check_http_post_response(client,
                                           url,
                                           data=swhids,
                                           status_code=200,
                                           http_origin="https://example.org")
    assert ACCESS_CONTROL_ALLOW_ORIGIN in resp
示例#27
0
def test_layout_with_staging_ribbon(client):
    url = reverse("swh-web-homepage")
    resp = check_http_get_response(
        client, url, status_code=200, server_name=random.choice(STAGING_SERVER_NAMES),
    )
    assert_contains(resp, "swh-corner-ribbon")
示例#28
0
def test_layout_with_oidc_auth_enabled(client):
    url = reverse("swh-web-homepage")
    resp = check_http_get_response(client, url, status_code=200)
    assert_contains(resp, reverse("oidc-login"))
示例#29
0
def test_layout_without_staging_ribbon(client):
    url = reverse("swh-web-homepage")
    resp = check_http_get_response(client, url, status_code=200)
    assert_not_contains(resp, "swh-corner-ribbon")
示例#30
0
def test_old_save_url_redirection(client):
    url = reverse("browse-origin-save")
    redirect_url = reverse("origin-save")

    resp = check_http_get_response(client, url, status_code=302)
    assert resp["location"] == redirect_url