core: fix error when using invalid key-values in attributes query

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-12-09 19:53:47 +01:00
parent cb3d9f83f1
commit 340a9bc8ee
4 changed files with 42 additions and 5 deletions

View File

@ -1,9 +1,11 @@
"""Groups API Viewset"""
from json import loads
from django.db.models.query import QuerySet
from django_filters.filters import ModelMultipleChoiceFilter
from django_filters.filters import CharFilter, ModelMultipleChoiceFilter
from django_filters.filterset import FilterSet
from rest_framework.fields import CharField, JSONField
from rest_framework.serializers import ListSerializer, ModelSerializer
from rest_framework.serializers import ListSerializer, ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
@ -62,6 +64,13 @@ class GroupSerializer(ModelSerializer):
class GroupFilter(FilterSet):
"""Filter for groups"""
attributes = CharFilter(
field_name="attributes",
lookup_expr="",
label="Attributes",
method="filter_attributes",
)
members_by_username = ModelMultipleChoiceFilter(
field_name="users__username",
to_field_name="username",
@ -72,10 +81,28 @@ class GroupFilter(FilterSet):
queryset=User.objects.all(),
)
# pylint: disable=unused-argument
def filter_attributes(self, queryset, name, value):
"""Filter attributes by query args"""
try:
value = loads(value)
except ValueError:
raise ValidationError(detail="filter: failed to parse JSON")
if not isinstance(value, dict):
raise ValidationError(detail="filter: value must be key:value mapping")
qs = {}
for key, _value in value.items():
qs[f"attributes__{key}"] = _value
try:
_ = len(queryset.filter(**qs))
return queryset.filter(**qs)
except ValueError:
return queryset
class Meta:
model = Group
fields = ["name", "is_superuser", "members_by_pk", "members_by_username"]
fields = ["name", "is_superuser", "members_by_pk", "attributes", "members_by_username"]
class GroupViewSet(UsedByMixin, ModelViewSet):

View File

@ -233,7 +233,11 @@ class UsersFilter(FilterSet):
qs = {}
for key, _value in value.items():
qs[f"attributes__{key}"] = _value
try:
_ = len(queryset.filter(**qs))
return queryset.filter(**qs)
except ValueError:
return queryset
class Meta:
model = User

View File

@ -2058,6 +2058,11 @@ paths:
operationId: core_groups_list
description: Group Viewset
parameters:
- in: query
name: attributes
schema:
type: string
description: Attributes
- in: query
name: is_superuser
schema:
@ -11846,6 +11851,7 @@ paths:
- ml
- mn
- mr
- ms
- my
- nb
- ne

View File

@ -62,7 +62,7 @@ export class UserListPage extends TablePage<User> {
search: this.search || "",
attributes: this.hideServiceAccounts
? JSON.stringify({
"goauthentik.io/user/service-account__isnull": "true",
"goauthentik.io/user/service-account__isnull": true,
})
: undefined,
});