feat(domains): migrate user namespaces to wildcard CNAMEs
Build and publish Docker image / build-and-publish (push) Successful in 8s

This commit is contained in:
wfalkowski committed 2026-10-20 18:10:23 +00:00
1 parent 82fa50e9d5
commit 2768f5f97d
6 files changed
+503 -296

No files matched your search

+3 -78
View File
@@ -965,65 +965,19 @@ async def handle_delete_domain(client_id, data):
await send_message(client_id, {'type': 'error', 'error': str(e)})
async def handle_list_domains(client_id, data):
"""Handle list domains request - FIXED to separate custom and delegated domains"""
"""Return the user's claimed platform domains from the database."""
client_info = connected_clients.get(client_id)
if not client_info or not client_info['authenticated']:
await send_message(client_id, {'type': 'error', 'error': 'Not authenticated'})
return
user_id = client_info['user_id']
username = client_info['username']
include_serverless = data.get('includeServerless', True)
try:
# Get from database - THIS RETURNS ALL DOMAINS (both delegated and custom)
all_domains = get_user_domains(user_id, include_serverless)
# IMPORTANT: Separate delegated domains from custom domains
delegated_domains = [d for d in all_domains if not d.get('is_custom')]
# Also sync with DNS to ensure consistency for delegated domains only
if domain_manager:
# First ensure the user domain exists
user_domain = f"u-{username}.{domain_manager.base_domain}"
domain_exists = domain_manager._check_domain_exists(user_domain)
if domain_exists is None:
logger.error(f"Error checking domain {user_domain}")
elif not domain_exists:
# Create the user domain if it doesn't exist
logger.info(f"Creating user domain: {user_domain}")
if domain_manager._create_domain(user_domain):
logger.info(f"✓ Created user domain: {user_domain}")
else:
logger.error(f"✗ Failed to create user domain: {user_domain}")
# Now list delegated domains from DNS
result = domain_manager.list_user_domains(username)
if result.get('success'):
# Create a set of existing delegated domains from database
db_domain_set = {d['full_domain'] for d in delegated_domains}
# Add any delegated domains from DNS that aren't in database
for dns_domain in result.get('domains', []):
if dns_domain['full_domain'] not in db_domain_set:
# Add to database
domain_record = {
'user_id': user_id,
'subdomain': dns_domain['subdomain'],
'full_domain': dns_domain['full_domain'],
'record_type': dns_domain['record_type'],
'ip_address': dns_domain['ip_address'],
'ttl': dns_domain.get('ttl', 3600),
'created_at': dns_domain.get('created_at', datetime.now().isoformat())
}
create_domain_record(domain_record)
# Refresh delegated domains list from database
all_domains_refreshed = get_user_domains(user_id, include_serverless)
delegated_domains = [d for d in all_domains_refreshed if not d.get('is_custom')]
# SEND ONLY DELEGATED DOMAINS in the domains_list response
# Custom domains should be fetched via list_custom_domains
await send_message(client_id, {
@@ -1646,41 +1600,12 @@ async def handle_add_credits(client_id, data):
await send_message(client_id, {'type': 'error', 'error': 'Failed to add credits'})
def sync_user_domains_with_dns(user_id: str) -> bool:
"""Sync user domains between database and DNS"""
"""Ensure the user's wildcard namespace exists without creating a child zone."""
try:
user = get_user_by_id(user_id)
if not user or not domain_manager:
return False
username = user['username']
# Get domains from DNS
dns_result = domain_manager.list_user_domains(username)
if not dns_result.get('success'):
return False
dns_domains = {d['full_domain']: d for d in dns_result.get('domains', [])}
# Get domains from database
db_domains = get_user_domains(user_id, True)
db_domain_set = {d['full_domain'] for d in db_domains}
# Add missing DNS domains to database
for dns_domain in dns_result.get('domains', []):
if dns_domain['full_domain'] not in db_domain_set:
domain_record = {
'user_id': user_id,
'subdomain': dns_domain['subdomain'],
'full_domain': dns_domain['full_domain'],
'record_type': dns_domain['record_type'],
'ip_address': dns_domain['ip_address'],
'ttl': dns_domain.get('ttl', 3600),
'created_at': dns_domain.get('created_at', datetime.now().isoformat())
}
create_domain_record(domain_record)
logger.info(f"Added missing domain to DB: {dns_domain['full_domain']}")
return True
return domain_manager.ensure_user_namespace(user['username']).get('success', False)
except Exception as e:
logger.error(f"Error syncing domains: {e}")