예제 #1
0
    def validate(self, attrs):
        validated_attrs = super().validate(attrs)
        status_type_url = validated_attrs['status_type']

        # dynamic so that it can be mocked in tests easily
        Client = import_string(settings.ZDS_CLIENT_CLASS)
        client = Client.from_url(status_type_url)
        client.auth = APICredential.get_auth(
            status_type_url, scopes=['zds.scopes.zaaktypes.lezen'])

        try:
            status_type = client.retrieve('statustype', url=status_type_url)
            validated_attrs['__is_eindstatus'] = status_type['isEindstatus']
        except requests.HTTPError as exc:
            raise serializers.ValidationError(
                exc.args[0], code='relation-validation-error') from exc
        except KeyError as exc:
            raise serializers.ValidationError(
                exc.args[0], code='relation-validation-error') from exc

        # validate that all InformationObjects have indicatieGebruiksrecht set
        if validated_attrs['__is_eindstatus']:
            zaak = validated_attrs['zaak']
            zios = zaak.zaakinformatieobject_set.all()
            for zio in zios:
                io_url = zio.informatieobject
                client = Client.from_url(io_url)
                client.auth = APICredential.get_auth(
                    io_url, scopes=['zds.scopes.zaaktypes.lezen'])
                informatieobject = client.retrieve(
                    'enkelvoudiginformatieobject', url=io_url)
                if informatieobject['indicatieGebruiksrecht'] is None:
                    raise serializers.ValidationError(
                        "Er zijn gerelateerde informatieobjecten waarvoor `indicatieGebruiksrecht` nog niet "
                        "gespecifieerd is. Je moet deze zetten voor je de zaak kan afsluiten.",
                        code='indicatiegebruiksrecht-unset')

            brondatum_calculator = BrondatumCalculator(
                zaak, validated_attrs['datum_status_gezet'])
            try:
                brondatum_calculator.calculate()
            except Resultaat.DoesNotExist as exc:
                raise serializers.ValidationError(
                    exc.args[0], code='resultaat-does-not-exist') from exc
            except DetermineProcessEndDateException as exc:
                # ideally, we'd like to do this in the validate function, but that's unfortunately too
                # early since we don't know the end date yet
                # thought: we _can_ use the datumStatusGezet though!
                raise serializers.ValidationError(
                    exc.args[0], code='archiefactiedatum-error')

            # nasty to pass state around...
            self.context['brondatum_calculator'] = brondatum_calculator

        return validated_attrs
예제 #2
0
    def fetch_object(url: str, do_underscoreize=True) -> dict:
        from vng_api_common.models import APICredential

        client_auth = APICredential.get_auth(url)
        headers = client_auth.credentials() if client_auth else {}

        try:
            response = requests.get(url, headers=headers)
        except requests.exceptions.RequestException as exc:
            raise FetchError(exc.args[0]) from exc

        try:
            response.raise_for_status()
        except requests.HTTPError as exc:
            raise FetchError(exc.args[0]) from exc

        try:
            data = response.json()
        except json.JSONDecodeError as exc:
            raise FetchJsonError(exc.args[0]) from exc

        if not do_underscoreize:
            return data

        return underscoreize(data)
예제 #3
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
예제 #4
0
def get_ztc_auth(url: str) -> dict:
    logger.info("Authenticating for %s", url)
    auth = APICredential.get_auth(url, scopes=["zds.scopes.zaaktypes.lezen"])
    if auth is None:
        logger.warning("Could not authenticate for %s", url)
        return {}
    return auth.credentials()
    def __call__(self, context: OrderedDict):
        object_url = context['object']
        informatieobject_uuid = str(
            context['informatieobject'].latest_version.uuid)
        object_type = context['object_type']

        informatieobject_url = get_absolute_url(
            'enkelvoudiginformatieobject-detail', uuid=informatieobject_uuid)

        # dynamic so that it can be mocked in tests easily
        Client = import_string(settings.ZDS_CLIENT_CLASS)
        client = Client.from_url(object_url)
        client.auth = APICredential.get_auth(object_url)
        try:
            if object_type == 'zaak':
                resource = 'zaakinformatieobject'
                component = 'ZRC'
            elif object_type == 'besluit':
                resource = 'besluitinformatieobject'
                component = 'BRC'
            oios = client.list(resource,
                               query_params={
                                   object_type: object_url,
                                   'informatieobject': informatieobject_url
                               })

        except ClientError as exc:
            raise serializers.ValidationError(
                exc.args[0], code='relation-validation-error') from exc

        if len(oios) == 0:
            raise serializers.ValidationError(
                self.message.format(component=component), code=self.code)
    def __call__(self, object_informatie_object: ObjectInformatieObject):
        object_url = object_informatie_object.object

        informatieobject_url = get_absolute_url(
            'enkelvoudiginformatieobject-detail',
            uuid=object_informatie_object.informatieobject.latest_version.uuid)

        Client = import_string(settings.ZDS_CLIENT_CLASS)
        client = Client.from_url(object_url)
        client.auth = APICredential.get_auth(object_url)

        resource = f"{object_informatie_object.object_type}informatieobject"

        try:
            relations = client.list(resource,
                                    query_params={
                                        object_informatie_object.object_type:
                                        object_url,
                                        'informatieobject':
                                        informatieobject_url,
                                    })
        except ClientError as exc:
            raise serializers.ValidationError(
                exc.args[0], code='relation-lookup-error') from exc

        if len(relations) >= 1:
            raise serializers.ValidationError(self.message, code=self.code)
예제 #7
0
    def __call__(self, objectklantinteractie: ObjectContactMoment):
        object_url = objectklantinteractie.object
        klantinteractie_uuid = getattr(objectklantinteractie,
                                       self.resource_name).uuid
        klantinteractie_url = get_absolute_url(f"{self.resource_name}-detail",
                                               uuid=klantinteractie_uuid)

        Client = import_string(settings.ZDS_CLIENT_CLASS)
        client = Client.from_url(object_url)
        client.auth = APICredential.get_auth(object_url)

        resource = f"{objectklantinteractie.object_type}{self.resource_name}"

        try:
            relations = client.list(
                resource,
                query_params={
                    objectklantinteractie.object_type: object_url,
                    f"{self.resource_name}": klantinteractie_url,
                },
            )
        except ClientError as exc:
            raise serializers.ValidationError(
                exc.args[0], code="relation-lookup-error") from exc

        if len(relations) >= 1:
            raise serializers.ValidationError(self.message, code=self.code)
예제 #8
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()
예제 #9
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
예제 #10
0
def get_auth(url: str) -> dict:
    logger.info("Authenticating for %s", url)
    auth = APICredential.get_auth(url)
    if auth is None:
        logger.warning("Could not authenticate for %s", url)
        return {}
    return auth.credentials()
예제 #11
0
def delete_remote_oio(oio_url: str) -> None:
    client_auth = APICredential.get_auth(oio_url)
    if client_auth is None:
        logger.warning("Missing credentials for %s", oio_url)
    headers = client_auth.credentials() if client_auth else {}

    response = requests.delete(oio_url, headers=headers)
    response.raise_for_status()
예제 #12
0
def fetch_object(resource: str, url: str) -> dict:
    """
    Fetch a remote object by URL.
    """
    Client = import_string(settings.ZDS_CLIENT_CLASS)
    client = Client.from_url(url)
    client.auth = APICredential.get_auth(url)
    obj = client.retrieve(resource, url=url)
    return obj
예제 #13
0
 def _get_zaaktype(self, zaaktype_url: str) -> dict:
     if not hasattr(self, "_zaaktype"):
         # dynamic so that it can be mocked in tests easily
         Client = import_string(settings.ZDS_CLIENT_CLASS)
         client = Client.from_url(zaaktype_url)
         client.auth = APICredential.get_auth(
             zaaktype_url, scopes=["zds.scopes.zaaktypes.lezen"])
         self._zaaktype = client.request(zaaktype_url, "zaaktype")
     return self._zaaktype
예제 #14
0
 def _get_eigenschap(self, eigenschap_url):
     if not hasattr(self, "_eigenschap"):
         self._eigenschap = None
         if eigenschap_url:
             Client = import_string(settings.ZDS_CLIENT_CLASS)
             client = Client.from_url(eigenschap_url)
             client.auth = APICredential.get_auth(
                 eigenschap_url, scopes=["zds.scopes.zaaktypes.lezen"])
             self._eigenschap = client.request(eigenschap_url, "eigenschap")
     return self._eigenschap
예제 #15
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
예제 #16
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
예제 #17
0
    def _derive_roltype_attributes(self):
        if self.omschrijving and self.omschrijving_generiek:
            return

        Client = import_string(settings.ZDS_CLIENT_CLASS)
        client = Client.from_url(self.roltype)
        client.auth = APICredential.get_auth(self.roltype)
        roltype = client.retrieve("roltype", url=self.roltype)

        self.omschrijving = roltype["omschrijving"]
        self.omschrijving_generiek = roltype["omschrijvingGeneriek"]
예제 #18
0
 def _get_informatieobjecttype(self, informatieobjecttype_url: str) -> dict:
     if not hasattr(self, 'informatieobjecttype'):
         # dynamic so that it can be mocked in tests easily
         Client = import_string(settings.ZDS_CLIENT_CLASS)
         client = Client.from_url(informatieobjecttype_url)
         client.auth = APICredential.get_auth(
             informatieobjecttype_url,
             scopes=['zds.scopes.zaaktypes.lezen']
         )
         self._informatieobjecttype = client.request(informatieobjecttype_url, 'informatieobjecttype')
     return self._informatieobjecttype
 def _get_resultaat_type(self, resultaat_type_url):
     if not hasattr(self, '_resultaat_type'):
         self._resultaat_type = None
         if resultaat_type_url:
             Client = import_string(settings.ZDS_CLIENT_CLASS)
             client = Client.from_url(resultaat_type_url)
             client.auth = APICredential.get_auth(
                 resultaat_type_url, scopes=['zds.scopes.zaaktypes.lezen'])
             self._resultaat_type = client.request(resultaat_type_url,
                                                   'resultaattype')
     return self._resultaat_type
예제 #20
0
 def _get_resultaattype(self, resultaattype_url: str):
     if not hasattr(self, "_resultaattype"):
         self._resultaattype = None
         if resultaattype_url:
             Client = import_string(settings.ZDS_CLIENT_CLASS)
             client = Client.from_url(resultaattype_url)
             client.auth = APICredential.get_auth(
                 resultaattype_url, scopes=["zds.scopes.zaaktypes.lezen"])
             self._resultaattype = client.retrieve("resultaattype",
                                                   url=resultaattype_url)
     return self._resultaattype
예제 #21
0
def create_remote_zaakbesluit(besluit_url: str, zaak_url: str) -> dict:
    client_auth = APICredential.get_auth(zaak_url)
    if client_auth is None:
        logger.warning("Missing credentials for %s", zaak_url)

    list_url = f"{zaak_url}/besluiten"
    headers = client_auth.credentials() if client_auth else {}
    body = {"besluit": besluit_url}

    response = requests.post(list_url, json=body, headers=headers)
    response.raise_for_status()
    return response.json()
    def validate(self, attrs):
        validated_attrs = super().validate(attrs)
        status_type_url = validated_attrs['status_type']

        # dynamic so that it can be mocked in tests easily
        Client = import_string(settings.ZDS_CLIENT_CLASS)
        client = Client.from_url(status_type_url)
        client.auth = APICredential.get_auth(
            status_type_url, scopes=['zds.scopes.zaaktypes.lezen'])

        try:
            status_type = client.request(status_type_url, 'statustype')
            validated_attrs['__is_eindstatus'] = status_type['isEindstatus']
        except requests.HTTPError as exc:
            raise serializers.ValidationError(
                exc.args[0], code='relation-validation-error') from exc
        except KeyError as exc:
            raise serializers.ValidationError(
                exc.args[0], code='relation-validation-error') from exc

        # validate that all InformationObjects have indicatieGebruiksrecht set
        if validated_attrs['__is_eindstatus']:
            zios = validated_attrs['zaak'].zaakinformatieobject_set.all()
            for zio in zios:
                io_url = zio.informatieobject
                client = Client.from_url(io_url)
                client.auth = APICredential.get_auth(
                    io_url, scopes=['zds.scopes.zaaktypes.lezen'])
                informatieobject = client.request(
                    io_url, 'enkelvoudiginformatieobject')
                if informatieobject['indicatieGebruiksrecht'] is None:
                    raise serializers.ValidationError(
                        "Er zijn gerelateerde informatieobjecten waarvoor `indicatieGebruiksrecht` nog niet "
                        "gespecifieerd is. Je moet deze zetten voor je de zaak kan afsluiten.",
                        code='indicatiegebruiksrecht-unset')

        return validated_attrs
예제 #23
0
    def __call__(self, context: OrderedDict):
        object_url = context["object"]
        informatieobject_uuid = str(
            context["informatieobject"].latest_version.uuid)
        object_type = context["object_type"]

        informatieobject_url = get_absolute_url(
            "enkelvoudiginformatieobject-detail", uuid=informatieobject_uuid)

        # dynamic so that it can be mocked in tests easily
        Client = import_string(settings.ZDS_CLIENT_CLASS)
        client = Client.from_url(object_url)
        client.auth = APICredential.get_auth(object_url)
        try:
            if object_type == "zaak":
                resource = "zaakinformatieobject"
                component = "ZRC"
                oas_schema = settings.ZRC_API_SPEC
            elif object_type == "besluit":
                resource = "besluitinformatieobject"
                component = "BRC"
                oas_schema = settings.BRC_API_SPEC

            try:
                ResourceValidator(
                    object_type.capitalize(),
                    oas_schema,
                    get_auth=get_zrc_auth,
                    headers={"Accept-Crs": "EPSG:4326"},
                )(object_url)
            except exceptions.ValidationError as exc:
                raise serializers.ValidationError({"object": exc.detail},
                                                  code=ResourceValidator.code)

            oios = client.list(
                resource,
                query_params={
                    object_type: object_url,
                    "informatieobject": informatieobject_url,
                },
            )

        except ClientError as exc:
            raise serializers.ValidationError(
                exc.args[0], code="relation-validation-error") from exc

        if len(oios) == 0:
            raise serializers.ValidationError(
                self.message.format(component=component), code=self.code)
    def handle(self, **options):
        new_secrets = [
            JWTSecret(id=old.id, identifier=old.identifier, secret=old.secret)
            for old in OldJWTSecret.objects.all()
        ]
        JWTSecret.objects.bulk_create(new_secrets)

        new_credentials = [
            APICredential(id=old.id,
                          api_root=old.api_root,
                          client_id=old.client_id,
                          secret=old.secret)
            for old in OldAPICredential.objects.all()
        ]
        APICredential.objects.bulk_create(new_credentials)
예제 #25
0
    def _get_object(self) -> dict:
        """
        Retrieve the `Object` specified as URL in `ZaakObject.object`.

        :return: A `dict` representing the object.
        """
        if not hasattr(self, '_object'):
            object_url = self.object
            self._object = None
            if object_url:
                Client = import_string(settings.ZDS_CLIENT_CLASS)
                client = Client.from_url(object_url)
                client.auth = APICredential.get_auth(object_url)
                self._object = client.retrieve(self.object_type.lower(), url=object_url)
        return self._object
예제 #26
0
def get_zds_client(url: str):
    """
    Retrieve a ZDS Client instance for the given API URL.

    The client respects the setting ``CUSTOM_CLIENT_FETCHER`` as used by vng-api-common,
    and will have the auth configured.
    """
    Client = get_client_class()
    default = Client.from_url(url)

    if getattr(settings, "CUSTOM_CLIENT_FETCHER", None):
        client = import_string(settings.CUSTOM_CLIENT_FETCHER)(default.base_url)
        return client
    else:
        default.auth = APICredential.get_auth(url)
        return default
예제 #27
0
def create_remote_oio(io_url: str,
                      object_url: str,
                      object_type: str = "zaak") -> dict:
    client_auth = APICredential.get_auth(io_url)
    if client_auth is None:
        logger.warning("Missing credentials for %s", io_url)

    url = _get_oio_endpoint(io_url)
    headers = client_auth.credentials() if client_auth else {}
    body = {
        "informatieobject": io_url,
        "object": object_url,
        "objectType": object_type
    }

    response = requests.post(url, json=body, headers=headers)
    response.raise_for_status()
    return response.json()
예제 #28
0
    def _get_information_objects(self) -> list:
        if not hasattr(self, "_information_objects"):
            self._information_objects = []

            if self.instance:
                Client = import_string(settings.ZDS_CLIENT_CLASS)

                zios = self.instance.zaakinformatieobject_set.all()
                for zio in zios:
                    io_url = zio.informatieobject
                    client = Client.from_url(io_url)
                    client.auth = APICredential.get_auth(
                        io_url, scopes=["scopes.documenten.lezen"])
                    informatieobject = client.request(
                        io_url, "enkelvoudiginformatieobject")
                    self._information_objects.append(informatieobject)

        return self._information_objects
예제 #29
0
    def __call__(self, attrs: OrderedDict):
        object_url = attrs["object"]
        object_type = attrs["object_type"]
        klantinteractie_url = get_absolute_url(
            f"{self.resource_name}-detail",
            uuid=attrs[self.resource_name].uuid)

        # dynamic so that it can be mocked in tests easily
        Client = import_string(settings.ZDS_CLIENT_CLASS)
        client = Client.from_url(object_url)
        client.auth = APICredential.get_auth(object_url)

        resource = f"{object_type}{self.resource_name}"
        oas_schema = settings.ZRC_API_SPEC

        try:
            ResourceValidator(
                object_type.capitalize(),
                oas_schema,
                get_auth=get_auth,
                headers={"Accept-Crs": "EPSG:4326"},
            )(object_url)
        except exceptions.ValidationError as exc:
            raise serializers.ValidationError({"object": exc.detail},
                                              code=ResourceValidator.code)

        try:
            relations = client.list(
                resource,
                query_params={
                    object_type: object_url,
                    f"{self.resource_name}": klantinteractie_url,
                },
            )

        except ClientError as exc:
            raise serializers.ValidationError(
                exc.args[0], code="relation-validation-error") from exc

        if len(relations) == 0:
            raise serializers.ValidationError(
                self.message.format(object=object_type), code=self.code)
예제 #30
0
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