97 lines
2.8 KiB
Python
97 lines
2.8 KiB
Python
"""Enterprise models"""
|
|
|
|
from datetime import timedelta
|
|
from typing import TYPE_CHECKING
|
|
from uuid import uuid4
|
|
|
|
from django.contrib.postgres.indexes import HashIndex
|
|
from django.db import models
|
|
from django.utils.timezone import now
|
|
from django.utils.translation import gettext as _
|
|
from rest_framework.serializers import BaseSerializer
|
|
|
|
from authentik.core.models import ExpiringModel
|
|
from authentik.lib.models import SerializerModel
|
|
|
|
if TYPE_CHECKING:
|
|
from authentik.enterprise.license import LicenseKey
|
|
|
|
|
|
def usage_expiry():
|
|
"""Keep license usage records for 3 months"""
|
|
return now() + timedelta(days=30 * 3)
|
|
|
|
|
|
THRESHOLD_WARNING_ADMIN_WEEKS = 2
|
|
THRESHOLD_WARNING_USER_WEEKS = 4
|
|
THRESHOLD_WARNING_EXPIRY_WEEKS = 2
|
|
THRESHOLD_READ_ONLY_WEEKS = 6
|
|
|
|
|
|
class License(SerializerModel):
|
|
"""An authentik enterprise license"""
|
|
|
|
license_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
|
|
key = models.TextField()
|
|
|
|
name = models.TextField()
|
|
expiry = models.DateTimeField()
|
|
internal_users = models.BigIntegerField()
|
|
external_users = models.BigIntegerField()
|
|
|
|
@property
|
|
def serializer(self) -> type[BaseSerializer]:
|
|
from authentik.enterprise.api import LicenseSerializer
|
|
|
|
return LicenseSerializer
|
|
|
|
@property
|
|
def status(self) -> "LicenseKey":
|
|
"""Get parsed license status"""
|
|
from authentik.enterprise.license import LicenseKey
|
|
|
|
return LicenseKey.validate(self.key, check_expiry=False)
|
|
|
|
class Meta:
|
|
indexes = (HashIndex(fields=("key",)),)
|
|
verbose_name = _("License")
|
|
verbose_name_plural = _("Licenses")
|
|
|
|
|
|
class LicenseUsageStatus(models.TextChoices):
|
|
"""License states an instance/tenant can be in"""
|
|
|
|
UNLICENSED = "unlicensed"
|
|
VALID = "valid"
|
|
EXPIRED = "expired"
|
|
EXPIRY_SOON = "expiry_soon"
|
|
# User limit exceeded, 2 week threshold, show message in admin interface
|
|
LIMIT_EXCEEDED_ADMIN = "limit_exceeded_admin"
|
|
# User limit exceeded, 4 week threshold, show message in user interface
|
|
LIMIT_EXCEEDED_USER = "limit_exceeded_user"
|
|
READ_ONLY = "read_only"
|
|
|
|
@property
|
|
def is_valid(self) -> bool:
|
|
"""Quickly check if a license is valid"""
|
|
return self in [LicenseUsageStatus.VALID, LicenseUsageStatus.EXPIRY_SOON]
|
|
|
|
|
|
class LicenseUsage(ExpiringModel):
|
|
"""a single license usage record"""
|
|
|
|
expires = models.DateTimeField(default=usage_expiry)
|
|
|
|
usage_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
|
|
|
|
internal_user_count = models.BigIntegerField()
|
|
external_user_count = models.BigIntegerField()
|
|
status = models.TextField(choices=LicenseUsageStatus.choices)
|
|
|
|
record_date = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
verbose_name = _("License Usage")
|
|
verbose_name_plural = _("License Usage Records")
|
|
indexes = ExpiringModel.Meta.indexes
|