Ejemplo n.º 1
0
    def filter_for_authorizations(
            self, scope: Scope,
            authorizations: models.QuerySet) -> models.QuerySet:
        """
        Filter objects whitelisted by the authorizations.

        For BRC, authorizations are defined around ``Autorisatie.besluittype``,
        limiting scopes that apply for the ``besluittype`` at hand.

        This means that ``besluiten`` are included if, and only if:

        * the ``besluittype`` is provided in ``authorizations``
        * the scopes for the ``besluittype`` in each ``authorization`` contain the
          required``scope``

        :param scope: a (possibly complex) scope that must be granted on the
          authorizations
        :param authorizations: queryset of
          :class:`vng_api_common.authorizations.Autorisatie` objects

        :return: a queryset of filtered results according to the
          authorizations provided
        """
        prefix = ("" if not self.authorizations_lookup else
                  f"{self.authorizations_lookup}__")

        # keep a list of allowed besluittypen
        besluittypen = []
        for authorization in authorizations:
            if scope.is_contained_in(authorization.scopes):
                besluittype_path = urlparse(authorization.besluittype).path
                besluittype = get_resource_for_path(besluittype_path)
                besluittypen.append(besluittype)

        # filtering:
        # * only allow the white-listed besluittypen, explicitly
        queryset = self.filter(**{f"{prefix}besluittype__in": besluittypen})
        return queryset
Ejemplo n.º 2
0
    def filter_for_authorizations(
            self, scope: Scope,
            authorizations: models.QuerySet) -> models.QuerySet:
        """
        Filter objects whitelisted by the authorizations.

        For ZRC, authorizations are defined around ``Autorisatie.zaaktype``,
        with a ``max_vertrouwelijkheidaanduiding`` limiting the confidentiality
        level of ``zaken`` (inclusive), and scopes that apply for the
        ``zaaktype`` at hand.

        This means that ``zaken`` are included if, and only if:

        * the ``zaaktype`` is provided in ``authorizations``
        * the scopes for the ``zaaktype`` in each ``authorization`` contain the
          required``scope``
        * the ``zaak.vertrouwelijkheidaanduiding`` is less then or equal to the
          ``authorization.max_vertrouwelijkheidaanduiding``

        :param scope: a (possibly complex) scope that must be granted on the
          authorizations
        :param authorizations: queryset of
          :class:`vng_api_common.authorizations.Autorisatie` objects

        :return: a queryset of filtered results according to the
          authorizations provided
        """
        # keep a list of allowed zaaktypen
        zaaktypen = []

        prefix = ("" if not self.authorizations_lookup else
                  f"{self.authorizations_lookup}__")

        # annotate the queryset so we can map a string value to a logical number
        order_case = VertrouwelijkheidsAanduiding.get_order_expression(
            f"{prefix}vertrouwelijkheidaanduiding")

        # build the case/when to map the max_vertrouwelijkheidaanduiding based
        # on the ``zaaktype``
        vertrouwelijkheidaanduiding_whens = []
        for authorization in authorizations:
            # test if this authorization has the scope that's needed
            if not scope.is_contained_in(authorization.scopes):
                continue

            # this zaaktype is allowed
            zaaktype_path = urlparse(authorization.zaaktype).path
            zaaktype = get_resource_for_path(zaaktype_path)
            zaaktypen.append(zaaktype)

            # extract the order and map it to the database value
            choice_item = VertrouwelijkheidsAanduiding.get_choice(
                authorization.max_vertrouwelijkheidaanduiding)
            vertrouwelijkheidaanduiding_whens.append(
                When(**{f"{prefix}zaaktype": zaaktype},
                     then=Value(choice_item.order)))

        # apply the order annnotation so we can filter later
        annotations = {f"{prefix}_va_order": order_case}
        # filtering:
        # * only allow the white-listed zaaktypen, explicitly
        # * apply the filtering to limit cases within case-types to the maximal
        #   confidentiality level
        filters = {
            f"{prefix}zaaktype__in":
            zaaktypen,
            f"{prefix}_va_order__lte":
            Case(*vertrouwelijkheidaanduiding_whens,
                 output_field=IntegerField()),
        }

        # bring it all together now to build the resulting queryset
        queryset = self.annotate(**annotations).filter(**filters)
        return queryset
Ejemplo n.º 3
0
    def filter_for_authorizations(
        self, scope: Scope, authorizations: models.QuerySet
    ) -> models.QuerySet:
        """
        Filter objects whitelisted by the authorizations.

        For DRC, authorizations are defined around ``Autorisatie.informatieobjecttype``,
        with a ``max_vertrouwelijkheidaanduiding`` limiting the confidentiality
        level of ``informatieobjecten`` (inclusive), and scopes that apply for the
        ``informatieobjecttype`` at hand.

        This means that ``informatieobjecten`` are included if, and only if:

        * the ``informatieobjecttype`` is provided in ``authorizations``
        * the scopes for the ``informatieobjecttype`` in each ``authorization`` contain the
          required``scope``
        * the ``informatieobjecttype.vertrouwelijkheidaanduiding`` is less then or equal to the
          ``authorization.max_vertrouwelijkheidaanduiding``

        :param scope: a (possibly complex) scope that must be granted on the
          authorizations
        :param authorizations: queryset of
          :class:`vng_api_common.authorizations.Autorisatie` objects

        :return: a queryset of filtered results according to the
          authorizations provided
        """
        # keep a list of allowed informatieobjecttypen
        informatieobjecttypen = []

        # annotate the queryset so we can map a string value to a logical number
        order_case = VertrouwelijkheidsAanduiding.get_order_expression(
            "vertrouwelijkheidaanduiding"
        )

        # build the case/when to map the max_vertrouwelijkheidaanduiding based
        # on the ``informatieobjecttype``
        vertrouwelijkheidaanduiding_whens = []
        for authorization in authorizations:
            # test if this authorization has the scope that's needed
            if not scope.is_contained_in(authorization.scopes):
                continue

            # this informatieobjecttype is allowed
            informatieobjecttypen.append(authorization.informatieobjecttype)

            # extract the order and map it to the database value
            choice_item = VertrouwelijkheidsAanduiding.get_choice(
                authorization.max_vertrouwelijkheidaanduiding
            )
            vertrouwelijkheidaanduiding_whens.append(
                When(
                    **{"informatieobjecttype": authorization.informatieobjecttype},
                    then=Value(choice_item.order),
                )
            )

        # apply the order annnotation so we can filter later
        annotations = {"_va_order": order_case}
        # filtering:
        # * only allow the white-listed informatieobjecttypen, explicitly
        # * apply the filtering to limit cases within case-types to the maximal
        #   confidentiality level
        filters = {
            "informatieobjecttype__in": informatieobjecttypen,
            "_va_order__lte": Case(
                *vertrouwelijkheidaanduiding_whens, output_field=IntegerField()
            ),
        }
        if self.authorizations_lookup:
            # If the current queryset is not an InformatieObjectQuerySet, first
            # retrieve the canonical IDs of EnkelvoudigInformatieObjects
            # for which the user is authorized and then return the objects
            # related to those EnkelvoudigInformatieObjectCanonicals
            model = apps.get_model("datamodel", "EnkelvoudigInformatieObject")
            filtered = (
                model.objects.annotate(**annotations)
                .filter(**filters)
                .values("canonical")
            )
            queryset = self.filter(informatieobject__in=filtered)
        # bring it all together now to build the resulting queryset
        else:
            queryset = self.annotate(**annotations).filter(**filters)
        return queryset