Ejemplo n.º 1
0
def get_paginated_results(
    client: Client, resource: str, minimum=None, *args, **kwargs
) -> list:
    query_params = kwargs.get("query_params", {})

    results = []
    response = client.list(resource, *args, **kwargs)

    results += response["results"]

    if minimum and len(results) >= minimum:
        return results

    while response["next"]:
        next_url = urlparse(response["next"])
        query = parse_qs(next_url.query)
        new_page = int(query["page"][0])
        query_params["page"] = [new_page]
        kwargs["query_params"] = query_params
        response = client.list(resource, *args, **kwargs)
        results += response["results"]

        if minimum and len(results) >= minimum:
            return results

    return results
Ejemplo n.º 2
0
def test_set_client_base_url():
    Client.load_config(CONFIG_FILE)
    client = Client("client1")

    client.base_url = "https://another.example"

    assert client.base_url == "https://another.example"
Ejemplo n.º 3
0
 def ready(self):
     Client.load_config(
         vrl={
             'scheme': 'https',
             'host': 'ref.tst.vng.cloud',
             'port': 443,
             'auth': None,
         })
Ejemplo n.º 4
0
def test_client_loading():
    Client.load_config(zrc={
        "scheme": "http",
        "host": "localhost",
        "port": 8000
    })

    client = Client("zrc")
    assert client.base_url == "http://localhost:8000/api/v1/"
Ejemplo n.º 5
0
def test_client_from_url_thread_safe():
    client1 = Client.from_url(
        "https://example.com/api/v1/zaken/7C61204C-BFD8-4A66-B826-5DF8CB7F9A60"
    )
    client2 = Client.from_url(
        "https://example2.com/api/v2/zaken/7C61204C-BFD8-4A66-B826-5DF8CB7F9A60"
    )

    assert client1.base_url == "https://example.com/api/v1/"
    assert client2.base_url == "https://example2.com/api/v2/"
Ejemplo n.º 6
0
def test_client_from_static_config():
    Client.load_config(CONFIG_FILE)

    client = Client("client1")

    assert (
        repr(client) ==
        "<Client: service='client1' base_url='https://example.com/api/v1/'>")

    assert client.base_url == "https://example.com/api/v1/"
    assert client.auth.client_id == "some-client-id"
    assert client.auth.secret == "oh-no"
Ejemplo n.º 7
0
def test_client_loading():
    Client.load_config(zrc={
        'scheme': 'http',
        'host': 'localhost',
        'port': 8000,
    })

    client = Client('zrc')
    assert client.base_url == 'http://localhost:8000/api/v1/'

    # reset class
    # FIXME: this is very un-pythonic, find a better caching solution
    Client.CONFIG = None
Ejemplo n.º 8
0
def sync_delete_zio(relation: ZaakInformatieObject):
    zaak_url = get_absolute_url("zaak-detail", relation.zaak.uuid)

    logger.info("Zaak: %s", zaak_url)
    logger.info("Informatieobject: %s", relation.informatieobject)

    # Define the remote resource with which we need to interact
    resource = "objectinformatieobject"
    client = Client.from_url(relation.informatieobject)
    client.auth = APICredential.get_auth(relation.informatieobject)

    # Retrieve the url of the relation between the object and
    # the informatieobject
    response = client.list(
        resource,
        query_params={
            "object": zaak_url,
            "informatieobject": relation.informatieobject,
        },
    )
    try:
        relation_url = response[0]["url"]
    except IndexError as exc:
        msg = "No relations found in DRC for this Zaak"
        logger.error(msg, exc_info=1)
        raise IndexError(msg) from exc

    try:
        client.delete(resource, url=relation_url)
    except Exception as exc:
        logger.error(f"Could not delete remote relation", exc_info=1)
        raise SyncError(f"Could not delete remote relation") from exc
Ejemplo n.º 9
0
def test_load_with_auth():
    Client.load_config(
        zrc={
            "scheme": "http",
            "host": "localhost",
            "port": 8000,
            "auth": {"client_id": "foo", "secret": "bar"},
        }
    )

    client = Client("zrc")
    credentials = client.auth.credentials()

    assert "Authorization" in credentials
    bits = credentials["Authorization"].split(".")
    assert len(bits) == 3
Ejemplo n.º 10
0
def get_client(url: str, url_is_api_root=False) -> Optional[Client]:
    """
    Get a client instance for the given URL.

    If the setting CUSTOM_CLIENT_FETCHER is defined, then this callable is invoked.
    Otherwise we fall back on the default implementation.

    If no suitable client is found, ``None`` is returned.
    """
    custom_client_fetcher = getattr(settings, "CUSTOM_CLIENT_FETCHER", None)
    if custom_client_fetcher:
        client_getter = import_string(custom_client_fetcher)
        return client_getter(url)

    # default implementation
    Client = import_string(settings.ZDS_CLIENT_CLASS)

    if url_is_api_root and not url.endswith("/"):
        url = f"{url}/"

    client = Client.from_url(url)
    if client is None:
        return None

    APICredential = apps.get_model("vng_api_common", "APICredential")

    if url_is_api_root:
        client.base_url = url

    client.auth = APICredential.get_auth(url)
    return client
Ejemplo n.º 11
0
    def get_client(cls) -> Client:
        """
        Construct a client, prepared with the required auth.
        """
        config = cls.get_solo()

        if getattr(settings, "CUSTOM_CLIENT_FETCHER", None):
            client = import_string(settings.CUSTOM_CLIENT_FETCHER)(config.api_root)
            return client
        else:
            Client = import_string(settings.ZDS_CLIENT_CLASS)

            api_root = config.api_root
            if not api_root:
                raise ImproperlyConfigured(
                    f"Configure the API root in '{cls._meta.verbose_name}'"
                )

            if not api_root.endswith("/"):
                api_root = f"{api_root}/"

            client = Client.from_url(api_root)
            client.base_url = api_root
            client.auth = APICredential.get_auth(api_root)

            return client
Ejemplo n.º 12
0
def sync_create(relation: ZaakInformatieObject):
    operation = 'create'

    # build the URL of the Zaak
    path = reverse('zaak-detail',
                   kwargs={
                       'version': settings.REST_FRAMEWORK['DEFAULT_VERSION'],
                       'uuid': relation.zaak.uuid,
                   })
    domain = Site.objects.get_current().domain
    protocol = 'https' if settings.IS_HTTPS else 'http'
    zaak_url = f'{protocol}://{domain}{path}'

    logger.info("Zaak: %s", zaak_url)
    logger.info("Informatieobject: %s", relation.informatieobject)

    # Define the remote resource with which we need to interact
    resource = 'objectinformatieobject'
    client = Client.from_url(relation.informatieobject)
    client.auth = APICredential.get_auth(relation.informatieobject)

    try:
        client.create(
            resource, {
                'object': zaak_url,
                'informatieobject': relation.informatieobject,
                'objectType': 'zaak'
            })
    except Exception as exc:
        logger.error(f"Could not {operation} remote relation", exc_info=1)
        raise SyncError(f"Could not {operation} remote relation") from exc
def sync(relation: ObjectInformatieObject, operation: str):
    # build the URL of the informatieobject
    path = reverse('enkelvoudiginformatieobject-detail', kwargs={
        'version': settings.REST_FRAMEWORK['DEFAULT_VERSION'],
        'uuid': relation.informatieobject.uuid,
    })
    domain = Site.objects.get_current().domain
    protocol = 'https' if settings.IS_HTTPS else 'http'
    informatieobject_url = f'{protocol}://{domain}{path}'

    logger.info("Remote object: %s", relation.object)
    logger.info("Informatieobject: %s", informatieobject_url)

    # figure out which remote resource we need to interact with
    resource = f"{relation.object_type}informatieobject"
    client = Client.from_url(relation.object)

    try:
        pattern = get_operation_url(client.schema, f'{resource}_{operation}', pattern_only=True)
    except ValueError as exc:
        raise SyncError("Could not determine remote operation") from exc

    # we enforce in the standard that it's a subresource so that we can do this.
    # The real resource URL is extracted from the ``openapi.yaml`` based on
    # the operation
    params = extract_params(f"{relation.object}/irrelevant", pattern)

    try:
        operation_function = getattr(client, operation)
        operation_function(resource, {'informatieobject': informatieobject_url}, **params)
    except Exception as exc:
        logger.error(f"Could not {operation} remote relation", exc_info=1)
        raise SyncError(f"Could not {operation} remote relation") from exc
Ejemplo n.º 14
0
    def register(self) -> None:
        """
        Registers the webhook with the notification component.
        """
        dummy_detail_url = urljoin(self.config.api_root, f'foo/{uuid.uuid4()}')
        client = Client.from_url(dummy_detail_url)

        # This authentication is to create a subscription at the NC.
        client.auth = APICredential.get_auth(
            self.config.api_root, scopes=[SCOPE_NOTIFICATIES_CONSUMEREN_LABEL])

        # This authentication is for the NC to call us. Thus, it's *not* for
        # calling the NC to create a subscription.
        self_auth = ClientAuth(client_id=self.client_id,
                               secret=self.secret,
                               scopes=[SCOPE_NOTIFICATIES_PUBLICEREN_LABEL])
        data = {
            'callbackUrl':
            self.callback_url,
            'auth':
            self_auth.credentials()['Authorization'],
            'kanalen': [
                {
                    "naam": channel,
                    # FIXME: You need to be able to configure these.
                    "filters": {},
                } for channel in self.channels
            ],
        }

        # register the subscriber
        subscriber = client.create('abonnement', data=data)

        self._subscription = subscriber['url']
        self.save(update_fields=['_subscription'])
Ejemplo n.º 15
0
def sync_create_zaakcontactmoment(relation: ZaakContactMoment):
    zaak_url = get_absolute_url("zaak-detail", relation.zaak.uuid)

    logger.info("Zaak: %s", zaak_url)
    logger.info("Contactmoment: %s", relation.contactmoment)

    # Define the remote resource with which we need to interact
    resource = "objectcontactmoment"
    client = Client.from_url(relation.contactmoment)
    client.auth = APICredential.get_auth(relation.contactmoment)

    try:
        response = client.create(
            resource,
            {
                "object": zaak_url,
                "contactmoment": relation.contactmoment,
                "objectType": "zaak",
            },
        )
    except Exception as exc:
        logger.error(f"Could not create remote relation", exc_info=1)
        raise SyncError(f"Could not create remote relation") from exc

    # save ZaakBesluit url for delete signal
    relation._objectcontactmoment = response["url"]
    relation.save()
Ejemplo n.º 16
0
def test_regression_double_slashes():
    object_url = "http://example.com/api/v1/zaken/28dcfc90-2d26-4d4e-8261-a9202ee56185"
    client = Client.from_url(object_url)
    # prevents http request to fetch the schema
    client._schema = {
        "openapi": "3.0.0",
        "servers": [{"url": "/api/v1"}],
        "paths": {
            "/zaken/{zaak_uuid}/informatieobjecten": {
                "post": {"operationId": "zaakinformatieobject_create"}
            }
        },
    }
    pattern = get_operation_url(
        client.schema, "zaakinformatieobject_create", pattern_only=True
    )
    params = extract_params("{}/irrelevant".format(object_url), pattern)

    url = get_operation_url(
        client.schema, "zaakinformatieobject_create", base_url=client.base_url, **params
    )

    assert (
        url == "/api/v1/zaken/28dcfc90-2d26-4d4e-8261-a9202ee56185/informatieobjecten"
    )
Ejemplo n.º 17
0
def test_schema_with_local_references():
    Client.load_config(dummy={"scheme": "https", "host": "example.com"}, )
    client = Client("dummy")

    client._schema = {
        "openapi": "3.0.0",
        "servers": [{
            "url": "/api/v1"
        }],
        "paths": {
            "/api/packages/{packageId}": {
                "get": {
                    "tags": ["Packages"],
                    "operationId": "api.packages._packageId.get",
                    "summary": "Retrieves a specified package.",
                    "description":
                    "Retrieves information about a single document package.",
                    "parameters": [{
                        "$ref": "#/components/parameters/packageId"
                    }],
                }
            }
        },
        "components": {
            "parameters": {
                "packageId": {
                    "name": "packageId",
                    "description": "The unique package id.",
                    "in": "path",
                    "required": True,
                    "schema": {
                        "type": "string",
                        "example": "asd0sdf08gdfg3njkfg0345dg=",
                    },
                }
            }
        },
    }

    # Parameter #/components/parameters/packageId has value of 'in' != "headers", so no headers will be returned
    headers = get_headers(spec=client._schema,
                          operation="api.packages._packageId.get")
    assert headers == {}
Ejemplo n.º 18
0
def sync_delete_zaakverzoek(relation: ZaakVerzoek):
    resource = "objectverzoek"
    client = Client.from_url(relation.verzoek)
    client.auth = APICredential.get_auth(relation.verzoek)

    try:
        client.delete(resource, url=relation._objectverzoek)
    except Exception as exc:
        logger.error(f"Could not delete remote relation", exc_info=1)
        raise SyncError(f"Could not delete remote relation") from exc
Ejemplo n.º 19
0
def sync_delete_zaakcontactmoment(relation: ZaakContactMoment):
    resource = "objectcontactmoment"
    client = Client.from_url(relation.contactmoment)
    client.auth = APICredential.get_auth(relation.contactmoment)

    try:
        client.delete(resource, url=relation._objectcontactmoment)
    except Exception as exc:
        logger.error(f"Could not delete remote relation", exc_info=1)
        raise SyncError(f"Could not delete remote relation") from exc
Ejemplo n.º 20
0
def test_schema_non_required_header_params_in_local_references():
    Client.load_config(dummy={"scheme": "https", "host": "example.com"}, )
    client = Client("dummy")

    client._schema = {
        "openapi": "3.0.0",
        "servers": [{
            "url": "/api/v1"
        }],
        "paths": {
            "/api/packages/": {
                "get": {
                    "tags": ["Packages"],
                    "operationId": "api.packages._packageId.get",
                    "summary": "Retrieves a specified package.",
                    "description":
                    "Retrieves information about a single document package.",
                    "parameters": [{
                        "$ref": "#/components/parameters/testHeader"
                    }],
                }
            }
        },
        "components": {
            "parameters": {
                "testHeader": {
                    "in": "header",
                    "name": "Accept-Crs",
                    "description": "test param",
                    "schema": {
                        "type": "string",
                        "enum": ["EPSG:4326"]
                    },
                },
            }
        },
    }

    headers = get_headers(spec=client._schema,
                          operation="api.packages._packageId.get")
    assert headers == {}
Ejemplo n.º 21
0
def test_load_with_auth():
    Client.load_config(zrc={
        'scheme': 'http',
        'host': 'localhost',
        'port': 8000,
        'auth': {
            'client_id': 'foo',
            'secret': 'bar',
        }
    })

    client = Client('zrc')
    credentials = client.auth.credentials()

    assert 'Authorization' in credentials
    bits = credentials['Authorization'].split('.')
    assert len(bits) == 3

    # reset class
    # FIXME: this is very un-pythonic, find a better caching solution
    Client.CONFIG = None
Ejemplo n.º 22
0
    def get_client(self):
        """
        Return a properly configured `Client` instance.

        :return: A `Client` instance.
        """
        base_path = ''
        if self.base_url:
            o = urlparse(self.base_url)
            base_path = o.path

        return Client('ztc', base_path)
Ejemplo n.º 23
0
def test_partial_update_request():
    auth = {"client_id": "yes", "secret": "oh-no"}
    Client.load_config(dummy={
        "scheme": "https",
        "host": "example.com",
        "auth": auth
    })
    client = Client("dummy")
    client._schema = SCHEMA

    with requests_mock.Mocker() as m:
        m.patch(
            "https://example.com/api/v1/some-resource/1",
            json={"id": 1},
            status_code=200,
        )

        response = client.partial_update("some-resource",
                                         id=1,
                                         data={"foo": "bar"})

    assert response["id"] == 1
    assert m.last_request.json() == {"foo": "bar"}
    assert m.last_request.method == "PATCH"
    assert "Authorization" in m.last_request.headers
Ejemplo n.º 24
0
def test_create_request_extra_headers():
    auth = {"client_id": "yes", "secret": "oh-no"}
    Client.load_config(dummy={
        "scheme": "https",
        "host": "example.com",
        "auth": auth
    })
    client = Client("dummy")
    client._schema = SCHEMA

    with requests_mock.Mocker() as m:
        m.post("https://example.com/api/v1/some-resource",
               json={"id": 1},
               status_code=201)

        response = client.create(
            "some-resource",
            data={"foo": "bar"},
            request_kwargs={"headers": {
                "X-Api-Version": "1.0.2"
            }},
        )

    assert response["id"] == 1
    assert m.last_request.json() == {"foo": "bar"}
    assert m.last_request.headers["X-Api-Version"] == "1.0.2"
Ejemplo n.º 25
0
    def get_client(self, service):
        """
        Return a properly configured `Client` instance.

        :param service: The service key for this client.
        :return: A `Client` instance.
        """
        base_url = getattr(self, '{}_base_url'.format(service))
        base_path = ''
        if base_url:
            o = urlparse(base_url)
            base_path = o.path

        return Client(service, base_path)
Ejemplo n.º 26
0
    def __init__(self):
        config = {
            'zrc': {
                'scheme': settings.ZRC_SCHEME,
                'host': settings.ZRC_HOST,
                'port': settings.ZRC_PORT,
                'auth': settings.ZRC_AUTH,
            },
            'drc': {
                'scheme': settings.DRC_SCHEME,
                'host': settings.DRC_HOST,
                'port': settings.DRC_PORT,
                'auth': settings.DRC_AUTH,
            },
            'ztc': {
                'scheme': settings.ZTC_SCHEME,
                'host': settings.ZTC_HOST,
                'port': settings.ZTC_PORT,
                'auth': settings.ZTC_AUTH,
            }
        }

        Client.load_config(**config)
Ejemplo n.º 27
0
class SelectieLijstProcestypenListView(ZACViewMixin, TemplateView):
    template_name = 'demo/selectielijst/procestype_list.html'
    title = 'Selectielijst'
    subtitle = 'Procestypen/resultaten ter ondersteuning van ZTC'

    def _pre_dispatch(self, request, *args, **kwargs):
        self.vrl_client = Client('vrl', base_path='/referentielijsten/api/v1/')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        procestypen = self.vrl_client.list('procestype')

        context['rows'] = procestypen

        return context
Ejemplo n.º 28
0
def test_read_request_explicit_url():
    Client.load_config(dummy={"scheme": "https", "host": "example.com"})
    client = Client("dummy")
    client._schema = SCHEMA
    resource_url = "https://example.com/api/v1/some-resource/2"

    with requests_mock.Mocker() as m:
        m.get(resource_url, json={"ok": "yarp"})

        response = client.retrieve("some-resource", url=resource_url)

    assert response == {"ok": "yarp"}
    assert m.last_request.url == resource_url
def test_delete_request():
    auth = {"client_id": "yes", "secret": "oh-no"}
    Client.load_config(dummy={
        "scheme": "https",
        "host": "example.com",
        "auth": auth
    })
    client = Client("dummy")
    client._schema = SCHEMA

    with requests_mock.Mocker() as m:
        m.delete("https://example.com/api/v1/some-resource/1", status_code=204)

        client.delete("some-resource", id=1)

    assert m.last_request.method == "DELETE"
    assert "Authorization" in m.last_request.headers
Ejemplo n.º 30
0
def test_kwargs_forwarded_to_requests():
    Client.load_config(dummy={"scheme": "https", "host": "example.com"})
    client = Client("dummy")
    client._schema = SCHEMA

    with requests_mock.Mocker() as m:
        m.get("https://example.com/api/v1/some-resource", json=[{"ok": "yes"}])

        client.list(
            "some-resource",
            request_kwargs={"headers": {
                "Other-Header": "value",
            }},
        )

    assert "Other-Header" in m.last_request.headers
    assert m.last_request.headers["Other-Header"] == "value"