/** * Email Domain Validation Utilities * * Validates email domain formats (the part after @ in email addresses) * Used for SSO domain allowlist feature to restrict auto-provisioning to specific domains. */ /** * Validates an email domain format (the part after @ in email addresses) * Valid: example.com, sub.domain.org, my-company.co.uk * Invalid: http://example.com, @example.com, example, .com * * @param domain - The domain string to validate * @returns true if the domain is a valid email domain format */ export function isValidEmailDomain(domain: string): boolean { if (!domain || typeof domain !== 'string') { return false } const trimmed = domain.trim() if (!trimmed) { return false } // Domain regex: must have at least one dot, valid characters, and proper TLD // Allows subdomains, hyphens (not at start/end of labels), alphanumeric characters const domainRegex = /^(?!-)[A-Za-z0-9-]{1,63}(?() for (const domain of domains) { const result = validateEmailDomain(domain) if (!result.valid) { return { valid: false, error: `Invalid domain "${domain}": ${result.error}` } } const cleanedDomain = result.cleanedDomain! // Check for duplicates (case-insensitive) if (seenDomains.has(cleanedDomain)) { return { valid: false, error: `Duplicate domain: ${cleanedDomain}` } } seenDomains.add(cleanedDomain) cleanedDomains.push(cleanedDomain) } return { valid: true, cleanedDomains } } /** * Cleans a domain string by removing common user input mistakes * Does NOT validate - use validateEmailDomain for validation * * @param domain - The domain string to clean * @returns Cleaned domain string */ export function cleanEmailDomain(domain: string): string { if (!domain || typeof domain !== 'string') { return '' } let cleaned = domain.trim().toLowerCase() // Remove leading @ if (cleaned.startsWith('@')) { cleaned = cleaned.substring(1) } // Remove protocol if present cleaned = cleaned.replace(/^https?:\/\//, '') // Remove trailing slash and path cleaned = cleaned.split('/')[0] // Remove www. prefix cleaned = cleaned.replace(/^www\./, '') return cleaned }