diff --git a/authentik/core/api/sources.py b/authentik/core/api/sources.py index 4cf6e352b..a013369c1 100644 --- a/authentik/core/api/sources.py +++ b/authentik/core/api/sources.py @@ -13,7 +13,7 @@ from structlog.stdlib import get_logger from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer from authentik.core.models import Source -from authentik.flows.challenge import Challenge +from authentik.core.types import UserSettingSerializer from authentik.lib.templatetags.authentik_utils import verbose_name from authentik.lib.utils.reflection import all_subclasses from authentik.policies.engine import PolicyEngine @@ -77,14 +77,14 @@ class SourceViewSet( ) return Response(TypeCreateSerializer(data, many=True).data) - @swagger_auto_schema(responses={200: Challenge(many=True)}) + @swagger_auto_schema(responses={200: UserSettingSerializer(many=True)}) @action(detail=False) def user_settings(self, request: Request) -> Response: """Get all sources the user can configure""" _all_sources: Iterable[Source] = Source.objects.filter( enabled=True ).select_subclasses() - matching_sources: list[Challenge] = [] + matching_sources: list[UserSettingSerializer] = [] for source in _all_sources: user_settings = source.ui_user_settings if not user_settings: @@ -94,6 +94,7 @@ class SourceViewSet( if not policy_engine.passing: continue source_settings = source.ui_user_settings + source_settings["object_uid"] = str(source.pk) if not source_settings.is_valid(): LOGGER.warning(source_settings.errors) matching_sources.append(source_settings.validated_data) diff --git a/authentik/core/types.py b/authentik/core/types.py index 0f93a1589..07855987d 100644 --- a/authentik/core/types.py +++ b/authentik/core/types.py @@ -33,3 +33,17 @@ class UILoginButtonSerializer(Serializer): def update(self, instance: Model, validated_data: dict) -> Model: return Model() + + +class UserSettingSerializer(Serializer): + """Serializer for User settings for stages and sources""" + + object_uid = CharField() + component = CharField() + title = CharField() + + def create(self, validated_data: dict) -> Model: + return Model() + + def update(self, instance: Model, validated_data: dict) -> Model: + return Model() diff --git a/authentik/flows/api/stages.py b/authentik/flows/api/stages.py index 43029a19c..4837abd6d 100644 --- a/authentik/flows/api/stages.py +++ b/authentik/flows/api/stages.py @@ -12,8 +12,8 @@ from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer +from authentik.core.types import UserSettingSerializer from authentik.flows.api.flows import FlowSerializer -from authentik.flows.challenge import Challenge from authentik.flows.models import Stage from authentik.lib.templatetags.authentik_utils import verbose_name from authentik.lib.utils.reflection import all_subclasses @@ -77,7 +77,7 @@ class StageViewSet( data = sorted(data, key=lambda x: x["name"]) return Response(TypeCreateSerializer(data, many=True).data) - @swagger_auto_schema(responses={200: Challenge(many=True)}) + @swagger_auto_schema(responses={200: UserSettingSerializer(many=True)}) @action(detail=False) def user_settings(self, request: Request) -> Response: """Get all stages the user can configure""" @@ -87,8 +87,8 @@ class StageViewSet( user_settings = stage.ui_user_settings if not user_settings: continue - stage_challenge = user_settings - if not stage_challenge.is_valid(): - LOGGER.warning(stage_challenge.errors) - matching_stages.append(stage_challenge.initial_data) + user_settings.initial_data["object_uid"] = stage.pk + if not user_settings.is_valid(): + LOGGER.warning(user_settings.errors) + matching_stages.append(user_settings.initial_data) return Response(matching_stages) diff --git a/authentik/flows/models.py b/authentik/flows/models.py index d36cbb2e2..136882acd 100644 --- a/authentik/flows/models.py +++ b/authentik/flows/models.py @@ -10,7 +10,7 @@ from model_utils.managers import InheritanceManager from rest_framework.serializers import BaseSerializer from structlog.stdlib import get_logger -from authentik.flows.challenge import Challenge +from authentik.core.types import UserSettingSerializer from authentik.lib.models import InheritanceForeignKey, SerializerModel from authentik.policies.models import PolicyBindingModel @@ -65,7 +65,7 @@ class Stage(SerializerModel): raise NotImplementedError @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.""" return None diff --git a/swagger.yaml b/swagger.yaml index 2dcde19bd..b370c7640 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -7207,13 +7207,12 @@ paths: type: integer responses: '200': - description: Challenge that gets sent to the client based on which stage - is currently active + description: Serializer for User settings for stages and sources schema: description: '' type: array items: - $ref: '#/definitions/Challenge' + $ref: '#/definitions/UserSetting' tags: - sources parameters: [] @@ -7859,13 +7858,12 @@ paths: type: integer responses: '200': - description: Challenge that gets sent to the client based on which stage - is currently active + description: Serializer for User settings for stages and sources schema: description: '' type: array items: - $ref: '#/definitions/Challenge' + $ref: '#/definitions/UserSetting' tags: - stages parameters: [] @@ -13483,6 +13481,26 @@ definitions: title: Verbose name plural type: string readOnly: true + UserSetting: + description: Serializer for User settings for stages and sources + required: + - object_uid + - component + - title + type: object + properties: + object_uid: + title: Object uid + type: string + minLength: 1 + component: + title: Component + type: string + minLength: 1 + title: + title: Title + type: string + minLength: 1 LDAPSource: description: LDAP Source Serializer required: