authentik.endpoints.models
1from datetime import UTC, datetime 2from typing import TYPE_CHECKING, Any 3from uuid import uuid4 4 5from django.core.cache import cache 6from django.db import models 7from django.db.models import OuterRef, Subquery 8from django.utils.timezone import now 9from django.utils.translation import gettext_lazy as _ 10from model_utils.managers import InheritanceManager 11from rest_framework.serializers import Serializer 12from structlog.stdlib import get_logger 13 14from authentik.core.models import AttributesMixin, ExpiringModel 15from authentik.flows.models import Stage 16from authentik.flows.stage import StageView 17from authentik.lib.merge import MERGE_LIST_UNIQUE 18from authentik.lib.models import InheritanceForeignKey, InternallyManagedMixin, SerializerModel 19from authentik.lib.utils.time import timedelta_from_string, timedelta_string_validator 20from authentik.policies.models import PolicyBinding, PolicyBindingModel 21from authentik.tasks.schedules.common import ScheduleSpec 22from authentik.tasks.schedules.models import ScheduledModel 23 24if TYPE_CHECKING: 25 from authentik.endpoints.controller import BaseController 26 27LOGGER = get_logger() 28DEVICE_FACTS_CACHE_TIMEOUT = 3600 29 30 31class Device(InternallyManagedMixin, ExpiringModel, AttributesMixin, PolicyBindingModel): 32 device_uuid = models.UUIDField(default=uuid4, primary_key=True) 33 34 name = models.TextField(unique=True) 35 identifier = models.TextField(unique=True) 36 connections = models.ManyToManyField("Connector", through="DeviceConnection") 37 access_group = models.ForeignKey( 38 "DeviceAccessGroup", null=True, on_delete=models.SET_DEFAULT, default=None 39 ) 40 41 @property 42 def cache_key_facts(self): 43 return f"goauthentik.io/endpoints/devices/{self.device_uuid}/facts" 44 45 @property 46 def cached_facts(self) -> DeviceFactSnapshot: 47 if cached := cache.get(self.cache_key_facts): 48 return cached 49 facts = self.facts 50 cache.set(self.cache_key_facts, facts, timeout=DEVICE_FACTS_CACHE_TIMEOUT) 51 return facts 52 53 @property 54 def facts(self) -> DeviceFactSnapshot: 55 data = {} 56 last_updated = datetime.fromtimestamp(0, UTC) 57 for snapshot_data, snapshort_created in DeviceFactSnapshot.objects.filter( 58 snapshot_id__in=Subquery( 59 DeviceFactSnapshot.objects.filter( 60 connection__connector=OuterRef("connection__connector"), connection__device=self 61 ) 62 .order_by("-created") 63 .values("snapshot_id")[:1] 64 ) 65 ).values_list("data", "created"): 66 MERGE_LIST_UNIQUE.merge(data, snapshot_data) 67 last_updated = max(last_updated, snapshort_created) 68 return DeviceFactSnapshot(data=data, created=last_updated) 69 70 def __str__(self): 71 return f"Device {self.name} {self.identifier} ({self.pk})" 72 73 class Meta(ExpiringModel.Meta): 74 verbose_name = _("Device") 75 verbose_name_plural = _("Devices") 76 77 78class DeviceUserBinding(PolicyBinding): 79 is_primary = models.BooleanField(default=False) 80 # Used for storing a reference to the connector if this user/group binding was created 81 # by a connector and not manually 82 connector = models.ForeignKey("Connector", on_delete=models.CASCADE, null=True) 83 84 class Meta(PolicyBinding.Meta): 85 verbose_name = _("Device User binding") 86 verbose_name_plural = _("Device User bindings") 87 88 89class DeviceConnection(InternallyManagedMixin, SerializerModel): 90 device_connection_uuid = models.UUIDField(default=uuid4, primary_key=True) 91 device = models.ForeignKey("Device", on_delete=models.CASCADE) 92 connector = models.ForeignKey("Connector", on_delete=models.CASCADE) 93 94 def create_snapshot(self, data: dict[str, Any]): 95 expires = now() + timedelta_from_string(self.connector.snapshot_expiry) 96 # If this is the first snapshot for this connection, purge the cache 97 if not DeviceFactSnapshot.objects.filter(connection=self).exists(): 98 LOGGER.debug("Purging facts cache for device", device=self.device) 99 cache.delete(self.device.cache_key_facts) 100 return DeviceFactSnapshot.objects.create( 101 connection=self, 102 data=data, 103 expiring=True, 104 expires=expires, 105 ) 106 107 @property 108 def serializer(self) -> type[Serializer]: 109 from authentik.endpoints.api.device_connections import DeviceConnectionSerializer 110 111 return DeviceConnectionSerializer 112 113 class Meta: 114 verbose_name = _("Device connection") 115 verbose_name_plural = _("Device connections") 116 117 118class DeviceFactSnapshot(InternallyManagedMixin, ExpiringModel, SerializerModel): 119 snapshot_id = models.UUIDField(primary_key=True, default=uuid4) 120 connection = models.ForeignKey(DeviceConnection, on_delete=models.CASCADE) 121 data = models.JSONField(default=dict) 122 created = models.DateTimeField(auto_now_add=True) 123 124 def __str__(self): 125 return f"Device fact snapshot {self.snapshot_id} from {self.created}" 126 127 @property 128 def serializer(self) -> type[Serializer]: 129 from authentik.endpoints.api.device_fact_snapshots import DeviceFactSnapshotSerializer 130 131 return DeviceFactSnapshotSerializer 132 133 class Meta(ExpiringModel.Meta): 134 verbose_name = _("Device fact snapshot") 135 verbose_name_plural = _("Device fact snapshots") 136 137 138class Connector(ScheduledModel, SerializerModel): 139 connector_uuid = models.UUIDField(default=uuid4, primary_key=True) 140 141 name = models.TextField() 142 enabled = models.BooleanField(default=True) 143 144 snapshot_expiry = models.TextField( 145 default="hours=24", 146 validators=[timedelta_string_validator], 147 ) 148 149 objects = InheritanceManager() 150 151 @property 152 def stage(self) -> type[StageView] | None: 153 return None 154 155 @property 156 def component(self) -> str: 157 raise NotImplementedError 158 159 @property 160 def controller(self) -> type[BaseController[Connector]]: 161 raise NotImplementedError 162 163 @property 164 def schedule_specs(self) -> list[ScheduleSpec]: 165 from authentik.endpoints.controller import Capabilities 166 from authentik.endpoints.tasks import endpoints_sync 167 168 if Capabilities.ENROLL_AUTOMATIC_API not in self.controller(self).capabilities(): 169 return [] 170 return [ 171 ScheduleSpec( 172 actor=endpoints_sync, 173 uid=self.name, 174 args=(self.pk,), 175 crontab="3-59/15 * * * *", 176 send_on_save=True, 177 ), 178 ] 179 180 181class DeviceAccessGroup(AttributesMixin, SerializerModel, PolicyBindingModel): 182 183 name = models.TextField(unique=True) 184 185 @property 186 def serializer(self) -> type[Serializer]: 187 from authentik.endpoints.api.device_access_group import DeviceAccessGroupSerializer 188 189 return DeviceAccessGroupSerializer 190 191 class Meta: 192 verbose_name = _("Device access group") 193 verbose_name_plural = _("Device access groups") 194 195 196class StageMode(models.TextChoices): 197 """Modes the Stage can operate in""" 198 199 OPTIONAL = "optional" 200 REQUIRED = "required" 201 202 203class EndpointStage(Stage): 204 """Stage which associates the currently used device with the current session.""" 205 206 connector = InheritanceForeignKey(Connector, on_delete=models.CASCADE) 207 208 mode = models.TextField(choices=StageMode.choices, default=StageMode.OPTIONAL) 209 210 @property 211 def view(self) -> type[StageView]: 212 from authentik.endpoints.stage import EndpointStageView 213 214 return EndpointStageView 215 216 @property 217 def serializer(self) -> type[Serializer]: 218 from authentik.endpoints.api.stages import EndpointStageSerializer 219 220 return EndpointStageSerializer 221 222 @property 223 def component(self) -> str: 224 return "ak-endpoints-stage-form" 225 226 class Meta(PolicyBinding.Meta): 227 verbose_name = _("Endpoint Stage") 228 verbose_name_plural = _("Endpoint Stages")
32class Device(InternallyManagedMixin, ExpiringModel, AttributesMixin, PolicyBindingModel): 33 device_uuid = models.UUIDField(default=uuid4, primary_key=True) 34 35 name = models.TextField(unique=True) 36 identifier = models.TextField(unique=True) 37 connections = models.ManyToManyField("Connector", through="DeviceConnection") 38 access_group = models.ForeignKey( 39 "DeviceAccessGroup", null=True, on_delete=models.SET_DEFAULT, default=None 40 ) 41 42 @property 43 def cache_key_facts(self): 44 return f"goauthentik.io/endpoints/devices/{self.device_uuid}/facts" 45 46 @property 47 def cached_facts(self) -> DeviceFactSnapshot: 48 if cached := cache.get(self.cache_key_facts): 49 return cached 50 facts = self.facts 51 cache.set(self.cache_key_facts, facts, timeout=DEVICE_FACTS_CACHE_TIMEOUT) 52 return facts 53 54 @property 55 def facts(self) -> DeviceFactSnapshot: 56 data = {} 57 last_updated = datetime.fromtimestamp(0, UTC) 58 for snapshot_data, snapshort_created in DeviceFactSnapshot.objects.filter( 59 snapshot_id__in=Subquery( 60 DeviceFactSnapshot.objects.filter( 61 connection__connector=OuterRef("connection__connector"), connection__device=self 62 ) 63 .order_by("-created") 64 .values("snapshot_id")[:1] 65 ) 66 ).values_list("data", "created"): 67 MERGE_LIST_UNIQUE.merge(data, snapshot_data) 68 last_updated = max(last_updated, snapshort_created) 69 return DeviceFactSnapshot(data=data, created=last_updated) 70 71 def __str__(self): 72 return f"Device {self.name} {self.identifier} ({self.pk})" 73 74 class Meta(ExpiringModel.Meta): 75 verbose_name = _("Device") 76 verbose_name_plural = _("Devices")
Device(pbm_uuid, policy_engine_mode, policybindingmodel_ptr, attributes, expires, expiring, device_uuid, name, identifier, access_group)
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.
In the example::
class Pizza(Model):
toppings = ManyToManyField(Topping, related_name='pizzas')
Pizza.toppings and Topping.pizzas are ManyToManyDescriptor
instances.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
54 @property 55 def facts(self) -> DeviceFactSnapshot: 56 data = {} 57 last_updated = datetime.fromtimestamp(0, UTC) 58 for snapshot_data, snapshort_created in DeviceFactSnapshot.objects.filter( 59 snapshot_id__in=Subquery( 60 DeviceFactSnapshot.objects.filter( 61 connection__connector=OuterRef("connection__connector"), connection__device=self 62 ) 63 .order_by("-created") 64 .values("snapshot_id")[:1] 65 ) 66 ).values_list("data", "created"): 67 MERGE_LIST_UNIQUE.merge(data, snapshot_data) 68 last_updated = max(last_updated, snapshort_created) 69 return DeviceFactSnapshot(data=data, created=last_updated)
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related object on the forward side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Restaurant.place is a ForwardOneToOneDescriptor instance.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Inherited Members
The requested object does not exist
The query returned multiple objects when only one was expected.
79class DeviceUserBinding(PolicyBinding): 80 is_primary = models.BooleanField(default=False) 81 # Used for storing a reference to the connector if this user/group binding was created 82 # by a connector and not manually 83 connector = models.ForeignKey("Connector", on_delete=models.CASCADE, null=True) 84 85 class Meta(PolicyBinding.Meta): 86 verbose_name = _("Device User binding") 87 verbose_name_plural = _("Device User bindings")
DeviceUserBinding(policy_binding_uuid, enabled, policy, group, user, target, negate, timeout, failure_result, order, policybinding_ptr, is_primary, connector)
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
Accessor to the related object on the forward side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Restaurant.place is a ForwardOneToOneDescriptor instance.
Accessor to the related object on the reverse side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Place.restaurant is a ReverseOneToOneDescriptor instance.
Inherited Members
The requested object does not exist
The query returned multiple objects when only one was expected.
90class DeviceConnection(InternallyManagedMixin, SerializerModel): 91 device_connection_uuid = models.UUIDField(default=uuid4, primary_key=True) 92 device = models.ForeignKey("Device", on_delete=models.CASCADE) 93 connector = models.ForeignKey("Connector", on_delete=models.CASCADE) 94 95 def create_snapshot(self, data: dict[str, Any]): 96 expires = now() + timedelta_from_string(self.connector.snapshot_expiry) 97 # If this is the first snapshot for this connection, purge the cache 98 if not DeviceFactSnapshot.objects.filter(connection=self).exists(): 99 LOGGER.debug("Purging facts cache for device", device=self.device) 100 cache.delete(self.device.cache_key_facts) 101 return DeviceFactSnapshot.objects.create( 102 connection=self, 103 data=data, 104 expiring=True, 105 expires=expires, 106 ) 107 108 @property 109 def serializer(self) -> type[Serializer]: 110 from authentik.endpoints.api.device_connections import DeviceConnectionSerializer 111 112 return DeviceConnectionSerializer 113 114 class Meta: 115 verbose_name = _("Device connection") 116 verbose_name_plural = _("Device connections")
DeviceConnection(device_connection_uuid, device, connector)
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
95 def create_snapshot(self, data: dict[str, Any]): 96 expires = now() + timedelta_from_string(self.connector.snapshot_expiry) 97 # If this is the first snapshot for this connection, purge the cache 98 if not DeviceFactSnapshot.objects.filter(connection=self).exists(): 99 LOGGER.debug("Purging facts cache for device", device=self.device) 100 cache.delete(self.device.cache_key_facts) 101 return DeviceFactSnapshot.objects.create( 102 connection=self, 103 data=data, 104 expiring=True, 105 expires=expires, 106 )
108 @property 109 def serializer(self) -> type[Serializer]: 110 from authentik.endpoints.api.device_connections import DeviceConnectionSerializer 111 112 return DeviceConnectionSerializer
Get serializer for this model
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related object on the reverse side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Place.restaurant is a ReverseOneToOneDescriptor instance.
Inherited Members
The requested object does not exist
The query returned multiple objects when only one was expected.
119class DeviceFactSnapshot(InternallyManagedMixin, ExpiringModel, SerializerModel): 120 snapshot_id = models.UUIDField(primary_key=True, default=uuid4) 121 connection = models.ForeignKey(DeviceConnection, on_delete=models.CASCADE) 122 data = models.JSONField(default=dict) 123 created = models.DateTimeField(auto_now_add=True) 124 125 def __str__(self): 126 return f"Device fact snapshot {self.snapshot_id} from {self.created}" 127 128 @property 129 def serializer(self) -> type[Serializer]: 130 from authentik.endpoints.api.device_fact_snapshots import DeviceFactSnapshotSerializer 131 132 return DeviceFactSnapshotSerializer 133 134 class Meta(ExpiringModel.Meta): 135 verbose_name = _("Device fact snapshot") 136 verbose_name_plural = _("Device fact snapshots")
DeviceFactSnapshot(expires, expiring, snapshot_id, connection, data, created)
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
128 @property 129 def serializer(self) -> type[Serializer]: 130 from authentik.endpoints.api.device_fact_snapshots import DeviceFactSnapshotSerializer 131 132 return DeviceFactSnapshotSerializer
Get serializer for this model
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Method descriptor with partial application of the given arguments and keywords.
Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.
Method descriptor with partial application of the given arguments and keywords.
Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.
Inherited Members
The requested object does not exist
The query returned multiple objects when only one was expected.
139class Connector(ScheduledModel, SerializerModel): 140 connector_uuid = models.UUIDField(default=uuid4, primary_key=True) 141 142 name = models.TextField() 143 enabled = models.BooleanField(default=True) 144 145 snapshot_expiry = models.TextField( 146 default="hours=24", 147 validators=[timedelta_string_validator], 148 ) 149 150 objects = InheritanceManager() 151 152 @property 153 def stage(self) -> type[StageView] | None: 154 return None 155 156 @property 157 def component(self) -> str: 158 raise NotImplementedError 159 160 @property 161 def controller(self) -> type[BaseController[Connector]]: 162 raise NotImplementedError 163 164 @property 165 def schedule_specs(self) -> list[ScheduleSpec]: 166 from authentik.endpoints.controller import Capabilities 167 from authentik.endpoints.tasks import endpoints_sync 168 169 if Capabilities.ENROLL_AUTOMATIC_API not in self.controller(self).capabilities(): 170 return [] 171 return [ 172 ScheduleSpec( 173 actor=endpoints_sync, 174 uid=self.name, 175 args=(self.pk,), 176 crontab="3-59/15 * * * *", 177 send_on_save=True, 178 ), 179 ]
Connector(connector_uuid, name, enabled, snapshot_expiry)
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
164 @property 165 def schedule_specs(self) -> list[ScheduleSpec]: 166 from authentik.endpoints.controller import Capabilities 167 from authentik.endpoints.tasks import endpoints_sync 168 169 if Capabilities.ENROLL_AUTOMATIC_API not in self.controller(self).capabilities(): 170 return [] 171 return [ 172 ScheduleSpec( 173 actor=endpoints_sync, 174 uid=self.name, 175 args=(self.pk,), 176 crontab="3-59/15 * * * *", 177 send_on_save=True, 178 ), 179 ]
Accessor to the related objects manager on the one-to-many relation created by GenericRelation.
In the example::
class Post(Model):
comments = GenericRelation(Comment)
post.comments is a ReverseGenericManyToOneDescriptor instance.
Accessor to the related objects manager on the one-to-many relation created by GenericRelation.
In the example::
class Post(Model):
comments = GenericRelation(Comment)
post.comments is a ReverseGenericManyToOneDescriptor instance.
Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.
In the example::
class Pizza(Model):
toppings = ManyToManyField(Topping, related_name='pizzas')
Pizza.toppings and Topping.pizzas are ManyToManyDescriptor
instances.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related object on the reverse side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Place.restaurant is a ReverseOneToOneDescriptor instance.
Accessor to the related object on the reverse side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Place.restaurant is a ReverseOneToOneDescriptor instance.
The requested object does not exist
The query returned multiple objects when only one was expected.
182class DeviceAccessGroup(AttributesMixin, SerializerModel, PolicyBindingModel): 183 184 name = models.TextField(unique=True) 185 186 @property 187 def serializer(self) -> type[Serializer]: 188 from authentik.endpoints.api.device_access_group import DeviceAccessGroupSerializer 189 190 return DeviceAccessGroupSerializer 191 192 class Meta: 193 verbose_name = _("Device access group") 194 verbose_name_plural = _("Device access groups")
DeviceAccessGroup(pbm_uuid, policy_engine_mode, policybindingmodel_ptr, attributes, name)
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
186 @property 187 def serializer(self) -> type[Serializer]: 188 from authentik.endpoints.api.device_access_group import DeviceAccessGroupSerializer 189 190 return DeviceAccessGroupSerializer
Get serializer for this model
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related object on the forward side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Restaurant.place is a ForwardOneToOneDescriptor instance.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Inherited Members
The requested object does not exist
The query returned multiple objects when only one was expected.
197class StageMode(models.TextChoices): 198 """Modes the Stage can operate in""" 199 200 OPTIONAL = "optional" 201 REQUIRED = "required"
Modes the Stage can operate in
204class EndpointStage(Stage): 205 """Stage which associates the currently used device with the current session.""" 206 207 connector = InheritanceForeignKey(Connector, on_delete=models.CASCADE) 208 209 mode = models.TextField(choices=StageMode.choices, default=StageMode.OPTIONAL) 210 211 @property 212 def view(self) -> type[StageView]: 213 from authentik.endpoints.stage import EndpointStageView 214 215 return EndpointStageView 216 217 @property 218 def serializer(self) -> type[Serializer]: 219 from authentik.endpoints.api.stages import EndpointStageSerializer 220 221 return EndpointStageSerializer 222 223 @property 224 def component(self) -> str: 225 return "ak-endpoints-stage-form" 226 227 class Meta(PolicyBinding.Meta): 228 verbose_name = _("Endpoint Stage") 229 verbose_name_plural = _("Endpoint Stages")
Stage which associates the currently used device with the current session.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
211 @property 212 def view(self) -> type[StageView]: 213 from authentik.endpoints.stage import EndpointStageView 214 215 return EndpointStageView
Return StageView class that implements logic for this stage
217 @property 218 def serializer(self) -> type[Serializer]: 219 from authentik.endpoints.api.stages import EndpointStageSerializer 220 221 return EndpointStageSerializer
Get serializer for this model
Method descriptor with partial application of the given arguments and keywords.
Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.
Accessor to the related object on the forward side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Restaurant.place is a ForwardOneToOneDescriptor instance.
Inherited Members
- authentik.flows.models.Stage
- stage_uuid
- name
- objects
- ui_user_settings
- is_in_memory
- flow_set
- flowstagebinding_set
- emailstage
- endpointstage
- invitationstage
- passwordstage
- promptstage
- authenticatorstaticstage
- authenticatorduostage
- authenticatoremailstage
- authenticatorsmsstage
- authenticatorwebauthnstage
- authenticatorvalidatestage
- captchastage
- identificationstage
- authenticatortotpstage
- consentstage
- denystage
- dummystage
- redirectstage
- userdeletestage
- userloginstage
- userlogoutstage
- userwritestage
- authenticatorendpointgdtcstage
- mutualtlsstage
- sourcestage
The requested object does not exist
The query returned multiple objects when only one was expected.