diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py index 379958bd5..f334fd8db 100644 --- a/authentik/core/api/users.py +++ b/authentik/core/api/users.py @@ -2,12 +2,11 @@ from json import loads from django.db.models.query import QuerySet -from django.http.response import Http404 from django.urls import reverse_lazy from django.utils.http import urlencode from django_filters.filters import BooleanFilter, CharFilter from django_filters.filterset import FilterSet -from drf_spectacular.utils import OpenApiResponse, extend_schema, extend_schema_field +from drf_spectacular.utils import extend_schema, extend_schema_field from guardian.utils import get_anonymous_user from rest_framework.decorators import action from rest_framework.fields import CharField, JSONField, SerializerMethodField @@ -173,7 +172,7 @@ class UserViewSet(UsedByMixin, ModelViewSet): @extend_schema( responses={ "200": LinkSerializer(many=False), - "404": OpenApiResponse(description="No recovery flow found."), + "404": LinkSerializer(many=False), }, ) @action(detail=True, pagination_class=None, filter_backends=[]) @@ -184,7 +183,7 @@ class UserViewSet(UsedByMixin, ModelViewSet): # Check that there is a recovery flow, if not return an error flow = tenant.flow_recovery if not flow: - raise Http404 + return Response({"link": ""}, status=404) user: User = self.get_object() token, __ = Token.objects.get_or_create( identifier=f"{user.uid}-password-reset", diff --git a/schema.yml b/schema.yml index 8fc5277d6..d9b62ce6e 100644 --- a/schema.yml +++ b/schema.yml @@ -3096,7 +3096,11 @@ paths: $ref: '#/components/schemas/Link' description: '' '404': - description: No recovery flow found. + content: + application/json: + schema: + $ref: '#/components/schemas/Link' + description: '' '400': $ref: '#/components/schemas/ValidationError' '403': diff --git a/web/src/pages/users/UserListPage.ts b/web/src/pages/users/UserListPage.ts index 826fff144..c0ec93361 100644 --- a/web/src/pages/users/UserListPage.ts +++ b/web/src/pages/users/UserListPage.ts @@ -9,13 +9,14 @@ import "../../elements/buttons/ActionButton"; import { TableColumn } from "../../elements/table/Table"; import { PAGE_SIZE } from "../../constants"; import { CoreApi, User } from "authentik-api"; -import { DEFAULT_CONFIG } from "../../api/Config"; +import { DEFAULT_CONFIG, tenant } from "../../api/Config"; import "../../elements/forms/DeleteForm"; import "./UserActiveForm"; import "./UserForm"; import { showMessage } from "../../elements/messages/MessageContainer"; import { MessageLevel } from "../../elements/messages/Message"; import { first } from "../../utils"; +import { until } from "lit-html/directives/until"; @customElement("ak-user-list") export class UserListPage extends TablePage { @@ -128,27 +129,33 @@ export class UserListPage extends TablePage { - { - return new CoreApi(DEFAULT_CONFIG).coreUsersRecoveryRetrieve({ - id: item.pk || 0, - }).then(rec => { - showMessage({ - level: MessageLevel.success, - message: t`Successfully generated recovery link`, - description: rec.link - }); - }).catch((ex: Response) => { - ex.json().then(() => { - showMessage({ - level: MessageLevel.error, - message: t`No recovery flow is configured.`, - }); - }); - }); - }}> - ${t`Reset Password`} - + ${until(tenant().then(te => { + if (te.flowRecovery) { + return html` + { + return new CoreApi(DEFAULT_CONFIG).coreUsersRecoveryRetrieve({ + id: item.pk || 0, + }).then(rec => { + showMessage({ + level: MessageLevel.success, + message: t`Successfully generated recovery link`, + description: rec.link + }); + }).catch((ex: Response) => { + ex.json().then(() => { + showMessage({ + level: MessageLevel.error, + message: t`No recovery flow is configured.`, + }); + }); + }); + }}> + ${t`Reset Password`} + `; + } + return html``; + }))} ${t`Impersonate`} `,