diff --git a/api/domains.go b/api/domains.go index a26ea38..bed94d4 100644 --- a/api/domains.go +++ b/api/domains.go @@ -101,7 +101,7 @@ func addDomain(c *gin.Context) { user := c.MustGet("LoggedUser").(*happydns.User) - source, err := storage.MainStore.GetSource(user, uz.IdSource) + provider, err := storage.MainStore.GetProvider(user, uz.IdProvider) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Unable to find the provider.")}) return @@ -111,7 +111,7 @@ func addDomain(c *gin.Context) { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "This domain has already been imported."}) return - } else if err := source.DomainExists(uz.DomainName); err != nil { + } else if err := provider.DomainExists(uz.DomainName); err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) return } else if err := storage.MainStore.CreateDomain(user, &uz); err != nil { @@ -144,7 +144,7 @@ func DomainHandler(c *gin.Context) { } else if src, exists := c.Get("sourcemeta"); exists { source = src.(*happydns.SourceMeta) } - if source != nil && source.Id != domain.IdSource { + if source != nil && source.Id != domain.IdProvider { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found (not child of source)"}) return } @@ -167,7 +167,7 @@ func GetDomain(c *gin.Context) { ret := &apiDomain{ Id: domain.Id, IdUser: domain.IdUser, - IdSource: domain.IdSource, + IdSource: domain.IdProvider, DomainName: domain.DomainName, ZoneHistory: []happydns.ZoneMeta{}, } @@ -188,7 +188,7 @@ func GetDomain(c *gin.Context) { func delDomain(c *gin.Context) { if err := storage.MainStore.DeleteDomain(c.MustGet("domain").(*happydns.Domain)); err != nil { log.Printf("%s was unable to DeleteDomain: %w", c.ClientIP(), err) - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to delete your domain: %w", err)}) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to delete your domain: %s", err.Error())}) return } @@ -199,9 +199,9 @@ func axfrDomain(c *gin.Context) { user := c.MustGet("LoggedUser").(*happydns.User) domain := c.MustGet("domain").(*happydns.Domain) - source, err := storage.MainStore.GetSource(user, domain.IdSource) + source, err := storage.MainStore.GetSource(user, domain.IdProvider) if err != nil { - c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": fmt.Sprintf("Unable to find your provider: %w", err)}) + c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": fmt.Sprintf("Unable to find your provider: %s", err.Error())}) return } @@ -246,7 +246,7 @@ func prepareRR(next func(c *gin.Context, source *happydns.SourceCombined, domain return } - source, err := storage.MainStore.GetSource(user, domain.IdSource) + source, err := storage.MainStore.GetSource(user, domain.IdProvider) if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": fmt.Sprintf("Unable to find the required source: %w", err)}) return diff --git a/api/providers.go b/api/providers.go index 921576b..2107d5d 100644 --- a/api/providers.go +++ b/api/providers.go @@ -100,7 +100,7 @@ func DecodeProvider(c *gin.Context) (*happydns.ProviderCombined, int, error) { return nil, http.StatusBadRequest, err } - _, err = src.NewDNSServiceProvider() + err = src.Validate() if err != nil { return nil, http.StatusBadRequest, err } diff --git a/api/services.go b/api/services.go index 207a73b..96fe0aa 100644 --- a/api/services.go +++ b/api/services.go @@ -67,7 +67,7 @@ func analyzeDomain(c *gin.Context) { return } - source, err := storage.MainStore.GetSource(user, domain.IdSource) + source, err := storage.MainStore.GetSource(user, domain.IdProvider) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Unable to get the related source: %w", err)}) return diff --git a/api/sources.go b/api/sources.go index 983d460..7047cd4 100644 --- a/api/sources.go +++ b/api/sources.go @@ -233,7 +233,7 @@ func deleteSource(c *gin.Context) { } for _, domain := range domains { - if domain.IdSource == sourcemeta.Id { + if domain.IdProvider == sourcemeta.Id { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You cannot delete this source because there is still some domains associated with it."}) return } diff --git a/api/zones.go b/api/zones.go index 5dda365..d09f17b 100644 --- a/api/zones.go +++ b/api/zones.go @@ -192,13 +192,13 @@ func importZone(c *gin.Context) { user := c.MustGet("LoggedUser").(*happydns.User) domain := c.MustGet("domain").(*happydns.Domain) - source, err := storage.MainStore.GetSource(user, domain.IdSource) + provider, err := storage.MainStore.GetProvider(user, domain.IdProvider) if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": fmt.Sprintf("Unable to find your provider: %w", err)}) return } - zone, err := source.ImportZone(domain) + zone, err := provider.ImportZone(domain) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) return @@ -251,9 +251,9 @@ func importZone(c *gin.Context) { func loadRecordsFromZoneId(user *happydns.User, domain *happydns.Domain, id string) ([]dns.RR, int, error) { if id == "@" { - source, err := storage.MainStore.GetSource(user, domain.IdSource) + source, err := storage.MainStore.GetSource(user, domain.IdProvider) if err != nil { - return nil, http.StatusNotFound, fmt.Errorf("Unable to find the given source: %q for %q", domain.IdSource, domain.DomainName) + return nil, http.StatusNotFound, fmt.Errorf("Unable to find the given source: %q for %q", domain.IdProvider, domain.DomainName) } rrs, err := source.ImportZone(domain) @@ -309,7 +309,7 @@ func applyZone(c *gin.Context) { domain := c.MustGet("domain").(*happydns.Domain) zone := c.MustGet("zone").(*happydns.Zone) - source, err := storage.MainStore.GetSource(user, domain.IdSource) + source, err := storage.MainStore.GetSource(user, domain.IdProvider) if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": fmt.Sprintf("Unable to find your provider: %w", err)}) return diff --git a/model/domain.go b/model/domain.go index f845c4c..00c49ff 100644 --- a/model/domain.go +++ b/model/domain.go @@ -43,9 +43,9 @@ type Domain struct { // IdUser is the identifier of the Domain's Owner. IdUser int64 `json:"id_owner"` - // IsSource is the identifier of the Source used to access and edit the + // IsProvider is the identifier of the Provider used to access and edit the // Domain. - IdSource int64 `json:"id_source"` + IdProvider int64 `json:"id_provider"` // DomainName is the FQDN of the managed Domain. DomainName string `json:"domain"` @@ -70,10 +70,10 @@ func (d *Domain) HasZone(zoneId int64) (found bool) { } // NewDomain fills a new Domain structure. -func NewDomain(u *User, st *SourceMeta, dn string) (d *Domain) { +func NewDomain(u *User, st *ProviderMeta, dn string) (d *Domain) { d = &Domain{ IdUser: u.Id, - IdSource: st.Id, + IdProvider: st.Id, DomainName: dns.Fqdn(dn), } diff --git a/model/provider.go b/model/provider.go index 31b2c51..2ad9147 100644 --- a/model/provider.go +++ b/model/provider.go @@ -32,7 +32,11 @@ package happydns import ( + "fmt" + "strings" + "github.com/StackExchange/dnscontrol/v3/providers" + "github.com/miekg/dns" ) // Provider is where Domains and Zones can be managed. @@ -60,3 +64,54 @@ type ProviderCombined struct { Provider ProviderMeta } + +func (p *ProviderCombined) Validate() (err error) { + _, err = p.NewDNSServiceProvider() + return +} + +func (p *ProviderCombined) DomainExists(fqdn string) (err error) { + var s providers.DNSServiceProvider + s, err = p.NewDNSServiceProvider() + if err != nil { + return + } + + defer func() { + if a := recover(); a != nil { + err = fmt.Errorf("%s", a) + } + }() + + _, err = s.GetZoneRecords(strings.TrimSuffix(fqdn, ".")) + if err != nil { + return + } + + return nil +} + +func (p *ProviderCombined) ImportZone(dn *Domain) (rrs []dns.RR, err error) { + var s providers.DNSServiceProvider + s, err = p.NewDNSServiceProvider() + if err != nil { + return + } + + defer func() { + if a := recover(); a != nil { + err = fmt.Errorf("%s", a) + } + }() + + rcs, err := s.GetZoneRecords(strings.TrimSuffix(dn.DomainName, ".")) + if err != nil { + return rrs, err + } + + for _, rc := range rcs { + rrs = append(rrs, rc.ToRR()) + } + + return +} diff --git a/storage/leveldb/domain.go b/storage/leveldb/domain.go index 129426a..5303d20 100644 --- a/storage/leveldb/domain.go +++ b/storage/leveldb/domain.go @@ -193,11 +193,11 @@ func (s *LevelDBStorage) TidyDomains() error { log.Printf("Deleting orphan domain (user %d not found): %v\n", domain.IdUser, domain) } - _, err = s.GetSource(u, domain.IdSource) + _, err = s.GetSource(u, domain.IdProvider) if err == leveldb.ErrNotFound { // Drop domain of unexistant source err = tx.Delete(iter.Key(), nil) - log.Printf("Deleting orphan domain (source %d not found): %v\n", domain.IdSource, domain) + log.Printf("Deleting orphan domain (source %d not found): %v\n", domain.IdProvider, domain) } } else { // Drop unreadable domains diff --git a/ui/src/components/hProviderListDomains.vue b/ui/src/components/hProviderListDomains.vue index 24d54d7..5cc8b01 100644 --- a/ui/src/components/hProviderListDomains.vue +++ b/ui/src/components/hProviderListDomains.vue @@ -64,7 +64,7 @@ @@ -136,10 +136,10 @@ export default { }, noDomainsList () { - return !this.sourceSpecs_getAll[this.provider._srctype] || !this.sourceSpecs_getAll[this.provider._srctype].capabilities || this.sourceSpecs_getAll[this.provider._srctype].capabilities.indexOf('ListDomains') === -1 + return !this.providerSpecs_getAll[this.provider._srctype] || !this.providerSpecs_getAll[this.provider._srctype].capabilities || this.providerSpecs_getAll[this.provider._srctype].capabilities.indexOf('ListDomains') === -1 }, - ...mapGetters('sourceSpecs', ['sourceSpecs_getAll']), + ...mapGetters('providerSpecs', ['providerSpecs_getAll']), ...mapGetters('domains', ['domains_getAll']) }, @@ -152,7 +152,7 @@ export default { this.getImportableDomains() }, - sourceSpecs_getAll: function (ss) { + providerSpecs_getAll: function (ss) { if (ss) { this.getImportableDomains() } @@ -241,7 +241,7 @@ export default { this.$router.replace('/providers/' + encodeURIComponent(this.myProvider._id)) }) - if (!this.showDomainsWithActions || this.sourceSpecs_getAll[this.provider._srctype].capabilities.indexOf('ListDomainsWithActions') === -1) { + if (!this.showDomainsWithActions || this.providerSpecs_getAll[this.provider._srctype].capabilities.indexOf('ListDomainsWithActions') === -1) { return } diff --git a/ui/src/views/domain.vue b/ui/src/views/domain.vue index 65de574..5e6ec18 100644 --- a/ui/src/views/domain.vue +++ b/ui/src/views/domain.vue @@ -230,6 +230,18 @@ export default { this.importInProgress = false this.updateDomainInfo() this.selectedHistory = response.data.id + }, + (error) => { + this.importInProgress = false + this.$root.$bvToast.toast( + error.response.data.errmsg, { + title: this.$t('errors.occurs', { when: 'importing the zone' }), + autoHideDelay: 5000, + variant: 'danger', + toaster: 'b-toaster-content-right' + } + ) + this.$router.push('/domains/') } ) },