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/"
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" )
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()
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
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'])
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
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_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
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
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
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
def get_client(cls) -> Client: """ Construct a client, prepared with the required auth. """ config = cls.get_solo() 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 return client
def sync_delete(relation: ZaakInformatieObject): operation = 'delete' # 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) # 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 {operation} remote relation", exc_info=1) raise SyncError(f"Could not {operation} remote relation") from exc
def sync_create_vio(relation: VerzoekInformatieObject): operation = "create" # build the URL of the Verzoek path = reverse( "verzoek-detail", kwargs={ "version": settings.REST_FRAMEWORK["DEFAULT_VERSION"], "uuid": relation.verzoek.uuid, }, ) domain = Site.objects.get_current().domain protocol = "https" if settings.IS_HTTPS else "http" verzoek_url = f"{protocol}://{domain}{path}" logger.info("Verzoek: %s", verzoek_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) # TODO? client.auth = APICredential.get_auth(relation.informatieobject) try: operation_function = getattr(client, operation) operation_function( resource, { "object": verzoek_url, "informatieobject": relation.informatieobject, "objectType": "verzoek", }, ) 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_delete_vio(relation: VerzoekInformatieObject): operation = "delete" # build the URL of the Verzoek path = reverse( "verzoek-detail", kwargs={ "version": settings.REST_FRAMEWORK["DEFAULT_VERSION"], "uuid": relation.verzoek.uuid, }, ) domain = Site.objects.get_current().domain protocol = "https" if settings.IS_HTTPS else "http" verzoek_url = f"{protocol}://{domain}{path}" logger.info("Verzoek: %s", verzoek_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 response = client.list(resource, query_params={"object": verzoek_url}) try: relation_url = response[0]["url"] except IndexError as exc: msg = "No relations found in DRC for this Verzoek" logger.error(msg, exc_info=1) raise IndexError(msg) from exc try: operation_function = getattr(client, operation) operation_function(resource, url=relation_url) 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_create_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) try: client.create( resource, { "object": zaak_url, "informatieobject": relation.informatieobject, "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
def test_client_from_detail_url(detail_url, expected_base_path): client = Client.from_url(detail_url) assert client.base_path == expected_base_path