authentik.enterprise.models
Enterprise models
1"""Enterprise models""" 2 3from datetime import timedelta 4from typing import TYPE_CHECKING 5from uuid import uuid4 6 7from django.contrib.postgres.indexes import HashIndex 8from django.db import models 9from django.utils.timezone import now 10from django.utils.translation import gettext as _ 11from rest_framework.serializers import BaseSerializer 12 13from authentik.core.models import ExpiringModel 14from authentik.lib.models import InternallyManagedMixin, SerializerModel 15 16if TYPE_CHECKING: 17 from authentik.enterprise.license import LicenseKey 18 19 20def usage_expiry(): 21 """Keep license usage records for 3 months""" 22 return now() + timedelta(days=30 * 3) 23 24 25THRESHOLD_WARNING_ADMIN_WEEKS = 2 26THRESHOLD_WARNING_USER_WEEKS = 4 27THRESHOLD_WARNING_EXPIRY_WEEKS = 2 28THRESHOLD_READ_ONLY_WEEKS = 6 29 30 31class License(SerializerModel): 32 """An authentik enterprise license""" 33 34 license_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4) 35 key = models.TextField() 36 37 name = models.TextField() 38 expiry = models.DateTimeField() 39 internal_users = models.BigIntegerField() 40 external_users = models.BigIntegerField() 41 42 @property 43 def is_valid(self) -> bool: 44 return self.expiry >= now() 45 46 @property 47 def serializer(self) -> type[BaseSerializer]: 48 from authentik.enterprise.api import LicenseSerializer 49 50 return LicenseSerializer 51 52 @property 53 def status(self) -> LicenseKey: 54 """Get parsed license status""" 55 from authentik.enterprise.license import LicenseKey 56 57 return LicenseKey.validate(self.key, check_expiry=False) 58 59 class Meta: 60 indexes = (HashIndex(fields=("key",)),) 61 verbose_name = _("License") 62 verbose_name_plural = _("Licenses") 63 64 65class LicenseUsageStatus(models.TextChoices): 66 """License states an instance/tenant can be in""" 67 68 UNLICENSED = "unlicensed" 69 VALID = "valid" 70 EXPIRED = "expired" 71 EXPIRY_SOON = "expiry_soon" 72 # User limit exceeded, 2 week threshold, show message in admin interface 73 LIMIT_EXCEEDED_ADMIN = "limit_exceeded_admin" 74 # User limit exceeded, 4 week threshold, show message in user interface 75 LIMIT_EXCEEDED_USER = "limit_exceeded_user" 76 READ_ONLY = "read_only" 77 78 @property 79 def is_valid(self) -> bool: 80 """Quickly check if a license is valid""" 81 return self in [LicenseUsageStatus.VALID, LicenseUsageStatus.EXPIRY_SOON] 82 83 84class LicenseUsage(InternallyManagedMixin, ExpiringModel): 85 """a single license usage record""" 86 87 expires = models.DateTimeField(default=usage_expiry) 88 89 usage_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4) 90 91 internal_user_count = models.BigIntegerField() 92 external_user_count = models.BigIntegerField() 93 status = models.TextField(choices=LicenseUsageStatus.choices) 94 95 record_date = models.DateTimeField(auto_now_add=True) 96 97 class Meta: 98 verbose_name = _("License Usage") 99 verbose_name_plural = _("License Usage Records") 100 indexes = ExpiringModel.Meta.indexes
21def usage_expiry(): 22 """Keep license usage records for 3 months""" 23 return now() + timedelta(days=30 * 3)
Keep license usage records for 3 months
32class License(SerializerModel): 33 """An authentik enterprise license""" 34 35 license_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4) 36 key = models.TextField() 37 38 name = models.TextField() 39 expiry = models.DateTimeField() 40 internal_users = models.BigIntegerField() 41 external_users = models.BigIntegerField() 42 43 @property 44 def is_valid(self) -> bool: 45 return self.expiry >= now() 46 47 @property 48 def serializer(self) -> type[BaseSerializer]: 49 from authentik.enterprise.api import LicenseSerializer 50 51 return LicenseSerializer 52 53 @property 54 def status(self) -> LicenseKey: 55 """Get parsed license status""" 56 from authentik.enterprise.license import LicenseKey 57 58 return LicenseKey.validate(self.key, check_expiry=False) 59 60 class Meta: 61 indexes = (HashIndex(fields=("key",)),) 62 verbose_name = _("License") 63 verbose_name_plural = _("Licenses")
An authentik enterprise license
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.
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.
47 @property 48 def serializer(self) -> type[BaseSerializer]: 49 from authentik.enterprise.api import LicenseSerializer 50 51 return LicenseSerializer
Get serializer for this model
53 @property 54 def status(self) -> LicenseKey: 55 """Get parsed license status""" 56 from authentik.enterprise.license import LicenseKey 57 58 return LicenseKey.validate(self.key, check_expiry=False)
Get parsed license status
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.
66class LicenseUsageStatus(models.TextChoices): 67 """License states an instance/tenant can be in""" 68 69 UNLICENSED = "unlicensed" 70 VALID = "valid" 71 EXPIRED = "expired" 72 EXPIRY_SOON = "expiry_soon" 73 # User limit exceeded, 2 week threshold, show message in admin interface 74 LIMIT_EXCEEDED_ADMIN = "limit_exceeded_admin" 75 # User limit exceeded, 4 week threshold, show message in user interface 76 LIMIT_EXCEEDED_USER = "limit_exceeded_user" 77 READ_ONLY = "read_only" 78 79 @property 80 def is_valid(self) -> bool: 81 """Quickly check if a license is valid""" 82 return self in [LicenseUsageStatus.VALID, LicenseUsageStatus.EXPIRY_SOON]
License states an instance/tenant can be in
85class LicenseUsage(InternallyManagedMixin, ExpiringModel): 86 """a single license usage record""" 87 88 expires = models.DateTimeField(default=usage_expiry) 89 90 usage_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4) 91 92 internal_user_count = models.BigIntegerField() 93 external_user_count = models.BigIntegerField() 94 status = models.TextField(choices=LicenseUsageStatus.choices) 95 96 record_date = models.DateTimeField(auto_now_add=True) 97 98 class Meta: 99 verbose_name = _("License Usage") 100 verbose_name_plural = _("License Usage Records") 101 indexes = ExpiringModel.Meta.indexes
a single license usage record
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.
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.
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.
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.
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.