diff --git a/api/src/backend/api/filters.py b/api/src/backend/api/filters.py index 10edc304fd..92db0ddf90 100644 --- a/api/src/backend/api/filters.py +++ b/api/src/backend/api/filters.py @@ -1,5 +1,4 @@ from datetime import date, datetime, timedelta, timezone -from functools import lru_cache from dateutil.parser import parse from django.conf import settings @@ -67,19 +66,8 @@ from api.uuid_utils import ( uuid7_range, uuid7_start, ) +from api.provider_types import get_provider_type_choices from api.v1.serializers import TaskBase -from prowler.providers.common.provider import Provider as SDKProvider - - -@lru_cache(maxsize=1) -def get_provider_type_choices(): - """Provider-type filter choices driven by the SDK's available providers - instead of a static enum, so filtering covers external providers too. - - Cached because the installed providers are fixed for the process lifetime - and provider-type filters live on hot list endpoints. - """ - return [(name, name) for name in SDKProvider.get_available_providers()] class CustomDjangoFilterBackend(DjangoFilterBackend): diff --git a/api/src/backend/api/provider_types.py b/api/src/backend/api/provider_types.py new file mode 100644 index 0000000000..ce909d59d6 --- /dev/null +++ b/api/src/backend/api/provider_types.py @@ -0,0 +1,15 @@ +from functools import lru_cache + +from prowler.providers.common.provider import Provider as SDKProvider + + +@lru_cache(maxsize=1) +def get_provider_type_choices(): + """Provider-type choices from the SDK's available providers, so they cover + external providers and not just a static enum. + + Cached for the process lifetime; hot-installing a provider needs + coordinated cache invalidation (tracked separately) to show up here without + a restart. Shared by the filters and the provider serializer. + """ + return [(name, name) for name in SDKProvider.get_available_providers()] diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index 03c4a99e7e..2a4e1cad94 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -71,9 +71,9 @@ from api.v1.serializer_utils.lighthouse import ( OpenAICredentialsSerializer, ) from api.v1.serializer_utils.processors import ProcessorConfigField +from api.provider_types import get_provider_type_choices from api.v1.serializer_utils.providers import ProviderSecretField from prowler.lib.mutelist.mutelist import Mutelist -from prowler.providers.common.provider import Provider as SDKProvider # Base @@ -855,12 +855,9 @@ class ProviderGroupMembershipSerializer(RLSSerializer, BaseWriteSerializer): # Providers class ProviderEnumSerializerField(serializers.ChoiceField): def __init__(self, **kwargs): - # The SDK is the source of truth for which providers exist, so the - # accepted values track the installed providers (built-in or external) - # instead of a static enum. - kwargs["choices"] = [ - (name, name) for name in SDKProvider.get_available_providers() - ] + # Accepted values track the SDK's installed providers (built-in or + # external), shared with the filters via one cached source. + kwargs["choices"] = get_provider_type_choices() super().__init__(**kwargs)