113 lines
4.1 KiB
Python
113 lines
4.1 KiB
Python
from rest_framework import serializers
|
|
from django.contrib.auth import get_user_model
|
|
from django.contrib.auth.password_validation import validate_password
|
|
from django.core.exceptions import ValidationError as DjangoValidationError
|
|
from eox_tenant.models import TenantConfig
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class CreateTenantSerializer(serializers.Serializer):
|
|
"""Serializer for tenant creation request."""
|
|
tenant_name = serializers.RegexField(
|
|
regex=r'^[a-z0-9-]+$',
|
|
max_length=63,
|
|
help_text="Tenant name (lowercase alphanumeric and hyphens only)"
|
|
)
|
|
platform_name = serializers.CharField(max_length=255, required=False)
|
|
theme_name = serializers.CharField(max_length=255, required=False, default='indigo')
|
|
org_filter = serializers.ListField(
|
|
child=serializers.CharField(),
|
|
required=False,
|
|
help_text="List of course organizations for this tenant"
|
|
)
|
|
|
|
# EDNX settings (all optional with sensible defaults)
|
|
ednx_tenant_restrict_users = serializers.BooleanField(
|
|
required=False,
|
|
default=True,
|
|
help_text="Restrict users to their assigned tenant (EDNX_TENANT_RESTRICT_USERS)"
|
|
)
|
|
ednx_tenant_user_filter_enabled = serializers.BooleanField(
|
|
required=False,
|
|
default=True,
|
|
help_text="Enable user filtering by tenant (EDNX_TENANT_USER_FILTER_ENABLED)"
|
|
)
|
|
ednx_use_signal = serializers.BooleanField(
|
|
required=False,
|
|
default=True,
|
|
help_text="Use signals for tenant context (EDNX_USE_SIGNAL)"
|
|
)
|
|
ednx_account_registration_sources = serializers.ListField(
|
|
child=serializers.CharField(),
|
|
required=False,
|
|
help_text="Allowed account registration sources (auto-generated from tenant domain if not provided)"
|
|
)
|
|
|
|
def validate_tenant_name(self, value):
|
|
"""Ensure tenant name doesn't use reserved words."""
|
|
reserved = ['local', 'studio', 'apps', 'meilisearch', 'www', 'api', 'admin']
|
|
if value in reserved:
|
|
raise serializers.ValidationError(f"'{value}' is a reserved name")
|
|
return value
|
|
|
|
|
|
class TenantResponseSerializer(serializers.Serializer):
|
|
"""Serializer for tenant creation response."""
|
|
status = serializers.CharField()
|
|
tenant_id = serializers.IntegerField()
|
|
tenant_name = serializers.CharField()
|
|
lms_url = serializers.CharField()
|
|
authn_url = serializers.CharField()
|
|
learner_dashboard_url = serializers.CharField()
|
|
|
|
|
|
class TenantAdminCreateSerializer(serializers.Serializer):
|
|
"""Serializer for tenant admin creation request."""
|
|
tenant_name = serializers.CharField(
|
|
max_length=63,
|
|
help_text="Tenant name (must exist)"
|
|
)
|
|
username = serializers.CharField(
|
|
max_length=150,
|
|
help_text="Username for the admin user"
|
|
)
|
|
email = serializers.EmailField(
|
|
help_text="Email address for the admin user"
|
|
)
|
|
password = serializers.CharField(
|
|
write_only=True,
|
|
help_text="Password for the admin user"
|
|
)
|
|
org_name = serializers.CharField(
|
|
max_length=255,
|
|
help_text="Organization name for role assignment"
|
|
)
|
|
|
|
def validate_tenant_name(self, value):
|
|
"""Validate that tenant exists."""
|
|
external_key = f"{value}.local.openedx.io"
|
|
if not TenantConfig.objects.filter(external_key=external_key).exists():
|
|
raise serializers.ValidationError("Tenant does not exist")
|
|
return value
|
|
|
|
def validate_username(self, value):
|
|
"""Validate username is unique."""
|
|
if User.objects.filter(username=value).exists():
|
|
raise serializers.ValidationError("Username already exists")
|
|
return value
|
|
|
|
def validate_email(self, value):
|
|
"""Validate email is unique."""
|
|
if User.objects.filter(email=value).exists():
|
|
raise serializers.ValidationError("Email already exists")
|
|
return value
|
|
|
|
def validate_password(self, value):
|
|
"""Validate password meets Django security requirements."""
|
|
try:
|
|
validate_password(value)
|
|
except DjangoValidationError as e:
|
|
raise serializers.ValidationError(list(e.messages))
|
|
return value
|