authentik.core.api.object_types
API Utilities
1"""API Utilities""" 2 3from drf_spectacular.utils import extend_schema 4from rest_framework.decorators import action 5from rest_framework.fields import ( 6 BooleanField, 7 CharField, 8) 9from rest_framework.request import Request 10from rest_framework.response import Response 11 12from authentik.core.api.utils import PassiveSerializer 13from authentik.lib.models import DeprecatedMixin 14from authentik.lib.utils.reflection import all_subclasses 15 16 17class TypeCreateSerializer(PassiveSerializer): 18 """Types of an object that can be created""" 19 20 name = CharField(required=True) 21 description = CharField(required=True) 22 component = CharField(required=True) 23 model_name = CharField(required=True) 24 25 icon_url = CharField(required=False) 26 requires_enterprise = BooleanField(default=False) 27 deprecated = BooleanField(default=False) 28 29 30class CreatableType: 31 """Class to inherit from to mark a model as creatable, even if the model itself is marked 32 as abstract""" 33 34 35class NonCreatableType: 36 """Class to inherit from to mark a model as non-creatable even if it is not abstract""" 37 38 39class TypesMixin: 40 """Mixin which adds an API endpoint to list all possible types that can be created""" 41 42 @extend_schema(responses={200: TypeCreateSerializer(many=True)}) 43 @action(detail=False, pagination_class=None, filter_backends=[]) 44 def types(self, request: Request, additional: list[dict] | None = None) -> Response: 45 """Get all creatable types""" 46 data = [] 47 for subclass in all_subclasses(self.queryset.model): 48 instance = None 49 if subclass._meta.abstract: 50 if not issubclass(subclass, CreatableType): 51 continue 52 # Circumvent the django protection for not being able to instantiate 53 # abstract models. We need a model instance to access .component 54 # and further down .icon_url 55 instance = subclass.__new__(subclass) 56 # Django re-sets abstract = False so we need to override that 57 instance.Meta.abstract = True 58 else: 59 if issubclass(subclass, NonCreatableType): 60 continue 61 instance = subclass() 62 try: 63 type_signature = { 64 "name": subclass._meta.verbose_name, 65 "description": subclass.__doc__, 66 "component": instance.component, 67 "model_name": subclass._meta.model_name, 68 "icon_url": getattr(instance, "icon_url", None), 69 "requires_enterprise": False, 70 "deprecated": isinstance(instance, DeprecatedMixin), 71 } 72 try: 73 from authentik.enterprise.apps import EnterpriseConfig 74 75 type_signature["requires_enterprise"] = isinstance( 76 subclass._meta.app_config, EnterpriseConfig 77 ) 78 except ModuleNotFoundError: 79 pass 80 81 data.append(type_signature) 82 except NotImplementedError: 83 continue 84 if additional: 85 data.extend(additional) 86 data = sorted(data, key=lambda x: x["name"]) 87 return Response(TypeCreateSerializer(data, many=True).data)
18class TypeCreateSerializer(PassiveSerializer): 19 """Types of an object that can be created""" 20 21 name = CharField(required=True) 22 description = CharField(required=True) 23 component = CharField(required=True) 24 model_name = CharField(required=True) 25 26 icon_url = CharField(required=False) 27 requires_enterprise = BooleanField(default=False) 28 deprecated = BooleanField(default=False)
Types of an object that can be created
Inherited Members
class
CreatableType:
31class CreatableType: 32 """Class to inherit from to mark a model as creatable, even if the model itself is marked 33 as abstract"""
Class to inherit from to mark a model as creatable, even if the model itself is marked as abstract
class
NonCreatableType:
36class NonCreatableType: 37 """Class to inherit from to mark a model as non-creatable even if it is not abstract"""
Class to inherit from to mark a model as non-creatable even if it is not abstract
class
TypesMixin:
40class TypesMixin: 41 """Mixin which adds an API endpoint to list all possible types that can be created""" 42 43 @extend_schema(responses={200: TypeCreateSerializer(many=True)}) 44 @action(detail=False, pagination_class=None, filter_backends=[]) 45 def types(self, request: Request, additional: list[dict] | None = None) -> Response: 46 """Get all creatable types""" 47 data = [] 48 for subclass in all_subclasses(self.queryset.model): 49 instance = None 50 if subclass._meta.abstract: 51 if not issubclass(subclass, CreatableType): 52 continue 53 # Circumvent the django protection for not being able to instantiate 54 # abstract models. We need a model instance to access .component 55 # and further down .icon_url 56 instance = subclass.__new__(subclass) 57 # Django re-sets abstract = False so we need to override that 58 instance.Meta.abstract = True 59 else: 60 if issubclass(subclass, NonCreatableType): 61 continue 62 instance = subclass() 63 try: 64 type_signature = { 65 "name": subclass._meta.verbose_name, 66 "description": subclass.__doc__, 67 "component": instance.component, 68 "model_name": subclass._meta.model_name, 69 "icon_url": getattr(instance, "icon_url", None), 70 "requires_enterprise": False, 71 "deprecated": isinstance(instance, DeprecatedMixin), 72 } 73 try: 74 from authentik.enterprise.apps import EnterpriseConfig 75 76 type_signature["requires_enterprise"] = isinstance( 77 subclass._meta.app_config, EnterpriseConfig 78 ) 79 except ModuleNotFoundError: 80 pass 81 82 data.append(type_signature) 83 except NotImplementedError: 84 continue 85 if additional: 86 data.extend(additional) 87 data = sorted(data, key=lambda x: x["name"]) 88 return Response(TypeCreateSerializer(data, many=True).data)
Mixin which adds an API endpoint to list all possible types that can be created
@extend_schema(responses={200: TypeCreateSerializer(many=True)})
@action(detail=False, pagination_class=None, filter_backends=[])
def
types( self, request: rest_framework.request.Request, additional: list[dict] | None = None) -> rest_framework.response.Response:
43 @extend_schema(responses={200: TypeCreateSerializer(many=True)}) 44 @action(detail=False, pagination_class=None, filter_backends=[]) 45 def types(self, request: Request, additional: list[dict] | None = None) -> Response: 46 """Get all creatable types""" 47 data = [] 48 for subclass in all_subclasses(self.queryset.model): 49 instance = None 50 if subclass._meta.abstract: 51 if not issubclass(subclass, CreatableType): 52 continue 53 # Circumvent the django protection for not being able to instantiate 54 # abstract models. We need a model instance to access .component 55 # and further down .icon_url 56 instance = subclass.__new__(subclass) 57 # Django re-sets abstract = False so we need to override that 58 instance.Meta.abstract = True 59 else: 60 if issubclass(subclass, NonCreatableType): 61 continue 62 instance = subclass() 63 try: 64 type_signature = { 65 "name": subclass._meta.verbose_name, 66 "description": subclass.__doc__, 67 "component": instance.component, 68 "model_name": subclass._meta.model_name, 69 "icon_url": getattr(instance, "icon_url", None), 70 "requires_enterprise": False, 71 "deprecated": isinstance(instance, DeprecatedMixin), 72 } 73 try: 74 from authentik.enterprise.apps import EnterpriseConfig 75 76 type_signature["requires_enterprise"] = isinstance( 77 subclass._meta.app_config, EnterpriseConfig 78 ) 79 except ModuleNotFoundError: 80 pass 81 82 data.append(type_signature) 83 except NotImplementedError: 84 continue 85 if additional: 86 data.extend(additional) 87 data = sorted(data, key=lambda x: x["name"]) 88 return Response(TypeCreateSerializer(data, many=True).data)
Get all creatable types