diff --git a/authentik/admin/api/metrics.py b/authentik/admin/api/metrics.py index ad3943e16..9ed67ff75 100644 --- a/authentik/admin/api/metrics.py +++ b/authentik/admin/api/metrics.py @@ -13,7 +13,7 @@ from rest_framework.permissions import IsAdminUser from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import Serializer -from rest_framework.viewsets import ViewSet +from rest_framework.viewsets import ReadOnlyModelViewSet from authentik.events.models import Event, EventAction @@ -81,7 +81,7 @@ class LoginMetricsSerializer(Serializer): raise NotImplementedError -class AdministrationMetricsViewSet(ViewSet): +class AdministrationMetricsViewSet(ReadOnlyModelViewSet): """Login Metrics per 1h""" permission_classes = [IsAdminUser] diff --git a/authentik/api/templates/api/swagger.html b/authentik/api/templates/api/swagger.html index b5e9cc52e..921a25865 100644 --- a/authentik/api/templates/api/swagger.html +++ b/authentik/api/templates/api/swagger.html @@ -1,10 +1,12 @@ {% load static %} +{% load i18n %} + {% block title %}{% trans title|default:config.authentik.branding.title %}{% endblock %} Model: + raise NotImplementedError + + def update(self, instance: Model, validated_data: dict) -> Model: + raise NotImplementedError + + class UserViewSet(ModelViewSet): """User Viewset""" @@ -50,3 +89,11 @@ class UserViewSet(ModelViewSet): def me(self, request: Request) -> Response: """Get information about current user""" return Response(UserSerializer(request.user).data) + + @swagger_auto_schema(responses={200: UserMetricsSerializer(many=False)}) + @action(detail=False) + def metrics(self, request: Request) -> Response: + """User metrics per 1h""" + serializer = UserMetricsSerializer(True) + serializer.context["request"] = request + return Response(serializer.data) diff --git a/swagger.yaml b/swagger.yaml index 0e9790483..ea14438dd 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -24,7 +24,27 @@ paths: get: operationId: admin_metrics_list description: Login Metrics per 1h - parameters: [] + parameters: + - name: ordering + in: query + description: Which field to use when ordering the results. + required: false + type: string + - name: search + in: query + description: A search term. + required: false + type: string + - name: page + in: query + description: Page Index + required: false + type: integer + - name: page_size + in: query + description: Page Size + required: false + type: integer responses: '200': description: Login Metrics per 1h @@ -33,6 +53,21 @@ paths: tags: - admin parameters: [] + /admin/metrics/{id}/: + get: + operationId: admin_metrics_read + description: Login Metrics per 1h + parameters: [] + responses: + '200': + description: '' + tags: + - admin + parameters: + - name: id + in: path + required: true + type: string /admin/system_tasks/: get: operationId: admin_system_tasks_list @@ -1617,6 +1652,54 @@ paths: tags: - core parameters: [] + /core/users/metrics/: + get: + operationId: core_users_metrics + description: User metrics per 1h + parameters: + - name: username + in: query + description: '' + required: false + type: string + - name: name + in: query + description: '' + required: false + type: string + - name: is_active + in: query + description: '' + required: false + type: string + - name: ordering + in: query + description: Which field to use when ordering the results. + required: false + type: string + - name: search + in: query + description: A search term. + required: false + type: string + - name: page + in: query + description: Page Index + required: false + type: integer + - name: page_size + in: query + description: Page Size + required: false + type: integer + responses: + '200': + description: User Metrics + schema: + $ref: '#/definitions/UserMetrics' + tags: + - core + parameters: [] /core/users/{id}/: get: operationId: core_users_read @@ -10981,6 +11064,28 @@ definitions: $ref: '#/definitions/User' application: $ref: '#/definitions/Application' + UserMetrics: + description: User Metrics + type: object + properties: + logins_per_1h: + description: '' + type: array + items: + $ref: '#/definitions/Coordinate' + readOnly: true + logins_failed_per_1h: + description: '' + type: array + items: + $ref: '#/definitions/Coordinate' + readOnly: true + authorizations_per_1h: + description: '' + type: array + items: + $ref: '#/definitions/Coordinate' + readOnly: true CertificateKeyPair: description: CertificateKeyPair Serializer required: diff --git a/tests/e2e/test_provider_oauth2_oidc_implicit.py b/tests/e2e/test_provider_oauth2_oidc_implicit.py index 52bc5664b..e3e207607 100644 --- a/tests/e2e/test_provider_oauth2_oidc_implicit.py +++ b/tests/e2e/test_provider_oauth2_oidc_implicit.py @@ -197,6 +197,7 @@ class TestProviderOAuth2OIDCImplicit(SeleniumTestCase): self.container = self.setup_client() self.driver.get("http://localhost:9009/implicit/") + sleep(2) self.login() self.wait.until(