Compare commits
	
		
			11 Commits
		
	
	
		
			web/parts/
			...
			flow-no-we
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4aa497346d | |||
| 7f5cfdc3d3 | |||
| 42501f6d1e | |||
| 2759b1c089 | |||
| ce6d76babe | |||
| 5cc2bd5b36 | |||
| bad8a8ead5 | |||
| 1f7a2d5194 | |||
| 5e328403d6 | |||
| f03e56af93 | |||
| 516aa9d9b1 | 
| @ -8,7 +8,13 @@ from uuid import UUID | ||||
| from django.core.serializers.json import DjangoJSONEncoder | ||||
| from django.db import models | ||||
| from django.http import JsonResponse | ||||
| from rest_framework.fields import BooleanField, CharField, ChoiceField, DictField | ||||
| from rest_framework.fields import ( | ||||
|     BooleanField, | ||||
|     CharField, | ||||
|     ChoiceField, | ||||
|     DictField, | ||||
|     ListField, | ||||
| ) | ||||
| from rest_framework.request import Request | ||||
|  | ||||
| from authentik.core.api.utils import PassiveSerializer | ||||
| @ -39,6 +45,12 @@ class ErrorDetailSerializer(PassiveSerializer): | ||||
|     code = CharField() | ||||
|  | ||||
|  | ||||
| class MessageSerializer(PassiveSerializer): | ||||
|     message = CharField() | ||||
|     level = CharField() | ||||
|     tags = ListField(child=CharField()) | ||||
|  | ||||
|  | ||||
| class ContextualFlowInfo(PassiveSerializer): | ||||
|     """Contextual flow information for a challenge""" | ||||
|  | ||||
| @ -55,6 +67,7 @@ class Challenge(PassiveSerializer): | ||||
|     flow_info = ContextualFlowInfo(required=False) | ||||
|     component = CharField(default="") | ||||
|  | ||||
|     messages = ListField(child=MessageSerializer(), allow_empty=True, required=False) | ||||
|     response_errors = DictField( | ||||
|         child=ErrorDetailSerializer(many=True), allow_empty=True, required=False | ||||
|     ) | ||||
| @ -170,7 +183,6 @@ class FrameChallenge(Challenge): | ||||
|  | ||||
|  | ||||
| class FrameChallengeResponse(ChallengeResponse): | ||||
|  | ||||
|     component = CharField(default="xak-flow-frame") | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -4,6 +4,7 @@ from typing import TYPE_CHECKING | ||||
|  | ||||
| from django.conf import settings | ||||
| from django.contrib.auth.models import AnonymousUser | ||||
| from django.contrib.messages import get_messages | ||||
| from django.http import HttpRequest | ||||
| from django.http.request import QueryDict | ||||
| from django.http.response import HttpResponse | ||||
| @ -21,6 +22,7 @@ from authentik.flows.challenge import ( | ||||
|     ChallengeResponse, | ||||
|     ContextualFlowInfo, | ||||
|     HttpChallengeResponse, | ||||
|     MessageSerializer, | ||||
|     RedirectChallenge, | ||||
|     SessionEndChallenge, | ||||
|     WithUserInfoChallenge, | ||||
| @ -191,6 +193,22 @@ class ChallengeStageView(StageView): | ||||
|                 ) | ||||
|                 flow_info.is_valid() | ||||
|                 challenge.initial_data["flow_info"] = flow_info.data | ||||
|             if "messages" not in challenge.initial_data and not isinstance( | ||||
|                 challenge, RedirectStage | ||||
|             ): | ||||
|                 messages = MessageSerializer( | ||||
|                     data=[ | ||||
|                         { | ||||
|                             "message": message.message, | ||||
|                             "level": message.level_tag, | ||||
|                             "tags": message.tags, | ||||
|                         } | ||||
|                         for message in get_messages(self.request) | ||||
|                     ], | ||||
|                     many=True, | ||||
|                 ) | ||||
|                 messages.is_valid() | ||||
|                 challenge.initial_data["messages"] = messages.data | ||||
|             if isinstance(challenge, WithUserInfoChallenge): | ||||
|                 # If there's a pending user, update the `username` field | ||||
|                 # this field is only used by password managers. | ||||
|  | ||||
| @ -55,6 +55,7 @@ class TestFlowInspector(APITestCase): | ||||
|                     "layout": "stacked", | ||||
|                 }, | ||||
|                 "flow_designation": "authentication", | ||||
|                 "messages": [], | ||||
|                 "password_fields": False, | ||||
|                 "primary_action": "Log in", | ||||
|                 "sources": [], | ||||
|  | ||||
| @ -88,6 +88,7 @@ class TesOAuth2DeviceInit(OAuthTestCase): | ||||
|                     "layout": "stacked", | ||||
|                     "title": self.device_flow.title, | ||||
|                 }, | ||||
|                 "messages": [], | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @ -7,7 +7,6 @@ from django.contrib.messages.storage.session import SessionStorage | ||||
| from django.core.cache import cache | ||||
| from django.http.request import HttpRequest | ||||
|  | ||||
| SESSION_KEY = "_messages" | ||||
| CACHE_PREFIX = "goauthentik.io/root/messages_" | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -145,9 +145,8 @@ class EmailStageView(ChallengeStageView): | ||||
|                 user.save() | ||||
|             return self.executor.stage_ok() | ||||
|         if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: | ||||
|             self.logger.debug("No pending user") | ||||
|             messages.error(self.request, _("No pending user.")) | ||||
|             return self.executor.stage_invalid() | ||||
|             self.logger.warning("No pending user") | ||||
|             return self.executor.stage_invalid(_("No pending user")) | ||||
|         # Check if we've already sent the initial e-mail | ||||
|         if PLAN_CONTEXT_EMAIL_SENT not in self.executor.plan.context: | ||||
|             try: | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| """Delete stage logic""" | ||||
|  | ||||
| from django.contrib import messages | ||||
| from django.contrib.auth import logout | ||||
| from django.http import HttpRequest, HttpResponse | ||||
| from django.utils.translation import gettext as _ | ||||
| @ -16,10 +15,8 @@ class UserDeleteStageView(StageView): | ||||
|         """Delete currently pending user""" | ||||
|         user = self.get_pending_user() | ||||
|         if not user.is_authenticated: | ||||
|             message = _("No Pending User.") | ||||
|             messages.error(request, message) | ||||
|             self.logger.debug(message) | ||||
|             return self.executor.stage_invalid() | ||||
|             self.logger.warning("No authenticated user") | ||||
|             return self.executor.stage_invalid(_("No authenticated User.")) | ||||
|         logout(self.request) | ||||
|         user.delete() | ||||
|         self.logger.debug("Deleted user", user=user) | ||||
|  | ||||
| @ -80,10 +80,8 @@ class UserLoginStageView(ChallengeStageView): | ||||
|     def do_login(self, request: HttpRequest, remember: bool = False) -> HttpResponse: | ||||
|         """Attach the currently pending user to the current session""" | ||||
|         if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: | ||||
|             message = _("No Pending user to login.") | ||||
|             messages.error(request, message) | ||||
|             self.logger.debug(message) | ||||
|             return self.executor.stage_invalid() | ||||
|             self.logger.warning("No pending user to login") | ||||
|             return self.executor.stage_invalid(_("No Pending user to login.")) | ||||
|         backend = self.executor.plan.context.get( | ||||
|             PLAN_CONTEXT_AUTHENTICATION_BACKEND, BACKEND_INBUILT | ||||
|         ) | ||||
|  | ||||
							
								
								
									
										120
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								schema.yml
									
									
									
									
									
								
							| @ -39432,6 +39432,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-access-denied | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -39546,6 +39550,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-source-oauth-apple | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -39873,6 +39881,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-authenticator-duo | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -40032,6 +40044,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-authenticator-email | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -40288,6 +40304,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-authenticator-sms | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -40451,6 +40471,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-authenticator-static | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -40572,6 +40596,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-authenticator-totp | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -40799,6 +40827,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-authenticator-validate | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -40852,6 +40884,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-authenticator-webauthn | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -41001,6 +41037,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-autosubmit | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -41264,6 +41304,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-captcha | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -41663,6 +41707,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-consent | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -42464,6 +42512,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-dummy | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -42666,6 +42718,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-email | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -43593,6 +43649,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-flow-error | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -43921,6 +43981,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: xak-flow-frame | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -44731,6 +44795,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-identification | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -46324,6 +46392,22 @@ components: | ||||
|       - strict | ||||
|       - regex | ||||
|       type: string | ||||
|     Message: | ||||
|       type: object | ||||
|       description: Base serializer class which doesn't implement create/update methods | ||||
|       properties: | ||||
|         message: | ||||
|           type: string | ||||
|         level: | ||||
|           type: string | ||||
|         tags: | ||||
|           type: array | ||||
|           items: | ||||
|             type: string | ||||
|       required: | ||||
|       - level | ||||
|       - message | ||||
|       - tags | ||||
|     Metadata: | ||||
|       type: object | ||||
|       description: Serializer for blueprint metadata | ||||
| @ -47209,6 +47293,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-provider-oauth2-device-code | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -47237,6 +47325,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-provider-oauth2-device-code-finish | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -49387,6 +49479,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-password | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -52942,6 +53038,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-source-plex | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -53467,6 +53567,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-prompt | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -54663,6 +54767,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: xak-flow-redirect | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -56528,6 +56636,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-session-end | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -56662,6 +56774,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: xak-flow-shell | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
| @ -57943,6 +58059,10 @@ components: | ||||
|         component: | ||||
|           type: string | ||||
|           default: ak-stage-user-login | ||||
|         messages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Message' | ||||
|         response_errors: | ||||
|           type: object | ||||
|           additionalProperties: | ||||
|  | ||||
| @ -5,12 +5,13 @@ import { | ||||
|     TITLE_DEFAULT, | ||||
| } from "@goauthentik/common/constants"; | ||||
| import { globalAK } from "@goauthentik/common/global"; | ||||
| import { MessageLevel } from "@goauthentik/common/messages"; | ||||
| import { configureSentry } from "@goauthentik/common/sentry"; | ||||
| import { first } from "@goauthentik/common/utils"; | ||||
| import { WebsocketClient } from "@goauthentik/common/ws"; | ||||
| import { Interface } from "@goauthentik/elements/Interface"; | ||||
| import "@goauthentik/elements/LoadingOverlay"; | ||||
| import "@goauthentik/elements/ak-locale-context"; | ||||
| import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; | ||||
| import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand"; | ||||
| import { themeImage } from "@goauthentik/elements/utils/images"; | ||||
| import "@goauthentik/flow/components/ak-brand-footer"; | ||||
| @ -44,6 +45,7 @@ import { | ||||
|     FlowErrorChallenge, | ||||
|     FlowLayoutEnum, | ||||
|     FlowsApi, | ||||
|     Message, | ||||
|     ResponseError, | ||||
|     ShellChallenge, | ||||
|     UiThemeEnum, | ||||
| @ -83,8 +85,6 @@ export class FlowExecutor extends Interface implements StageHost { | ||||
|     @state() | ||||
|     flowInfo?: ContextualFlowInfo; | ||||
|  | ||||
|     ws: WebsocketClient; | ||||
|  | ||||
|     static get styles(): CSSResult[] { | ||||
|         return [PFBase, PFLogin, PFDrawer, PFButton, PFTitle, PFList, PFBackgroundImage].concat(css` | ||||
|             :host { | ||||
| @ -174,7 +174,6 @@ export class FlowExecutor extends Interface implements StageHost { | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.ws = new WebsocketClient(); | ||||
|         const inspector = new URL(window.location.toString()).searchParams.get("inspector"); | ||||
|         if (inspector === "" || inspector === "open") { | ||||
|             this.inspectorOpen = true; | ||||
| @ -233,6 +232,7 @@ export class FlowExecutor extends Interface implements StageHost { | ||||
|             if (this.challenge.flowInfo) { | ||||
|                 this.flowInfo = this.challenge.flowInfo; | ||||
|             } | ||||
|             this.showMessages(this.challenge.messages); | ||||
|             return !this.challenge.responseErrors; | ||||
|         } catch (exc: unknown) { | ||||
|             this.errorMessage(exc as Error | ResponseError | FetchError); | ||||
| @ -265,6 +265,7 @@ export class FlowExecutor extends Interface implements StageHost { | ||||
|             if (this.challenge.flowInfo) { | ||||
|                 this.flowInfo = this.challenge.flowInfo; | ||||
|             } | ||||
|             this.showMessages(this.challenge.messages); | ||||
|         } catch (exc: unknown) { | ||||
|             // Catch JSON or Update errors | ||||
|             this.errorMessage(exc as Error | ResponseError | FetchError); | ||||
| @ -273,6 +274,15 @@ export class FlowExecutor extends Interface implements StageHost { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     showMessages(messages: Array<Message> | undefined) { | ||||
|         for (const message of (messages ??= [])) { | ||||
|             showMessage({ | ||||
|                 level: message.level as MessageLevel, | ||||
|                 message: message.message, | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async errorMessage(error: Error | ResponseError | FetchError): Promise<void> { | ||||
|         let body = ""; | ||||
|         if (error instanceof FetchError) { | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| import "@goauthentik/elements/messages/MessageContainer"; | ||||
| import "@goauthentik/flow/FlowExecutor"; | ||||
| // Statically import some stages to speed up load speed | ||||
| import "@goauthentik/flow/stages/access_denied/AccessDeniedStage"; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	