flows: always show flow inspector in debug mode, don't require admin in debug (#3786)

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens L 2022-10-14 16:44:59 +03:00 committed by GitHub
parent 884f5249d1
commit 79e8b72569
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 8 deletions

View File

@ -28,6 +28,7 @@ class Capabilities(models.TextChoices):
CAN_SAVE_MEDIA = "can_save_media" CAN_SAVE_MEDIA = "can_save_media"
CAN_GEO_IP = "can_geo_ip" CAN_GEO_IP = "can_geo_ip"
CAN_IMPERSONATE = "can_impersonate" CAN_IMPERSONATE = "can_impersonate"
CAN_DEBUG = "can_debug"
class ErrorReportingConfigSerializer(PassiveSerializer): class ErrorReportingConfigSerializer(PassiveSerializer):
@ -66,6 +67,8 @@ class ConfigView(APIView):
caps.append(Capabilities.CAN_GEO_IP) caps.append(Capabilities.CAN_GEO_IP)
if CONFIG.y_bool("impersonation"): if CONFIG.y_bool("impersonation"):
caps.append(Capabilities.CAN_IMPERSONATE) caps.append(Capabilities.CAN_IMPERSONATE)
if settings.DEBUG:
caps.append(Capabilities.CAN_DEBUG)
return caps return caps
def get_config(self) -> ConfigSerializer: def get_config(self) -> ConfigSerializer:

View File

@ -73,17 +73,17 @@ class FlowInspectorView(APIView):
flow: Flow flow: Flow
_logger: BoundLogger _logger: BoundLogger
def check_permissions(self, request):
"""Always allow access when in debug mode"""
if settings.DEBUG:
return None
return super().check_permissions(request)
def setup(self, request: HttpRequest, flow_slug: str): def setup(self, request: HttpRequest, flow_slug: str):
super().setup(request, flow_slug=flow_slug) super().setup(request, flow_slug=flow_slug)
self.flow = get_object_or_404(Flow.objects.select_related(), slug=flow_slug) self.flow = get_object_or_404(Flow.objects.select_related(), slug=flow_slug)
self._logger = get_logger().bind(flow_slug=flow_slug) self._logger = get_logger().bind(flow_slug=flow_slug)
# pylint: disable=unused-argument, too-many-return-statements
def dispatch(self, request: HttpRequest, flow_slug: str) -> HttpResponse:
if SESSION_KEY_HISTORY not in self.request.session:
return HttpResponse(status=400)
return super().dispatch(request, flow_slug=flow_slug)
@extend_schema( @extend_schema(
responses={ responses={
200: FlowInspectionSerializer(), 200: FlowInspectionSerializer(),
@ -95,7 +95,7 @@ class FlowInspectorView(APIView):
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Get current flow state and record it""" """Get current flow state and record it"""
plans = [] plans = []
for plan in request.session[SESSION_KEY_HISTORY]: for plan in request.session.get(SESSION_KEY_HISTORY, []):
plan_serializer = FlowInspectorPlanSerializer( plan_serializer = FlowInspectorPlanSerializer(
instance=plan, context={"request": request} instance=plan, context={"request": request}
) )

View File

@ -25809,6 +25809,7 @@ components:
- can_save_media - can_save_media
- can_geo_ip - can_geo_ip
- can_impersonate - can_impersonate
- can_debug
type: string type: string
CaptchaChallenge: CaptchaChallenge:
type: object type: object

View File

@ -36,6 +36,7 @@ import PFTitle from "@patternfly/patternfly/components/Title/title.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { import {
CapabilitiesEnum,
ChallengeChoices, ChallengeChoices,
ChallengeTypes, ChallengeTypes,
CurrentTenant, CurrentTenant,
@ -154,7 +155,11 @@ export class FlowExecutor extends AKElement implements StageHost {
super(); super();
this.ws = new WebsocketClient(); this.ws = new WebsocketClient();
this.flowSlug = window.location.pathname.split("/")[3]; this.flowSlug = window.location.pathname.split("/")[3];
this.inspectorOpen = window.location.search.includes("inspector"); this.inspectorOpen =
globalAK()?.config.capabilities.includes(CapabilitiesEnum.Debug) || false;
if (window.location.search.includes("inspector")) {
this.inspectorOpen = !this.inspectorOpen;
}
tenant().then((tenant) => (this.tenant = tenant)); tenant().then((tenant) => (this.tenant = tenant));
} }

View File

@ -31,3 +31,7 @@ This data is not cleaned, so if your flow involves inputting a password, it will
## Session ID ## Session ID
The unique ID for the currently used session. This can be used to debug issues with flows restarting/losing state. The unique ID for the currently used session. This can be used to debug issues with flows restarting/losing state.
# Access to the inspector
By default, the inspector can only be enabled when the currently authenticated user is a superuser. When running authentik with debug-mode enabled, the inspector is enabled by default and can be accessed by both unauthenticated users and standard users.