authentik.sources.telegram.models

Telegram source

  1"""Telegram source"""
  2
  3from typing import Any
  4from urllib.parse import urlencode
  5
  6from django.db import models
  7from django.http import HttpRequest
  8from django.templatetags.static import static
  9from django.urls import reverse
 10from django.utils.translation import gettext_lazy as _
 11from rest_framework.serializers import BaseSerializer, Serializer
 12
 13from authentik.core.models import (
 14    GroupSourceConnection,
 15    PropertyMapping,
 16    Source,
 17    UserSourceConnection,
 18)
 19from authentik.core.types import UILoginButton, UserSettingSerializer
 20from authentik.flows.challenge import RedirectChallenge
 21from authentik.flows.models import Flow
 22
 23
 24class TelegramSource(Source):
 25    """Log in with Telegram."""
 26
 27    bot_username = models.TextField(help_text=_("Telegram bot username"))
 28    bot_token = models.TextField(help_text=_("Telegram bot token"))
 29
 30    request_message_access = models.BooleanField(
 31        default=False, help_text=_("Request access to send messages from your bot.")
 32    )
 33
 34    pre_authentication_flow = models.ForeignKey(
 35        Flow,
 36        on_delete=models.CASCADE,
 37        help_text=_("Flow used before authentication."),
 38        related_name="telegram_source_pre_authentication",
 39    )
 40
 41    @property
 42    def component(self) -> str:
 43        return "ak-source-telegram-form"
 44
 45    @property
 46    def icon_url(self) -> str | None:
 47        icon = super().icon_url
 48        if not icon:
 49            icon = static("authentik/sources/telegram.svg")
 50        return icon
 51
 52    @property
 53    def serializer(self) -> type[BaseSerializer]:
 54        from authentik.sources.telegram.api.source import TelegramSourceSerializer
 55
 56        return TelegramSourceSerializer
 57
 58    def ui_login_button(self, request: HttpRequest) -> UILoginButton:
 59        return UILoginButton(
 60            challenge=RedirectChallenge(
 61                data={
 62                    "to": reverse(
 63                        "authentik_sources_telegram:start",
 64                        kwargs={"source_slug": self.slug},
 65                    ),
 66                }
 67            ),
 68            name=self.name,
 69            icon_url=self.icon_url,
 70            promoted=self.promoted,
 71        )
 72
 73    def ui_user_settings(self) -> UserSettingSerializer | None:
 74        return UserSettingSerializer(
 75            data={
 76                "title": self.name,
 77                "component": "ak-user-settings-source-telegram",
 78                "icon_url": self.icon_url,
 79                "configure_url": urlencode(
 80                    {
 81                        "bot_username": self.bot_username,
 82                        "request_message_access": str(self.request_message_access),
 83                    }
 84                ),
 85            }
 86        )
 87
 88    @property
 89    def property_mapping_type(self) -> type[PropertyMapping]:
 90        return TelegramSourcePropertyMapping
 91
 92    def get_base_user_properties(
 93        self, info: dict[str, Any] | None = None, **kwargs
 94    ) -> dict[str, Any | dict[str, Any]]:
 95        info = info or {}
 96        name = info.get("first_name", "")
 97        if "last_name" in info:
 98            name += " " + info["last_name"]
 99        return {
100            "username": info.get("username", None),
101            "email": None,
102            "name": name if name else None,
103        }
104
105    def get_base_group_properties(self, group_id: str, **kwargs):
106        return {
107            "name": group_id,
108        }
109
110    class Meta:
111        verbose_name = _("Telegram Source")
112        verbose_name_plural = _("Telegram Sources")
113
114
115class TelegramSourcePropertyMapping(PropertyMapping):
116    """Map Telegram properties to User or Group object attributes"""
117
118    @property
119    def component(self) -> str:
120        return "ak-property-mapping-source-telegram-form"
121
122    @property
123    def serializer(self) -> type[Serializer]:
124        from authentik.sources.telegram.api.property_mappings import (
125            TelegramSourcePropertyMappingSerializer,
126        )
127
128        return TelegramSourcePropertyMappingSerializer
129
130    class Meta:
131        verbose_name = _("Telegram Source Property Mapping")
132        verbose_name_plural = _("Telegram Source Property Mappings")
133
134
135class UserTelegramSourceConnection(UserSourceConnection):
136    """Connect user and Telegram source"""
137
138    @property
139    def serializer(self) -> type[Serializer]:
140        from authentik.sources.telegram.api.source_connection import (
141            UserTelegramSourceConnectionSerializer,
142        )
143
144        return UserTelegramSourceConnectionSerializer
145
146    class Meta:
147        verbose_name = _("User Telegram Source Connection")
148        verbose_name_plural = _("User Telegram Source Connections")
149
150
151class GroupTelegramSourceConnection(GroupSourceConnection):
152    """Group-source connection for Telegram"""
153
154    @property
155    def serializer(self) -> type[Serializer]:
156        from authentik.sources.telegram.api.source_connection import (
157            GroupTelegramSourceConnectionSerializer,
158        )
159
160        return GroupTelegramSourceConnectionSerializer
161
162    class Meta:
163        verbose_name = _("Group Telegram Source Connection")
164        verbose_name_plural = _("Group Telegram Source Connections")
class TelegramSource(authentik.core.models.Source):
 25class TelegramSource(Source):
 26    """Log in with Telegram."""
 27
 28    bot_username = models.TextField(help_text=_("Telegram bot username"))
 29    bot_token = models.TextField(help_text=_("Telegram bot token"))
 30
 31    request_message_access = models.BooleanField(
 32        default=False, help_text=_("Request access to send messages from your bot.")
 33    )
 34
 35    pre_authentication_flow = models.ForeignKey(
 36        Flow,
 37        on_delete=models.CASCADE,
 38        help_text=_("Flow used before authentication."),
 39        related_name="telegram_source_pre_authentication",
 40    )
 41
 42    @property
 43    def component(self) -> str:
 44        return "ak-source-telegram-form"
 45
 46    @property
 47    def icon_url(self) -> str | None:
 48        icon = super().icon_url
 49        if not icon:
 50            icon = static("authentik/sources/telegram.svg")
 51        return icon
 52
 53    @property
 54    def serializer(self) -> type[BaseSerializer]:
 55        from authentik.sources.telegram.api.source import TelegramSourceSerializer
 56
 57        return TelegramSourceSerializer
 58
 59    def ui_login_button(self, request: HttpRequest) -> UILoginButton:
 60        return UILoginButton(
 61            challenge=RedirectChallenge(
 62                data={
 63                    "to": reverse(
 64                        "authentik_sources_telegram:start",
 65                        kwargs={"source_slug": self.slug},
 66                    ),
 67                }
 68            ),
 69            name=self.name,
 70            icon_url=self.icon_url,
 71            promoted=self.promoted,
 72        )
 73
 74    def ui_user_settings(self) -> UserSettingSerializer | None:
 75        return UserSettingSerializer(
 76            data={
 77                "title": self.name,
 78                "component": "ak-user-settings-source-telegram",
 79                "icon_url": self.icon_url,
 80                "configure_url": urlencode(
 81                    {
 82                        "bot_username": self.bot_username,
 83                        "request_message_access": str(self.request_message_access),
 84                    }
 85                ),
 86            }
 87        )
 88
 89    @property
 90    def property_mapping_type(self) -> type[PropertyMapping]:
 91        return TelegramSourcePropertyMapping
 92
 93    def get_base_user_properties(
 94        self, info: dict[str, Any] | None = None, **kwargs
 95    ) -> dict[str, Any | dict[str, Any]]:
 96        info = info or {}
 97        name = info.get("first_name", "")
 98        if "last_name" in info:
 99            name += " " + info["last_name"]
100        return {
101            "username": info.get("username", None),
102            "email": None,
103            "name": name if name else None,
104        }
105
106    def get_base_group_properties(self, group_id: str, **kwargs):
107        return {
108            "name": group_id,
109        }
110
111    class Meta:
112        verbose_name = _("Telegram Source")
113        verbose_name_plural = _("Telegram Sources")

Log in with Telegram.

def bot_username(unknown):

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

def bot_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 request_message_access(unknown):

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

pre_authentication_flow

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.

component: str
42    @property
43    def component(self) -> str:
44        return "ak-source-telegram-form"

Return component used to edit this object

icon_url: str | None
46    @property
47    def icon_url(self) -> str | None:
48        icon = super().icon_url
49        if not icon:
50            icon = static("authentik/sources/telegram.svg")
51        return icon

Get the URL to the source icon

serializer: type[rest_framework.serializers.BaseSerializer]
53    @property
54    def serializer(self) -> type[BaseSerializer]:
55        from authentik.sources.telegram.api.source import TelegramSourceSerializer
56
57        return TelegramSourceSerializer

Get serializer for this model

def ui_login_button( self, request: django.http.request.HttpRequest) -> authentik.core.types.UILoginButton:
59    def ui_login_button(self, request: HttpRequest) -> UILoginButton:
60        return UILoginButton(
61            challenge=RedirectChallenge(
62                data={
63                    "to": reverse(
64                        "authentik_sources_telegram:start",
65                        kwargs={"source_slug": self.slug},
66                    ),
67                }
68            ),
69            name=self.name,
70            icon_url=self.icon_url,
71            promoted=self.promoted,
72        )

If source uses a http-based flow, return UI Information about the login button. If source doesn't use http-based flow, return None.

def ui_user_settings(self) -> authentik.core.types.UserSettingSerializer | None:
74    def ui_user_settings(self) -> UserSettingSerializer | None:
75        return UserSettingSerializer(
76            data={
77                "title": self.name,
78                "component": "ak-user-settings-source-telegram",
79                "icon_url": self.icon_url,
80                "configure_url": urlencode(
81                    {
82                        "bot_username": self.bot_username,
83                        "request_message_access": str(self.request_message_access),
84                    }
85                ),
86            }
87        )

Entrypoint to integrate with User settings. Can either return None if no user settings are available, or UserSettingSerializer.

property_mapping_type: type[authentik.core.models.PropertyMapping]
89    @property
90    def property_mapping_type(self) -> type[PropertyMapping]:
91        return TelegramSourcePropertyMapping

Return property mapping type used by this object

def get_base_user_properties( self, info: dict[str, Any] | None = None, **kwargs) -> dict[str, typing.Any | dict[str, typing.Any]]:
 93    def get_base_user_properties(
 94        self, info: dict[str, Any] | None = None, **kwargs
 95    ) -> dict[str, Any | dict[str, Any]]:
 96        info = info or {}
 97        name = info.get("first_name", "")
 98        if "last_name" in info:
 99            name += " " + info["last_name"]
100        return {
101            "username": info.get("username", None),
102            "email": None,
103            "name": name if name else None,
104        }

Get base properties for a user to build final properties upon.

def get_base_group_properties(self, group_id: str, **kwargs):
106    def get_base_group_properties(self, group_id: str, **kwargs):
107        return {
108            "name": group_id,
109        }

Get base properties for a group to build final properties upon.

pre_authentication_flow_id
source_ptr_id
source_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 TelegramSource.DoesNotExist(authentik.core.models.Source.DoesNotExist):

The requested object does not exist

class TelegramSource.MultipleObjectsReturned(authentik.core.models.Source.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.

class TelegramSourcePropertyMapping(authentik.core.models.PropertyMapping):
116class TelegramSourcePropertyMapping(PropertyMapping):
117    """Map Telegram properties to User or Group object attributes"""
118
119    @property
120    def component(self) -> str:
121        return "ak-property-mapping-source-telegram-form"
122
123    @property
124    def serializer(self) -> type[Serializer]:
125        from authentik.sources.telegram.api.property_mappings import (
126            TelegramSourcePropertyMappingSerializer,
127        )
128
129        return TelegramSourcePropertyMappingSerializer
130
131    class Meta:
132        verbose_name = _("Telegram Source Property Mapping")
133        verbose_name_plural = _("Telegram Source Property Mappings")

Map Telegram properties to User or Group object attributes

component: str
119    @property
120    def component(self) -> str:
121        return "ak-property-mapping-source-telegram-form"

Return component used to edit this object

serializer: type[rest_framework.serializers.Serializer]
123    @property
124    def serializer(self) -> type[Serializer]:
125        from authentik.sources.telegram.api.property_mappings import (
126            TelegramSourcePropertyMappingSerializer,
127        )
128
129        return TelegramSourcePropertyMappingSerializer

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 TelegramSourcePropertyMapping.DoesNotExist(authentik.core.models.PropertyMapping.DoesNotExist):

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class UserTelegramSourceConnection(authentik.core.models.UserSourceConnection):
136class UserTelegramSourceConnection(UserSourceConnection):
137    """Connect user and Telegram source"""
138
139    @property
140    def serializer(self) -> type[Serializer]:
141        from authentik.sources.telegram.api.source_connection import (
142            UserTelegramSourceConnectionSerializer,
143        )
144
145        return UserTelegramSourceConnectionSerializer
146
147    class Meta:
148        verbose_name = _("User Telegram Source Connection")
149        verbose_name_plural = _("User Telegram Source Connections")

Connect user and Telegram source

serializer: type[rest_framework.serializers.Serializer]
139    @property
140    def serializer(self) -> type[Serializer]:
141        from authentik.sources.telegram.api.source_connection import (
142            UserTelegramSourceConnectionSerializer,
143        )
144
145        return UserTelegramSourceConnectionSerializer

Get serializer for this model

usersourceconnection_ptr_id
usersourceconnection_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 UserTelegramSourceConnection.DoesNotExist(authentik.core.models.UserSourceConnection.DoesNotExist):

The requested object does not exist

class UserTelegramSourceConnection.MultipleObjectsReturned(authentik.core.models.UserSourceConnection.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.

class GroupTelegramSourceConnection(authentik.core.models.GroupSourceConnection):
152class GroupTelegramSourceConnection(GroupSourceConnection):
153    """Group-source connection for Telegram"""
154
155    @property
156    def serializer(self) -> type[Serializer]:
157        from authentik.sources.telegram.api.source_connection import (
158            GroupTelegramSourceConnectionSerializer,
159        )
160
161        return GroupTelegramSourceConnectionSerializer
162
163    class Meta:
164        verbose_name = _("Group Telegram Source Connection")
165        verbose_name_plural = _("Group Telegram Source Connections")

Group-source connection for Telegram

serializer: type[rest_framework.serializers.Serializer]
155    @property
156    def serializer(self) -> type[Serializer]:
157        from authentik.sources.telegram.api.source_connection import (
158            GroupTelegramSourceConnectionSerializer,
159        )
160
161        return GroupTelegramSourceConnectionSerializer

Get serializer for this model

groupsourceconnection_ptr_id
groupsourceconnection_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 GroupTelegramSourceConnection.DoesNotExist(authentik.core.models.GroupSourceConnection.DoesNotExist):

The requested object does not exist

class GroupTelegramSourceConnection.MultipleObjectsReturned(authentik.core.models.GroupSourceConnection.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.