core: add configure_url to UserSettings for both stages and sources
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -24,8 +24,7 @@ from structlog.stdlib import get_logger | ||||
|  | ||||
| from authentik.core.exceptions import PropertyMappingExpressionException | ||||
| from authentik.core.signals import password_changed | ||||
| from authentik.core.types import UILoginButton | ||||
| from authentik.flows.challenge import Challenge | ||||
| from authentik.core.types import UILoginButton, UserSettingSerializer | ||||
| from authentik.flows.models import Flow | ||||
| from authentik.lib.config import CONFIG | ||||
| from authentik.lib.models import CreatedUpdatedModel, SerializerModel | ||||
| @ -342,9 +341,9 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel): | ||||
|         return None | ||||
|  | ||||
|     @property | ||||
|     def ui_user_settings(self) -> Optional[Challenge]: | ||||
|     def ui_user_settings(self) -> Optional[UserSettingSerializer]: | ||||
|         """Entrypoint to integrate with User settings. Can either return None if no | ||||
|         user settings are available, or a challenge.""" | ||||
|         user settings are available, or UserSettingSerializer.""" | ||||
|         return None | ||||
|  | ||||
|     def __str__(self): | ||||
|  | ||||
| @ -36,3 +36,4 @@ class UserSettingSerializer(PassiveSerializer): | ||||
|     object_uid = CharField() | ||||
|     component = CharField() | ||||
|     title = CharField() | ||||
|     configure_url = CharField() | ||||
|  | ||||
| @ -5,7 +5,6 @@ from django.urls.base import reverse | ||||
| from drf_spectacular.utils import extend_schema | ||||
| from rest_framework import mixins | ||||
| from rest_framework.decorators import action | ||||
| from rest_framework.fields import BooleanField, CharField | ||||
| from rest_framework.request import Request | ||||
| from rest_framework.response import Response | ||||
| from rest_framework.serializers import ModelSerializer, SerializerMethodField | ||||
| @ -21,12 +20,6 @@ from authentik.lib.utils.reflection import all_subclasses | ||||
| LOGGER = get_logger() | ||||
|  | ||||
|  | ||||
| class StageUserSettingSerializer(UserSettingSerializer): | ||||
|     """User settings but can include a configure flow""" | ||||
|  | ||||
|     configure_flow = CharField(required=False) | ||||
|  | ||||
|  | ||||
| class StageSerializer(ModelSerializer, MetaNameSerializer): | ||||
|     """Stage Serializer""" | ||||
|  | ||||
| @ -87,7 +80,7 @@ class StageViewSet( | ||||
|         data = sorted(data, key=lambda x: x["name"]) | ||||
|         return Response(TypeCreateSerializer(data, many=True).data) | ||||
|  | ||||
|     @extend_schema(responses={200: StageUserSettingSerializer(many=True)}) | ||||
|     @extend_schema(responses={200: UserSettingSerializer(many=True)}) | ||||
|     @action(detail=False, pagination_class=None, filter_backends=[]) | ||||
|     def user_settings(self, request: Request) -> Response: | ||||
|         """Get all stages the user can configure""" | ||||
| @ -98,8 +91,8 @@ class StageViewSet( | ||||
|             if not user_settings: | ||||
|                 continue | ||||
|             user_settings.initial_data["object_uid"] = str(stage.pk) | ||||
|             if hasattr(stage, "configure_flow"): | ||||
|                 user_settings.initial_data["configure_flow"] = reverse( | ||||
|             if hasattr(stage, "configure_url"): | ||||
|                 user_settings.initial_data["configure_url"] = reverse( | ||||
|                     "authentik_flows:configure", | ||||
|                     kwargs={"stage_uuid": stage.uuid.hex}, | ||||
|                 ) | ||||
|  | ||||
| @ -43,7 +43,7 @@ class Challenge(PassiveSerializer): | ||||
|     type = ChoiceField( | ||||
|         choices=[(x.value, x.name) for x in ChallengeTypes], | ||||
|     ) | ||||
|     flow_info = ContextualFlowInfo() | ||||
|     flow_info = ContextualFlowInfo(required=False) | ||||
|     component = CharField(default="") | ||||
|  | ||||
|     response_errors = DictField( | ||||
|  | ||||
| @ -93,7 +93,11 @@ class TestFlowExecutor(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": FlowNonApplicableException.__doc__, | ||||
|                 "title": "", | ||||
|                 "flow_info": { | ||||
|                     "background": flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|             }, | ||||
|         ) | ||||
| @ -422,10 +426,13 @@ class TestFlowExecutor(TestCase): | ||||
|             self.assertJSONEqual( | ||||
|                 force_str(response.content), | ||||
|                 { | ||||
|                     "background": flow.background_url, | ||||
|                     "type": ChallengeTypes.NATIVE.value, | ||||
|                     "component": "ak-stage-dummy", | ||||
|                     "title": binding.stage.name, | ||||
|                     "flow_info": { | ||||
|                         "background": flow.background_url, | ||||
|                         "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                         "title": "", | ||||
|                     }, | ||||
|                 }, | ||||
|             ) | ||||
|  | ||||
| @ -453,10 +460,13 @@ class TestFlowExecutor(TestCase): | ||||
|         self.assertJSONEqual( | ||||
|             force_str(response.content), | ||||
|             { | ||||
|                 "background": flow.background_url, | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "component": "ak-stage-dummy", | ||||
|                 "title": binding4.stage.name, | ||||
|                 "flow_info": { | ||||
|                     "background": flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @ -8,6 +8,7 @@ from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect | ||||
| from django.http.request import QueryDict | ||||
| from django.shortcuts import get_object_or_404, redirect | ||||
| from django.template.response import TemplateResponse | ||||
| from django.urls.base import reverse | ||||
| from django.utils.decorators import method_decorator | ||||
| from django.views.decorators.clickjacking import xframe_options_sameorigin | ||||
| from django.views.generic import View | ||||
| @ -309,9 +310,13 @@ class FlowExecutorView(APIView): | ||||
|             AccessDeniedChallenge( | ||||
|                 { | ||||
|                     "error_message": error_message, | ||||
|                     "title": self.flow.title, | ||||
|                     "type": ChallengeTypes.NATIVE.value, | ||||
|                     "component": "ak-stage-access-denied", | ||||
|                     "flow_info": { | ||||
|                         "title": self.flow.title, | ||||
|                         "background": self.flow.background_url, | ||||
|                         "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     }, | ||||
|                 } | ||||
|             ) | ||||
|         ) | ||||
| @ -413,7 +418,10 @@ def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpRespons | ||||
|         ) | ||||
|         return HttpChallengeResponse( | ||||
|             RedirectChallenge( | ||||
|                 {"type": ChallengeTypes.REDIRECT, "to": str(redirect_url)} | ||||
|                 { | ||||
|                     "type": ChallengeTypes.REDIRECT, | ||||
|                     "to": str(redirect_url), | ||||
|                 } | ||||
|             ) | ||||
|         ) | ||||
|     if isinstance(source, TemplateResponse): | ||||
| @ -425,7 +433,7 @@ def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpRespons | ||||
|                 } | ||||
|             ) | ||||
|         ) | ||||
|     # Check for actual HttpResponse (without isinstance as we dont want to check inheritance) | ||||
|     # Check for actual HttpResponse (without isinstance as we don't want to check inheritance) | ||||
|     if source.__class__ == HttpResponse: | ||||
|         return HttpChallengeResponse( | ||||
|             ShellChallenge( | ||||
|  | ||||
| @ -87,6 +87,10 @@ class OAuthSource(Source): | ||||
|             data={ | ||||
|                 "title": f"OAuth {self.name}", | ||||
|                 "component": "ak-user-settings-source-oauth", | ||||
|                 "configure_url": reverse( | ||||
|                     "authentik_sources_oauth:oauth-client-login", | ||||
|                     kwargs={"source_slug": self.slug}, | ||||
|                 ), | ||||
|             } | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @ -47,7 +47,11 @@ class TestUserDenyStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
| @ -108,7 +108,6 @@ class TestIdentificationStage(TestCase): | ||||
|         self.assertJSONEqual( | ||||
|             force_str(response.content), | ||||
|             { | ||||
|                 "background": self.flow.background_url, | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "component": "ak-stage-identification", | ||||
|                 "password_fields": True, | ||||
| @ -118,6 +117,11 @@ class TestIdentificationStage(TestCase): | ||||
|                         {"code": "invalid", "string": "Failed to " "authenticate."} | ||||
|                     ] | ||||
|                 }, | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|                 "sources": [ | ||||
|                     { | ||||
|                         "challenge": { | ||||
| @ -129,7 +133,6 @@ class TestIdentificationStage(TestCase): | ||||
|                         "name": "test", | ||||
|                     } | ||||
|                 ], | ||||
|                 "title": "", | ||||
|                 "user_fields": ["email"], | ||||
|             }, | ||||
|         ) | ||||
| @ -181,7 +184,6 @@ class TestIdentificationStage(TestCase): | ||||
|         self.assertJSONEqual( | ||||
|             force_str(response.content), | ||||
|             { | ||||
|                 "background": flow.background_url, | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "component": "ak-stage-identification", | ||||
|                 "user_fields": ["email"], | ||||
| @ -191,7 +193,11 @@ class TestIdentificationStage(TestCase): | ||||
|                     kwargs={"flow_slug": "unique-enrollment-string"}, | ||||
|                 ), | ||||
|                 "primary_action": "Log in", | ||||
|                 "title": self.flow.title, | ||||
|                 "flow_info": { | ||||
|                     "background": flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": self.flow.title, | ||||
|                 }, | ||||
|                 "sources": [ | ||||
|                     { | ||||
|                         "icon_url": "/static/authentik/sources/.svg", | ||||
| @ -229,7 +235,6 @@ class TestIdentificationStage(TestCase): | ||||
|         self.assertJSONEqual( | ||||
|             force_str(response.content), | ||||
|             { | ||||
|                 "background": flow.background_url, | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "component": "ak-stage-identification", | ||||
|                 "user_fields": ["email"], | ||||
| @ -239,7 +244,11 @@ class TestIdentificationStage(TestCase): | ||||
|                     kwargs={"flow_slug": "unique-recovery-string"}, | ||||
|                 ), | ||||
|                 "primary_action": "Log in", | ||||
|                 "title": self.flow.title, | ||||
|                 "flow_info": { | ||||
|                     "background": flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": self.flow.title, | ||||
|                 }, | ||||
|                 "sources": [ | ||||
|                     { | ||||
|                         "challenge": { | ||||
|  | ||||
| @ -62,8 +62,12 @@ class TestUserLoginStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @ -67,8 +67,12 @@ class TestPasswordStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
| @ -205,7 +209,11 @@ class TestPasswordStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
| @ -54,8 +54,12 @@ class TestUserDeleteStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @ -108,7 +108,11 @@ class TestUserLoginStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
| @ -151,8 +151,12 @@ class TestUserWriteStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
| @ -184,8 +188,12 @@ class TestUserWriteStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
| @ -217,7 +225,11 @@ class TestUserWriteStage(TestCase): | ||||
|             { | ||||
|                 "component": "ak-stage-access-denied", | ||||
|                 "error_message": None, | ||||
|                 "title": "", | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "flow_info": { | ||||
|                     "background": self.flow.background_url, | ||||
|                     "cancel_url": reverse("authentik_flows:cancel"), | ||||
|                     "title": "", | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
							
								
								
									
										38
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								schema.yml
									
									
									
									
									
								
							| @ -11170,7 +11170,7 @@ paths: | ||||
|               schema: | ||||
|                 type: array | ||||
|                 items: | ||||
|                   $ref: '#/components/schemas/StageUserSetting' | ||||
|                   $ref: '#/components/schemas/UserSetting' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
| @ -15361,7 +15361,6 @@ components: | ||||
|         error_message: | ||||
|           type: string | ||||
|       required: | ||||
|       - flow_info | ||||
|       - type | ||||
|     ActionEnum: | ||||
|       enum: | ||||
| @ -15692,7 +15691,6 @@ components: | ||||
|       required: | ||||
|       - activation_barcode | ||||
|       - activation_code | ||||
|       - flow_info | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
|       - stage_uuid | ||||
| @ -15801,7 +15799,6 @@ components: | ||||
|             type: string | ||||
|       required: | ||||
|       - codes | ||||
|       - flow_info | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
|       - type | ||||
| @ -15899,7 +15896,6 @@ components: | ||||
|           type: string | ||||
|       required: | ||||
|       - config_url | ||||
|       - flow_info | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
|       - type | ||||
| @ -16077,7 +16073,6 @@ components: | ||||
|             $ref: '#/components/schemas/DeviceChallenge' | ||||
|       required: | ||||
|       - device_challenges | ||||
|       - flow_info | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
|       - type | ||||
| @ -16120,7 +16115,6 @@ components: | ||||
|           type: object | ||||
|           additionalProperties: {} | ||||
|       required: | ||||
|       - flow_info | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
|       - registration | ||||
| @ -16169,7 +16163,6 @@ components: | ||||
|             type: string | ||||
|       required: | ||||
|       - attrs | ||||
|       - flow_info | ||||
|       - type | ||||
|       - url | ||||
|     BackendsEnum: | ||||
| @ -16222,7 +16215,6 @@ components: | ||||
|         site_key: | ||||
|           type: string | ||||
|       required: | ||||
|       - flow_info | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
|       - site_key | ||||
| @ -16430,7 +16422,6 @@ components: | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Permission' | ||||
|       required: | ||||
|       - flow_info | ||||
|       - header_text | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
| @ -16730,7 +16721,6 @@ components: | ||||
|             items: | ||||
|               $ref: '#/components/schemas/ErrorDetail' | ||||
|       required: | ||||
|       - flow_info | ||||
|       - type | ||||
|     DummyChallengeResponseRequest: | ||||
|       type: object | ||||
| @ -16889,7 +16879,6 @@ components: | ||||
|             items: | ||||
|               $ref: '#/components/schemas/ErrorDetail' | ||||
|       required: | ||||
|       - flow_info | ||||
|       - type | ||||
|     EmailChallengeResponseRequest: | ||||
|       type: object | ||||
| @ -17700,7 +17689,6 @@ components: | ||||
|           items: | ||||
|             $ref: '#/components/schemas/UILoginButton' | ||||
|       required: | ||||
|       - flow_info | ||||
|       - password_fields | ||||
|       - primary_action | ||||
|       - type | ||||
| @ -21644,7 +21632,6 @@ components: | ||||
|         recovery_url: | ||||
|           type: string | ||||
|       required: | ||||
|       - flow_info | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
|       - type | ||||
| @ -23394,7 +23381,6 @@ components: | ||||
|           type: string | ||||
|       required: | ||||
|       - client_id | ||||
|       - flow_info | ||||
|       - slug | ||||
|       - type | ||||
|     PlexAuthenticationChallengeResponseRequest: | ||||
| @ -23754,7 +23740,6 @@ components: | ||||
|             $ref: '#/components/schemas/StagePrompt' | ||||
|       required: | ||||
|       - fields | ||||
|       - flow_info | ||||
|       - type | ||||
|     PromptChallengeResponseRequest: | ||||
|       type: object | ||||
| @ -24210,7 +24195,6 @@ components: | ||||
|         to: | ||||
|           type: string | ||||
|       required: | ||||
|       - flow_info | ||||
|       - to | ||||
|       - type | ||||
|     RefreshTokenModel: | ||||
| @ -24927,7 +24911,6 @@ components: | ||||
|           type: string | ||||
|       required: | ||||
|       - body | ||||
|       - flow_info | ||||
|       - type | ||||
|     SignatureAlgorithmEnum: | ||||
|       enum: | ||||
| @ -25093,22 +25076,6 @@ components: | ||||
|             $ref: '#/components/schemas/FlowRequest' | ||||
|       required: | ||||
|       - name | ||||
|     StageUserSetting: | ||||
|       type: object | ||||
|       description: User settings but can include a configure flow | ||||
|       properties: | ||||
|         object_uid: | ||||
|           type: string | ||||
|         component: | ||||
|           type: string | ||||
|         title: | ||||
|           type: string | ||||
|         configure_flow: | ||||
|           type: string | ||||
|       required: | ||||
|       - component | ||||
|       - object_uid | ||||
|       - title | ||||
|     StaticDevice: | ||||
|       type: object | ||||
|       description: Serializer for static authenticator devices | ||||
| @ -25788,8 +25755,11 @@ components: | ||||
|           type: string | ||||
|         title: | ||||
|           type: string | ||||
|         configure_url: | ||||
|           type: string | ||||
|       required: | ||||
|       - component | ||||
|       - configure_url | ||||
|       - object_uid | ||||
|       - title | ||||
|     UserWriteStage: | ||||
|  | ||||
| @ -1,7 +0,0 @@ | ||||
| export class AppURLManager { | ||||
|  | ||||
|     static sourceOAuth(slug: string, action: string): string { | ||||
|         return `/source/oauth/${action}/${slug}/`; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -86,8 +86,8 @@ export class FlowExecutor extends LitElement implements StageHost { | ||||
|  | ||||
|     private postUpdate(): void { | ||||
|         tenant().then(tenant => { | ||||
|             if (this.challenge?.flowInfo.title) { | ||||
|                 document.title = `${this.challenge.flowInfo.title} - ${tenant.brandingTitle}`; | ||||
|             if (this.challenge?.flowInfo?.title) { | ||||
|                 document.title = `${this.challenge.flowInfo?.title} - ${tenant.brandingTitle}`; | ||||
|             } else { | ||||
|                 document.title = tenant.brandingTitle || TITLE_DEFAULT; | ||||
|             } | ||||
| @ -124,7 +124,7 @@ export class FlowExecutor extends LitElement implements StageHost { | ||||
|         }).then((challenge) => { | ||||
|             this.challenge = challenge; | ||||
|             // Only set background on first update, flow won't change throughout execution | ||||
|             if (this.challenge?.flowInfo.background) { | ||||
|             if (this.challenge?.flowInfo?.background) { | ||||
|                 this.setBackground(this.challenge.flowInfo.background); | ||||
|             } | ||||
|             this.postUpdate(); | ||||
| @ -271,7 +271,7 @@ export class FlowExecutor extends LitElement implements StageHost { | ||||
|                         ${this.tenant?.brandingTitle != "authentik" ? html` | ||||
|                             <li><a href="https://goauthentik.io">${t`Powered by authentik`}</a></li> | ||||
|                         ` : html``} | ||||
|                         ${this.challenge?.flowInfo.background?.startsWith("/static") ? html` | ||||
|                         ${this.challenge?.flowInfo?.background?.startsWith("/static") ? html` | ||||
|                             <li><a href="https://unsplash.com/@danasaki">${t`Background image`}</a></li> | ||||
|                         ` : html``} | ||||
|                     </ul> | ||||
|  | ||||
| @ -28,7 +28,7 @@ export class FlowAccessDenied extends BaseStage<AccessDeniedChallenge, FlowChall | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|  | ||||
| @ -14,6 +14,7 @@ import "../../FormStatic"; | ||||
| import { AuthenticatorDuoChallenge, StagesApi } from "authentik-api"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { AuthenticatorDuoChallengeResponseRequest } from "authentik-api/dist/models/AuthenticatorDuoChallengeResponseRequest"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
| @customElement("ak-stage-authenticator-duo") | ||||
| export class AuthenticatorDuoStage extends BaseStage<AuthenticatorDuoChallenge, AuthenticatorDuoChallengeResponseRequest> { | ||||
| @ -49,7 +50,7 @@ export class AuthenticatorDuoStage extends BaseStage<AuthenticatorDuoChallenge, | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
| @ -59,7 +60,7 @@ export class AuthenticatorDuoStage extends BaseStage<AuthenticatorDuoChallenge, | ||||
|                         userAvatar="${this.challenge.pendingUserAvatar}" | ||||
|                         user=${this.challenge.pendingUser}> | ||||
|                         <div slot="link"> | ||||
|                             <a href="${this.challenge.flowInfo.cancelUrl}">${t`Not you?`}</a> | ||||
|                             <a href="${ifDefined(this.challenge.flowInfo?.cancelUrl)}">${t`Not you?`}</a> | ||||
|                         </div> | ||||
|                     </ak-form-static> | ||||
|                     <img src=${this.challenge.activationBarcode} /> | ||||
|  | ||||
| @ -13,6 +13,7 @@ import "../../../elements/EmptyState"; | ||||
| import "../../FormStatic"; | ||||
| import { AuthenticatorStaticChallenge } from "authentik-api"; | ||||
| import { AuthenticatorStaticChallengeResponseRequest } from "authentik-api/dist/models/AuthenticatorStaticChallengeResponseRequest"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
| export const STATIC_TOKEN_STYLE = css` | ||||
| /* Static OTP Tokens */ | ||||
| @ -46,7 +47,7 @@ export class AuthenticatorStaticStage extends BaseStage<AuthenticatorStaticChall | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
| @ -56,7 +57,7 @@ export class AuthenticatorStaticStage extends BaseStage<AuthenticatorStaticChall | ||||
|                         userAvatar="${this.challenge.pendingUserAvatar}" | ||||
|                         user=${this.challenge.pendingUser}> | ||||
|                         <div slot="link"> | ||||
|                             <a href="${this.challenge.flowInfo.cancelUrl}">${t`Not you?`}</a> | ||||
|                             <a href="${ifDefined(this.challenge.flowInfo?.cancelUrl)}">${t`Not you?`}</a> | ||||
|                         </div> | ||||
|                     </ak-form-static> | ||||
|                     <ak-form-element | ||||
|  | ||||
| @ -15,6 +15,7 @@ import "../../../elements/EmptyState"; | ||||
| import "../../FormStatic"; | ||||
| import { MessageLevel } from "../../../elements/messages/Message"; | ||||
| import { AuthenticatorTOTPChallenge, AuthenticatorTOTPChallengeResponseRequest } from "authentik-api"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
|  | ||||
| @customElement("ak-stage-authenticator-totp") | ||||
| @ -33,7 +34,7 @@ export class AuthenticatorTOTPStage extends BaseStage<AuthenticatorTOTPChallenge | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
| @ -43,7 +44,7 @@ export class AuthenticatorTOTPStage extends BaseStage<AuthenticatorTOTPChallenge | ||||
|                         userAvatar="${this.challenge.pendingUserAvatar}" | ||||
|                         user=${this.challenge.pendingUser}> | ||||
|                         <div slot="link"> | ||||
|                             <a href="${this.challenge.flowInfo.cancelUrl}">${t`Not you?`}</a> | ||||
|                             <a href="${ifDefined(this.challenge.flowInfo?.cancelUrl)}">${t`Not you?`}</a> | ||||
|                         </div> | ||||
|                     </ak-form-static> | ||||
|                     <input type="hidden" name="otp_uri" value=${this.challenge.configUrl} /> | ||||
|  | ||||
| @ -162,7 +162,7 @@ export class AuthenticatorValidateStage extends BaseStage<AuthenticatorValidatio | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|                 ${this.selectedDeviceChallenge ? "" : html`<p class="pf-c-login__main-header-desc"> | ||||
|                     ${t`Select an identification method.`} | ||||
|  | ||||
| @ -15,6 +15,7 @@ import { PasswordManagerPrefill } from "../identification/IdentificationStage"; | ||||
| import "../../FormStatic"; | ||||
| import { AuthenticatorValidationChallenge } from "authentik-api/dist/models/AuthenticatorValidationChallenge"; | ||||
| import { AuthenticatorValidationChallengeResponseRequest, DeviceChallenge } from "authentik-api"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
| @customElement("ak-stage-authenticator-validate-code") | ||||
| export class AuthenticatorValidateStageWebCode extends BaseStage<AuthenticatorValidationChallenge, AuthenticatorValidationChallengeResponseRequest> { | ||||
| @ -43,7 +44,7 @@ export class AuthenticatorValidateStageWebCode extends BaseStage<AuthenticatorVa | ||||
|                     userAvatar="${this.challenge.pendingUserAvatar}" | ||||
|                     user=${this.challenge.pendingUser}> | ||||
|                     <div slot="link"> | ||||
|                         <a href="${this.challenge.flowInfo.cancelUrl}">${t`Not you?`}</a> | ||||
|                         <a href="${ifDefined(this.challenge.flowInfo?.cancelUrl)}">${t`Not you?`}</a> | ||||
|                     </div> | ||||
|                 </ak-form-static> | ||||
|                 <ak-form-element | ||||
|  | ||||
| @ -14,6 +14,7 @@ import "../../../elements/EmptyState"; | ||||
| import "../../FormStatic"; | ||||
| import { AuthenticatorValidationChallenge } from "authentik-api/dist/models/AuthenticatorValidationChallenge"; | ||||
| import { AuthenticatorValidationChallengeResponseRequest, DeviceChallenge } from "authentik-api"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
| @customElement("ak-stage-authenticator-validate-duo") | ||||
| export class AuthenticatorValidateStageWebDuo extends BaseStage<AuthenticatorValidationChallenge, AuthenticatorValidationChallengeResponseRequest> { | ||||
| @ -48,7 +49,7 @@ export class AuthenticatorValidateStageWebDuo extends BaseStage<AuthenticatorVal | ||||
|                     userAvatar="${this.challenge.pendingUserAvatar}" | ||||
|                     user=${this.challenge.pendingUser}> | ||||
|                     <div slot="link"> | ||||
|                         <a href="${this.challenge.flowInfo.cancelUrl}">${t`Not you?`}</a> | ||||
|                         <a href="${ifDefined(this.challenge.flowInfo?.cancelUrl)}">${t`Not you?`}</a> | ||||
|                     </div> | ||||
|                 </ak-form-static> | ||||
|  | ||||
|  | ||||
| @ -85,7 +85,7 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage<AuthenticatorW | ||||
|     render(): TemplateResult { | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge?.flowInfo.title} | ||||
|                     ${this.challenge?.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|  | ||||
| @ -32,7 +32,7 @@ export class AutosubmitStage extends BaseStage<AutosubmitChallenge, AutoSubmitCh | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|  | ||||
| @ -13,6 +13,7 @@ import "../../../elements/forms/FormElement"; | ||||
| import "../../../elements/EmptyState"; | ||||
| import "../../FormStatic"; | ||||
| import { CaptchaChallenge, CaptchaChallengeResponseRequest } from "authentik-api"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
| @customElement("ak-stage-captcha") | ||||
| export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeResponseRequest> { | ||||
| @ -57,7 +58,7 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
| @ -67,7 +68,7 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe | ||||
|                         userAvatar="${this.challenge.pendingUserAvatar}" | ||||
|                         user=${this.challenge.pendingUser}> | ||||
|                         <div slot="link"> | ||||
|                             <a href="${this.challenge.flowInfo.cancelUrl}">${t`Not you?`}</a> | ||||
|                             <a href="${ifDefined(this.challenge.flowInfo?.cancelUrl)}">${t`Not you?`}</a> | ||||
|                         </div> | ||||
|                     </ak-form-static> | ||||
|                     <div class="ak-loading"> | ||||
|  | ||||
| @ -11,6 +11,7 @@ import { BaseStage } from "../base"; | ||||
| import "../../../elements/EmptyState"; | ||||
| import "../../FormStatic"; | ||||
| import { ConsentChallenge, ConsentChallengeResponseRequest } from "authentik-api"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
|  | ||||
| @customElement("ak-stage-consent") | ||||
| @ -29,7 +30,7 @@ export class ConsentStage extends BaseStage<ConsentChallenge, ConsentChallengeRe | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
| @ -39,7 +40,7 @@ export class ConsentStage extends BaseStage<ConsentChallenge, ConsentChallengeRe | ||||
|                         userAvatar="${this.challenge.pendingUserAvatar}" | ||||
|                         user=${this.challenge.pendingUser}> | ||||
|                         <div slot="link"> | ||||
|                             <a href="${this.challenge.flowInfo.cancelUrl}">${t`Not you?`}</a> | ||||
|                             <a href="${ifDefined(this.challenge.flowInfo?.cancelUrl)}">${t`Not you?`}</a> | ||||
|                         </div> | ||||
|                     </ak-form-static> | ||||
|                     <div class="pf-c-form__group"> | ||||
|  | ||||
| @ -28,7 +28,7 @@ export class DummyStage extends BaseStage<DummyChallenge, DummyChallengeResponse | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|  | ||||
| @ -27,7 +27,7 @@ export class EmailStage extends BaseStage<EmailChallenge, EmailChallengeResponse | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|  | ||||
| @ -206,7 +206,7 @@ export class IdentificationStage extends BaseStage<IdentificationChallenge, Iden | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|  | ||||
| @ -13,6 +13,7 @@ import "../../../elements/EmptyState"; | ||||
| import { PasswordManagerPrefill } from "../identification/IdentificationStage"; | ||||
| import "../../FormStatic"; | ||||
| import { PasswordChallenge, PasswordChallengeResponseRequest } from "authentik-api"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
| @customElement("ak-stage-password") | ||||
| export class PasswordStage extends BaseStage<PasswordChallenge, PasswordChallengeResponseRequest> { | ||||
| @ -30,7 +31,7 @@ export class PasswordStage extends BaseStage<PasswordChallenge, PasswordChalleng | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
| @ -40,7 +41,7 @@ export class PasswordStage extends BaseStage<PasswordChallenge, PasswordChalleng | ||||
|                         userAvatar="${this.challenge.pendingUserAvatar}" | ||||
|                         user=${this.challenge.pendingUser}> | ||||
|                         <div slot="link"> | ||||
|                             <a href="${this.challenge.flowInfo.cancelUrl}">${t`Not you?`}</a> | ||||
|                             <a href="${ifDefined(this.challenge.flowInfo?.cancelUrl)}">${t`Not you?`}</a> | ||||
|                         </div> | ||||
|                     </ak-form-static> | ||||
|                     <input name="username" autocomplete="username" type="hidden" value="${this.challenge.pendingUser}"> | ||||
|  | ||||
| @ -111,7 +111,7 @@ export class PromptStage extends BaseStage<PromptChallenge, PromptChallengeRespo | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl"> | ||||
|                     ${this.challenge.flowInfo.title} | ||||
|                     ${this.challenge.flowInfo?.title} | ||||
|                 </h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|  | ||||
| @ -4169,10 +4169,6 @@ msgstr "Use the user's email address, but deny enrollment when the email address | ||||
| msgid "Use the user's username, but deny enrollment when the username already exists." | ||||
| msgstr "Use the user's username, but deny enrollment when the username already exists." | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceForm.ts | ||||
| msgid "Use this redirect URL:" | ||||
| msgstr "Use this redirect URL:" | ||||
|  | ||||
| #: src/pages/tenants/TenantForm.ts | ||||
| msgid "Use this tenant for each domain that doesn't have a dedicated tenant." | ||||
| msgstr "Use this tenant for each domain that doesn't have a dedicated tenant." | ||||
|  | ||||
| @ -4157,10 +4157,6 @@ msgstr "" | ||||
| msgid "Use the user's username, but deny enrollment when the username already exists." | ||||
| msgstr "" | ||||
|  | ||||
| #:  | ||||
| msgid "Use this redirect URL:" | ||||
| msgstr "" | ||||
|  | ||||
| #:  | ||||
| msgid "Use this tenant for each domain that doesn't have a dedicated tenant." | ||||
| msgstr "" | ||||
|  | ||||
| @ -8,7 +8,6 @@ import "../../../elements/forms/HorizontalFormElement"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
| import { until } from "lit-html/directives/until"; | ||||
| import { first } from "../../../utils"; | ||||
| import { AppURLManager } from "../../../api/legacy"; | ||||
| import { ModelForm } from "../../../elements/forms/ModelForm"; | ||||
|  | ||||
| @customElement("ak-source-oauth-form") | ||||
| @ -95,14 +94,6 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> { | ||||
|             </ak-form-group>`; | ||||
|     } | ||||
|  | ||||
|     getRedirectURI(slug?: string): string { | ||||
|         if (!slug) { | ||||
|             return ""; | ||||
|         } | ||||
|         const path = AppURLManager.sourceOAuth(slug, "callback"); | ||||
|         return `${window.location.protocol}//${window.location.host}${path}`; | ||||
|     } | ||||
|  | ||||
|     renderForm(): TemplateResult { | ||||
|         return html`<form class="pf-c-form pf-m-horizontal"> | ||||
|             <ak-form-element-horizontal | ||||
| @ -115,16 +106,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> { | ||||
|                 label=${t`Slug`} | ||||
|                 ?required=${true} | ||||
|                 name="slug"> | ||||
|                 <input type="text" value="${ifDefined(this.instance?.slug)}" class="pf-c-form-control" required @input=${(ev: Event) => { | ||||
|                     const current = (ev.target as HTMLInputElement).value; | ||||
|                     const label = this.shadowRoot?.querySelector<HTMLSpanElement>("#callback-url"); | ||||
|                     if (!label) return; | ||||
|                     label.innerText = this.getRedirectURI(current); | ||||
|                 }}> | ||||
|                 <p class="pf-c-form__helper-text"> | ||||
|                     ${t`Use this redirect URL:`} | ||||
|                     <span id="callback-url">${this.getRedirectURI(this.instance?.slug)}</span> | ||||
|                 </p> | ||||
|                 <input type="text" value="${ifDefined(this.instance?.slug)}" class="pf-c-form-control" required> | ||||
|             </ak-form-element-horizontal> | ||||
|             <ak-form-element-horizontal name="enabled"> | ||||
|                 <div class="pf-c-check"> | ||||
|  | ||||
| @ -13,7 +13,7 @@ import AKGlobal from "../../authentik.css"; | ||||
| import PFBase from "@patternfly/patternfly/patternfly-base.css"; | ||||
| import PFForm from "@patternfly/patternfly/components/Form/form.css"; | ||||
| import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; | ||||
| import { SourcesApi, StagesApi, StageUserSetting, UserSetting } from "authentik-api"; | ||||
| import { SourcesApi, StagesApi, UserSetting } from "authentik-api"; | ||||
| import { DEFAULT_CONFIG } from "../../api/Config"; | ||||
| import { until } from "lit-html/directives/until"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
| @ -35,22 +35,22 @@ export class UserSettingsPage extends LitElement { | ||||
|         return [PFBase, PFPage, PFFlex, PFDisplay, PFGallery, PFContent, PFCard, PFDescriptionList, PFSizing, PFForm, PFFormControl, AKGlobal]; | ||||
|     } | ||||
|  | ||||
|     renderStageSettings(stage: StageUserSetting): TemplateResult { | ||||
|     renderStageSettings(stage: UserSetting): TemplateResult { | ||||
|         switch (stage.component) { | ||||
|             case "ak-user-settings-authenticator-webauthn": | ||||
|                 return html`<ak-user-settings-authenticator-webauthn objectId=${stage.objectUid} configureFlow=${stage.configureFlow}> | ||||
|                 return html`<ak-user-settings-authenticator-webauthn objectId=${stage.objectUid} configureUrl=${stage.configureUrl}> | ||||
|                 </ak-user-settings-authenticator-webauthn>`; | ||||
|             case "ak-user-settings-password": | ||||
|                 return html`<ak-user-settings-password objectId=${stage.objectUid}> | ||||
|                 return html`<ak-user-settings-password objectId=${stage.objectUid} configureUrl=${stage.configureUrl}> | ||||
|                 </ak-user-settings-password>`; | ||||
|             case "ak-user-settings-authenticator-totp": | ||||
|                 return html`<ak-user-settings-authenticator-totp objectId=${stage.objectUid} configureFlow=${stage.configureFlow}> | ||||
|                 return html`<ak-user-settings-authenticator-totp objectId=${stage.objectUid} configureUrl=${stage.configureUrl}> | ||||
|                 </ak-user-settings-authenticator-totp>`; | ||||
|             case "ak-user-settings-authenticator-static": | ||||
|                 return html`<ak-user-settings-authenticator-static objectId=${stage.objectUid} configureFlow=${stage.configureFlow}> | ||||
|                 return html`<ak-user-settings-authenticator-static objectId=${stage.objectUid} configureUrl=${stage.configureUrl}> | ||||
|                 </ak-user-settings-authenticator-static>`; | ||||
|             case "ak-user-settings-authenticator-duo": | ||||
|                 return html`<ak-user-settings-authenticator-duo objectId=${stage.objectUid} configureFlow=${stage.configureFlow}> | ||||
|                 return html`<ak-user-settings-authenticator-duo objectId=${stage.objectUid} configureUrl=${stage.configureUrl}> | ||||
|                 </ak-user-settings-authenticator-duo>`; | ||||
|             default: | ||||
|                 return html`<p>${t`Error: unsupported stage settings: ${stage.component}`}</p>`; | ||||
| @ -60,7 +60,7 @@ export class UserSettingsPage extends LitElement { | ||||
|     renderSourceSettings(source: UserSetting): TemplateResult { | ||||
|         switch (source.component) { | ||||
|             case "ak-user-settings-source-oauth": | ||||
|                 return html`<ak-user-settings-source-oauth objectId=${source.objectUid} title=${source.title}> | ||||
|                 return html`<ak-user-settings-source-oauth objectId=${source.objectUid} title=${source.title} configureUrl=${source.configureUrl}> | ||||
|                 </ak-user-settings-source-oauth>`; | ||||
|             default: | ||||
|                 return html`<p>${t`Error: unsupported source settings: ${source.component}`}</p>`; | ||||
|  | ||||
| @ -11,6 +11,9 @@ export abstract class BaseUserSettings extends LitElement { | ||||
|     @property() | ||||
|     objectId!: string; | ||||
|  | ||||
|     @property() | ||||
|     configureUrl?: string; | ||||
|  | ||||
|     static get styles(): CSSResult[] { | ||||
|         return [PFBase, PFCard, PFButton, PFForm, PFFormControl, AKGlobal]; | ||||
|     } | ||||
|  | ||||
| @ -4,7 +4,7 @@ import { SourcesApi } from "authentik-api"; | ||||
| import { until } from "lit-html/directives/until"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { t } from "@lingui/macro"; | ||||
| import { AppURLManager } from "../../../api/legacy"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
| @customElement("ak-user-settings-source-oauth") | ||||
| export class SourceSettingsOAuth extends BaseUserSettings { | ||||
| @ -40,7 +40,7 @@ export class SourceSettingsOAuth extends BaseUserSettings { | ||||
|             } | ||||
|             return html`<p>${t`Not connected.`}</p> | ||||
|                 <a class="pf-c-button pf-m-primary" | ||||
|                     href=${AppURLManager.sourceOAuth(this.objectId, "login")}> | ||||
|                     href=${ifDefined(this.configureUrl)}> | ||||
|                     ${t`Connect`} | ||||
|                 </a>`; | ||||
|         }))}`; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import { AuthenticatorsApi } from "authentik-api"; | ||||
| import { t } from "@lingui/macro"; | ||||
| import { customElement, html, property, TemplateResult } from "lit-element"; | ||||
| import { customElement, html, TemplateResult } from "lit-element"; | ||||
| import { until } from "lit-html/directives/until"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { BaseUserSettings } from "./BaseUserSettings"; | ||||
| @ -8,9 +8,6 @@ import { BaseUserSettings } from "./BaseUserSettings"; | ||||
| @customElement("ak-user-settings-authenticator-duo") | ||||
| export class UserSettingsAuthenticatorDuo extends BaseUserSettings { | ||||
|  | ||||
|     @property() | ||||
|     configureFlow?: string; | ||||
|  | ||||
|     renderEnabled(): TemplateResult { | ||||
|         return html`<div class="pf-c-card__body"> | ||||
|                 <p> | ||||
| @ -48,8 +45,8 @@ export class UserSettingsAuthenticatorDuo extends BaseUserSettings { | ||||
|                 </p> | ||||
|             </div> | ||||
|             <div class="pf-c-card__footer"> | ||||
|                 ${this.configureFlow ? | ||||
|                     html`<a href="${this.configureFlow}?next=/%23%2Fuser" | ||||
|                 ${this.configureUrl ? | ||||
|                     html`<a href="${this.configureUrl}?next=/%23%2Fuser" | ||||
|                             class="pf-c-button pf-m-primary">${t`Enable Static Tokens`} | ||||
|                         </a>`: html``} | ||||
|             </div>`; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import { AuthenticatorsApi } from "authentik-api"; | ||||
| import { t } from "@lingui/macro"; | ||||
| import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; | ||||
| import { CSSResult, customElement, html, TemplateResult } from "lit-element"; | ||||
| import { until } from "lit-html/directives/until"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { STATIC_TOKEN_STYLE } from "../../../flows/stages/authenticator_static/AuthenticatorStaticStage"; | ||||
| @ -9,9 +9,6 @@ import { BaseUserSettings } from "./BaseUserSettings"; | ||||
| @customElement("ak-user-settings-authenticator-static") | ||||
| export class UserSettingsAuthenticatorStatic extends BaseUserSettings { | ||||
|  | ||||
|     @property() | ||||
|     configureFlow?: string; | ||||
|  | ||||
|     static get styles(): CSSResult[] { | ||||
|         return super.styles.concat(STATIC_TOKEN_STYLE); | ||||
|     } | ||||
| @ -63,8 +60,8 @@ export class UserSettingsAuthenticatorStatic extends BaseUserSettings { | ||||
|                 </p> | ||||
|             </div> | ||||
|             <div class="pf-c-card__footer"> | ||||
|                 ${this.configureFlow ? | ||||
|                     html`<a href="${this.configureFlow}?next=/%23%2Fuser" | ||||
|                 ${this.configureUrl ? | ||||
|                     html`<a href="${this.configureUrl}?next=/%23%2Fuser" | ||||
|                             class="pf-c-button pf-m-primary">${t`Enable Static Tokens`} | ||||
|                         </a>`: html``} | ||||
|             </div>`; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import { AuthenticatorsApi } from "authentik-api"; | ||||
| import { t } from "@lingui/macro"; | ||||
| import { customElement, html, property, TemplateResult } from "lit-element"; | ||||
| import { customElement, html, TemplateResult } from "lit-element"; | ||||
| import { until } from "lit-html/directives/until"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { BaseUserSettings } from "./BaseUserSettings"; | ||||
| @ -8,9 +8,6 @@ import { BaseUserSettings } from "./BaseUserSettings"; | ||||
| @customElement("ak-user-settings-authenticator-totp") | ||||
| export class UserSettingsAuthenticatorTOTP extends BaseUserSettings { | ||||
|  | ||||
|     @property() | ||||
|     configureFlow?: string; | ||||
|  | ||||
|     renderEnabled(): TemplateResult { | ||||
|         return html`<div class="pf-c-card__body"> | ||||
|                 <p> | ||||
| @ -48,8 +45,8 @@ export class UserSettingsAuthenticatorTOTP extends BaseUserSettings { | ||||
|                 </p> | ||||
|             </div> | ||||
|             <div class="pf-c-card__footer"> | ||||
|                 ${this.configureFlow ? | ||||
|                     html`<a href="${this.configureFlow}?next=/%23%2Fuser" | ||||
|                 ${this.configureUrl ? | ||||
|                     html`<a href="${this.configureUrl}?next=/%23%2Fuser" | ||||
|                             class="pf-c-button pf-m-primary">${t`Enable TOTP`} | ||||
|                         </a>`: html``} | ||||
|             </div>`; | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; | ||||
| import { CSSResult, customElement, html, TemplateResult } from "lit-element"; | ||||
| import { t } from "@lingui/macro"; | ||||
| import { AuthenticatorsApi, WebAuthnDevice } from "authentik-api"; | ||||
| import { until } from "lit-html/directives/until"; | ||||
| @ -16,9 +16,6 @@ import { ifDefined } from "lit-html/directives/if-defined"; | ||||
| @customElement("ak-user-settings-authenticator-webauthn") | ||||
| export class UserSettingsAuthenticatorWebAuthn extends BaseUserSettings { | ||||
|  | ||||
|     @property() | ||||
|     configureFlow?: string; | ||||
|  | ||||
|     static get styles(): CSSResult[] { | ||||
|         return super.styles.concat(PFDataList); | ||||
|     } | ||||
| @ -100,8 +97,8 @@ export class UserSettingsAuthenticatorWebAuthn extends BaseUserSettings { | ||||
|                 </ul> | ||||
|             </div> | ||||
|             <div class="pf-c-card__footer"> | ||||
|                 ${this.configureFlow ? | ||||
|                     html`<a href="${this.configureFlow}?next=/%23%2Fuser" | ||||
|                 ${this.configureUrl ? | ||||
|                     html`<a href="${this.configureUrl}?next=/%23%2Fuser" | ||||
|                             class="pf-c-button pf-m-primary">${t`Configure WebAuthn`} | ||||
|                         </a>`: html``} | ||||
|             </div> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import { customElement, html, TemplateResult } from "lit-element"; | ||||
| import { t } from "@lingui/macro"; | ||||
| import { FlowURLManager } from "../../../api/legacy"; | ||||
| import { BaseUserSettings } from "./BaseUserSettings"; | ||||
| import { ifDefined } from "lit-html/directives/if-defined"; | ||||
|  | ||||
| @customElement("ak-user-settings-password") | ||||
| export class UserSettingsPassword extends BaseUserSettings { | ||||
| @ -14,7 +14,7 @@ export class UserSettingsPassword extends BaseUserSettings { | ||||
|                 ${t`Change your password`} | ||||
|             </div> | ||||
|             <div class="pf-c-card__body"> | ||||
|                 <a href="${FlowURLManager.configure(this.objectId, "?next=/%23%2Fuser")}" | ||||
|                 <a href="${ifDefined(this.configureUrl)}" | ||||
|                     class="pf-c-button pf-m-primary"> | ||||
|                     ${t`Change password`} | ||||
|                 </a> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer