Switch ServiceMeta.Domain, ServiceMeta.Ttl, ServiceMeta.NbResources, and ZoneMeta.DefaultTTL from binding:"required" to validate:"required". This keeps them marked as required in the OpenAPI spec (swaggo reads both tags) without gin rejecting valid zero values (0 for uint32, "" for root domain).
138 lines
4.8 KiB
Go
138 lines
4.8 KiB
Go
// This file is part of the happyDomain (R) project.
|
|
// Copyright (c) 2020-2024 happyDomain
|
|
// Authors: Pierre-Olivier Mercier, et al.
|
|
//
|
|
// This program is offered under a commercial and under the AGPL license.
|
|
// For commercial licensing, contact us at <contact@happydomain.org>.
|
|
//
|
|
// For AGPL licensing:
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package happydns
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
type Service struct {
|
|
ServiceMeta
|
|
Service ServiceBody `json:"Service"`
|
|
}
|
|
|
|
func (msg *Service) Meta() *ServiceMeta {
|
|
return &msg.ServiceMeta
|
|
}
|
|
|
|
// MarshalJSON computes Comment and NbResources from Service just before
|
|
// serialization so that these derived fields are always fresh.
|
|
func (s *Service) MarshalJSON() ([]byte, error) {
|
|
if s.Service != nil {
|
|
s.Comment = s.Service.GenComment()
|
|
s.NbResources = s.Service.GetNbResources()
|
|
}
|
|
|
|
type serviceAlias Service
|
|
return json.Marshal((*serviceAlias)(s))
|
|
}
|
|
|
|
// ServiceBody represents a service provided by one or more DNS record.
|
|
type ServiceBody interface {
|
|
// GetNbResources get the number of main Resources contains in the Service.
|
|
GetNbResources() int
|
|
|
|
// GenComment sum up the content of the Service, in a small usefull string.
|
|
GenComment() string
|
|
|
|
// GetRecords retrieves underlying RRs.
|
|
GetRecords(domain string, ttl uint32, origin string) ([]Record, error)
|
|
}
|
|
|
|
// MetadataEnricher is implemented by ServiceBody types that store fields
|
|
// not derivable from DNS records alone. After re-analysis, EnrichFromPrevious
|
|
// is called on the new service body with the previous instance of the same type.
|
|
type MetadataEnricher interface {
|
|
EnrichFromPrevious(old ServiceBody)
|
|
}
|
|
|
|
// SPFContributor is implemented by services that contribute SPF directives.
|
|
// When multiple services implement this interface for the same domain, their
|
|
// directives are merged into a single SPF TXT record (RFC 7208 requires
|
|
// exactly one SPF record per domain).
|
|
type SPFContributor interface {
|
|
// GetSPFDirectives returns the SPF directives this service contributes
|
|
// (e.g. "include:_spf.google.com", "ip4:203.0.113.0/24").
|
|
// The "v=spf1" prefix and "all" mechanism must NOT be included.
|
|
GetSPFDirectives() []string
|
|
|
|
// GetSPFAllPolicy returns the desired "all" policy (e.g. "~all", "-all").
|
|
// Return "" if the service has no opinion; the default is "~all".
|
|
GetSPFAllPolicy() string
|
|
}
|
|
|
|
// ServiceMeta holds the metadata associated to a Service.
|
|
type ServiceMeta struct {
|
|
// Type is the string representation of the Service's type.
|
|
Type string `json:"_svctype" binding:"required" readonly:"true"`
|
|
|
|
// Id is the Service's identifier.
|
|
Id Identifier `json:"_id,omitempty" swaggertype:"string" readonly:"true"`
|
|
|
|
// OwnerId is the User's identifier for the current Service.
|
|
OwnerId Identifier `json:"_ownerid,omitempty" swaggertype:"string"`
|
|
|
|
// Domain contains the abstract domain where this Service relates.
|
|
Domain string `json:"_domain" validate:"required"`
|
|
|
|
// Ttl contains the specific TTL for the underlying Resources.
|
|
Ttl uint32 `json:"_ttl" validate:"required"`
|
|
|
|
// Comment is a string that helps user to distinguish the Service.
|
|
Comment string `json:"_comment,omitempty"`
|
|
|
|
// UserComment is a supplementary string defined by the user to
|
|
// distinguish the Service.
|
|
UserComment string `json:"_mycomment,omitempty"`
|
|
|
|
// Aliases exposes the aliases defined on this Service.
|
|
Aliases []string `json:"_aliases,omitempty"`
|
|
|
|
// NbResources holds the number of Resources stored inside this Service.
|
|
NbResources int `json:"_tmp_hint_nb" validate:"required"`
|
|
|
|
// PropagatedAt is the estimated time at which the last published changes
|
|
// for this service will be fully propagated (old cached records expired).
|
|
PropagatedAt *time.Time `json:"_propagated_at,omitempty" format:"date-time"`
|
|
}
|
|
|
|
// ServiceCombined combined ServiceMeta + Service
|
|
type ServiceMessage struct {
|
|
ServiceMeta
|
|
Service json.RawMessage `json:"Service"`
|
|
}
|
|
|
|
func (msg *ServiceMessage) Meta() *ServiceMeta {
|
|
return &msg.ServiceMeta
|
|
}
|
|
|
|
type ServiceRecord struct {
|
|
Type string `json:"type"`
|
|
String string `json:"str"`
|
|
RR Record `json:"rr,omitempty"`
|
|
}
|
|
|
|
type ServiceUsecase interface {
|
|
ListRecords(*Domain, *Zone, *Service) ([]Record, error)
|
|
ValidateService(ServiceBody, Subdomain, Origin) ([]byte, error)
|
|
}
|