예제 #1
0
def _annotate_is_bookmarked(datasets, user):
    """
    Adds a boolean annotation to queryset from *dataset bookmarks
    @param datasets: django querysey
    @param user: request.user
    @return:
    """
    if datasets.model is ReferenceDataset:
        datasets = datasets.annotate(user_bookmark=FilteredRelation(
            "referencedatasetbookmark",
            condition=Q(referencedatasetbookmark__user=user),
        ))

    if datasets.model is DataSet:
        datasets = datasets.annotate(user_bookmark=FilteredRelation(
            "datasetbookmark", condition=Q(datasetbookmark__user=user)))

    if datasets.model is VisualisationCatalogueItem:
        datasets = datasets.annotate(user_bookmark=FilteredRelation(
            "visualisationbookmark",
            condition=Q(visualisationbookmark__user=user)))

    datasets = datasets.annotate(is_bookmarked=BoolOr(
        Case(
            When(user_bookmark__user__isnull=False, then=True),
            default=False,
            output_field=BooleanField(),
        )), )
    return datasets
예제 #2
0
 def withDetailStats(self):
     return self.annotate(
         deko_fahrzeuge=BoolOr('fahrzeuge__dekozug')).annotate(
             zug_max_speed=Least(F('speed_zug'),
                                 Min('fahrzeuge__speed_max')),
             fz_max_speed=Min('fahrzeuge__speed_max'),
             deko_zug=Case(When(deko_fahrzeuge=True, then=True),
                           default='deko'))
예제 #3
0
 def withTableStats(self):
     return self.annotate(
         position_count=Max('eintraege__position'),
         deko_fahrzeuge=BoolOr('fahrzeuge__dekozug')).annotate(
             fz_max_speed=Least(F('speed_zug'),
                                Min('fahrzeuge__speed_max')),
             gesamt_zeit=Case(
                 When(position_count=0, then=Value(datetime.timedelta(0))),
                 default=Max(Coalesce('eintraege__an', 'eintraege__ab')) -
                 Min(Coalesce('eintraege__ab', 'eintraege__an'))),
             anfang_zeit=Min(Coalesce('eintraege__an', 'eintraege__ab')),
             deko_zug=Case(When(deko_fahrzeuge=True, then=True),
                           default='deko'))
예제 #4
0
def _annotate_has_access(datasets, user):
    """
    Adds a bool annotation to queryset if user has access to the dataset
    @param datasets: django queryset
    @param user: request.user
    @return: queryset
    """
    if datasets.model is ReferenceDataset:
        datasets = datasets.annotate(has_access=Value(True, BooleanField()))

    if datasets.model is DataSet or datasets.model is VisualisationCatalogueItem:
        if datasets.model is DataSet:
            datasets = datasets.annotate(user_permission=FilteredRelation(
                "datasetuserpermission",
                condition=Q(datasetuserpermission__user=user),
            ), )

        if datasets.model is VisualisationCatalogueItem:
            datasets = datasets.annotate(user_permission=FilteredRelation(
                "visualisationuserpermission",
                condition=Q(visualisationuserpermission__user=user),
            ), )
        datasets = datasets.annotate(has_access=BoolOr(
            Case(
                When(
                    Q(user_access_type__in=[
                        UserAccessType.REQUIRES_AUTHENTICATION,
                        UserAccessType.OPEN,
                    ])
                    | (Q(
                        user_access_type=UserAccessType.REQUIRES_AUTHORIZATION,
                        user_permission__user__isnull=False,
                    ))
                    | Q(authorized_email_domains__contains=[
                        user.email.split("@")[1]
                    ]),
                    then=True,
                ),
                default=False,
                output_field=BooleanField(),
            )), )
    return datasets
예제 #5
0
def _annotate_source_table_match(datasets, query):
    if datasets.model is DataSet or datasets.model is ReferenceDataset:
        schema, table = _schema_table_from_search_term(query)
        search_filter = Q()
        if datasets.model is ReferenceDataset:
            search_filter |= Q(table_name=table)
        else:
            table_match = Q(sourcetable__table=table)
            if schema:
                table_match &= Q(sourcetable__schema=schema)
            search_filter |= table_match

        return datasets.annotate(table_match=BoolOr(
            Case(
                When(search_filter, then=True),
                default=False,
                output_field=BooleanField(),
            ), ), )

    return datasets.annotate(table_match=Value(False, BooleanField()), )
예제 #6
0
def _annotate_is_subscribed(datasets, user):
    """
    Adds a bool annotation which is True if the user has a subscription to the dataset
    @param datasets: django queryset
    @param user: request.user
    @return:
    """
    if datasets.model is ReferenceDataset or datasets.model is VisualisationCatalogueItem:
        return datasets.annotate(is_subscribed=Value(False, BooleanField()))

    if datasets.model is DataSet:
        datasets = datasets.annotate(user_subscription=FilteredRelation(
            "subscriptions", condition=Q(subscriptions__user=user)), )
        datasets = datasets.annotate(is_subscribed=BoolOr(
            Case(
                When(user_subscription__user__isnull=False, then=True),
                default=False,
                output_field=BooleanField(),
            )))
    return datasets
예제 #7
0
    def get_annotation(self, cte):
        resource_condition = self.build_topic_condition(F('kind_id'), '!=')

        whens = [
            # when selected node is not a topic, just use its changed status
            When(condition=WhenQ(*resource_condition), then=F('changed')),
        ]

        if self.include_self:
            # when selected node is a topic and it's changed and including self, then return that
            whens.append(
                When(condition=WhenQ(*[F('changed')]), then=F('changed')))

        return Coalesce(
            Case(
                *whens,
                # fallback to aggregating descendant changed status when a unchanged topic
                default=BoolOr(cte.col.changed)),
            Value(False),
            output_field=BooleanField())
예제 #8
0
def get_datasets_data_for_user_matching_query(datasets: QuerySet,
                                              query,
                                              use=None,
                                              user=None,
                                              id_field='id'):
    """
    Filters the dataset queryset for:
        1) visibility (whether the user can know if the dataset exists)
        2) matches the search terms

    Annotates the dataset queryset with:
        1) `has_access`, if the user can use the dataset's data.
    """
    is_reference_query = datasets.model is ReferenceDataset

    # Filter out datasets that the user is not allowed to even know about.
    visibility_filter = Q(published=True)

    if user:
        if is_reference_query:
            reference_type = DataSetType.REFERENCE.value
            reference_perm = dataset_type_to_manage_unpublished_permission_codename(
                reference_type)

            if user.has_perm(reference_perm):
                visibility_filter |= Q(published=False)

        if datasets.model is DataSet:
            master_type, datacut_type = (
                DataSetType.MASTER.value,
                DataSetType.DATACUT.value,
            )
            master_perm = dataset_type_to_manage_unpublished_permission_codename(
                master_type)
            datacut_perm = dataset_type_to_manage_unpublished_permission_codename(
                datacut_type)

            if user.has_perm(master_perm):
                visibility_filter |= Q(published=False, type=master_type)

            if user.has_perm(datacut_perm):
                visibility_filter |= Q(published=False, type=datacut_type)

    datasets = datasets.filter(visibility_filter)

    # Filter out datasets that don't match the search terms
    search = (SearchVector('name', weight='A', config='english') +
              SearchVector('short_description', weight='B', config='english') +
              SearchVector(StringAgg('tags__name', delimiter='\n'),
                           weight='B',
                           config='english'))
    search_query = SearchQuery(query, config='english')

    datasets = datasets.annotate(search=search,
                                 search_rank=SearchRank(search, search_query))

    if query:
        datasets = datasets.filter(search=search_query)

    # Mark up whether the user can access the data in the dataset.
    access_filter = Q()

    if user and datasets.model is not ReferenceDataset:
        access_filter &= (Q(user_access_type='REQUIRES_AUTHENTICATION')
                          & (Q(datasetuserpermission__user=user)
                             | Q(datasetuserpermission__isnull=True))) | Q(
                                 user_access_type='REQUIRES_AUTHORIZATION',
                                 datasetuserpermission__user=user)

    datasets = datasets.annotate(_has_access=Case(
        When(access_filter, then=True),
        default=False,
        output_field=BooleanField(),
    ) if access_filter else Value(True, BooleanField()), )

    # Pull in the source tag IDs for the dataset
    datasets = datasets.annotate(source_tag_ids=ArrayAgg(
        'tags', filter=Q(tags__type=TagType.SOURCE.value), distinct=True))
    datasets = datasets.annotate(source_tag_names=ArrayAgg(
        'tags__name', filter=Q(
            tags__type=TagType.SOURCE.value), distinct=True))

    # Pull in the topic tag IDs for the dataset
    datasets = datasets.annotate(topic_tag_ids=ArrayAgg(
        'tags', filter=Q(tags__type=TagType.TOPIC.value), distinct=True))
    datasets = datasets.annotate(topic_tag_names=ArrayAgg(
        'tags__name', filter=Q(tags__type=TagType.TOPIC.value), distinct=True))

    # Define a `purpose` column denoting the dataset type.
    if is_reference_query:
        datasets = datasets.annotate(
            purpose=Value(DataSetType.REFERENCE.value, IntegerField()))
    else:
        datasets = datasets.annotate(purpose=F('type'))

    # We are joining on the user permissions table to determine `_has_access`` to the dataset, so we need to
    # group them and remove duplicates. We aggregate all the `_has_access` fields together and return true if any
    # of the records say that access is available.
    datasets = datasets.values(
        id_field,
        'name',
        'slug',
        'short_description',
        'search_rank',
        'source_tag_names',
        'source_tag_ids',
        'topic_tag_names',
        'topic_tag_ids',
        'purpose',
        'published',
        'published_at',
    ).annotate(has_access=BoolOr('_has_access'))

    return datasets.values(
        id_field,
        'name',
        'slug',
        'short_description',
        'search_rank',
        'source_tag_names',
        'source_tag_ids',
        'topic_tag_names',
        'topic_tag_ids',
        'purpose',
        'published',
        'published_at',
        'has_access',
    )
예제 #9
0
def get_visualisations_data_for_user_matching_query(visualisations: QuerySet,
                                                    query,
                                                    user=None):
    """
    Filters the visualisation queryset for:
        1) visibility (whether the user can know if the visualisation exists)
        2) matches the search terms

    Annotates the visualisation queryset with:
        1) `has_access`, if the user can use the visualisation.
    """
    # Filter out visualisations that the user is not allowed to even know about.
    if not (user and user.has_perm(
            dataset_type_to_manage_unpublished_permission_codename(
                DataSetType.VISUALISATION.value))):
        visualisations = visualisations.filter(published=True)

    # Filter out visualisations that don't match the search terms
    search = SearchVector('name', weight='A', config='english') + SearchVector(
        'short_description', weight='B', config='english')
    search_query = SearchQuery(query, config='english')

    visualisations = visualisations.annotate(search=search,
                                             search_rank=SearchRank(
                                                 search, search_query))

    if query:
        visualisations = visualisations.filter(search=search_query)

    # Mark up whether the user can access the visualisation.
    if user:
        access_filter = (Q(user_access_type='REQUIRES_AUTHENTICATION')
                         &
                         (Q(visualisationuserpermission__user=user)
                          | Q(visualisationuserpermission__isnull=True))) | Q(
                              user_access_type='REQUIRES_AUTHORIZATION',
                              visualisationuserpermission__user=user,
                          )
    else:
        access_filter = Q()

    visualisations = visualisations.annotate(_has_access=Case(
        When(access_filter, then=True),
        default=False,
        output_field=BooleanField(),
    ) if access_filter else Value(True, BooleanField()), )

    # Pull in the source tag IDs for the dataset
    visualisations = visualisations.annotate(source_tag_ids=ArrayAgg(
        'tags', filter=Q(tags__type=TagType.SOURCE.value), distinct=True))

    visualisations = visualisations.annotate(source_tag_names=ArrayAgg(
        'tags__name', filter=Q(
            tags__type=TagType.SOURCE.value), distinct=True))

    # Pull in the topic tag IDs for the dataset
    visualisations = visualisations.annotate(topic_tag_ids=ArrayAgg(
        'tags', filter=Q(tags__type=TagType.TOPIC.value), distinct=True))

    visualisations = visualisations.annotate(topic_tag_names=ArrayAgg(
        'tags__name', filter=Q(tags__type=TagType.TOPIC.value), distinct=True))

    # Define a `purpose` column denoting the dataset type
    visualisations = visualisations.annotate(
        purpose=Value(DataSetType.VISUALISATION.value, IntegerField()))

    # We are joining on the user permissions table to determine `_has_access`` to the visualisation, so we need to
    # group them and remove duplicates. We aggregate all the `_has_access` fields together and return true if any
    # of the records say that access is available.
    visualisations = visualisations.values(
        'id',
        'name',
        'slug',
        'short_description',
        'search_rank',
        'source_tag_names',
        'source_tag_ids',
        'topic_tag_names',
        'topic_tag_ids',
        'purpose',
        'published',
        'published_at',
    ).annotate(has_access=BoolOr('_has_access'))

    return visualisations.values(
        'id',
        'name',
        'slug',
        'short_description',
        'search_rank',
        'source_tag_names',
        'source_tag_ids',
        'topic_tag_names',
        'topic_tag_ids',
        'purpose',
        'published',
        'published_at',
        'has_access',
    )