* rename consent permission Signed-off-by: Jens Langhammer <jens@goauthentik.io> * the user version Signed-off-by: Jens Langhammer <jens@goauthentik.io> t Signed-off-by: Jens Langhammer <jens@goauthentik.io> * initial role Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start form Signed-off-by: Jens Langhammer <jens@goauthentik.io> * some minor table refactoring Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix user, add assign Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add roles ui Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix backend Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add assign API for roles Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start adding toggle buttons Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start view page Signed-off-by: Jens Langhammer <jens@goauthentik.io> * exclude add_ permission for per-object perms Signed-off-by: Jens Langhammer <jens@goauthentik.io> * small cleanup Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add permission list for roles Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make sidebar update Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix page header not re-rendering? Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fixup Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add search Signed-off-by: Jens Langhammer <jens@goauthentik.io> * show first category in table groupBy except when its empty Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make model and object PK optional but required together Signed-off-by: Jens Langhammer <jens@goauthentik.io> * allow for setting global perms Signed-off-by: Jens Langhammer <jens@goauthentik.io> * exclude non-authentik permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * exclude models which aren't allowed (base models etc) Signed-off-by: Jens Langhammer <jens@goauthentik.io> * ensure all models have verbose_name set, exclude some more internal objects Signed-off-by: Jens Langhammer <jens@goauthentik.io> * lint fix Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix role perm assign Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add unasign for global perms Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add meta changes Signed-off-by: Jens Langhammer <jens@goauthentik.io> * clear modal state after submit Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add roles to our group Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix duplicate url names Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make recursive group query more usable Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add name field to role itself and move group creation to signal Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start sync Signed-off-by: Jens Langhammer <jens@goauthentik.io> * move rbac stuff to separate django app Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix lint and such Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix go Signed-off-by: Jens Langhammer <jens@goauthentik.io> * update Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start API changes Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add more API tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make admin interface not require superuser for now, improve error handling Signed-off-by: Jens Langhammer <jens@goauthentik.io> * replace some IsAdminUser where applicable Signed-off-by: Jens Langhammer <jens@goauthentik.io> * migrate flow inspector perms to actual permission Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix license not being a serializermodel Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add permission modal to models without view page Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add additional permissions to assign/unassign permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add action to unassign user permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add permissions tab to remaining view pages Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix flow inspector permission check Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix codecov config? Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add more API tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * ensure viewsets have an order set Signed-off-by: Jens Langhammer <jens@goauthentik.io> * hopefully the last api name change Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make perm modal less confusing Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start user view permission page Signed-off-by: Jens Langhammer <jens@goauthentik.io> * only make delete bulk form expandable if usedBy is set Signed-off-by: Jens Langhammer <jens@goauthentik.io> * expand permission tables Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add more things Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add user global permission table Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix lint Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix tests' url names Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add tests for assign perms Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add unassign tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rebuild permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * prevent assigning/unassigning permissions to internal service accounts Signed-off-by: Jens Langhammer <jens@goauthentik.io> * only enable default api browser in debug Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix role object permissions showing duplicate Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix role link on role object permissions table Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix object permission modal having duplicate close buttons Signed-off-by: Jens Langhammer <jens@goauthentik.io> * return error if user has no global perm and no object perms also improve error display on table Signed-off-by: Jens Langhammer <jens@goauthentik.io> * small optimisation Signed-off-by: Jens Langhammer <jens@goauthentik.io> * optimise even more Signed-off-by: Jens Langhammer <jens@goauthentik.io> * update locale Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add system permission for non-object permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * allow access to admin interface based on perm Signed-off-by: Jens Langhammer <jens@goauthentik.io> * clean Signed-off-by: Jens Langhammer <jens@goauthentik.io> * don't exclude base models Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
119 lines
4.5 KiB
Python
119 lines
4.5 KiB
Python
"""Flow Inspector"""
|
|
from hashlib import sha256
|
|
from typing import Any
|
|
|
|
from django.conf import settings
|
|
from django.http import Http404
|
|
from django.http.request import HttpRequest
|
|
from django.http.response import HttpResponse
|
|
from django.shortcuts import get_object_or_404
|
|
from django.utils.decorators import method_decorator
|
|
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
|
from drf_spectacular.types import OpenApiTypes
|
|
from drf_spectacular.utils import OpenApiResponse, extend_schema
|
|
from rest_framework.fields import BooleanField, ListField, SerializerMethodField
|
|
from rest_framework.request import Request
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
from structlog.stdlib import BoundLogger, get_logger
|
|
|
|
from authentik.core.api.utils import PassiveSerializer
|
|
from authentik.events.utils import sanitize_dict
|
|
from authentik.flows.api.bindings import FlowStageBindingSerializer
|
|
from authentik.flows.models import Flow
|
|
from authentik.flows.planner import FlowPlan
|
|
from authentik.flows.views.executor import SESSION_KEY_HISTORY, SESSION_KEY_PLAN
|
|
from authentik.root.install_id import get_install_id
|
|
|
|
|
|
class FlowInspectorPlanSerializer(PassiveSerializer):
|
|
"""Serializer for an active FlowPlan"""
|
|
|
|
current_stage = SerializerMethodField()
|
|
next_planned_stage = SerializerMethodField(required=False)
|
|
plan_context = SerializerMethodField()
|
|
session_id = SerializerMethodField()
|
|
|
|
def get_current_stage(self, plan: FlowPlan) -> FlowStageBindingSerializer:
|
|
"""Get the current stage"""
|
|
return FlowStageBindingSerializer(instance=plan.bindings[0]).data
|
|
|
|
def get_next_planned_stage(self, plan: FlowPlan) -> FlowStageBindingSerializer:
|
|
"""Get the next planned stage"""
|
|
if len(plan.bindings) < 2:
|
|
return FlowStageBindingSerializer().data
|
|
return FlowStageBindingSerializer(instance=plan.bindings[1]).data
|
|
|
|
def get_plan_context(self, plan: FlowPlan) -> dict[str, Any]:
|
|
"""Get the plan's context, sanitized"""
|
|
return sanitize_dict(plan.context)
|
|
|
|
def get_session_id(self, plan: FlowPlan) -> str:
|
|
"""Get a unique session ID"""
|
|
request: Request = self.context["request"]
|
|
return sha256(
|
|
f"{request._request.session.session_key}-{get_install_id()}".encode("ascii")
|
|
).hexdigest()
|
|
|
|
|
|
class FlowInspectionSerializer(PassiveSerializer):
|
|
"""Serializer for inspect endpoint"""
|
|
|
|
plans = ListField(child=FlowInspectorPlanSerializer())
|
|
current_plan = FlowInspectorPlanSerializer(required=False)
|
|
is_completed = BooleanField()
|
|
|
|
|
|
@method_decorator(xframe_options_sameorigin, name="dispatch")
|
|
class FlowInspectorView(APIView):
|
|
"""Flow inspector API"""
|
|
|
|
flow: Flow
|
|
_logger: BoundLogger
|
|
permission_classes = []
|
|
|
|
def setup(self, request: HttpRequest, flow_slug: str):
|
|
super().setup(request, flow_slug=flow_slug)
|
|
self._logger = get_logger().bind(flow_slug=flow_slug)
|
|
self.flow = get_object_or_404(Flow.objects.select_related(), slug=flow_slug)
|
|
if settings.DEBUG:
|
|
return
|
|
if request.user.has_perm("authentik_flow.inspect_flow", self.flow):
|
|
return
|
|
raise Http404
|
|
|
|
@extend_schema(
|
|
responses={
|
|
200: FlowInspectionSerializer(),
|
|
400: OpenApiResponse(description="No flow plan in session."),
|
|
},
|
|
request=OpenApiTypes.NONE,
|
|
operation_id="flows_inspector_get",
|
|
)
|
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
|
"""Get current flow state and record it"""
|
|
plans = []
|
|
for plan in request.session.get(SESSION_KEY_HISTORY, []):
|
|
plan_serializer = FlowInspectorPlanSerializer(
|
|
instance=plan, context={"request": request}
|
|
)
|
|
plans.append(plan_serializer.data)
|
|
is_completed = False
|
|
if SESSION_KEY_PLAN in request.session:
|
|
current_plan: FlowPlan = request.session[SESSION_KEY_PLAN]
|
|
else:
|
|
try:
|
|
current_plan = request.session.get(SESSION_KEY_HISTORY, [])[-1]
|
|
except IndexError:
|
|
return Response(status=400)
|
|
is_completed = True
|
|
current_serializer = FlowInspectorPlanSerializer(
|
|
instance=current_plan, context={"request": request}
|
|
)
|
|
response = {
|
|
"plans": plans,
|
|
"current_plan": current_serializer.data,
|
|
"is_completed": is_completed,
|
|
}
|
|
return Response(response)
|