diff --git a/authentik/events/api.py b/authentik/events/api.py index 906d8d2b5..0d60dfbab 100644 --- a/authentik/events/api.py +++ b/authentik/events/api.py @@ -48,6 +48,15 @@ class EventViewSet(ReadOnlyModelViewSet): queryset = Event.objects.all() serializer_class = EventSerializer + ordering = ["-created"] + search_fields = [ + "user", + "action", + "app", + "context", + "client_ip", + ] + filterset_fields = ["action"] @swagger_auto_schema( method="GET", responses={200: EventTopPerUserSerialier(many=True)} diff --git a/authentik/events/apps.py b/authentik/events/apps.py index 5899645df..ad9e7d205 100644 --- a/authentik/events/apps.py +++ b/authentik/events/apps.py @@ -10,7 +10,6 @@ class AuthentikEventsConfig(AppConfig): name = "authentik.events" label = "authentik_events" verbose_name = "authentik Events" - mountpoint = "events/" def ready(self): import_module("authentik.events.signals") diff --git a/authentik/events/templates/events/list.html b/authentik/events/templates/events/list.html deleted file mode 100644 index 0424a75d7..000000000 --- a/authentik/events/templates/events/list.html +++ /dev/null @@ -1,90 +0,0 @@ -{% extends "base/page.html" %} - -{% load i18n %} -{% load authentik_utils %} - -{% block page_content %} -
-
-
-

- - {% trans 'Event Log' %} -

-
-
-
-
-
-
- {% include 'partials/toolbar_search.html' %} - - {% include 'partials/pagination.html' %} -
-
- - - - - - - - - - - - {% for entry in object_list %} - - - - - - - - {% endfor %} - -
{% trans 'Action' %}{% trans 'Context' %}{% trans 'User' %}{% trans 'Creation Date' %}{% trans 'Client IP' %}
-
-
{{ entry.action }}
- {{ entry.app|default:'-' }} -
-
-
-
- {{ entry.context }} -
- {% if entry.user.on_behalf_of %} - - {% blocktrans with username=entry.user.on_behalf_of.username %} - On behalf of {{ username }} - {% endblocktrans %} - - {% endif %} -
-
-
-
{{ entry.user.username }}
- - {% blocktrans with pk=entry.user.pk %} - ID: {{ pk }} - {% endblocktrans %} - -
-
- - {{ entry.created }} - - - - {{ entry.client_ip }} - -
-
- {% include 'partials/pagination.html' %} -
-
-
-
-{% endblock %} diff --git a/authentik/events/urls.py b/authentik/events/urls.py deleted file mode 100644 index ff208e2b8..000000000 --- a/authentik/events/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -"""authentik events urls""" -from django.urls import path - -from authentik.events.views import EventListView - -urlpatterns = [ - # Event Log - path("log/", EventListView.as_view(), name="log"), -] diff --git a/authentik/events/views.py b/authentik/events/views.py deleted file mode 100644 index 0bbb83f2b..000000000 --- a/authentik/events/views.py +++ /dev/null @@ -1,30 +0,0 @@ -"""authentik Event administration""" -from django.contrib.auth.mixins import LoginRequiredMixin -from django.views.generic import ListView -from guardian.mixins import PermissionListMixin - -from authentik.admin.views.utils import SearchListMixin, UserPaginateListMixin -from authentik.events.models import Event - - -class EventListView( - PermissionListMixin, - LoginRequiredMixin, - SearchListMixin, - UserPaginateListMixin, - ListView, -): - """Show list of all invitations""" - - model = Event - template_name = "events/list.html" - permission_required = "authentik_events.view_event" - ordering = "-created" - - search_fields = [ - "user", - "action", - "app", - "context", - "client_ip", - ] diff --git a/authentik/flows/api.py b/authentik/flows/api.py index 2ac784c7d..4389f8fe9 100644 --- a/authentik/flows/api.py +++ b/authentik/flows/api.py @@ -78,6 +78,8 @@ class FlowViewSet(ModelViewSet): queryset = Flow.objects.all() serializer_class = FlowSerializer lookup_field = "slug" + search_fields = ["name", "slug", "designation", "title"] + filterset_fields = ["flow_uuid", "name", "slug", "designation"] @swagger_auto_schema(responses={200: FlowDiagramSerializer()}) @action(detail=True, methods=["get"]) diff --git a/authentik/outposts/controllers/docker.py b/authentik/outposts/controllers/docker.py index e12d7872c..f8c625f41 100644 --- a/authentik/outposts/controllers/docker.py +++ b/authentik/outposts/controllers/docker.py @@ -154,6 +154,7 @@ class DockerController(BaseController): ), "AUTHENTIK_TOKEN": self.outpost.token.key, }, + "labels": self._get_labels(), } }, } diff --git a/authentik/providers/oauth2/models.py b/authentik/providers/oauth2/models.py index 6dd5ab3c9..dc0511e19 100644 --- a/authentik/providers/oauth2/models.py +++ b/authentik/providers/oauth2/models.py @@ -398,7 +398,7 @@ class AuthorizationCode(ExpiringModel, BaseGrantModel): verbose_name_plural = _("Authorization Codes") def __str__(self): - return "{0} - {1}".format(self.provider, self.code) + return f"Authorization code for {self.provider} for user {self.user}" @dataclass @@ -461,7 +461,7 @@ class RefreshToken(ExpiringModel, BaseGrantModel): self._id_token = json.dumps(asdict(value)) def __str__(self): - return f"{self.provider} - {self.access_token}" + return f"Refresh Token for {self.provider} for user {self.access_token.user}" @property def at_hash(self): diff --git a/authentik/providers/proxy/controllers/k8s/ingress.py b/authentik/providers/proxy/controllers/k8s/ingress.py index ea4de5acc..1b02a54bc 100644 --- a/authentik/providers/proxy/controllers/k8s/ingress.py +++ b/authentik/providers/proxy/controllers/k8s/ingress.py @@ -74,11 +74,13 @@ class IngressReconciler(KubernetesObjectReconciler[NetworkingV1beta1Ingress]): # goes to the same pod "nginx.ingress.kubernetes.io/affinity": "cookie", "traefik.ingress.kubernetes.io/affinity": "true", + "nginx.ingress.kubernetes.io/proxy-buffers-number": "4", + "nginx.ingress.kubernetes.io/proxy-buffer-size": "16k", } annotations.update( self.controller.outpost.config.kubernetes_ingress_annotations ) - return dict() + return annotations def get_reference_object(self) -> NetworkingV1beta1Ingress: """Get deployment object for outpost""" diff --git a/authentik/providers/proxy/forms.py b/authentik/providers/proxy/forms.py index a83715105..2c3277253 100644 --- a/authentik/providers/proxy/forms.py +++ b/authentik/providers/proxy/forms.py @@ -7,7 +7,7 @@ from authentik.providers.proxy.models import ProxyProvider class ProxyProviderForm(forms.ModelForm): - """Security Gateway Provider form""" + """Proxy Provider form""" instance: ProxyProvider diff --git a/authentik/root/settings.py b/authentik/root/settings.py index 3975f7d8e..d68852758 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -142,6 +142,7 @@ SWAGGER_SETTINGS = { REST_FRAMEWORK = { "DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination", "PAGE_SIZE": 100, + "DATETIME_FORMAT": "%s", "DEFAULT_FILTER_BACKENDS": [ "rest_framework_guardian.filters.ObjectPermissionsFilter", "django_filters.rest_framework.DjangoFilterBackend", diff --git a/lifecycle/system_migrations/to_0_13_events..py b/lifecycle/system_migrations/to_0_14_events..py similarity index 100% rename from lifecycle/system_migrations/to_0_13_events..py rename to lifecycle/system_migrations/to_0_14_events..py diff --git a/swagger.yaml b/swagger.yaml index 6aca8b15b..a577d2f9a 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -868,6 +868,11 @@ paths: operationId: events_events_list description: Event Read-Only Viewset parameters: + - name: action + in: query + description: '' + required: false + type: string - name: ordering in: query description: Which field to use when ordering the results. @@ -919,6 +924,11 @@ paths: operationId: events_events_top_per_user description: Get the top_n events grouped by user count parameters: + - name: action + in: query + description: '' + required: false + type: string - name: ordering in: query description: Which field to use when ordering the results. @@ -1194,6 +1204,26 @@ paths: operationId: flows_instances_list description: Flow Viewset parameters: + - name: flow_uuid + in: query + description: '' + required: false + type: string + - name: name + in: query + description: '' + required: false + type: string + - name: slug + in: query + description: '' + required: false + type: string + - name: designation + in: query + description: '' + required: false + type: string - name: ordering in: query description: Which field to use when ordering the results. @@ -8133,6 +8163,14 @@ definitions: type: string format: uuid x-nullable: true + verbose_name: + title: Verbose name + type: string + readOnly: true + verbose_name_plural: + title: Verbose name plural + type: string + readOnly: true __type__: title: 'type ' type: string @@ -8181,6 +8219,14 @@ definitions: type: string format: uuid x-nullable: true + verbose_name: + title: Verbose name + type: string + readOnly: true + verbose_name_plural: + title: Verbose name plural + type: string + readOnly: true server_uri: title: Server URI type: string @@ -8296,6 +8342,14 @@ definitions: type: string format: uuid x-nullable: true + verbose_name: + title: Verbose name + type: string + readOnly: true + verbose_name_plural: + title: Verbose name plural + type: string + readOnly: true provider_type: title: Provider type type: string diff --git a/web/package-lock.json b/web/package-lock.json index bb7222d7d..7311fccec 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -304,9 +304,9 @@ } }, "@types/codemirror": { - "version": "0.0.102", - "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.102.tgz", - "integrity": "sha512-WZZW8VL8BAzzAZWkiYnM5VsYz1qWYieRqHPPtC/BB015QXd3LPXtBlbRYA8lauKgM10qWYeLH8p5LsIn2SLXfA==", + "version": "0.0.103", + "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.103.tgz", + "integrity": "sha512-dYQTrIcZal0pnYz/ODjpJB+yadKJhGHywylAlHKjE8VSzGiw2A+6S+hD6jfyXw02ToFR9DO52X+O1pvHn31sbg==", "requires": { "@types/tern": "*" } diff --git a/web/package.json b/web/package.json index 6f4cda537..00ace845e 100644 --- a/web/package.json +++ b/web/package.json @@ -12,7 +12,7 @@ "@sentry/browser": "^5.29.2", "@sentry/tracing": "^5.29.2", "@types/chart.js": "^2.9.29", - "@types/codemirror": "0.0.102", + "@types/codemirror": "0.0.103", "chart.js": "^2.9.4", "codemirror": "^5.59.0", "construct-style-sheets-polyfill": "^2.4.3", diff --git a/web/src/api/Events.ts b/web/src/api/Events.ts index 408e38dec..b0b08fd65 100644 --- a/web/src/api/Events.ts +++ b/web/src/api/Events.ts @@ -1,6 +1,37 @@ -import { DefaultClient } from "./Client"; +import { DefaultClient, PBResponse, QueryArguments } from "./Client"; + +export interface EventUser { + pk: number; + email?: string; + username: string; + on_behalf_of?: EventUser; +} + +export interface EventContext { + [key: string]: EventContext | string | number; +} export class Event { + pk: string; + user: EventUser; + action: string; + app: string; + context: EventContext; + client_ip: string; + created: string; + + constructor() { + throw Error(); + } + + static get(pk: string): Promise { + return DefaultClient.fetch(["events", "events", pk]); + } + + static list(filter?: QueryArguments): Promise> { + return DefaultClient.fetch>(["events", "events"], filter); + } + // events/events/top_per_user/?filter_action=authorize_application static topForUser(action: string): Promise { return DefaultClient.fetch(["events", "events", "top_per_user"], { diff --git a/web/src/elements/table/Table.ts b/web/src/elements/table/Table.ts index b9e38984e..690baf139 100644 --- a/web/src/elements/table/Table.ts +++ b/web/src/elements/table/Table.ts @@ -115,6 +115,7 @@ export abstract class Table extends LitElement { this.apiEndpoint(this.page).then((r) => { this.data = r; this.page = r.pagination.current; + this.expandedRows = []; }); } @@ -144,7 +145,7 @@ export abstract class Table extends LitElement {
- ${inner ? inner : html``} + ${inner ? inner : html``}
@@ -178,7 +179,7 @@ export abstract class Table extends LitElement { - ${this.renderExpanded(item)} + ${this.expandedRows[idx] ? this.renderExpanded(item) : html``} `; }); diff --git a/web/src/elements/table/TableSearch.ts b/web/src/elements/table/TableSearch.ts index 1cc676c7b..4d6d1ab13 100644 --- a/web/src/elements/table/TableSearch.ts +++ b/web/src/elements/table/TableSearch.ts @@ -26,9 +26,9 @@ export class TableSearch extends LitElement { if (el.value === "") return; this.onSearch(el?.value); }}> - { + { if (!this.onSearch) return; - this.onSearch(""); + this.onSearch((ev.target as HTMLInputElement).value); }}>