authentik.providers.rac.models

RAC Models

  1"""RAC Models"""
  2
  3from typing import Any
  4from uuid import uuid4
  5
  6from deepmerge import always_merger
  7from django.db import models
  8from django.db.models import QuerySet
  9from django.http import HttpRequest
 10from django.templatetags.static import static
 11from django.utils.translation import gettext as _
 12from rest_framework.serializers import Serializer
 13from structlog.stdlib import get_logger
 14
 15from authentik.core.expression.exceptions import PropertyMappingExpressionException
 16from authentik.core.models import ExpiringModel, PropertyMapping, Provider, User, default_token_key
 17from authentik.events.models import Event, EventAction
 18from authentik.lib.models import InternallyManagedMixin, SerializerModel
 19from authentik.lib.utils.time import timedelta_string_validator
 20from authentik.outposts.models import OutpostModel
 21from authentik.policies.models import PolicyBindingModel
 22
 23LOGGER = get_logger()
 24
 25
 26class Protocols(models.TextChoices):
 27    """Supported protocols"""
 28
 29    RDP = "rdp"
 30    VNC = "vnc"
 31    SSH = "ssh"
 32
 33
 34class AuthenticationMode(models.TextChoices):
 35    """Authentication modes"""
 36
 37    STATIC = "static"
 38    PROMPT = "prompt"
 39
 40
 41class RACProvider(OutpostModel, Provider):
 42    """Remotely access computers/servers via RDP/SSH/VNC."""
 43
 44    settings = models.JSONField(default=dict)
 45    auth_mode = models.TextField(
 46        choices=AuthenticationMode.choices, default=AuthenticationMode.PROMPT
 47    )
 48    connection_expiry = models.TextField(
 49        default="hours=8",
 50        validators=[timedelta_string_validator],
 51        help_text=_(
 52            "Determines how long a session lasts. Default of 0 means "
 53            "that the sessions lasts until the browser is closed. "
 54            "(Format: hours=-1;minutes=-2;seconds=-3)"
 55        ),
 56    )
 57    delete_token_on_disconnect = models.BooleanField(
 58        default=False,
 59        help_text=_("When set to true, connection tokens will be deleted upon disconnect."),
 60    )
 61
 62    @property
 63    def launch_url(self) -> str | None:
 64        """URL to this provider and initiate authorization for the user.
 65        Can return None for providers that are not URL-based"""
 66        return "goauthentik.io://providers/rac/launch"
 67
 68    @property
 69    def icon_url(self) -> str | None:
 70        return static("authentik/sources/rac.svg")
 71
 72    @property
 73    def component(self) -> str:
 74        return "ak-provider-rac-form"
 75
 76    @property
 77    def serializer(self) -> type[Serializer]:
 78        from authentik.providers.rac.api.providers import RACProviderSerializer
 79
 80        return RACProviderSerializer
 81
 82    class Meta:
 83        verbose_name = _("RAC Provider")
 84        verbose_name_plural = _("RAC Providers")
 85
 86
 87class Endpoint(SerializerModel, PolicyBindingModel):
 88    """Remote-accessible endpoint"""
 89
 90    name = models.TextField()
 91    host = models.TextField()
 92    protocol = models.TextField(choices=Protocols.choices)
 93    settings = models.JSONField(default=dict)
 94    auth_mode = models.TextField(choices=AuthenticationMode.choices)
 95    provider = models.ForeignKey("RACProvider", on_delete=models.CASCADE)
 96    maximum_connections = models.IntegerField(default=1)
 97
 98    property_mappings = models.ManyToManyField(
 99        "authentik_core.PropertyMapping", default=None, blank=True
100    )
101
102    @property
103    def serializer(self) -> type[Serializer]:
104        from authentik.providers.rac.api.endpoints import EndpointSerializer
105
106        return EndpointSerializer
107
108    def __str__(self):
109        return f"RAC Endpoint {self.name}"
110
111    class Meta:
112        verbose_name = _("RAC Endpoint")
113        verbose_name_plural = _("RAC Endpoints")
114
115
116class RACPropertyMapping(PropertyMapping):
117    """Configure settings for remote access endpoints."""
118
119    static_settings = models.JSONField(default=dict)
120
121    def evaluate(self, user: User | None, request: HttpRequest | None, **kwargs) -> Any:
122        """Evaluate `self.expression` using `**kwargs` as Context."""
123        settings = {}
124        for key, value in self.static_settings.items():
125            if value and value != "":
126                settings[key] = value
127        if self.expression != "":
128            always_merger.merge(settings, super().evaluate(user, request, **kwargs))
129        return settings
130
131    @property
132    def component(self) -> str:
133        return "ak-property-mapping-provider-rac-form"
134
135    @property
136    def serializer(self) -> type[Serializer]:
137        from authentik.providers.rac.api.property_mappings import (
138            RACPropertyMappingSerializer,
139        )
140
141        return RACPropertyMappingSerializer
142
143    class Meta:
144        verbose_name = _("RAC Provider Property Mapping")
145        verbose_name_plural = _("RAC Provider Property Mappings")
146
147
148class ConnectionToken(InternallyManagedMixin, ExpiringModel):
149    """Token for a single connection to a specified endpoint"""
150
151    connection_token_uuid = models.UUIDField(default=uuid4, primary_key=True)
152    provider = models.ForeignKey(RACProvider, on_delete=models.CASCADE)
153    endpoint = models.ForeignKey(Endpoint, on_delete=models.CASCADE)
154    token = models.TextField(default=default_token_key)
155    settings = models.JSONField(default=dict)
156    session = models.ForeignKey("authentik_core.AuthenticatedSession", on_delete=models.CASCADE)
157
158    def get_settings(self) -> dict:
159        """Get settings"""
160        default_settings = {}
161        if ":" in self.endpoint.host:
162            host, _, port = self.endpoint.host.partition(":")
163            default_settings["hostname"] = host
164            default_settings["port"] = str(port)
165        else:
166            default_settings["hostname"] = self.endpoint.host
167        if self.endpoint.protocol == Protocols.RDP:
168            default_settings["resize-method"] = "display-update"
169        default_settings["client-name"] = f"authentik - {self.session.user}"
170        settings = {}
171        always_merger.merge(settings, default_settings)
172        always_merger.merge(settings, self.endpoint.provider.settings)
173        always_merger.merge(settings, self.endpoint.settings)
174
175        def mapping_evaluator(mappings: QuerySet):
176            for mapping in mappings:
177                mapping: RACPropertyMapping
178                try:
179                    mapping_settings = mapping.evaluate(
180                        self.session.user, None, endpoint=self.endpoint, provider=self.provider
181                    )
182                    always_merger.merge(settings, mapping_settings)
183                except PropertyMappingExpressionException as exc:
184                    Event.new(
185                        EventAction.CONFIGURATION_ERROR,
186                        message=f"Failed to evaluate property-mapping: '{mapping.name}'",
187                        provider=self.provider,
188                        mapping=mapping,
189                    ).set_user(self.session.user).save()
190                    LOGGER.warning("Failed to evaluate property mapping", exc=exc)
191
192        mapping_evaluator(
193            RACPropertyMapping.objects.filter(provider__in=[self.provider]).order_by("name")
194        )
195        mapping_evaluator(
196            RACPropertyMapping.objects.filter(endpoint__in=[self.endpoint]).order_by("name")
197        )
198        always_merger.merge(settings, self.settings)
199
200        settings["drive-path"] = f"/tmp/connection/{self.token}"  # nosec
201        settings["create-drive-path"] = "true"
202        # Ensure all values of the settings dict are strings
203        for key, value in settings.items():
204            if isinstance(value, str):
205                continue
206            # Special case for bools
207            if isinstance(value, bool):
208                settings[key] = str(value).lower()
209                continue
210            settings[key] = str(value)
211        return settings
212
213    def __str__(self):
214        return f"RAC Connection token {self.session_id} to {self.provider_id}/{self.endpoint_id}"
215
216    class Meta:
217        verbose_name = _("RAC Connection token")
218        verbose_name_plural = _("RAC Connection tokens")
219        indexes = ExpiringModel.Meta.indexes
LOGGER = <BoundLoggerLazyProxy(logger=None, wrapper_class=None, processors=None, context_class=None, initial_values={}, logger_factory_args=())>
class Protocols(django.db.models.enums.TextChoices):
27class Protocols(models.TextChoices):
28    """Supported protocols"""
29
30    RDP = "rdp"
31    VNC = "vnc"
32    SSH = "ssh"

Supported protocols

class AuthenticationMode(django.db.models.enums.TextChoices):
35class AuthenticationMode(models.TextChoices):
36    """Authentication modes"""
37
38    STATIC = "static"
39    PROMPT = "prompt"

Authentication modes

42class RACProvider(OutpostModel, Provider):
43    """Remotely access computers/servers via RDP/SSH/VNC."""
44
45    settings = models.JSONField(default=dict)
46    auth_mode = models.TextField(
47        choices=AuthenticationMode.choices, default=AuthenticationMode.PROMPT
48    )
49    connection_expiry = models.TextField(
50        default="hours=8",
51        validators=[timedelta_string_validator],
52        help_text=_(
53            "Determines how long a session lasts. Default of 0 means "
54            "that the sessions lasts until the browser is closed. "
55            "(Format: hours=-1;minutes=-2;seconds=-3)"
56        ),
57    )
58    delete_token_on_disconnect = models.BooleanField(
59        default=False,
60        help_text=_("When set to true, connection tokens will be deleted upon disconnect."),
61    )
62
63    @property
64    def launch_url(self) -> str | None:
65        """URL to this provider and initiate authorization for the user.
66        Can return None for providers that are not URL-based"""
67        return "goauthentik.io://providers/rac/launch"
68
69    @property
70    def icon_url(self) -> str | None:
71        return static("authentik/sources/rac.svg")
72
73    @property
74    def component(self) -> str:
75        return "ak-provider-rac-form"
76
77    @property
78    def serializer(self) -> type[Serializer]:
79        from authentik.providers.rac.api.providers import RACProviderSerializer
80
81        return RACProviderSerializer
82
83    class Meta:
84        verbose_name = _("RAC Provider")
85        verbose_name_plural = _("RAC Providers")

Remotely access computers/servers via RDP/SSH/VNC.

def settings(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def auth_mode(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def connection_expiry(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def delete_token_on_disconnect(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

launch_url: str | None
63    @property
64    def launch_url(self) -> str | None:
65        """URL to this provider and initiate authorization for the user.
66        Can return None for providers that are not URL-based"""
67        return "goauthentik.io://providers/rac/launch"

URL to this provider and initiate authorization for the user. Can return None for providers that are not URL-based

icon_url: str | None
69    @property
70    def icon_url(self) -> str | None:
71        return static("authentik/sources/rac.svg")
component: str
73    @property
74    def component(self) -> str:
75        return "ak-provider-rac-form"

Return component used to edit this object

serializer: type[rest_framework.serializers.Serializer]
77    @property
78    def serializer(self) -> type[Serializer]:
79        from authentik.providers.rac.api.providers import RACProviderSerializer
80
81        return RACProviderSerializer

Get serializer for this model

def get_auth_mode_display(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

provider_ptr_id
provider_ptr

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.

endpoint_set

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.

connectiontoken_set

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.

class RACProvider.DoesNotExist(authentik.core.models.Provider.DoesNotExist):

The requested object does not exist

class RACProvider.MultipleObjectsReturned(authentik.core.models.Provider.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.

 88class Endpoint(SerializerModel, PolicyBindingModel):
 89    """Remote-accessible endpoint"""
 90
 91    name = models.TextField()
 92    host = models.TextField()
 93    protocol = models.TextField(choices=Protocols.choices)
 94    settings = models.JSONField(default=dict)
 95    auth_mode = models.TextField(choices=AuthenticationMode.choices)
 96    provider = models.ForeignKey("RACProvider", on_delete=models.CASCADE)
 97    maximum_connections = models.IntegerField(default=1)
 98
 99    property_mappings = models.ManyToManyField(
100        "authentik_core.PropertyMapping", default=None, blank=True
101    )
102
103    @property
104    def serializer(self) -> type[Serializer]:
105        from authentik.providers.rac.api.endpoints import EndpointSerializer
106
107        return EndpointSerializer
108
109    def __str__(self):
110        return f"RAC Endpoint {self.name}"
111
112    class Meta:
113        verbose_name = _("RAC Endpoint")
114        verbose_name_plural = _("RAC Endpoints")

Remote-accessible endpoint

def name(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def host(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def protocol(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def settings(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def auth_mode(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

provider

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.

def maximum_connections(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

property_mappings

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.

serializer: type[rest_framework.serializers.Serializer]
103    @property
104    def serializer(self) -> type[Serializer]:
105        from authentik.providers.rac.api.endpoints import EndpointSerializer
106
107        return EndpointSerializer

Get serializer for this model

def get_protocol_display(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_auth_mode_display(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

provider_id
policybindingmodel_ptr_id
policybindingmodel_ptr

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.

connectiontoken_set

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.

The requested object does not exist

The query returned multiple objects when only one was expected.

class RACPropertyMapping(authentik.core.models.PropertyMapping):
117class RACPropertyMapping(PropertyMapping):
118    """Configure settings for remote access endpoints."""
119
120    static_settings = models.JSONField(default=dict)
121
122    def evaluate(self, user: User | None, request: HttpRequest | None, **kwargs) -> Any:
123        """Evaluate `self.expression` using `**kwargs` as Context."""
124        settings = {}
125        for key, value in self.static_settings.items():
126            if value and value != "":
127                settings[key] = value
128        if self.expression != "":
129            always_merger.merge(settings, super().evaluate(user, request, **kwargs))
130        return settings
131
132    @property
133    def component(self) -> str:
134        return "ak-property-mapping-provider-rac-form"
135
136    @property
137    def serializer(self) -> type[Serializer]:
138        from authentik.providers.rac.api.property_mappings import (
139            RACPropertyMappingSerializer,
140        )
141
142        return RACPropertyMappingSerializer
143
144    class Meta:
145        verbose_name = _("RAC Provider Property Mapping")
146        verbose_name_plural = _("RAC Provider Property Mappings")

Configure settings for remote access endpoints.

def static_settings(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def evaluate( self, user: authentik.core.models.User | None, request: django.http.request.HttpRequest | None, **kwargs) -> Any:
122    def evaluate(self, user: User | None, request: HttpRequest | None, **kwargs) -> Any:
123        """Evaluate `self.expression` using `**kwargs` as Context."""
124        settings = {}
125        for key, value in self.static_settings.items():
126            if value and value != "":
127                settings[key] = value
128        if self.expression != "":
129            always_merger.merge(settings, super().evaluate(user, request, **kwargs))
130        return settings

Evaluate self.expression using **kwargs as Context.

component: str
132    @property
133    def component(self) -> str:
134        return "ak-property-mapping-provider-rac-form"

Return component used to edit this object

serializer: type[rest_framework.serializers.Serializer]
136    @property
137    def serializer(self) -> type[Serializer]:
138        from authentik.providers.rac.api.property_mappings import (
139            RACPropertyMappingSerializer,
140        )
141
142        return RACPropertyMappingSerializer

Get serializer for this model

propertymapping_ptr_id
propertymapping_ptr

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.

class RACPropertyMapping.DoesNotExist(authentik.core.models.PropertyMapping.DoesNotExist):

The requested object does not exist

class RACPropertyMapping.MultipleObjectsReturned(authentik.core.models.PropertyMapping.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.

149class ConnectionToken(InternallyManagedMixin, ExpiringModel):
150    """Token for a single connection to a specified endpoint"""
151
152    connection_token_uuid = models.UUIDField(default=uuid4, primary_key=True)
153    provider = models.ForeignKey(RACProvider, on_delete=models.CASCADE)
154    endpoint = models.ForeignKey(Endpoint, on_delete=models.CASCADE)
155    token = models.TextField(default=default_token_key)
156    settings = models.JSONField(default=dict)
157    session = models.ForeignKey("authentik_core.AuthenticatedSession", on_delete=models.CASCADE)
158
159    def get_settings(self) -> dict:
160        """Get settings"""
161        default_settings = {}
162        if ":" in self.endpoint.host:
163            host, _, port = self.endpoint.host.partition(":")
164            default_settings["hostname"] = host
165            default_settings["port"] = str(port)
166        else:
167            default_settings["hostname"] = self.endpoint.host
168        if self.endpoint.protocol == Protocols.RDP:
169            default_settings["resize-method"] = "display-update"
170        default_settings["client-name"] = f"authentik - {self.session.user}"
171        settings = {}
172        always_merger.merge(settings, default_settings)
173        always_merger.merge(settings, self.endpoint.provider.settings)
174        always_merger.merge(settings, self.endpoint.settings)
175
176        def mapping_evaluator(mappings: QuerySet):
177            for mapping in mappings:
178                mapping: RACPropertyMapping
179                try:
180                    mapping_settings = mapping.evaluate(
181                        self.session.user, None, endpoint=self.endpoint, provider=self.provider
182                    )
183                    always_merger.merge(settings, mapping_settings)
184                except PropertyMappingExpressionException as exc:
185                    Event.new(
186                        EventAction.CONFIGURATION_ERROR,
187                        message=f"Failed to evaluate property-mapping: '{mapping.name}'",
188                        provider=self.provider,
189                        mapping=mapping,
190                    ).set_user(self.session.user).save()
191                    LOGGER.warning("Failed to evaluate property mapping", exc=exc)
192
193        mapping_evaluator(
194            RACPropertyMapping.objects.filter(provider__in=[self.provider]).order_by("name")
195        )
196        mapping_evaluator(
197            RACPropertyMapping.objects.filter(endpoint__in=[self.endpoint]).order_by("name")
198        )
199        always_merger.merge(settings, self.settings)
200
201        settings["drive-path"] = f"/tmp/connection/{self.token}"  # nosec
202        settings["create-drive-path"] = "true"
203        # Ensure all values of the settings dict are strings
204        for key, value in settings.items():
205            if isinstance(value, str):
206                continue
207            # Special case for bools
208            if isinstance(value, bool):
209                settings[key] = str(value).lower()
210                continue
211            settings[key] = str(value)
212        return settings
213
214    def __str__(self):
215        return f"RAC Connection token {self.session_id} to {self.provider_id}/{self.endpoint_id}"
216
217    class Meta:
218        verbose_name = _("RAC Connection token")
219        verbose_name_plural = _("RAC Connection tokens")
220        indexes = ExpiringModel.Meta.indexes

Token for a single connection to a specified endpoint

def connection_token_uuid(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

provider

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.

endpoint

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.

def token(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def settings(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

session

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.

def get_settings(self) -> dict:
159    def get_settings(self) -> dict:
160        """Get settings"""
161        default_settings = {}
162        if ":" in self.endpoint.host:
163            host, _, port = self.endpoint.host.partition(":")
164            default_settings["hostname"] = host
165            default_settings["port"] = str(port)
166        else:
167            default_settings["hostname"] = self.endpoint.host
168        if self.endpoint.protocol == Protocols.RDP:
169            default_settings["resize-method"] = "display-update"
170        default_settings["client-name"] = f"authentik - {self.session.user}"
171        settings = {}
172        always_merger.merge(settings, default_settings)
173        always_merger.merge(settings, self.endpoint.provider.settings)
174        always_merger.merge(settings, self.endpoint.settings)
175
176        def mapping_evaluator(mappings: QuerySet):
177            for mapping in mappings:
178                mapping: RACPropertyMapping
179                try:
180                    mapping_settings = mapping.evaluate(
181                        self.session.user, None, endpoint=self.endpoint, provider=self.provider
182                    )
183                    always_merger.merge(settings, mapping_settings)
184                except PropertyMappingExpressionException as exc:
185                    Event.new(
186                        EventAction.CONFIGURATION_ERROR,
187                        message=f"Failed to evaluate property-mapping: '{mapping.name}'",
188                        provider=self.provider,
189                        mapping=mapping,
190                    ).set_user(self.session.user).save()
191                    LOGGER.warning("Failed to evaluate property mapping", exc=exc)
192
193        mapping_evaluator(
194            RACPropertyMapping.objects.filter(provider__in=[self.provider]).order_by("name")
195        )
196        mapping_evaluator(
197            RACPropertyMapping.objects.filter(endpoint__in=[self.endpoint]).order_by("name")
198        )
199        always_merger.merge(settings, self.settings)
200
201        settings["drive-path"] = f"/tmp/connection/{self.token}"  # nosec
202        settings["create-drive-path"] = "true"
203        # Ensure all values of the settings dict are strings
204        for key, value in settings.items():
205            if isinstance(value, str):
206                continue
207            # Special case for bools
208            if isinstance(value, bool):
209                settings[key] = str(value).lower()
210                continue
211            settings[key] = str(value)
212        return settings

Get settings

def expires(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def expiring(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

provider_id
endpoint_id
session_id
class ConnectionToken.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

class ConnectionToken.MultipleObjectsReturned(django.core.exceptions.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.