authentik.enterprise.lifecycle.utils
1from datetime import datetime 2from urllib import parse 3 4from django.contrib.contenttypes.models import ContentType 5from django.db.models import Model 6from django.urls import reverse 7from rest_framework.serializers import ChoiceField, Serializer, UUIDField 8 9from authentik.core.api.utils import ModelSerializer 10from authentik.core.models import Application, Group, User 11from authentik.rbac.models import Role 12 13 14def parse_content_type(value: str) -> dict: 15 app_label, model = value.split(".") 16 return {"app_label": app_label, "model": model} 17 18 19def model_choices() -> list[tuple[str, str]]: 20 return [ 21 ("authentik_core.application", "Application"), 22 ("authentik_core.group", "Group"), 23 ("authentik_rbac.role", "Role"), 24 ] 25 26 27def admin_link_for_model(model: Model) -> str: 28 if isinstance(model, Application): 29 url = f"/core/applications/{model.slug}" 30 elif isinstance(model, Group): 31 url = f"/identity/groups/{model.pk}" 32 elif isinstance(model, Role): 33 url = f"/identity/roles/{model.pk}" 34 else: 35 raise TypeError("Unsupported model") 36 return url + ";" + parse.quote('{"page":"page-lifecycle"}') 37 38 39def link_for_model(model: Model) -> str: 40 return f"{reverse("authentik_core:if-admin")}#{admin_link_for_model(model)}" 41 42 43def start_of_day(dt: datetime) -> datetime: 44 return dt.replace(hour=0, minute=0, second=0, microsecond=0) 45 46 47class ContentTypeField(ChoiceField): 48 def __init__(self, **kwargs): 49 super().__init__(choices=model_choices(), **kwargs) 50 51 def to_representation(self, content_type: ContentType) -> str: 52 return f"{content_type.app_label}.{content_type.model}" 53 54 def to_internal_value(self, data: str) -> ContentType: 55 return ContentType.objects.get(**parse_content_type(data)) 56 57 58class GenericForeignKeySerializer(Serializer): 59 content_type = ContentTypeField() 60 object_id = UUIDField() 61 62 63class ReviewerGroupSerializer(ModelSerializer): 64 class Meta: 65 model = Group 66 fields = [ 67 "pk", 68 "name", 69 ] 70 71 72class ReviewerUserSerializer(ModelSerializer): 73 class Meta: 74 model = User 75 fields = ["pk", "uuid", "username", "name"]
28def admin_link_for_model(model: Model) -> str: 29 if isinstance(model, Application): 30 url = f"/core/applications/{model.slug}" 31 elif isinstance(model, Group): 32 url = f"/identity/groups/{model.pk}" 33 elif isinstance(model, Role): 34 url = f"/identity/roles/{model.pk}" 35 else: 36 raise TypeError("Unsupported model") 37 return url + ";" + parse.quote('{"page":"page-lifecycle"}')
48class ContentTypeField(ChoiceField): 49 def __init__(self, **kwargs): 50 super().__init__(choices=model_choices(), **kwargs) 51 52 def to_representation(self, content_type: ContentType) -> str: 53 return f"{content_type.app_label}.{content_type.model}" 54 55 def to_internal_value(self, data: str) -> ContentType: 56 return ContentType.objects.get(**parse_content_type(data))
621 def __new__(cls, *args, **kwargs): 622 """ 623 When a field is instantiated, we store the arguments that were used, 624 so that we can present a helpful representation of the object. 625 """ 626 instance = super().__new__(cls) 627 instance._args = args 628 instance._kwargs = kwargs 629 return instance
When a field is instantiated, we store the arguments that were used, so that we can present a helpful representation of the object.
59class GenericForeignKeySerializer(Serializer): 60 content_type = ContentTypeField() 61 object_id = UUIDField()
The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.
Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.
In particular, if a data= argument is passed then:
.is_valid() - Available.
.initial_data - Available.
.validated_data - Only available after calling is_valid()
.errors - Only available after calling is_valid()
.data - Only available after calling is_valid()
If a data= argument is not passed then:
.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.
64class ReviewerGroupSerializer(ModelSerializer): 65 class Meta: 66 model = Group 67 fields = [ 68 "pk", 69 "name", 70 ]
A ModelSerializer is just a regular Serializer, except that:
- A set of default fields are automatically populated.
- A set of default validators are automatically populated.
- Default
.create()and.update()implementations are provided.
The process of automatically determining a set of serializer fields based on the model fields is reasonably complex, but you almost certainly don't need to dig into the implementation.
If the ModelSerializer class doesn't generate the set of fields that
you need you should either declare the extra/differing fields explicitly on
the serializer class, or simply use a Serializer class.
Inherited Members
73class ReviewerUserSerializer(ModelSerializer): 74 class Meta: 75 model = User 76 fields = ["pk", "uuid", "username", "name"]
A ModelSerializer is just a regular Serializer, except that:
- A set of default fields are automatically populated.
- A set of default validators are automatically populated.
- Default
.create()and.update()implementations are provided.
The process of automatically determining a set of serializer fields based on the model fields is reasonably complex, but you almost certainly don't need to dig into the implementation.
If the ModelSerializer class doesn't generate the set of fields that
you need you should either declare the extra/differing fields explicitly on
the serializer class, or simply use a Serializer class.