core: improve messaging when creating a recovery link for a user when no recovery flow exists
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		@ -1,4 +1,5 @@
 | 
				
			|||||||
"""User API Views"""
 | 
					"""User API Views"""
 | 
				
			||||||
 | 
					from django.http.response import Http404
 | 
				
			||||||
from django.urls import reverse_lazy
 | 
					from django.urls import reverse_lazy
 | 
				
			||||||
from django.utils.http import urlencode
 | 
					from django.utils.http import urlencode
 | 
				
			||||||
from drf_yasg.utils import swagger_auto_schema, swagger_serializer_method
 | 
					from drf_yasg.utils import swagger_auto_schema, swagger_serializer_method
 | 
				
			||||||
@ -19,6 +20,7 @@ from authentik.core.middleware import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
from authentik.core.models import Token, TokenIntents, User
 | 
					from authentik.core.models import Token, TokenIntents, User
 | 
				
			||||||
from authentik.events.models import EventAction
 | 
					from authentik.events.models import EventAction
 | 
				
			||||||
 | 
					from authentik.flows.models import Flow, FlowDesignation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UserSerializer(ModelSerializer):
 | 
					class UserSerializer(ModelSerializer):
 | 
				
			||||||
@ -121,12 +123,16 @@ class UserViewSet(ModelViewSet):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @permission_required("authentik_core.reset_user_password")
 | 
					    @permission_required("authentik_core.reset_user_password")
 | 
				
			||||||
    @swagger_auto_schema(
 | 
					    @swagger_auto_schema(
 | 
				
			||||||
        responses={"200": LinkSerializer(many=False)},
 | 
					        responses={"200": LinkSerializer(many=False), "404": "No recovery flow found."},
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    @action(detail=True, pagination_class=None, filter_backends=[])
 | 
					    @action(detail=True, pagination_class=None, filter_backends=[])
 | 
				
			||||||
    # pylint: disable=invalid-name, unused-argument
 | 
					    # pylint: disable=invalid-name, unused-argument
 | 
				
			||||||
    def recovery(self, request: Request, pk: int) -> Response:
 | 
					    def recovery(self, request: Request, pk: int) -> Response:
 | 
				
			||||||
        """Create a temporary link that a user can use to recover their accounts"""
 | 
					        """Create a temporary link that a user can use to recover their accounts"""
 | 
				
			||||||
 | 
					        # Check that there is a recovery flow, if not return an error
 | 
				
			||||||
 | 
					        flow = Flow.with_policy(request, designation=FlowDesignation.RECOVERY)
 | 
				
			||||||
 | 
					        if not flow:
 | 
				
			||||||
 | 
					            raise Http404
 | 
				
			||||||
        user: User = self.get_object()
 | 
					        user: User = self.get_object()
 | 
				
			||||||
        token, __ = Token.objects.get_or_create(
 | 
					        token, __ = Token.objects.get_or_create(
 | 
				
			||||||
            identifier=f"{user.uid}-password-reset",
 | 
					            identifier=f"{user.uid}-password-reset",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
"""OAuth Source tests"""
 | 
					"""OAuth Source tests"""
 | 
				
			||||||
from authentik.sources.oauth.api.source import OAuthSourceSerializer
 | 
					 | 
				
			||||||
from django.test import TestCase
 | 
					from django.test import TestCase
 | 
				
			||||||
from django.urls import reverse
 | 
					from django.urls import reverse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from authentik.sources.oauth.api.source import OAuthSourceSerializer
 | 
				
			||||||
from authentik.sources.oauth.models import OAuthSource
 | 
					from authentik.sources.oauth.models import OAuthSource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -21,20 +21,28 @@ class TestOAuthSource(TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def test_api_validate(self):
 | 
					    def test_api_validate(self):
 | 
				
			||||||
        """Test API validation"""
 | 
					        """Test API validation"""
 | 
				
			||||||
        self.assertTrue(OAuthSourceSerializer(data={
 | 
					        self.assertTrue(
 | 
				
			||||||
            "name": "foo",
 | 
					            OAuthSourceSerializer(
 | 
				
			||||||
            "slug": "bar",
 | 
					                data={
 | 
				
			||||||
            "provider_type": "google",
 | 
					                    "name": "foo",
 | 
				
			||||||
            "consumer_key": "foo",
 | 
					                    "slug": "bar",
 | 
				
			||||||
            "consumer_secret": "foo",
 | 
					                    "provider_type": "google",
 | 
				
			||||||
        }).is_valid())
 | 
					                    "consumer_key": "foo",
 | 
				
			||||||
        self.assertFalse(OAuthSourceSerializer(data={
 | 
					                    "consumer_secret": "foo",
 | 
				
			||||||
            "name": "foo",
 | 
					                }
 | 
				
			||||||
            "slug": "bar",
 | 
					            ).is_valid()
 | 
				
			||||||
            "provider_type": "openid-connect",
 | 
					        )
 | 
				
			||||||
            "consumer_key": "foo",
 | 
					        self.assertFalse(
 | 
				
			||||||
            "consumer_secret": "foo",
 | 
					            OAuthSourceSerializer(
 | 
				
			||||||
        }).is_valid())
 | 
					                data={
 | 
				
			||||||
 | 
					                    "name": "foo",
 | 
				
			||||||
 | 
					                    "slug": "bar",
 | 
				
			||||||
 | 
					                    "provider_type": "openid-connect",
 | 
				
			||||||
 | 
					                    "consumer_key": "foo",
 | 
				
			||||||
 | 
					                    "consumer_secret": "foo",
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ).is_valid()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_source_redirect(self):
 | 
					    def test_source_redirect(self):
 | 
				
			||||||
        """test redirect view"""
 | 
					        """test redirect view"""
 | 
				
			||||||
 | 
				
			|||||||
@ -2237,15 +2237,15 @@ paths:
 | 
				
			|||||||
          description: ''
 | 
					          description: ''
 | 
				
			||||||
          schema:
 | 
					          schema:
 | 
				
			||||||
            $ref: '#/definitions/Link'
 | 
					            $ref: '#/definitions/Link'
 | 
				
			||||||
        '403':
 | 
					 | 
				
			||||||
          description: Authentication credentials were invalid, absent or insufficient.
 | 
					 | 
				
			||||||
          schema:
 | 
					 | 
				
			||||||
            $ref: '#/definitions/GenericError'
 | 
					 | 
				
			||||||
        '404':
 | 
					        '404':
 | 
				
			||||||
          description: Object does not exist or caller has insufficient permissions
 | 
					          description: Object does not exist or caller has insufficient permissions
 | 
				
			||||||
            to access it.
 | 
					            to access it.
 | 
				
			||||||
          schema:
 | 
					          schema:
 | 
				
			||||||
            $ref: '#/definitions/APIException'
 | 
					            $ref: '#/definitions/APIException'
 | 
				
			||||||
 | 
					        '403':
 | 
				
			||||||
 | 
					          description: Authentication credentials were invalid, absent or insufficient.
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            $ref: '#/definitions/GenericError'
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
        - core
 | 
					        - core
 | 
				
			||||||
    parameters:
 | 
					    parameters:
 | 
				
			||||||
 | 
				
			|||||||
@ -737,8 +737,8 @@ msgstr "Copy Key"
 | 
				
			|||||||
#: src/pages/stages/prompt/PromptStageForm.ts:98
 | 
					#: src/pages/stages/prompt/PromptStageForm.ts:98
 | 
				
			||||||
#: src/pages/user-settings/tokens/UserTokenList.ts:50
 | 
					#: src/pages/user-settings/tokens/UserTokenList.ts:50
 | 
				
			||||||
#: src/pages/user-settings/tokens/UserTokenList.ts:58
 | 
					#: src/pages/user-settings/tokens/UserTokenList.ts:58
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:144
 | 
					#: src/pages/users/UserListPage.ts:151
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:152
 | 
					#: src/pages/users/UserListPage.ts:159
 | 
				
			||||||
msgid "Create"
 | 
					msgid "Create"
 | 
				
			||||||
msgstr "Create"
 | 
					msgstr "Create"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -808,7 +808,7 @@ msgstr "Create Stage binding"
 | 
				
			|||||||
msgid "Create Token"
 | 
					msgid "Create Token"
 | 
				
			||||||
msgstr "Create Token"
 | 
					msgstr "Create Token"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:147
 | 
					#: src/pages/users/UserListPage.ts:154
 | 
				
			||||||
msgid "Create User"
 | 
					msgid "Create User"
 | 
				
			||||||
msgstr "Create User"
 | 
					msgstr "Create User"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1531,7 +1531,7 @@ msgstr "If this flag is set, this Stage will jump to the next Stage when no Invi
 | 
				
			|||||||
msgid "If your authentik Instance is using a self-signed certificate, set this value."
 | 
					msgid "If your authentik Instance is using a self-signed certificate, set this value."
 | 
				
			||||||
msgstr "If your authentik Instance is using a self-signed certificate, set this value."
 | 
					msgstr "If your authentik Instance is using a self-signed certificate, set this value."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:136
 | 
					#: src/pages/users/UserListPage.ts:143
 | 
				
			||||||
msgid "Impersonate"
 | 
					msgid "Impersonate"
 | 
				
			||||||
msgstr "Impersonate"
 | 
					msgstr "Impersonate"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1996,6 +1996,10 @@ msgstr "No policies are currently bound to this object."
 | 
				
			|||||||
msgid "No policies cached. Users may experience slow response times."
 | 
					msgid "No policies cached. Users may experience slow response times."
 | 
				
			||||||
msgstr "No policies cached. Users may experience slow response times."
 | 
					msgstr "No policies cached. Users may experience slow response times."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: src/pages/users/UserListPage.ts:135
 | 
				
			||||||
 | 
					msgid "No recovery flow is configured."
 | 
				
			||||||
 | 
					msgstr "No recovery flow is configured."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: src/pages/flows/BoundStagesList.ts:114
 | 
					#: src/pages/flows/BoundStagesList.ts:114
 | 
				
			||||||
msgid "No stages are currently bound to this flow."
 | 
					msgid "No stages are currently bound to this flow."
 | 
				
			||||||
msgstr "No stages are currently bound to this flow."
 | 
					msgstr "No stages are currently bound to this flow."
 | 
				
			||||||
@ -2538,7 +2542,7 @@ msgstr "Required"
 | 
				
			|||||||
msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
 | 
					msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
 | 
				
			||||||
msgstr "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
 | 
					msgstr "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:133
 | 
					#: src/pages/users/UserListPage.ts:140
 | 
				
			||||||
#: src/pages/users/UserViewPage.ts:165
 | 
					#: src/pages/users/UserViewPage.ts:165
 | 
				
			||||||
msgid "Reset Password"
 | 
					msgid "Reset Password"
 | 
				
			||||||
msgstr "Reset Password"
 | 
					msgstr "Reset Password"
 | 
				
			||||||
 | 
				
			|||||||
@ -731,8 +731,8 @@ msgstr ""
 | 
				
			|||||||
#: src/pages/stages/prompt/PromptStageForm.ts:98
 | 
					#: src/pages/stages/prompt/PromptStageForm.ts:98
 | 
				
			||||||
#: src/pages/user-settings/tokens/UserTokenList.ts:50
 | 
					#: src/pages/user-settings/tokens/UserTokenList.ts:50
 | 
				
			||||||
#: src/pages/user-settings/tokens/UserTokenList.ts:58
 | 
					#: src/pages/user-settings/tokens/UserTokenList.ts:58
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:144
 | 
					#: src/pages/users/UserListPage.ts:151
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:152
 | 
					#: src/pages/users/UserListPage.ts:159
 | 
				
			||||||
msgid "Create"
 | 
					msgid "Create"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -802,7 +802,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Create Token"
 | 
					msgid "Create Token"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:147
 | 
					#: src/pages/users/UserListPage.ts:154
 | 
				
			||||||
msgid "Create User"
 | 
					msgid "Create User"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1523,7 +1523,7 @@ msgstr ""
 | 
				
			|||||||
msgid "If your authentik Instance is using a self-signed certificate, set this value."
 | 
					msgid "If your authentik Instance is using a self-signed certificate, set this value."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:136
 | 
					#: src/pages/users/UserListPage.ts:143
 | 
				
			||||||
msgid "Impersonate"
 | 
					msgid "Impersonate"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1988,6 +1988,10 @@ msgstr ""
 | 
				
			|||||||
msgid "No policies cached. Users may experience slow response times."
 | 
					msgid "No policies cached. Users may experience slow response times."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: src/pages/users/UserListPage.ts:135
 | 
				
			||||||
 | 
					msgid "No recovery flow is configured."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: src/pages/flows/BoundStagesList.ts:114
 | 
					#: src/pages/flows/BoundStagesList.ts:114
 | 
				
			||||||
msgid "No stages are currently bound to this flow."
 | 
					msgid "No stages are currently bound to this flow."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@ -2530,7 +2534,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
 | 
					msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: src/pages/users/UserListPage.ts:133
 | 
					#: src/pages/users/UserListPage.ts:140
 | 
				
			||||||
#: src/pages/users/UserViewPage.ts:165
 | 
					#: src/pages/users/UserViewPage.ts:165
 | 
				
			||||||
msgid "Reset Password"
 | 
					msgid "Reset Password"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
				
			|||||||
@ -127,6 +127,13 @@ export class UserListPage extends TablePage<User> {
 | 
				
			|||||||
                            message: t`Successfully generated recovery link`,
 | 
					                            message: t`Successfully generated recovery link`,
 | 
				
			||||||
                            description: rec.link
 | 
					                            description: rec.link
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
 | 
					                    }).catch((ex: Response) => {
 | 
				
			||||||
 | 
					                        ex.json().then(() => {
 | 
				
			||||||
 | 
					                            showMessage({
 | 
				
			||||||
 | 
					                                level: MessageLevel.error,
 | 
				
			||||||
 | 
					                                message: t`No recovery flow is configured.`,
 | 
				
			||||||
 | 
					                            });
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }}>
 | 
					                }}>
 | 
				
			||||||
                ${t`Reset Password`}
 | 
					                ${t`Reset Password`}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user