package domain import ( "strings" dnsModel "dove/models/dns" domainModel "dove/models/domain" dnsRepo "dove/repositories/dns" domainRepo "dove/repositories/domain" mailRepo "dove/repositories/mail" "dove/utils/shortcuts" "dove/utils/validate" ) type CreateDomainRequest struct { Name string `form:"name"` TLDName string `form:"tld_name"` } type DomainListResponse struct { Domains []domainModel.Domain `json:"domains"` } type TLDListResponse struct { TLDs []domainModel.TLD `json:"tlds"` } type DomainFormResponse struct { TLDs []domainModel.TLD `json:"tlds"` } func ListTLDs() TLDListResponse { return TLDListResponse{ TLDs: domainRepo.AllTLDs(), } } func ListDomains() DomainListResponse { return DomainListResponse{ Domains: domainRepo.AllDomains(), } } func DomainFormData() DomainFormResponse { return DomainFormResponse{ TLDs: domainRepo.AllTLDs(), } } func CreateDomain(request CreateDomainRequest) *shortcuts.Error { name := strings.TrimSpace(strings.ToLower(request.Name)) tldName := strings.TrimSpace(strings.ToLower(request.TLDName)) switch { case name == "": return shortcuts.ServiceError(shortcuts.BadRequest, DomainNameRequired) case !validate.DNSLabel(name): return shortcuts.ServiceError(shortcuts.BadRequest, DomainNameInvalid) case tldName == "": return shortcuts.ServiceError(shortcuts.BadRequest, DomainTLDRequired) } tld := domainRepo.FindTLDByName(tldName) switch { case tld == nil: return shortcuts.ServiceError(shortcuts.Unprocessable, TLDNotFound) case domainRepo.FindDomainByFullName(name, tldName) != nil: return shortcuts.ServiceError(shortcuts.Unprocessable, DomainAlreadyExists) } newDomain := &domainModel.Domain{ Name: name, TLDID: tld.ID, } if createError := domainRepo.CreateDomain(newDomain); createError != nil { return shortcuts.ServiceError(shortcuts.Internal, DomainCreationFailed) } seedDefaultRecords(newDomain.ID, name, tldName) return nil } func DeleteDomain(domainID uint) *shortcuts.Error { foundDomain := domainRepo.FindDomainByID(domainID) if foundDomain == nil { return shortcuts.ServiceError(shortcuts.NotFound, DomainNotFound) } if mailRepo.CountMailboxesByDomainID(foundDomain.ID) > 0 { return shortcuts.ServiceError(shortcuts.Unprocessable, DomainHasMailboxes) } deleteAllDNSRecords(foundDomain.ID) if deleteError := domainRepo.DeleteDomain(foundDomain); deleteError != nil { return shortcuts.ServiceError(shortcuts.Internal, DomainDeletionFailed) } return nil } func seedDefaultRecords(domainID uint, domainName string, tldName string) { mailHostname := DefaultMXTarget + "." + domainName + "." + tldName + "." dnsRepo.CreateARecord(&dnsModel.ARecord{ DomainID: domainID, Name: "@", Address: DefaultAddress, }) dnsRepo.CreateARecord(&dnsModel.ARecord{ DomainID: domainID, Name: DefaultMXTarget, Address: DefaultAddress, }) dnsRepo.CreateMXRecord(&dnsModel.MXRecord{ DomainID: domainID, Name: "@", Target: mailHostname, Priority: 10, }) dnsRepo.CreateSRVRecord(&dnsModel.SRVRecord{ DomainID: domainID, Name: "_submission._tcp", Target: mailHostname, Port: 587, Priority: 0, Weight: 0, Protocol: "tcp", }) dnsRepo.CreateSRVRecord(&dnsModel.SRVRecord{ DomainID: domainID, Name: "_imap._tcp", Target: mailHostname, Port: 143, Priority: 0, Weight: 0, Protocol: "tcp", }) dnsRepo.CreateSRVRecord(&dnsModel.SRVRecord{ DomainID: domainID, Name: "_pop3._tcp", Target: mailHostname, Port: 110, Priority: 0, Weight: 0, Protocol: "tcp", }) } func deleteAllDNSRecords(domainID uint) { dnsRepo.DeleteARecordsByDomainID(domainID) dnsRepo.DeleteAAAARecordsByDomainID(domainID) dnsRepo.DeleteCNAMERecordsByDomainID(domainID) dnsRepo.DeleteMXRecordsByDomainID(domainID) dnsRepo.DeleteTXTRecordsByDomainID(domainID) dnsRepo.DeleteSRVRecordsByDomainID(domainID) }