Ejemplo n.º 1
0
 def convert_value(self, value, field):
     """Used to convert incoming values from query params to the appropriate types for filter comparisons
     :param basestring value: value to be resolved
     :param rest_framework.fields.Field field: Field instance
     """
     if isinstance(field, ser.BooleanField):
         if utils.is_truthy(value):
             return True
         elif utils.is_falsy(value):
             return False
         else:
             raise InvalidFilterValue(value=value, field_type='bool')
     elif isinstance(field, self.DATE_FIELDS):
         try:
             return date_parser.parse(value)
         except ValueError:
             raise InvalidFilterValue(value=value, field_type='date')
     elif isinstance(field, (self.LIST_FIELDS, self.RELATIONSHIP_FIELDS, ser.SerializerMethodField)) \
             or isinstance((getattr(field, 'field', None)), self.LIST_FIELDS):
         if value == 'null':
             value = None
         return value
     else:
         try:
             return field.to_internal_value(value)
         except ValidationError:
             raise InvalidFilterValue(value=value, )
Ejemplo n.º 2
0
    def build_query_from_field(self, field_name, operation):
        if field_name == 'parent':
            if operation['op'] == 'eq':
                if operation['value']:
                    # filter[parent]=<nid>
                    parent = utils.get_object_or_error(AbstractNode,
                                                       operation['value'],
                                                       self.request,
                                                       display_name='parent')
                    node_ids = NodeRelation.objects.filter(
                        parent=parent,
                        is_node_link=False).values_list('child_id', flat=True)
                    return Q(id__in=node_ids)
            elif operation['op'] == 'ne':
                if not operation['value']:
                    # filter[parent][ne]=null
                    child_ids = (NodeRelation.objects.filter(
                        is_node_link=False,
                        child___contributors=self.get_user(),
                    ).exclude(parent__type='osf.collection').exclude(
                        child__is_deleted=True).values_list('child_id',
                                                            flat=True))
                    return Q(id__in=set(child_ids))
                # TODO: support this case in the future:
                # else filter[parent][ne]=<nid>
                raise InvalidFilterValue(
                    detail=
                    'Only "null" is accepted as valid input to "filter[parent][ne]"'
                )
            else:
                # filter[parent][gte]=''
                raise InvalidFilterOperator(value=operation['op'],
                                            valid_operators=['eq', 'ne'])

        if field_name == 'root':
            if None in operation['value']:
                raise InvalidFilterValue(value=operation['value'])
            with_as_root_query = Q(root__guids___id__in=operation['value'])
            return ~with_as_root_query if operation[
                'op'] == 'ne' else with_as_root_query

        if field_name == 'preprint':
            not_preprint_query = (Q(preprint_file=None)
                                  | Q(_is_preprint_orphan=True)
                                  | Q(_has_abandoned_preprint=True))

            return ~not_preprint_query if utils.is_truthy(
                operation['value']) else not_preprint_query

        return super(NodesFilterMixin,
                     self).build_query_from_field(field_name, operation)
Ejemplo n.º 3
0
    def get_filtered_queryset(self, field_name, params, default_queryset):
        """filters default queryset based on the serializer field type"""
        field = self.serializer_class._declared_fields[field_name]
        field_name = self.convert_key(field_name, field)

        if isinstance(field, ser.SerializerMethodField):
            return_val = [
                item for item in default_queryset if self.FILTERS[params['op']]
                (self.get_serializer_method(field_name)(item), params['value'])
            ]
        elif isinstance(field, ser.CharField):
            return_val = [
                item for item in default_queryset if params['value'].lower() in
                getattr(item, field_name, {}).lower()
            ]
        elif isinstance(field, ser.ListField):
            return_val = [
                item for item in default_queryset if params['value'].lower() in
                [lowercase(i.lower) for i in getattr(item, field_name, [])]
            ]
        else:
            try:
                return_val = [
                    item for item in default_queryset
                    if self.FILTERS[params['op']](getattr(
                        item, field_name, None), params['value'])
                ]
            except TypeError:
                raise InvalidFilterValue(
                    detail='Could not apply filter to specified field')

        return return_val
Ejemplo n.º 4
0
    def build_query_from_field(self, field_name, operation):
        if field_name == 'current_user_permissions':
            if operation[
                    'value'] not in permissions.API_CONTRIBUTOR_PERMISSIONS:
                raise InvalidFilterValue(value=operation['value'])
            perm = operation['value']
            # Filtering UserNodes on the requesting user's permissions to those nodes.
            user = self.request.user

            if user.is_anonymous:
                # Anonymous users have no perms to the current node in current versions, and in
                # older versions, will have read if node is public
                return Q() if StrictVersion(
                    self.request.version) < StrictVersion(
                        '2.11') and perm == permissions.READ else Q(id__in=[])
            elif perm == permissions.READ:
                return Q(
                    id__in=self.build_node_list(user, permissions.READ_NODE))
            elif perm == permissions.WRITE:
                return Q(
                    id__in=self.build_node_list(user, permissions.WRITE_NODE))
            elif perm == permissions.ADMIN:
                return Q(
                    id__in=self.build_node_list(user, permissions.ADMIN_NODE))
        return super(UserNodesFilterMixin,
                     self).build_query_from_field(field_name, operation)
Ejemplo n.º 5
0
 def build_query_from_field(self, field_name, operation):
     if field_name == 'permission':
         if operation['op'] != 'eq':
             raise InvalidFilterOperator(value=operation['op'],
                                         valid_operators=['eq'])
         # operation['value'] should be 'admin', 'write', or 'read'
         query_val = operation['value'].lower().strip()
         if query_val not in API_CONTRIBUTOR_PERMISSIONS:
             raise InvalidFilterValue(value=operation['value'])
         # This endpoint should only be returning *contributors* not group members
         resource = self.get_resource()
         if query_val == READ:
             # If read, return all contributors
             return Q(user_id__in=resource.contributors.values_list(
                 'id', flat=True))
         elif query_val == WRITE:
             # If write, return members of write and admin groups, both groups have write perms
             return Q(user_id__in=(resource.get_group(
                 WRITE).user_set.values_list('id', flat=True)
                                   | resource.get_group(ADMIN).user_set.
                                   values_list('id', flat=True)))
         elif query_val == ADMIN:
             # If admin, return only members of admin group
             return Q(user_id__in=resource.get_group(
                 ADMIN).user_set.values_list('id', flat=True))
     return super(BaseContributorList,
                  self).build_query_from_field(field_name, operation)
Ejemplo n.º 6
0
 def build_query_from_field(self, field_name, operation):
     if field_name == 'current_user_permissions':
         if not operation['value'] in PERMISSIONS:
             raise InvalidFilterValue(value=operation['value'])
         perm = operation['value']
         query = Q(contributor__user__id=self.get_user().id)
         if perm == READ:
             query &= Q(contributor__read=True)
         elif perm == WRITE:
             query &= Q(contributor__write=True)
         elif perm == ADMIN:
             query &= Q(contributor__admin=True)
         else:
             raise InvalidFilterValue(value=operation['value'])
         return query
     return super(UserNodesFilterMixin, self).build_query_from_field(field_name, operation)
Ejemplo n.º 7
0
 def convert_value(self, value, field):
     """Used to convert incoming values from query params to the appropriate types for filter comparisons
     :param basestring value: value to be resolved
     :param rest_framework.fields.Field field: Field instance
     """
     field = utils.decompose_field(field)
     if isinstance(field, ShowIfVersion):
         field = field.field
     if isinstance(field, ser.BooleanField):
         if utils.is_truthy(value):
             return True
         elif utils.is_falsy(value):
             return False
         else:
             raise InvalidFilterValue(
                 value=value,
                 field_type='bool',
             )
     elif isinstance(field, self.DATE_FIELDS):
         try:
             ret = date_parser.parse(value, ignoretz=False)
             if not ret.tzinfo:
                 ret = ret.replace(tzinfo=pytz.utc)
             return ret
         except ValueError:
             raise InvalidFilterValue(
                 value=value,
                 field_type='date',
             )
     elif isinstance(field,
                     (self.RELATIONSHIP_FIELDS, ser.SerializerMethodField,
                      ser.ManyRelatedField)):
         if value == 'null':
             value = None
         return value
     elif isinstance(field, self.LIST_FIELDS) or isinstance(
         (getattr(field, 'field', None)), self.LIST_FIELDS):
         if value == 'null':
             value = []
         return value
     else:
         try:
             return field.to_internal_value(value)
         except ValidationError:
             raise InvalidFilterValue(value=value, )
Ejemplo n.º 8
0
 def build_query_from_field(self, field_name, operation):
     if field_name == 'permission':
         if operation['op'] != 'eq':
             raise InvalidFilterOperator(value=operation['op'],
                                         valid_operators=['eq'])
         # operation['value'] should be 'admin', 'write', or 'read'
         if operation['value'].lower().strip() not in PERMISSIONS:
             raise InvalidFilterValue(value=operation['value'])
         return Q(**{operation['value'].lower().strip(): True})
     return super(BaseContributorList,
                  self).build_query_from_field(field_name, operation)
Ejemplo n.º 9
0
 def _operation_to_query(self, operation):
     if operation['source_field_name'] == 'root':
         if None in operation['value']:
             raise InvalidFilterValue()
         return Q('root__guids___id', 'in', operation['value'])
     if operation['source_field_name'] == 'parent_node':
         if operation['value']:
             parent = utils.get_object_or_error(AbstractNode, operation['value'], display_name='parent')
             return Q('_id', 'in', [node._id for node in parent.get_nodes(is_node_link=False)])
         else:
             return Q('parent_nodes__guids___id', 'eq', None)
     return super(NodesListFilterMixin, self)._operation_to_query(operation)
Ejemplo n.º 10
0
 def build_query_from_field(self, field_name, operation):
     if field_name == 'permission':
         if operation['op'] != 'eq':
             raise InvalidFilterOperator(value=operation['op'],
                                         valid_operators=['eq'])
         # operation['value'] should be 'admin', 'write', or 'read'
         query_val = operation['value'].lower().strip()
         if query_val not in PERMISSIONS:
             raise InvalidFilterValue(value=operation['value'])
         return Q(user__in=self.get_resource().get_group(
             query_val).user_set.all())
     return super(PreprintContributorsList,
                  self).build_query_from_field(field_name, operation)
Ejemplo n.º 11
0
 def build_query_from_field(self, field_name, operation):
     if field_name == 'role':
         if operation['op'] != 'eq':
             raise InvalidFilterOperator(value=operation['op'],
                                         valid_operators=['eq'])
         # operation['value'] should be 'member' or 'manager'
         role = operation['value'].lower().strip()
         if role not in GROUP_ROLES:
             raise InvalidFilterValue(value=operation['value'])
         group = self.get_osf_group(check_object_permissions=False)
         return Q(id__in=group.managers if role ==
                  MANAGER else group.members_only)
     return super(GroupMembersList,
                  self).build_query_from_field(field_name, operation)
Ejemplo n.º 12
0
    def build_query_from_field(self, field_name, operation):
        if field_name == 'permissions':
            if operation['op'] != 'eq':
                raise InvalidFilterOperator(value=operation['op'], valid_operators=['eq'])
            auth = get_user_auth(self.request)
            auth_user = getattr(auth, 'user', None)
            if not auth_user:
                raise NotAuthenticated()
            value = operation['value'].lstrip('[').rstrip(']')
            permissions = [v.strip() for v in value.split(',')]
            if any(p not in PERMISSIONS for p in permissions):
                valid_permissions = ', '.join(PERMISSIONS.keys())
                raise InvalidFilterValue('Invalid permission! Valid values are: {}'.format(valid_permissions))
            return Q(id__in=get_objects_for_user(auth_user, permissions, PreprintProvider, any_perm=True))

        return super(PreprintProviderList, self).build_query_from_field(field_name, operation)
Ejemplo n.º 13
0
    def get_filtered_queryset(self, field_name, params, default_queryset):
        """filters default queryset based on the serializer field type"""
        field = self.serializer_class._declared_fields[field_name]
        source_field_name = params['source_field_name']

        if isinstance(field, ser.SerializerMethodField):
            return_val = [
                item for item in default_queryset if self.FILTERS[params['op']]
                (self.get_serializer_method(field_name)(item), params['value'])
            ]
        elif isinstance(field, ser.CharField):
            if source_field_name in ('_id', 'root'):
                # Param parser treats certain ID fields as bulk queries: a list of options, instead of just one
                # Respect special-case behavior, and enforce exact match for these list fields.
                options = set(item.lower() for item in params['value'])
                return_val = [
                    item for item in default_queryset
                    if getattr(item, source_field_name, '') in options
                ]
            else:
                # TODO: What is {}.lower()? Possible bug
                return_val = [
                    item for item in default_queryset
                    if params['value'].lower() in getattr(
                        item, source_field_name, {}).lower()
                ]
        elif isinstance(field, ser.ListField):
            return_val = [
                item for item in default_queryset
                if params['value'].lower() in [
                    lowercase(i.lower)
                    for i in getattr(item, source_field_name, [])
                ]
            ]
        else:
            try:
                return_val = [
                    item for item in default_queryset
                    if self.FILTERS[params['op']](getattr(
                        item, source_field_name, None), params['value'])
                ]
            except TypeError:
                raise InvalidFilterValue(
                    detail='Could not apply filter to specified field')

        return return_val