Exemple #1
0
    def get_fields_params(self) -> []:
        if self.method != "GET":
            return []

        response_serializers = self.get_response_serializers()
        if isinstance(response_serializers, DynamicFieldsMixin):
            return [
                OpenApiParameter(
                    name="fields",
                    type=str,
                    location=OpenApiParameter.QUERY,
                    required=False,
                    description=_(
                        "Comma-separated fields, which should be displayed in the response. "
                        "For example: 'url, uuid, record__geometry'."),
                ),
                OpenApiParameter(
                    name=settings.UNAUTHORIZED_FIELDS_HEADER,
                    type=str,
                    location=OpenApiParameter.HEADER,
                    response=True,
                    description=
                    _("List of fields that are not allowed to display if the field-based "
                      "authorization is turned on. The value has the following format: "
                      "`objectType1:fieldA,fieldB; objectType2:fieldC,fieldD`"
                      ),
                ),
            ]

        return []
Exemple #2
0
class QueryRegionGroupReservationView(views.APIView):
    @extend_schema(
        parameters=[
            OpenApiParameter("min_time_id", OpenApiTypes.INT),
            OpenApiParameter("max_time_id", OpenApiTypes.INT),
            OpenApiParameter("region_group_id", OpenApiTypes.INT),
        ],
        responses=RegionReservationSerializer(many=True),
    )
    def get(self, request):
        """
        查询某一区域组的预定情况,返回一个数组,代表在该区域组里的每一个区域在
        [min_time_id, max_time_id] 每个时间段内的预定情况。
        """
        group = request.GET.get('region_group_id')
        min_time_id = request.GET.get('min_time_id')
        max_time_id = request.GET.get('max_time_id')
        reserved_time = Reservation.objects \
            .filter(time__gte=min_time_id, time__lte=max_time_id, region__group=group) \
            .values('region', 'time') \
            .annotate(reserved=Count('*')) \
            .annotate(region_id=F('region')) \
            .annotate(time_id=F('time')) \
            .values('region_id', 'time_id', 'reserved')
        serializer = RegionReservationSerializer(reserved_time, many=True)
        return Response(serializer.data)
Exemple #3
0
class MenuList(ListCreateAPIView):
    """
    Get list of non-empty menus with GET, or create a new one with POST.
    """
    permission_classes = [IsAuthenticatedOrReadOnly]

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return MenuListSerializer
        else:
            return MenuCreateSerializer

    def get_queryset(self):
        if self.request.method == 'GET':
            qs = Menu.objects.exclude(dishes__isnull=True)
            return filter_menu_queryset(qs, self.request.query_params)
        else:
            return Menu.objects.all()

    @extend_schema(parameters=[
        OpenApiParameter(
            'sort_by',
            description='Choose to sort list by name or dish count, descending',
            enum=['name', 'dish_count']),
        OpenApiParameter(
            'updated_after',
            description=
            'View only menus created after a date in YYYY-MM-DD format'),
        OpenApiParameter(
            'added_after',
            description=
            'View only menus updated after a date in YYYY-MM-DD format'),
    ])
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
class ListCreateMarketsView(MultipleFieldsSearch, ListCreateAPIView):

    queryset = Market.objects.all()
    serializer_class = MarketSerializer
    lookup_fields = ['district', 'region_5', 'name', 'address_city']

    @extend_schema(description='Create a Market')
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

    @extend_schema(
        description='List Markets with optional filters',
        parameters=[
            OpenApiParameter(name='district', description='District',
                             required=False, type=str, location='query'),
            OpenApiParameter(name='region_5', description='Region',
                             required=False, type=str, location='query'),
            OpenApiParameter(name='name', description='Name',
                             required=False, type=str, location='query'),
            OpenApiParameter(name='address_city', description='City',
                             required=False, type=str, location='query'),
        ],
    )
    def get(self, request, *args, **kwargs):

        if not bool(set(self.request.query_params).intersection(self.lookup_fields)):
            return JsonResponse({'message': "Should include at least one query param: [district,region_5,name,address_city]"}, status=400)

        return self.list(request, *args, **kwargs)
Exemple #5
0
class ParametersViewSet(viewsets.ViewSet):
    """Parameter viewset."""

    lookup_value_regex = r"\w+"
    serializer_class = None

    @extend_schema(responses=serializers.ApplicationSerializer(many=True))
    @action(methods=["get"], detail=False)
    def applications(self, request):
        """Return the list of registered applications."""
        applications = tools.registry.get_applications("global")
        return response.Response(applications)

    @extend_schema(responses=serializers.ParameterSerializer(many=True))
    @action(methods=["get"], detail=False)
    def structure(self, request):
        """Return parameter schema."""
        app = request.GET.get("app")
        data = tools.registry.get_structure("global", app)
        return response.Response(data)

    @extend_schema(parameters=[
        OpenApiParameter(name='id',
                         location=OpenApiParameter.PATH,
                         description='A registered application name',
                         type=str,
                         required=True),
    ])
    def retrieve(self, request, pk: str):
        """Return all parameters for given app."""
        parameters = request.localconfig.parameters.get_values_dict(pk)
        serializer = tools.registry.get_serializer_class("global",
                                                         pk)(parameters)
        return response.Response(serializer.data)

    @extend_schema(parameters=[
        OpenApiParameter(name='id',
                         location=OpenApiParameter.PATH,
                         description='A registered application name',
                         type=str,
                         required=True),
    ])
    def update(self, request, pk: str):
        """Save parameters for given app."""
        serializer = tools.registry.get_serializer_class("global",
                                                         pk)(data=request.data)
        serializer.is_valid(raise_exception=True)
        request.localconfig.parameters.set_values(serializer.validated_data,
                                                  app=pk)
        request.localconfig.save(update_fields=["_parameters"])
        return response.Response()
Exemple #6
0
class SCIM_PARAMS:
    MEMBER_ID = OpenApiParameter(
        name="member_id",
        location="path",
        required=True,
        type=int,
        description="The id of the member you'd like to query.",
    )
    TEAM_ID = OpenApiParameter(
        name="team_id",
        location="path",
        required=True,
        type=int,
        description="The id of the team you'd like to query / update.",
    )
Exemple #7
0
class GLOBAL_PARAMS:
    ORG_SLUG = OpenApiParameter(
        name="organization_slug",
        description="The slug of the organization the resource belongs to.",
        required=True,
        type=str,
        location="path",
    )
    PROJECT_SLUG = OpenApiParameter(
        name="project_slug",
        description="The slug of the project the resource belongs to.",
        required=True,
        type=str,
        location="path",
    )
Exemple #8
0
    def get_geo_headers(self) -> list:
        if not isinstance(self.view, GeoMixin):
            return []

        request_headers = []
        if self.method != "DELETE":
            request_headers.append(
                OpenApiParameter(
                    name=HEADER_ACCEPT,
                    type=str,
                    location=OpenApiParameter.HEADER,
                    required=False,
                    description=
                    _("The desired 'Coordinate Reference System' (CRS) of the response data. "
                      "According to the GeoJSON spec, WGS84 is the default (EPSG: 4326 "
                      "is the same as WGS84)."),
                    enum=[DEFAULT_CRS],
                ))

        if self.method in ("POST", "PUT", "PATCH"):
            request_headers.append(
                OpenApiParameter(
                    name=HEADER_CONTENT,
                    type=str,
                    location=OpenApiParameter.HEADER,
                    required=True,
                    description=
                    _("The 'Coordinate Reference System' (CRS) of the request data. "
                      "According to the GeoJSON spec, WGS84 is the default (EPSG: 4326 "
                      "is the same as WGS84)."),
                    enum=[DEFAULT_CRS],
                ), )

        response_headers = [
            OpenApiParameter(
                name=HEADER_CONTENT,
                type=str,
                location=OpenApiParameter.HEADER,
                description=
                _("The 'Coordinate Reference System' (CRS) of the request data. "
                  "According to the GeoJSON spec, WGS84 is the default (EPSG: 4326 "
                  "is the same as WGS84)."),
                enum=[DEFAULT_CRS],
                response=[200, 201],
            )
        ]

        return request_headers + response_headers
Exemple #9
0
class ExportTableView(APIView):
    permission_classes = (IsAuthenticated, )

    @extend_schema(
        parameters=[
            OpenApiParameter(
                name="table_id",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.INT,
                description=
                "The table id to create and start an export job for",
            )
        ],
        tags=["Database table export"],
        operation_id="export_table",
        description=
        ("Creates and starts a new export job for a table given some exporter "
         "options. Returns an error if the requesting user does not have permissions"
         "to view the table."),
        request=CreateExportJobSerializer,
        responses={
            200:
            ExportJobSerializer,
            400:
            get_error_schema([
                "ERROR_USER_NOT_IN_GROUP",
                "ERROR_REQUEST_BODY_VALIDATION",
                "ERROR_TABLE_ONLY_EXPORT_UNSUPPORTED",
                "ERROR_VIEW_UNSUPPORTED_FOR_EXPORT_TYPE",
                "ERROR_VIEW_NOT_IN_TABLE",
            ]),
            404:
            get_error_schema(
                ["ERROR_TABLE_DOES_NOT_EXIST", "ERROR_VIEW_DOES_NOT_EXIST"]),
        },
    )
    @transaction.atomic
    @map_exceptions({
        UserNotInGroup: ERROR_USER_NOT_IN_GROUP,
        TableDoesNotExist: ERROR_TABLE_DOES_NOT_EXIST,
        ViewDoesNotExist: ERROR_VIEW_DOES_NOT_EXIST,
        TableOnlyExportUnsupported: ERROR_TABLE_ONLY_EXPORT_UNSUPPORTED,
        ViewNotInTable: ERROR_VIEW_NOT_IN_TABLE,
    })
    def post(self, request, table_id):
        """
        Starts a new export job for the provided table, view, export type and options.
        """

        table = TableHandler().get_table(table_id)
        table.database.group.has_user(request.user, raise_error=True)

        option_data = _validate_options(request.data)

        view_id = option_data.pop("view_id", None)
        view = ViewHandler().get_view(view_id) if view_id else None

        job = ExportHandler.create_and_start_new_job(request.user, table, view,
                                                     option_data)
        return Response(ExportJobSerializer(job).data)
Exemple #10
0
class RegionRecommendationView(views.APIView):
    permission_classes = [permissions.IsAuthenticated]

    @extend_schema(
        parameters=[
            OpenApiParameter("id", OpenApiTypes.INT, OpenApiParameter.PATH),
        ],
        responses=RegionGroupSerializer(many=True),
    )
    def get(self, request):
        """
        根据用户的预定历史推荐区域
        """
        region_ids = Reservation.objects \
            .filter(user=request.user) \
            .values_list('region', flat=True) \
            .distinct()
        group_ids = Region.objects \
            .filter(id__in=region_ids) \
            .values_list('group', flat=True) \
            .distinct()
        region_groups = RegionGroup.objects \
            .filter(id__in=group_ids) \
            .annotate(capacity=Sum('regions__capacity'))
        serializer = RegionGroupDetailSerializer(region_groups, many=True)
        return Response(serializer.data)
Exemple #11
0
class EventViewSet(ReadOnlyModelViewSet):
    """Event Read-Only Viewset"""

    queryset = Event.objects.all()
    serializer_class = EventSerializer
    ordering = ["-created"]
    search_fields = [
        "event_uuid",
        "user",
        "action",
        "app",
        "context",
        "client_ip",
    ]
    filterset_class = EventsFilter

    @extend_schema(
        methods=["GET"],
        responses={200: EventTopPerUserSerializer(many=True)},
        parameters=[
            OpenApiParameter(
                "top_n",
                type=OpenApiTypes.INT,
                location=OpenApiParameter.QUERY,
                required=False,
            )
        ],
    )
    @action(detail=False, methods=["GET"], pagination_class=None)
    def top_per_user(self, request: Request):
        """Get the top_n events grouped by user count"""
        filtered_action = request.query_params.get("action", EventAction.LOGIN)
        top_n = int(request.query_params.get("top_n", "15"))
        return Response(
            get_objects_for_user(
                request.user, "authentik_events.view_event").filter(
                    action=filtered_action).exclude(
                        context__authorized_application=None).annotate(
                            application=KeyTextTransform(
                                "authorized_application", "context")).annotate(
                                    user_pk=KeyTextTransform("pk", "user")).
            values("application").annotate(
                counted_events=Count("application")).annotate(
                    unique_users=Count("user_pk", distinct=True)).values(
                        "unique_users", "application",
                        "counted_events").order_by("-counted_events")[:top_n])

    @extend_schema(responses={200: TypeCreateSerializer(many=True)})
    @action(detail=False, pagination_class=None, filter_backends=[])
    def actions(self, request: Request) -> Response:
        """Get all actions"""
        data = []
        for value, name in EventAction.choices:
            data.append({
                "name": name,
                "description": "",
                "component": value,
                "model_name": ""
            })
        return Response(TypeCreateSerializer(data, many=True).data)
Exemple #12
0
def test_exclude_discovered_parameter(no_warnings):
    @extend_schema_view(list=extend_schema(parameters=[
        # keep 'offset', remove 'limit', and add 'random'
        OpenApiParameter('limit', exclude=True),
        OpenApiParameter('random', bool),
    ]))
    class XViewset(viewsets.ReadOnlyModelViewSet):
        queryset = SimpleModel.objects.all()
        serializer_class = SimpleSerializer
        pagination_class = pagination.LimitOffsetPagination

    schema = generate_schema('x', XViewset)
    parameters = schema['paths']['/x/']['get']['parameters']
    assert len(parameters) == 2
    assert parameters[0]['name'] == 'offset'
    assert parameters[1]['name'] == 'random'
def test_explode_style_parameter_with_custom_schema(no_warnings):
    @extend_schema(
        parameters=[
            OpenApiParameter(
                name='bbox',
                type={
                    'type': 'array',
                    'minItems': 4,
                    'maxItems': 6,
                    'items': {
                        'type': 'number'
                    }
                },
                location=OpenApiParameter.QUERY,
                required=False,
                style='form',
                explode=False,
            )
        ],
        responses=OpenApiTypes.OBJECT,
    )
    @api_view(['GET'])
    def view_func(request, format=None):
        pass  # pragma: no cover

    schema = generate_schema('/x/', view_function=view_func)
    parameter = schema['paths']['/x/']['get']['parameters'][0]
    assert 'explode' in parameter
    assert 'style' in parameter
    assert parameter['schema']['type'] == 'array'
Exemple #14
0
class NodeViewSet(ViewSet):
    serializer_class = NodeSerializer

    @extend_schema(parameters=[
        OpenApiParameter('id',
                         location=OpenApiParameter.PATH,
                         description=PK_DESCRIPTION)
    ])
    def retrieve(self, request, pk: str = None):
        assert pk is not None
        blockchain = BlockchainBase.get_instance()

        node_id = hexstr(pk.lower())
        if node_id == PRIMARY_VALIDATOR_NODE_ID:
            node = blockchain.get_primary_validator()
        elif node_id == SELF_NODE_ID:
            node = blockchain.get_node_by_identifier(
                identifier=get_node_identifier())
        else:
            node = blockchain.get_node_by_identifier(identifier=node_id)

        if node is None:
            raise NotFound(detail='Node not found')

        serializer = self.serializer_class(node)
        return Response(serializer.data)
Exemple #15
0
 class Fixed(self.target_class):
     @extend_schema(parameters=[
         OpenApiParameter(name='breadcrumbs',
                          type=OpenApiTypes.STR,
                          location=OpenApiParameter.PATH)
     ])
     def get(self, request, *args, **kwargs):
         pass
Exemple #16
0
class ISSUE_ALERT_PARAMS:
    ISSUE_RULE_ID = OpenApiParameter(
        name="rule_id",
        location="path",
        required=True,
        type=int,
        description="The id of the rule you'd like to query",
    )
Exemple #17
0
class DocsParams:
    KPIS = OpenApiParameter(name='kpis',
                            type=OpenApiTypes.STR,
                            description='get tiles for specific kpis')

    TABLE = OpenApiParameter(name='table',
                             type=OpenApiTypes.STR,
                             required=True,
                             description="get specific graph by it's Name")

    TABLE_NAME = OpenApiParameter(
        'table_name',
        type=OpenApiTypes.STR,
        description="get specific graph by it's Name")

    ID = OpenApiParameter(
        name='id',
        description='id or array of ids you want to query (branch or group)')

    START_DATE = OpenApiParameter(name='start_date',
                                  type=OpenApiTypes.DATE,
                                  description='format: YYYY-MM-DD')

    END_DATE = OpenApiParameter(name='end_date',
                                type=OpenApiTypes.DATE,
                                description='format: YYYY-MM-DD')

    LEVEL = OpenApiParameter(name='level',
                             type=OpenApiTypes.STR,
                             required=True,
                             enum=LEVELS_ENUM,
                             description='level (farm/branch/group)')

    FARM_ID = OpenApiParameter(name='farm_id',
                               type=OpenApiTypes.STR,
                               required=True,
                               description='specify farm/s')
    META_FARM_ID = OpenApiParameter(
        name='farm_id',
        type=OpenApiTypes.STR,
        required=True,
        description="get the farm's branches and groups IDs lists")

    KPIS = OpenApiParameter(name=KPIS,
                            type=OpenApiTypes.STR,
                            description='get tiles for specific kpis')
    class XApiView(APIView):
        authentication_classes = []

        @extend_schema(
            parameters=[OpenApiParameter('id', OpenApiTypes.INT, OpenApiParameter.PATH)],
            responses={200: XSerializer(many=True)},
        )
        def get(self, request):
            pass  # pragma: no cover
Exemple #19
0
def test_exclude_parameter_from_customized_autoschema(no_warnings):
    class CustomSchema(AutoSchema):
        def get_override_parameters(self):
            return [OpenApiParameter('test')]

    @extend_schema_view(list=extend_schema(parameters=[
        OpenApiParameter('test', exclude=True),  # exclude from class override
        OpenApiParameter('never_existed', exclude=True),  # provoke error
        OpenApiParameter('keep', bool),  # for sanity check
    ]))
    class XViewset(viewsets.ReadOnlyModelViewSet):
        queryset = SimpleModel.objects.all()
        serializer_class = SimpleSerializer
        schema = CustomSchema()

    schema = generate_schema('x', XViewset)
    parameters = schema['paths']['/x/']['get']['parameters']
    assert len(parameters) == 1
    assert parameters[0]['name'] == 'keep'
    class XViewset(viewsets.GenericViewSet):
        @extend_schema(request=XSerializer, responses=YSerializer)
        def create(self, request):
            pass  # pragma: no cover

        @extend_schema(
            request=XSerializer,
            responses=YSerializer,
            parameters=[OpenApiParameter('id', int, OpenApiParameter.PATH)])
        def partial_update(self, request):
            pass  # pragma: no cover
Exemple #21
0
def test_response_header_warnings(capsys):
    @extend_schema(request=OpenApiTypes.ANY,
                   responses=OpenApiTypes.ANY,
                   parameters=[OpenApiParameter(name='test', response=True)])
    @api_view(['POST'])
    def view_func(request, format=None):
        pass  # pragma: no cover

    generate_schema('x', view_function=view_func)
    stderr = capsys.readouterr().err
    assert 'incompatible location type ignored' in stderr
Exemple #22
0
class ReportParamsView(generics.GenericAPIView):
    def get_slit(self):
        return get_slits_dict()[self.request.query_params["slit_name"]]

    def get_data_source(self):
        return get_data_sources_dict()[
            self.request.query_params["data_source_name"]]

    def get_report(self):
        return Report(self.get_data_source(), self.get_slit())

    def get_params(self):
        raise NotImplementedError

    @extend_schema(parameters=[
        OpenApiParameter("slit_name"),
        OpenApiParameter("data_source_name")
    ])
    def get(self, request, *args, **kwargs):
        return Response(self.get_params())
    class XViewset(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
        @extend_schema(responses=enveloper(XSerializer, True))
        def list(self, request, *args, **kwargs):
            return super().list(request, *args, **kwargs)  # pragma: no cover

        @extend_schema(
            responses=enveloper(XSerializer, False),
            parameters=[OpenApiParameter('id', int, OpenApiParameter.PATH)],
        )
        def retrieve(self, request, *args, **kwargs):
            return super().retrieve(request, *args, **kwargs)  # pragma: no cover
Exemple #24
0
class TailoredSkillsViewSet(viewsets.GenericViewSet):
    serializer_class = TailoredSkillsSerializer
    pagination_class = None

    def get_queryset(self, query):
        # SearchVector is currently disabled as it does not work properly on AWS RDS due to lack of
        # pg_catalog.english support from the migrations file. Retaled discussions:
        # https://stackoverflow.com/q/40032685/10748367
        # https://forums.aws.amazon.com/thread.jspa?threadID=143920
        # return Vacancy.objects.filter(search_vector=query)
        return Vacancy.objects.filter(title__search=query)

    @extend_schema(
        parameters=[
            OpenApiParameter(
                name="limit",
                type=int,
                required=False,
                description="A number of most wanted skills to display.",
            ),
            OpenApiParameter(
                name="q",
                required=True,
                description="A job title to be processed.",
            ),
        ],
        description=
        "Specify a job title and get the ranked skills that companies look for.",
    )
    def list(self, request):
        query, limit, user_agent, ip_address = parse_request(request)
        save_query_with_metadata.delay(query, user_agent, ip_address)
        queryset = self.get_queryset(query)
        tailored_skills = sort_skills(queryset)[:limit]
        data = OrderedDict({
            "vacancy_name": query,
            "number_of_vacancies": len(queryset),
            "rated_skills": tailored_skills,
        })
        return Response(data)
    class ExplicitPersonViewSet(viewsets.GenericViewSet):
        @extend_schema(request=explicit_poly_proxy,
                       responses=explicit_poly_proxy)
        def create(self, request, *args, **kwargs):
            return Response({})  # pragma: no cover

        @extend_schema(
            request=explicit_poly_proxy,
            responses=explicit_poly_proxy,
            parameters=[OpenApiParameter('id', int, OpenApiParameter.PATH)],
        )
        def partial_update(self, request, *args, **kwargs):
            return Response({})  # pragma: no cover
def id_or_type_parameter(name="id_or_type"):
    return OpenApiParameter(
        name,
        OpenApiTypes.STR,
        OpenApiParameter.PATH,
        required=True,
        description="A UUID or type string identifying the form.",
        examples=[
            OpenApiExample(
                "UUID",
                "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            ),
            OpenApiExample("Hacker Application Type", "hacker_application"),
        ])
Exemple #27
0
    def get_content_type_headers(self) -> list:
        if self.method not in ["POST", "PUT", "PATCH"]:
            return []

        return [
            OpenApiParameter(
                name="Content-Type",
                type=str,
                location=OpenApiParameter.HEADER,
                required=True,
                enum=["application/json"],
                description=_("Content type of the request body."),
            )
        ]
Exemple #28
0
class AccountStateViewSet(ViewSet):
    serializer_class = AccountStateSerializer

    # TODO(dmu) LOW: Are there better ways to generate correct documentation?
    @extend_schema(parameters=[OpenApiParameter('id', str, OpenApiParameter.PATH, description='Account number')])
    def retrieve(self, request, pk=None):
        # TODO(dmu) MEDIUM: There is a room for performance optimization use something like `?fields=` to
        #                   retrieval of unneeded fields using get_account_balance() and
        #                   get_account_balance_lock() directly.
        #                   Also see `drf-flex-fields` and `django-restql`.
        assert pk is not None

        blockchain = BlockchainBase.get_instance()
        serializer = self.serializer_class(blockchain.get_account_state(pk))
        return Response(serializer.data)
Exemple #29
0
class RegionGroupDetailView(views.APIView):
    @extend_schema(
        parameters=[
            OpenApiParameter("id", OpenApiTypes.INT, OpenApiParameter.PATH),
        ],
        responses=RegionGroupDetailSerializer(),
    )
    def get(self, request, id):
        """
        查询区域组下面的所有区域
        """
        region_group = RegionGroup.objects.annotate(
            capacity=Sum('regions__capacity')).get(id=id)
        serializer = RegionGroupDetailSerializer(region_group)
        return Response(serializer.data)
Exemple #30
0
class OAuthSourceViewSet(UsedByMixin, ModelViewSet):
    """Source Viewset"""

    queryset = OAuthSource.objects.all()
    serializer_class = OAuthSourceSerializer
    lookup_field = "slug"
    filterset_fields = [
        "name",
        "slug",
        "enabled",
        "authentication_flow",
        "enrollment_flow",
        "policy_engine_mode",
        "user_matching_mode",
        "provider_type",
        "request_token_url",
        "authorization_url",
        "access_token_url",
        "profile_url",
        "consumer_key",
        "additional_scopes",
    ]
    ordering = ["name"]

    @extend_schema(
        responses={200: SourceTypeSerializer(many=True)},
        parameters=[
            OpenApiParameter(
                name="name",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.STR,
            )
        ],
    )
    @action(detail=False, pagination_class=None, filter_backends=[])
    def source_types(self, request: Request) -> Response:
        """Get all creatable source types. If ?name is set, only returns the type for <name>.
        If <name> isn't found, returns the default type."""
        data = []
        if "name" in request.query_params:
            source_type = MANAGER.find_type(request.query_params.get("name"))
            if source_type.__class__ != SourceType:
                data.append(SourceTypeSerializer(source_type).data)
        else:
            for source_type in MANAGER.get():
                data.append(SourceTypeSerializer(source_type).data)
        return Response(data)