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:
parent
cfe0a7a694
commit
c5e2635903
|
@ -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(
|
||||||
|
OAuthSourceSerializer(
|
||||||
|
data={
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"slug": "bar",
|
"slug": "bar",
|
||||||
"provider_type": "google",
|
"provider_type": "google",
|
||||||
"consumer_key": "foo",
|
"consumer_key": "foo",
|
||||||
"consumer_secret": "foo",
|
"consumer_secret": "foo",
|
||||||
}).is_valid())
|
}
|
||||||
self.assertFalse(OAuthSourceSerializer(data={
|
).is_valid()
|
||||||
|
)
|
||||||
|
self.assertFalse(
|
||||||
|
OAuthSourceSerializer(
|
||||||
|
data={
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"slug": "bar",
|
"slug": "bar",
|
||||||
"provider_type": "openid-connect",
|
"provider_type": "openid-connect",
|
||||||
"consumer_key": "foo",
|
"consumer_key": "foo",
|
||||||
"consumer_secret": "foo",
|
"consumer_secret": "foo",
|
||||||
}).is_valid())
|
}
|
||||||
|
).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