From 080282a0bc2aab90b9c4a8259b73fad080e98a27 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 18 Mar 2021 17:38:52 +0100 Subject: [PATCH] events: add better filters to event API Signed-off-by: Jens Langhammer --- authentik/events/api/event.py | 53 ++++++++++++++++++++- swagger.yaml | 89 +++++++++++++++++++++++++---------- web/src/api/Flows.ts | 10 ---- 3 files changed, 116 insertions(+), 36 deletions(-) diff --git a/authentik/events/api/event.py b/authentik/events/api/event.py index cede53465..75cfbeae9 100644 --- a/authentik/events/api/event.py +++ b/authentik/events/api/event.py @@ -1,9 +1,10 @@ """Events API Views""" +import django_filters from django.db.models.aggregates import Count from django.db.models.fields.json import KeyTextTransform from drf_yasg2.utils import swagger_auto_schema from rest_framework.decorators import action -from rest_framework.fields import DictField, IntegerField +from rest_framework.fields import CharField, DictField, IntegerField from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import ModelSerializer, Serializer @@ -15,6 +16,11 @@ from authentik.events.models import Event, EventAction class EventSerializer(ModelSerializer): """Event Serializer""" + # Since we only use this serializer for read-only operations, + # no checking of the action is done here. + # This allows clients to check wildcards, prefixes and custom types + action = CharField() + class Meta: model = Event @@ -56,6 +62,49 @@ class EventTopPerUserSerializer(Serializer): raise NotImplementedError +class EventsFilter(django_filters.FilterSet): + """Filter for events""" + + username = django_filters.CharFilter( + field_name="user", lookup_expr="username", label="Username" + ) + context_model_pk = django_filters.CharFilter( + field_name="context", + lookup_expr="model__pk", + label="Context Model Primary Key", + method="filter_context_model_pk", + ) + context_model_name = django_filters.CharFilter( + field_name="context", + lookup_expr="model__model_name", + label="Context Model Name", + ) + context_model_app = django_filters.CharFilter( + field_name="context", lookup_expr="model__app", label="Context Model App" + ) + context_authorized_app = django_filters.CharFilter( + field_name="context", + lookup_expr="authorized_application__pk", + label="Context Authorized application", + ) + action = django_filters.CharFilter( + field_name="action", + lookup_expr="icontains", + ) + + # pylint: disable=unused-argument + def filter_context_model_pk(self, queryset, name, value): + """Because we store the PK as UUID.hex, + we need to remove the dashes that a client may send. We can't use a + UUIDField for this, as some models might not have a UUID PK""" + value = str(value).replace("-", "") + return queryset.filter(context__model__pk=value) + + class Meta: + model = Event + fields = ["action", "client_ip", "username"] + + class EventViewSet(ReadOnlyModelViewSet): """Event Read-Only Viewset""" @@ -70,7 +119,7 @@ class EventViewSet(ReadOnlyModelViewSet): "context", "client_ip", ] - filterset_fields = ["action"] + filterset_class = EventsFilter @swagger_auto_schema( method="GET", diff --git a/swagger.yaml b/swagger.yaml index 80d106180..0e9790483 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -1866,6 +1866,36 @@ paths: description: '' required: false type: string + - name: client_ip + in: query + description: '' + required: false + type: string + - name: username + in: query + description: '' + required: false + type: string + - name: context_model_pk + in: query + description: '' + required: false + type: string + - name: context_model_name + in: query + description: '' + required: false + type: string + - name: context_model_app + in: query + description: '' + required: false + type: string + - name: context_authorized_app + in: query + description: '' + required: false + type: string - name: ordering in: query description: Which field to use when ordering the results. @@ -1937,6 +1967,36 @@ paths: description: '' required: false type: string + - name: client_ip + in: query + description: '' + required: false + type: string + - name: username + in: query + description: '' + required: false + type: string + - name: context_model_pk + in: query + description: '' + required: false + type: string + - name: context_model_name + in: query + description: '' + required: false + type: string + - name: context_model_app + in: query + description: '' + required: false + type: string + - name: context_authorized_app + in: query + description: '' + required: false + type: string - name: ordering in: query description: Which field to use when ordering the results. @@ -10991,30 +11051,7 @@ definitions: action: title: Action type: string - enum: - - login - - login_failed - - logout - - user_write - - suspicious_request - - password_set - - secret_view - - invitation_used - - authorize_application - - source_linked - - impersonation_started - - impersonation_ended - - policy_execution - - policy_exception - - property_mapping_exception - - system_task_execution - - system_task_exception - - configuration_error - - model_created - - model_updated - - model_deleted - - update_available - - custom_ + minLength: 1 app: title: App type: string @@ -11032,6 +11069,10 @@ definitions: type: string format: date-time readOnly: true + expires: + title: Expires + type: string + format: date-time EventTopPerUser: description: Response object of Event's top_per_user required: diff --git a/web/src/api/Flows.ts b/web/src/api/Flows.ts index 47b1da83e..10f7c40f9 100644 --- a/web/src/api/Flows.ts +++ b/web/src/api/Flows.ts @@ -28,13 +28,3 @@ export interface ShellChallenge extends Challenge { export interface RedirectChallenge extends Challenge { to: string; } - -export enum FlowDesignation { - Authentication = "authentication", - Authorization = "authorization", - Invalidation = "invalidation", - Enrollment = "enrollment", - Unrenollment = "unenrollment", - Recovery = "recovery", - StageConfiguration = "stage_configuration", -}