ensure all viewsets have filter and search and add tests (#2946)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
b0af062d74
commit
80c1dbdfbb
|
@ -0,0 +1,29 @@
|
|||
"""authentik API Modelviewset tests"""
|
||||
from typing import Callable
|
||||
|
||||
from django.test import TestCase
|
||||
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||
|
||||
from authentik.api.v3.urls import router
|
||||
|
||||
|
||||
class TestModelViewSets(TestCase):
|
||||
"""Test Viewset"""
|
||||
|
||||
|
||||
def viewset_tester_factory(test_viewset: type[ModelViewSet]) -> Callable:
|
||||
"""Test Viewset"""
|
||||
|
||||
def tester(self: TestModelViewSets):
|
||||
self.assertIsNotNone(getattr(test_viewset, "search_fields", None))
|
||||
filterset_class = getattr(test_viewset, "filterset_class", None)
|
||||
if not filterset_class:
|
||||
self.assertIsNotNone(getattr(test_viewset, "filterset_fields", None))
|
||||
|
||||
return tester
|
||||
|
||||
|
||||
for _, viewset, _ in router.registry:
|
||||
if not issubclass(viewset, (ModelViewSet, ReadOnlyModelViewSet)):
|
||||
continue
|
||||
setattr(TestModelViewSets, f"test_viewset_{viewset.__name__}", viewset_tester_factory(viewset))
|
|
@ -89,6 +89,7 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
|
|||
"group",
|
||||
]
|
||||
lookup_field = "slug"
|
||||
filterset_fields = ["name", "slug"]
|
||||
ordering = ["name"]
|
||||
|
||||
def _filter_queryset_for_list(self, queryset: QuerySet) -> QuerySet:
|
||||
|
|
|
@ -66,6 +66,7 @@ class SourceViewSet(
|
|||
queryset = Source.objects.none()
|
||||
serializer_class = SourceSerializer
|
||||
lookup_field = "slug"
|
||||
search_fields = ["slug", "name"]
|
||||
|
||||
def get_queryset(self): # pragma: no cover
|
||||
return Source.objects.select_subclasses()
|
||||
|
|
|
@ -26,3 +26,4 @@ class NotificationWebhookMappingViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = NotificationWebhookMappingSerializer
|
||||
filterset_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -32,3 +32,4 @@ class NotificationRuleViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = NotificationRuleSerializer
|
||||
filterset_fields = ["name", "severity", "group__name"]
|
||||
ordering = ["name"]
|
||||
search_fields = ["name", "group__name"]
|
||||
|
|
|
@ -68,6 +68,7 @@ class NotificationTransportViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = NotificationTransport.objects.all()
|
||||
serializer_class = NotificationTransportSerializer
|
||||
filterset_fields = ["name", "mode", "webhook_url", "send_once"]
|
||||
search_fields = ["name", "mode", "webhook_url"]
|
||||
ordering = ["name"]
|
||||
|
||||
@permission_required("authentik_events.change_notificationtransport")
|
||||
|
|
|
@ -35,3 +35,4 @@ class FlowStageBindingViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = FlowStageBinding.objects.all()
|
||||
serializer_class = FlowStageBindingSerializer
|
||||
filterset_fields = "__all__"
|
||||
search_fields = ["stage__name"]
|
||||
|
|
|
@ -118,6 +118,7 @@ class DockerServiceConnectionViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = DockerServiceConnectionSerializer
|
||||
filterset_fields = ["name", "local", "url", "tls_verification", "tls_authentication"]
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class KubernetesServiceConnectionSerializer(ServiceConnectionSerializer):
|
||||
|
@ -152,3 +153,4 @@ class KubernetesServiceConnectionViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = KubernetesServiceConnectionSerializer
|
||||
filterset_fields = ["name", "local"]
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -21,3 +21,4 @@ class DummyPolicyViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = DummyPolicySerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -25,3 +25,4 @@ class EventMatcherPolicyViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = EventMatcherPolicySerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -21,3 +21,4 @@ class PasswordExpiryPolicyViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = PasswordExpiryPolicySerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -28,3 +28,4 @@ class ExpressionPolicyViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = ExpressionPolicySerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -20,4 +20,5 @@ class HaveIBeenPwendPolicyViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = HaveIBeenPwendPolicy.objects.all()
|
||||
serializer_class = HaveIBeenPwendPolicySerializer
|
||||
filterset_fields = "__all__"
|
||||
search_fields = ["name", "password_field"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -30,3 +30,4 @@ class PasswordPolicyViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = PasswordPolicySerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -26,6 +26,7 @@ class ReputationPolicyViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = ReputationPolicy.objects.all()
|
||||
serializer_class = ReputationPolicySerializer
|
||||
filterset_fields = "__all__"
|
||||
search_fields = ["name", "threshold"]
|
||||
ordering = ["name"]
|
||||
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ class LDAPProviderViewSet(UsedByMixin, ModelViewSet):
|
|||
"uid_start_number": ["iexact"],
|
||||
"gid_start_number": ["iexact"],
|
||||
}
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
||||
|
||||
|
@ -81,3 +82,5 @@ class LDAPOutpostConfigViewSet(ReadOnlyModelViewSet):
|
|||
queryset = LDAPProvider.objects.filter(application__isnull=False)
|
||||
serializer_class = LDAPOutpostConfigSerializer
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
filterset_fields = ["name"]
|
||||
|
|
|
@ -72,6 +72,7 @@ class OAuth2ProviderViewSet(UsedByMixin, ModelViewSet):
|
|||
"property_mappings",
|
||||
"issuer_mode",
|
||||
]
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
||||
@extend_schema(
|
||||
|
|
|
@ -39,3 +39,4 @@ class ScopeMappingViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = ScopeMappingSerializer
|
||||
filterset_class = ScopeMappingFilter
|
||||
ordering = ["scope_name", "name"]
|
||||
search_fields = ["name", "scope_name"]
|
||||
|
|
|
@ -103,6 +103,7 @@ class ProxyProviderViewSet(UsedByMixin, ModelViewSet):
|
|||
"redirect_uris": ["iexact"],
|
||||
"cookie_domain": ["iexact"],
|
||||
}
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
||||
|
||||
|
@ -166,3 +167,5 @@ class ProxyOutpostConfigViewSet(ReadOnlyModelViewSet):
|
|||
queryset = ProxyProvider.objects.filter(application__isnull=False)
|
||||
serializer_class = ProxyOutpostConfigSerializer
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
filterset_fields = ["name"]
|
||||
|
|
|
@ -99,6 +99,7 @@ class SAMLProviderViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = SAMLProviderSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
@extend_schema(
|
||||
responses={
|
||||
|
@ -216,4 +217,5 @@ class SAMLPropertyMappingViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = SAMLPropertyMapping.objects.all()
|
||||
serializer_class = SAMLPropertyMappingSerializer
|
||||
filterset_class = SAMLPropertyMappingFilter
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -91,6 +91,7 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
|
|||
"property_mappings",
|
||||
"property_mappings_group",
|
||||
]
|
||||
search_fields = ["name", "slug"]
|
||||
ordering = ["name"]
|
||||
|
||||
@extend_schema(
|
||||
|
@ -142,4 +143,5 @@ class LDAPPropertyMappingViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = LDAPPropertyMapping.objects.all()
|
||||
serializer_class = LDAPPropertyMappingSerializer
|
||||
filterset_class = LDAPPropertyMappingFilter
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -90,7 +90,6 @@ class OAuthSourceSerializer(SourceSerializer):
|
|||
if getattr(provider_type, url, None) is None:
|
||||
if url not in attrs:
|
||||
raise ValidationError(f"{url} is required for provider {provider_type.name}")
|
||||
print(attrs)
|
||||
return attrs
|
||||
|
||||
class Meta:
|
||||
|
@ -135,6 +134,7 @@ class OAuthSourceViewSet(UsedByMixin, ModelViewSet):
|
|||
"consumer_key",
|
||||
"additional_scopes",
|
||||
]
|
||||
search_fields = ["name", "slug"]
|
||||
ordering = ["name"]
|
||||
|
||||
@extend_schema(
|
||||
|
|
|
@ -26,6 +26,7 @@ class UserOAuthSourceConnectionViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = UserOAuthSourceConnection.objects.all()
|
||||
serializer_class = UserOAuthSourceConnectionSerializer
|
||||
filterset_fields = ["source__slug"]
|
||||
search_fields = ["source__slug"]
|
||||
permission_classes = [OwnerSuperuserPermissions]
|
||||
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
|
||||
ordering = ["source__slug"]
|
||||
|
|
|
@ -60,6 +60,7 @@ class PlexSourceViewSet(UsedByMixin, ModelViewSet):
|
|||
"client_id",
|
||||
"allow_friends",
|
||||
]
|
||||
search_fields = ["name", "slug"]
|
||||
ordering = ["name"]
|
||||
|
||||
@permission_required(None)
|
||||
|
|
|
@ -35,3 +35,4 @@ class PlexSourceConnectionViewSet(UsedByMixin, ModelViewSet):
|
|||
permission_classes = [OwnerSuperuserPermissions]
|
||||
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
|
||||
ordering = ["pk"]
|
||||
search_fields = ["source__slug"]
|
||||
|
|
|
@ -41,6 +41,7 @@ class SAMLSourceViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = SAMLSourceSerializer
|
||||
lookup_field = "slug"
|
||||
filterset_fields = "__all__"
|
||||
search_fields = ["name", "slug"]
|
||||
ordering = ["name"]
|
||||
|
||||
@extend_schema(responses={200: SAMLMetadataSerializer(many=False)})
|
||||
|
|
|
@ -51,6 +51,7 @@ class AuthenticatorDuoStageViewSet(UsedByMixin, ModelViewSet):
|
|||
"client_id",
|
||||
"api_hostname",
|
||||
]
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
||||
@extend_schema(
|
||||
|
|
|
@ -36,6 +36,7 @@ class AuthenticatorSMSStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = AuthenticatorSMSStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class SMSDeviceSerializer(ModelSerializer):
|
||||
|
|
|
@ -29,6 +29,7 @@ class AuthenticatorStaticStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = AuthenticatorStaticStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class StaticDeviceTokenSerializer(ModelSerializer):
|
||||
|
|
|
@ -29,6 +29,7 @@ class AuthenticatorTOTPStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = AuthenticatorTOTPStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class TOTPDeviceSerializer(ModelSerializer):
|
||||
|
|
|
@ -41,3 +41,4 @@ class AuthenticatorValidateStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = AuthenticatorValidateStageSerializer
|
||||
filterset_fields = ["name", "not_configured_action", "configuration_stages"]
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -33,6 +33,7 @@ class AuthenticateWebAuthnStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = AuthenticateWebAuthnStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class WebAuthnDeviceSerializer(ModelSerializer):
|
||||
|
|
|
@ -22,4 +22,5 @@ class CaptchaStageViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = CaptchaStage.objects.all()
|
||||
serializer_class = CaptchaStageSerializer
|
||||
filterset_fields = ["name", "public_key"]
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -28,6 +28,7 @@ class ConsentStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = ConsentStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class UserConsentSerializer(StageSerializer):
|
||||
|
@ -60,6 +61,7 @@ class UserConsentViewSet(
|
|||
OrderingFilter,
|
||||
SearchFilter,
|
||||
]
|
||||
search_fields = ["user__username"]
|
||||
|
||||
def get_queryset(self):
|
||||
user = self.request.user if self.request else get_anonymous_user()
|
||||
|
|
|
@ -22,3 +22,4 @@ class DenyStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = DenyStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -21,4 +21,5 @@ class DummyStageViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = DummyStage.objects.all()
|
||||
serializer_class = DummyStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -68,6 +68,7 @@ class EmailStageViewSet(UsedByMixin, ModelViewSet):
|
|||
"template",
|
||||
"activate_user_on_success",
|
||||
]
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
||||
@extend_schema(responses={200: TypeCreateSerializer(many=True)})
|
||||
|
|
|
@ -40,4 +40,5 @@ class IdentificationStageViewSet(UsedByMixin, ModelViewSet):
|
|||
"passwordless_flow",
|
||||
"show_source_labels",
|
||||
]
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -41,6 +41,7 @@ class InvitationStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = InvitationStageSerializer
|
||||
filterset_class = InvitationStageFilter
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class InvitationSerializer(ModelSerializer):
|
||||
|
|
|
@ -29,4 +29,5 @@ class PasswordStageViewSet(UsedByMixin, ModelViewSet):
|
|||
"configure_flow",
|
||||
"failed_attempts_before_cancel",
|
||||
]
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -29,6 +29,7 @@ class PromptStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = PromptStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class PromptSerializer(ModelSerializer):
|
||||
|
@ -59,3 +60,4 @@ class PromptViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = Prompt.objects.all().prefetch_related("promptstage_set")
|
||||
serializer_class = PromptSerializer
|
||||
filterset_fields = ["field_key", "label", "type", "placeholder"]
|
||||
search_fields = ["field_key", "label", "type", "placeholder"]
|
||||
|
|
|
@ -22,3 +22,4 @@ class UserDeleteStageViewSet(UsedByMixin, ModelViewSet):
|
|||
serializer_class = UserDeleteStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
ordering = ["name"]
|
||||
search_fields = ["name"]
|
||||
|
|
|
@ -23,4 +23,5 @@ class UserLoginStageViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = UserLoginStage.objects.all()
|
||||
serializer_class = UserLoginStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -21,4 +21,5 @@ class UserLogoutStageViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = UserLogoutStage.objects.all()
|
||||
serializer_class = UserLogoutStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -21,4 +21,5 @@ class UserWriteStageViewSet(UsedByMixin, ModelViewSet):
|
|||
queryset = UserWriteStage.objects.all()
|
||||
serializer_class = UserWriteStageSerializer
|
||||
filterset_fields = "__all__"
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
||||
|
|
16
schema.yml
16
schema.yml
|
@ -1601,6 +1601,10 @@ paths:
|
|||
operationId: core_applications_list
|
||||
description: Custom list method that checks Policy based access instead of guardian
|
||||
parameters:
|
||||
- in: query
|
||||
name: name
|
||||
schema:
|
||||
type: string
|
||||
- name: ordering
|
||||
required: false
|
||||
in: query
|
||||
|
@ -1625,6 +1629,10 @@ paths:
|
|||
description: A search term.
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: slug
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: superuser_full_list
|
||||
schema:
|
||||
|
@ -6114,6 +6122,10 @@ paths:
|
|||
operationId: outposts_ldap_list
|
||||
description: LDAPProvider Viewset
|
||||
parameters:
|
||||
- in: query
|
||||
name: name
|
||||
schema:
|
||||
type: string
|
||||
- name: ordering
|
||||
required: false
|
||||
in: query
|
||||
|
@ -6184,6 +6196,10 @@ paths:
|
|||
operationId: outposts_proxy_list
|
||||
description: ProxyProvider Viewset
|
||||
parameters:
|
||||
- in: query
|
||||
name: name
|
||||
schema:
|
||||
type: string
|
||||
- name: ordering
|
||||
required: false
|
||||
in: query
|
||||
|
|
Reference in New Issue