WIP Can import domain through dnscontrol

This commit is contained in:
nemunaire 2021-05-21 13:08:18 +02:00
parent af5c500215
commit 4a431565df
10 changed files with 94 additions and 27 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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),
}

View File

@ -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
}

View File

@ -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

View File

@ -64,7 +64,7 @@
<template v-else-if="listImportableDomains.length === 0" #no-domain>
<b-list-group-item class="text-center">
<i18n path="errors.domain-all-imported">
{{ sourceSpecs_getAll[provider._srctype].name }}
{{ providerSpecs_getAll[provider._srctype].name }}
</i18n>
</b-list-group-item>
</template>
@ -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
}

View File

@ -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/')
}
)
},