package migration import ( "encoding/json" "strings" "github.com/ultisuite/ulti-backend/internal/mail/hosted" ) var projectSelectColumns = []string{ "id::text", "COALESCE(domain_id::text, '')", "name", "source_provider", "auth_mode", "status", "cutover_at::text", "delta_mode", "created_at::text", "NULLIF(microsoft_tenant_id, '')", "microsoft_admin_consent_at::text", "COALESCE(NULLIF(microsoft_admin_consent_error, ''), '')", "cutover_dns_json", } func projectSelectSQL(tablePrefix string) string { if tablePrefix != "" && !strings.HasSuffix(tablePrefix, ".") { tablePrefix += "." } cols := make([]string, len(projectSelectColumns)) for i, col := range projectSelectColumns { cols[i] = tablePrefix + col } return strings.Join(cols, ", ") } type projectScanner struct { project Project cutoverDNSRaw []byte } func newProjectScanner() *projectScanner { return &projectScanner{} } func (s *projectScanner) targets() []any { return []any{ &s.project.ID, &s.project.DomainID, &s.project.Name, &s.project.SourceProvider, &s.project.AuthMode, &s.project.Status, &s.project.CutoverAt, &s.project.DeltaMode, &s.project.CreatedAt, &s.project.MicrosoftTenantID, &s.project.MicrosoftAdminConsentAt, &s.project.MicrosoftAdminConsentError, &s.cutoverDNSRaw, } } func (s *projectScanner) result() Project { applyCutoverDNS(&s.project, s.cutoverDNSRaw) return s.project } func applyCutoverDNS(p *Project, raw []byte) { p.CutoverDNS = nil raw = bytesTrimSpace(raw) if len(raw) == 0 || string(raw) == "{}" || string(raw) == "null" { return } var report hosted.DNSCheckReport if err := json.Unmarshal(raw, &report); err != nil { return } if !dnsReportHasContent(report) { return } p.CutoverDNS = &report } func dnsReportHasContent(r hosted.DNSCheckReport) bool { if strings.TrimSpace(r.Domain) != "" { return true } if len(r.Errors) > 0 || len(r.Warnings) > 0 { return true } if len(r.MXRecords) > 0 || len(r.TXTRecords) > 0 || len(r.ExpectedMX) > 0 { return true } if r.TXTVerified || r.MXVerified { return true } return strings.TrimSpace(r.TXTExpected) != "" } func bytesTrimSpace(b []byte) []byte { return []byte(strings.TrimSpace(string(b))) }