tenants: forbid creation of multiple default tenants

closes #2059

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2022-01-04 18:57:00 +01:00
parent 41d5bff9d3
commit 9d6f79558f
2 changed files with 30 additions and 3 deletions

View File

@ -1,6 +1,9 @@
"""Serializer for tenant models"""
from typing import Any
from drf_spectacular.utils import extend_schema
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, ListField
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
@ -24,6 +27,15 @@ class FooterLinkSerializer(PassiveSerializer):
class TenantSerializer(ModelSerializer):
"""Tenant Serializer"""
def validate(self, attrs: dict[str, Any]) -> dict[str, Any]:
if attrs.get("default", False):
tenants = Tenant.objects.filter(default=True)
if self.instance:
tenants = tenants.exclude(pk=self.instance.pk)
if tenants.exists():
raise ValidationError("Only a single Tenant can be set as default.")
return super().validate(attrs)
class Meta:
model = Tenant

View File

@ -1,16 +1,16 @@
"""Test tenants"""
from django.test import TestCase
from django.test.client import RequestFactory
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.tests.utils import create_test_tenant
from authentik.core.tests.utils import create_test_admin_user, create_test_tenant
from authentik.events.models import Event, EventAction
from authentik.lib.config import CONFIG
from authentik.lib.utils.time import timedelta_from_string
from authentik.tenants.models import Tenant
class TestTenants(TestCase):
class TestTenants(APITestCase):
"""Test tenants"""
def test_current_tenant(self):
@ -78,3 +78,18 @@ class TestTenants(TestCase):
self.assertEqual(
event.expires.year, (event.created + timedelta_from_string("weeks=3")).year
)
def test_create_default_multiple(self):
"""Test attempted creation of multiple default tenants"""
Tenant.objects.create(
domain="foo",
default=True,
branding_title="custom",
event_retention="weeks=3",
)
user = create_test_admin_user()
self.client.force_login(user)
response = self.client.post(
reverse("authentik_api:tenant-list"), data={"domain": "bar", "default": True}
)
self.assertEqual(response.status_code, 400)