From fd72f3bff8d554326167977fcc987519d3d497e4 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Sat, 10 Oct 2020 18:47:41 +0200 Subject: [PATCH] Refactor service add --- api/zones.go | 17 ++-------- model/service.go | 16 ++++++++++ model/zone.go | 81 ++++++++++++++++++++++++++++++++++-------------- 3 files changed, 76 insertions(+), 38 deletions(-) diff --git a/api/zones.go b/api/zones.go index 4683779..b62bd06 100644 --- a/api/zones.go +++ b/api/zones.go @@ -32,7 +32,6 @@ package api import ( - "crypto/sha1" "encoding/hex" "encoding/json" "errors" @@ -129,23 +128,13 @@ func addZoneService(opts *config.Options, req *RequestResources, body io.Reader) subdomain := strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(req.Ps.ByName("subdomain"), "."+req.Domain.DomainName), "@"), req.Domain.DomainName) - records := usc.Service.GenRRs(subdomain, usc.Ttl, req.Domain.DomainName) - if len(records) == 0 { + err = req.Zone.AppendService(subdomain, req.Domain.DomainName, usc) + if err != nil { return APIErrorResponse{ - err: fmt.Errorf("No record can be generated from your service."), + err: err, } } - hash := sha1.New() - io.WriteString(hash, records[0].String()) - - usc.Id = hash.Sum(nil) - usc.Domain = subdomain - usc.NbResources = usc.Service.GetNbResources() - usc.Comment = usc.Service.GenComment(req.Domain.DomainName) - - req.Zone.Services[subdomain] = append(req.Zone.Services[subdomain], usc) - err = storage.MainStore.UpdateZone(req.Zone) if err != nil { return APIErrorResponse{ diff --git a/model/service.go b/model/service.go index af50423..c72c28a 100644 --- a/model/service.go +++ b/model/service.go @@ -32,6 +32,10 @@ package happydns import ( + "crypto/sha1" + "fmt" + "io" + "github.com/miekg/dns" ) @@ -93,3 +97,15 @@ var UnmarshalServiceJSON func(*ServiceCombined, []byte) error func (svc *ServiceCombined) UnmarshalJSON(b []byte) error { return UnmarshalServiceJSON(svc, b) } + +func ValidateService(svc Service, subdomain, origin string) ([]byte, error) { + records := svc.GenRRs(subdomain, 0, origin) + if len(records) == 0 { + return nil, fmt.Errorf("No record can be generated from your service.") + } else { + hash := sha1.New() + io.WriteString(hash, records[0].String()) + + return hash.Sum(nil), nil + } +} diff --git a/model/zone.go b/model/zone.go index 1a65f77..7bc6040 100644 --- a/model/zone.go +++ b/model/zone.go @@ -85,6 +85,22 @@ func (z *Zone) DerivateNew() *Zone { return newZone } +func (z *Zone) AppendService(subdomain string, origin string, svc *ServiceCombined) error { + hash, err := ValidateService(svc.Service, subdomain, origin) + if err != nil { + return err + } + + svc.Id = hash + svc.Domain = subdomain + svc.NbResources = svc.Service.GetNbResources() + svc.Comment = svc.Service.GenComment(origin) + + z.Services[subdomain] = append(z.Services[subdomain], svc) + + return nil +} + // FindService finds the Service identified by the given id. func (z *Zone) FindService(id []byte) (string, *ServiceCombined) { for subdomain := range z.Services { @@ -96,12 +112,40 @@ func (z *Zone) FindService(id []byte) (string, *ServiceCombined) { return "", nil } +func (z *Zone) findSubdomainService(subdomain string, id []byte) (int, *ServiceCombined) { + if services, ok := z.Services[subdomain]; ok { + for k, svc := range services { + if bytes.Equal(svc.Id, id) { + return k, svc + } + } + } + + return -1, nil +} + // FindSubdomainService finds the Service identified by the given id, only under the given subdomain. func (z *Zone) FindSubdomainService(domain string, id []byte) *ServiceCombined { - for _, svc := range z.Services[domain] { - if bytes.Equal(svc.Id, id) { - return svc + _, svc := z.findSubdomainService(domain, id) + return svc +} + +func (z *Zone) eraseService(subdomain, origin string, old *ServiceCombined, idx int, new *ServiceCombined) error { + if new == nil { + // Disallow removing SOA + if subdomain == "" && old.Type == "abstract.Origin" { + return errors.New("You cannot delete this service. It is mandatory.") } + + if len(z.Services[subdomain]) <= 1 { + delete(z.Services, subdomain) + } else { + z.Services[subdomain] = append(z.Services[subdomain][:idx], z.Services[subdomain][idx+1:]...) + } + } else { + new.Comment = new.GenComment(origin) + new.NbResources = new.GetNbResources() + z.Services[subdomain][idx] = new } return nil @@ -110,27 +154,16 @@ func (z *Zone) FindSubdomainService(domain string, id []byte) *ServiceCombined { // EraseService overwrites the Service identified by the given id, under the given subdomain. // The the new service is nil, it removes the existing Service instead of overwrite it. func (z *Zone) EraseService(subdomain string, origin string, id []byte, s *ServiceCombined) error { - if services, ok := z.Services[subdomain]; ok { - for k, svc := range services { - if bytes.Equal(svc.Id, id) { - if s == nil { - // Disallow removing SOA - if subdomain == "" && svc.Type == "abstract.Origin" { - return errors.New("You cannot delete this service. It is mandatory.") - } - if len(z.Services[subdomain]) <= 1 { - delete(z.Services, subdomain) - } else { - z.Services[subdomain] = append(z.Services[subdomain][:k], z.Services[subdomain][k+1:]...) - } - } else { - s.Comment = s.GenComment(origin) - s.NbResources = s.GetNbResources() - z.Services[subdomain][k] = s - } - return nil - } - } + if idx, svc := z.findSubdomainService(subdomain, id); svc != nil { + return z.eraseService(subdomain, origin, svc, idx, s) + } + + return errors.New("Service not found") +} + +func (z *Zone) EraseServiceWithoutMeta(subdomain string, origin string, id []byte, s Service) error { + if idx, svc := z.findSubdomainService(subdomain, id); svc != nil { + return z.eraseService(subdomain, origin, svc, idx, &ServiceCombined{Service: s, ServiceMeta: svc.ServiceMeta}) } return errors.New("Service not found")