authentik.sources.plex.models
Plex source
1"""Plex source""" 2 3from typing import Any 4 5from django.contrib.postgres.fields import ArrayField 6from django.db import models 7from django.http.request import HttpRequest 8from django.templatetags.static import static 9from django.utils.translation import gettext_lazy as _ 10from rest_framework.fields import CharField 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 Challenge, ChallengeResponse 21from authentik.lib.generators import generate_id 22from authentik.lib.utils.time import fqdn_rand 23from authentik.stages.identification.stage import LoginChallengeMixin 24from authentik.tasks.schedules.common import ScheduleSpec 25from authentik.tasks.schedules.models import ScheduledModel 26 27 28class PlexAuthenticationChallenge(LoginChallengeMixin, Challenge): 29 """Challenge shown to the user in identification stage""" 30 31 client_id = CharField() 32 slug = CharField() 33 component = CharField(default="ak-source-plex") 34 35 36class PlexAuthenticationChallengeResponse(ChallengeResponse): 37 """Pseudo class for plex response""" 38 39 component = CharField(default="ak-source-plex") 40 41 42class PlexSource(ScheduledModel, Source): 43 """Authenticate against plex.tv""" 44 45 client_id = models.TextField( 46 default=generate_id, 47 help_text=_("Client identifier used to talk to Plex."), 48 ) 49 allowed_servers = ArrayField( 50 models.TextField(), 51 default=list, 52 blank=True, 53 help_text=_( 54 "Which servers a user has to be a member of to be granted access. " 55 "Empty list allows every server." 56 ), 57 ) 58 allow_friends = models.BooleanField( 59 default=True, 60 help_text=_("Allow friends to authenticate, even if you don't share a server."), 61 ) 62 plex_token = models.TextField(help_text=_("Plex token used to check friends")) 63 64 @property 65 def component(self) -> str: 66 return "ak-source-plex-form" 67 68 @property 69 def serializer(self) -> type[BaseSerializer]: 70 from authentik.sources.plex.api.source import PlexSourceSerializer 71 72 return PlexSourceSerializer 73 74 @property 75 def property_mapping_type(self) -> type[PropertyMapping]: 76 return PlexSourcePropertyMapping 77 78 @property 79 def schedule_specs(self) -> list[ScheduleSpec]: 80 from authentik.sources.plex.tasks import check_plex_token 81 82 return [ 83 ScheduleSpec( 84 actor=check_plex_token, 85 uid=self.slug, 86 args=(self.pk,), 87 crontab=f"{fqdn_rand(self.pk)} */3 * * *", 88 ), 89 ] 90 91 def get_base_user_properties(self, info: dict[str, Any], **kwargs): 92 return { 93 "username": info.get("username"), 94 "email": info.get("email"), 95 "name": info.get("title"), 96 } 97 98 def get_base_group_properties(self, group_id: str, **kwargs): 99 return { 100 "name": group_id, 101 } 102 103 @property 104 def icon_url(self) -> str: 105 icon = super().icon_url 106 if not icon: 107 icon = static("authentik/sources/plex.svg") 108 return icon 109 110 def ui_login_button(self, request: HttpRequest) -> UILoginButton: 111 return UILoginButton( 112 challenge=PlexAuthenticationChallenge( 113 data={ 114 "component": "ak-source-plex", 115 "client_id": self.client_id, 116 "slug": self.slug, 117 } 118 ), 119 icon_url=self.icon_url, 120 name=self.name, 121 promoted=self.promoted, 122 ) 123 124 def ui_user_settings(self) -> UserSettingSerializer | None: 125 return UserSettingSerializer( 126 data={ 127 "title": self.name, 128 "component": "ak-user-settings-source-plex", 129 "configure_url": self.client_id, 130 "icon_url": self.icon_url, 131 } 132 ) 133 134 class Meta: 135 verbose_name = _("Plex Source") 136 verbose_name_plural = _("Plex Sources") 137 138 139class PlexSourcePropertyMapping(PropertyMapping): 140 """Map Plex properties to User of Group object attributes""" 141 142 @property 143 def component(self) -> str: 144 return "ak-property-mapping-source-plex-form" 145 146 @property 147 def serializer(self) -> type[Serializer]: 148 from authentik.sources.plex.api.property_mappings import PlexSourcePropertyMappingSerializer 149 150 return PlexSourcePropertyMappingSerializer 151 152 class Meta: 153 verbose_name = _("Plex Source Property Mapping") 154 verbose_name_plural = _("Plex Source Property Mappings") 155 156 157class UserPlexSourceConnection(UserSourceConnection): 158 """Connect user and plex source""" 159 160 plex_token = models.TextField() 161 162 @property 163 def serializer(self) -> type[Serializer]: 164 from authentik.sources.plex.api.source_connection import UserPlexSourceConnectionSerializer 165 166 return UserPlexSourceConnectionSerializer 167 168 class Meta: 169 verbose_name = _("User Plex Source Connection") 170 verbose_name_plural = _("User Plex Source Connections") 171 172 173class GroupPlexSourceConnection(GroupSourceConnection): 174 """Group-source connection""" 175 176 @property 177 def serializer(self) -> type[Serializer]: 178 from authentik.sources.plex.api.source_connection import ( 179 GroupPlexSourceConnectionSerializer, 180 ) 181 182 return GroupPlexSourceConnectionSerializer 183 184 class Meta: 185 verbose_name = _("Group Plex Source Connection") 186 verbose_name_plural = _("Group Plex Source Connections")
29class PlexAuthenticationChallenge(LoginChallengeMixin, Challenge): 30 """Challenge shown to the user in identification stage""" 31 32 client_id = CharField() 33 slug = CharField() 34 component = CharField(default="ak-source-plex")
Challenge shown to the user in identification stage
37class PlexAuthenticationChallengeResponse(ChallengeResponse): 38 """Pseudo class for plex response""" 39 40 component = CharField(default="ak-source-plex")
Pseudo class for plex response
43class PlexSource(ScheduledModel, Source): 44 """Authenticate against plex.tv""" 45 46 client_id = models.TextField( 47 default=generate_id, 48 help_text=_("Client identifier used to talk to Plex."), 49 ) 50 allowed_servers = ArrayField( 51 models.TextField(), 52 default=list, 53 blank=True, 54 help_text=_( 55 "Which servers a user has to be a member of to be granted access. " 56 "Empty list allows every server." 57 ), 58 ) 59 allow_friends = models.BooleanField( 60 default=True, 61 help_text=_("Allow friends to authenticate, even if you don't share a server."), 62 ) 63 plex_token = models.TextField(help_text=_("Plex token used to check friends")) 64 65 @property 66 def component(self) -> str: 67 return "ak-source-plex-form" 68 69 @property 70 def serializer(self) -> type[BaseSerializer]: 71 from authentik.sources.plex.api.source import PlexSourceSerializer 72 73 return PlexSourceSerializer 74 75 @property 76 def property_mapping_type(self) -> type[PropertyMapping]: 77 return PlexSourcePropertyMapping 78 79 @property 80 def schedule_specs(self) -> list[ScheduleSpec]: 81 from authentik.sources.plex.tasks import check_plex_token 82 83 return [ 84 ScheduleSpec( 85 actor=check_plex_token, 86 uid=self.slug, 87 args=(self.pk,), 88 crontab=f"{fqdn_rand(self.pk)} */3 * * *", 89 ), 90 ] 91 92 def get_base_user_properties(self, info: dict[str, Any], **kwargs): 93 return { 94 "username": info.get("username"), 95 "email": info.get("email"), 96 "name": info.get("title"), 97 } 98 99 def get_base_group_properties(self, group_id: str, **kwargs): 100 return { 101 "name": group_id, 102 } 103 104 @property 105 def icon_url(self) -> str: 106 icon = super().icon_url 107 if not icon: 108 icon = static("authentik/sources/plex.svg") 109 return icon 110 111 def ui_login_button(self, request: HttpRequest) -> UILoginButton: 112 return UILoginButton( 113 challenge=PlexAuthenticationChallenge( 114 data={ 115 "component": "ak-source-plex", 116 "client_id": self.client_id, 117 "slug": self.slug, 118 } 119 ), 120 icon_url=self.icon_url, 121 name=self.name, 122 promoted=self.promoted, 123 ) 124 125 def ui_user_settings(self) -> UserSettingSerializer | None: 126 return UserSettingSerializer( 127 data={ 128 "title": self.name, 129 "component": "ak-user-settings-source-plex", 130 "configure_url": self.client_id, 131 "icon_url": self.icon_url, 132 } 133 ) 134 135 class Meta: 136 verbose_name = _("Plex Source") 137 verbose_name_plural = _("Plex Sources")
Authenticate against plex.tv
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.
69 @property 70 def serializer(self) -> type[BaseSerializer]: 71 from authentik.sources.plex.api.source import PlexSourceSerializer 72 73 return PlexSourceSerializer
Get serializer for this model
75 @property 76 def property_mapping_type(self) -> type[PropertyMapping]: 77 return PlexSourcePropertyMapping
Return property mapping type used by this object
92 def get_base_user_properties(self, info: dict[str, Any], **kwargs): 93 return { 94 "username": info.get("username"), 95 "email": info.get("email"), 96 "name": info.get("title"), 97 }
Get base properties for a user to build final properties upon.
99 def get_base_group_properties(self, group_id: str, **kwargs): 100 return { 101 "name": group_id, 102 }
Get base properties for a group to build final properties upon.
104 @property 105 def icon_url(self) -> str: 106 icon = super().icon_url 107 if not icon: 108 icon = static("authentik/sources/plex.svg") 109 return icon
Get the URL to the source icon
125 def ui_user_settings(self) -> UserSettingSerializer | None: 126 return UserSettingSerializer( 127 data={ 128 "title": self.name, 129 "component": "ak-user-settings-source-plex", 130 "configure_url": self.client_id, 131 "icon_url": self.icon_url, 132 } 133 )
Entrypoint to integrate with User settings. Can either return None if no user settings are available, or UserSettingSerializer.
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 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.core.models.Source
- MANAGED_INBUILT
- name
- slug
- user_path_template
- enabled
- promoted
- user_property_mappings
- group_property_mappings
- icon
- authentication_flow
- enrollment_flow
- user_matching_mode
- group_matching_mode
- objects
- icon_themed_urls
- get_user_path
- managed
- authentication_flow_id
- enrollment_flow_id
- get_user_matching_mode_display
- get_group_matching_mode_display
- policybindingmodel_ptr_id
- policybindingmodel_ptr
- user_set
- usersourceconnection_set
- groupsourceconnection_set
- oauthsource
- samlsource
- kerberossource
- ldapsource
- identificationstage_set
- plexsource
- scimsource
- telegramsource
- sourcestage_set
The requested object does not exist
The query returned multiple objects when only one was expected.
140class PlexSourcePropertyMapping(PropertyMapping): 141 """Map Plex properties to User of Group object attributes""" 142 143 @property 144 def component(self) -> str: 145 return "ak-property-mapping-source-plex-form" 146 147 @property 148 def serializer(self) -> type[Serializer]: 149 from authentik.sources.plex.api.property_mappings import PlexSourcePropertyMappingSerializer 150 151 return PlexSourcePropertyMappingSerializer 152 153 class Meta: 154 verbose_name = _("Plex Source Property Mapping") 155 verbose_name_plural = _("Plex Source Property Mappings")
Map Plex properties to User of Group object attributes
147 @property 148 def serializer(self) -> type[Serializer]: 149 from authentik.sources.plex.api.property_mappings import PlexSourcePropertyMappingSerializer 150 151 return PlexSourcePropertyMappingSerializer
Get serializer for this model
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.core.models.PropertyMapping
- pm_uuid
- name
- expression
- objects
- evaluate
- managed
- provider_set
- source_userpropertymappings_set
- source_grouppropertymappings_set
- notificationwebhookmapping
- oauthsourcepropertymapping
- scopemapping
- endpoint_set
- racpropertymapping
- radiusproviderpropertymapping
- samlsourcepropertymapping
- samlpropertymapping
- scimprovider_set
- scimmapping
- kerberossourcepropertymapping
- ldapsourcepropertymapping
- plexsourcepropertymapping
- scimsourcepropertymapping
- telegramsourcepropertymapping
- googleworkspaceprovider_set
- googleworkspaceprovidermapping
- microsoftentraprovider_set
- microsoftentraprovidermapping
The requested object does not exist
The query returned multiple objects when only one was expected.
158class UserPlexSourceConnection(UserSourceConnection): 159 """Connect user and plex source""" 160 161 plex_token = models.TextField() 162 163 @property 164 def serializer(self) -> type[Serializer]: 165 from authentik.sources.plex.api.source_connection import UserPlexSourceConnectionSerializer 166 167 return UserPlexSourceConnectionSerializer 168 169 class Meta: 170 verbose_name = _("User Plex Source Connection") 171 verbose_name_plural = _("User Plex Source Connections")
Connect user and plex source
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
163 @property 164 def serializer(self) -> type[Serializer]: 165 from authentik.sources.plex.api.source_connection import UserPlexSourceConnectionSerializer 166 167 return UserPlexSourceConnectionSerializer
Get serializer for this model
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.core.models.UserSourceConnection
- user
- source
- identifier
- objects
- created
- last_updated
- user_id
- source_id
- get_next_by_created
- get_previous_by_created
- get_next_by_last_updated
- get_previous_by_last_updated
- id
- useroauthsourceconnection
- usersamlsourceconnection
- userkerberossourceconnection
- userldapsourceconnection
- userplexsourceconnection
- usertelegramsourceconnection
The requested object does not exist
The query returned multiple objects when only one was expected.
174class GroupPlexSourceConnection(GroupSourceConnection): 175 """Group-source connection""" 176 177 @property 178 def serializer(self) -> type[Serializer]: 179 from authentik.sources.plex.api.source_connection import ( 180 GroupPlexSourceConnectionSerializer, 181 ) 182 183 return GroupPlexSourceConnectionSerializer 184 185 class Meta: 186 verbose_name = _("Group Plex Source Connection") 187 verbose_name_plural = _("Group Plex Source Connections")
Group-source connection
177 @property 178 def serializer(self) -> type[Serializer]: 179 from authentik.sources.plex.api.source_connection import ( 180 GroupPlexSourceConnectionSerializer, 181 ) 182 183 return GroupPlexSourceConnectionSerializer
Get serializer for this model
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.core.models.GroupSourceConnection
- group
- source
- identifier
- objects
- created
- last_updated
- group_id
- source_id
- get_next_by_created
- get_previous_by_created
- get_next_by_last_updated
- get_previous_by_last_updated
- id
- groupoauthsourceconnection
- groupsamlsourceconnection
- groupkerberossourceconnection
- groupldapsourceconnection
- groupplexsourceconnection
- grouptelegramsourceconnection
The requested object does not exist
The query returned multiple objects when only one was expected.