using System.Globalization; using System.Security.Cryptography; using Microsoft.IdentityModel.Tokens; using Tiku.Domain.Tenancy; namespace Tiku.Infrastructure.Tenancy; internal static class TenantDomainProvisioning { public static TenantDomain CreatePrimary(Guid tenantId, string host) { return new TenantDomain { TenantId = tenantId, Host = NormalizeHost(host), DomainType = TenantDomainType.Custom, Status = TenantDomainStatus.Pending, IsPrimary = true, VerificationToken = Base64UrlEncoder.Encode(RandomNumberGenerator.GetBytes(32)) }; } public static string NormalizeHost(string value) { var candidate = value.Trim().TrimEnd('.'); if (candidate.Length == 0 || candidate.Contains('/') || candidate.Contains(':') || candidate.Contains('*')) throw new ArgumentException("A DNS host without scheme, port, path or wildcard is required.", nameof(value)); string ascii; try { ascii = new IdnMapping().GetAscii(candidate).ToLowerInvariant(); } catch (ArgumentException) { throw new ArgumentException("The domain host is invalid.", nameof(value)); } if (ascii.Length > 253 || ascii.Split('.').Length < 2 || ascii.Split('.').Any(label => label.Length is 0 or > 63 || label.StartsWith('-') || label.EndsWith('-') || label.Any(character => !char.IsAsciiLetterOrDigit(character) && character != '-'))) throw new ArgumentException("The domain host is invalid.", nameof(value)); return ascii; } }