Can delete a record in a service
This commit is contained in:
parent
9d5f23cef6
commit
f5911cb256
10 changed files with 468 additions and 17 deletions
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/helpers"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
|
@ -208,3 +209,58 @@ func (zc *ZoneController) ExportZone(c *gin.Context) {
|
|||
|
||||
c.JSON(http.StatusOK, ret)
|
||||
}
|
||||
|
||||
//
|
||||
// @Summary Delete a given record in the zone.
|
||||
// @Schemes
|
||||
// @Description Delete a given record in the zone.
|
||||
// @Tags zones
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security securitydefinitions.basic
|
||||
// @Param domainId path string true "Domain identifier"
|
||||
// @Param zoneId path string true "Zone identifier"
|
||||
// @Param body body []string true "Records to delete as text, one record per line array"
|
||||
// @Success 200 {object} happydns.Zone "The updated zone"
|
||||
// @Failure 401 {object} happydns.ErrorResponse "Authentication failure"
|
||||
// @Failure 404 {object} happydns.ErrorResponse "Domain or Zone not found"
|
||||
// @Router /domains/{domainId}/zone/{zoneId}/records/delete [post]
|
||||
func (zc *ZoneController) DeleteRecords(c *gin.Context) {
|
||||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
zone := c.MustGet("zone").(*happydns.Zone)
|
||||
|
||||
var records []string
|
||||
err := c.ShouldBindJSON(&records)
|
||||
if err != nil {
|
||||
log.Printf("%s sends invalid JSON record: %s", c.ClientIP(), err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
rr, err := helpers.ParseRecord(record, domain.DomainName)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Make record relative
|
||||
rr = helpers.RRRelative(rr, domain.DomainName)
|
||||
|
||||
err = zc.zoneService.DeleteRecord(zone, domain.DomainName, rr)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = zc.zoneService.UpdateZone(zone.Id, func(z *happydns.Zone) {
|
||||
z.Services = zone.Services
|
||||
})
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, zone)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,4 +50,6 @@ func DeclareZoneRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDep
|
|||
apiZonesSubdomainRoutes.GET("", zc.GetZoneSubdomain)
|
||||
|
||||
DeclareZoneServiceRoutes(apiZonesRoutes, apiZonesSubdomainRoutes, zc, dependancies)
|
||||
|
||||
apiZonesRoutes.POST("/records/delete", zc.DeleteRecords)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,25 @@ func NewRecord(domain string, rrtype string, ttl uint32, origin string) happydns
|
|||
return rr
|
||||
}
|
||||
|
||||
func ParseRecord(input, origin string) (happydns.Record, error) {
|
||||
zp := dns.NewZoneParser(strings.NewReader(input), origin, "")
|
||||
zp.SetDefaultTTL(0)
|
||||
zp.SetIncludeAllowed(false)
|
||||
|
||||
rr, _ := zp.Next()
|
||||
if err := zp.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if rr.Header().Rrtype == dns.TypeTXT {
|
||||
return happydns.NewTXT(rr.(*dns.TXT)), nil
|
||||
} else if rr.Header().Rrtype == dns.TypeSPF {
|
||||
return happydns.NewSPF(rr.(*dns.SPF)), nil
|
||||
}
|
||||
|
||||
return rr, nil
|
||||
}
|
||||
|
||||
// RRRelative strips the end of the given RR if it is relative to origin.
|
||||
func RRRelative(rr happydns.Record, origin string) happydns.Record {
|
||||
if !strings.HasSuffix(origin, ".") {
|
||||
|
|
|
|||
|
|
@ -332,6 +332,185 @@ func TestNewRecord(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestParseRecord(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
origin string
|
||||
wantError bool
|
||||
validate func(t *testing.T, rr dns.RR)
|
||||
}{
|
||||
{
|
||||
name: "SOA record",
|
||||
input: "@ 3600 IN SOA a.misconfigured.dns.server.invalid. hostmaster 2025091001 10800 3600 604800 3600",
|
||||
origin: "example.com.",
|
||||
wantError: false,
|
||||
validate: func(t *testing.T, rr dns.RR) {
|
||||
soa, ok := rr.(*dns.SOA)
|
||||
if !ok {
|
||||
t.Fatal("Expected *dns.SOA type")
|
||||
}
|
||||
if soa.Ns != "a.misconfigured.dns.server.invalid." {
|
||||
t.Errorf("Expected Ns a.misconfigured.dns.server.invalid., got %s", soa.Ns)
|
||||
}
|
||||
if soa.Mbox != "hostmaster.example.com." {
|
||||
t.Errorf("Expected Mbox hostmaster.example.com., got %s", soa.Mbox)
|
||||
}
|
||||
if soa.Header().Ttl != 3600 {
|
||||
t.Errorf("Expected TTL 3600, got %d", soa.Header().Ttl)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "A record",
|
||||
input: "www 3600 IN A 192.0.2.1",
|
||||
origin: "example.com.",
|
||||
wantError: false,
|
||||
validate: func(t *testing.T, rr dns.RR) {
|
||||
a, ok := rr.(*dns.A)
|
||||
if !ok {
|
||||
t.Fatal("Expected *dns.A type")
|
||||
}
|
||||
if a.A.String() != "192.0.2.1" {
|
||||
t.Errorf("Expected IP 192.0.2.1, got %s", a.A.String())
|
||||
}
|
||||
if a.Header().Ttl != 3600 {
|
||||
t.Errorf("Expected TTL 3600, got %d", a.Header().Ttl)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "AAAA record",
|
||||
input: "www 7200 IN AAAA 2001:db8::1",
|
||||
origin: "example.com.",
|
||||
wantError: false,
|
||||
validate: func(t *testing.T, rr dns.RR) {
|
||||
aaaa, ok := rr.(*dns.AAAA)
|
||||
if !ok {
|
||||
t.Fatal("Expected *dns.AAAA type")
|
||||
}
|
||||
if aaaa.AAAA.String() != "2001:db8::1" {
|
||||
t.Errorf("Expected IP 2001:db8::1, got %s", aaaa.AAAA.String())
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MX record",
|
||||
input: "@ 1800 IN MX 10 mail.example.com.",
|
||||
origin: "example.com.",
|
||||
wantError: false,
|
||||
validate: func(t *testing.T, rr dns.RR) {
|
||||
mx, ok := rr.(*dns.MX)
|
||||
if !ok {
|
||||
t.Fatal("Expected *dns.MX type")
|
||||
}
|
||||
if mx.Preference != 10 {
|
||||
t.Errorf("Expected preference 10, got %d", mx.Preference)
|
||||
}
|
||||
if mx.Mx != "mail.example.com." {
|
||||
t.Errorf("Expected Mx 'mail.example.com.', got %q", mx.Mx)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CNAME record",
|
||||
input: "www 600 IN CNAME target.example.com.",
|
||||
origin: "example.com.",
|
||||
wantError: false,
|
||||
validate: func(t *testing.T, rr dns.RR) {
|
||||
cname, ok := rr.(*dns.CNAME)
|
||||
if !ok {
|
||||
t.Fatal("Expected *dns.CNAME type")
|
||||
}
|
||||
if cname.Target != "target.example.com." {
|
||||
t.Errorf("Expected Target 'target.example.com.', got %q", cname.Target)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "TXT record with single value",
|
||||
input: "_dmarc 300 IN TXT \"v=DMARC1; p=none\"",
|
||||
origin: "example.com.",
|
||||
wantError: false,
|
||||
validate: func(t *testing.T, rr dns.RR) {
|
||||
// ParseRecord returns happydns.TXT for TXT records
|
||||
if rr.Header().Rrtype != dns.TypeTXT {
|
||||
t.Errorf("Expected TypeTXT, got %d", rr.Header().Rrtype)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "NS record",
|
||||
input: "@ 86400 IN NS ns1.example.com.",
|
||||
origin: "example.com.",
|
||||
wantError: false,
|
||||
validate: func(t *testing.T, rr dns.RR) {
|
||||
ns, ok := rr.(*dns.NS)
|
||||
if !ok {
|
||||
t.Fatal("Expected *dns.NS type")
|
||||
}
|
||||
if ns.Ns != "ns1.example.com." {
|
||||
t.Errorf("Expected Ns 'ns1.example.com.', got %q", ns.Ns)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SRV record",
|
||||
input: "_http._tcp 3600 IN SRV 10 60 80 target.example.com.",
|
||||
origin: "example.com.",
|
||||
wantError: false,
|
||||
validate: func(t *testing.T, rr dns.RR) {
|
||||
srv, ok := rr.(*dns.SRV)
|
||||
if !ok {
|
||||
t.Fatal("Expected *dns.SRV type")
|
||||
}
|
||||
if srv.Priority != 10 {
|
||||
t.Errorf("Expected Priority 10, got %d", srv.Priority)
|
||||
}
|
||||
if srv.Weight != 60 {
|
||||
t.Errorf("Expected Weight 60, got %d", srv.Weight)
|
||||
}
|
||||
if srv.Port != 80 {
|
||||
t.Errorf("Expected Port 80, got %d", srv.Port)
|
||||
}
|
||||
if srv.Target != "target.example.com." {
|
||||
t.Errorf("Expected Target 'target.example.com.', got %q", srv.Target)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid record",
|
||||
input: "invalid record format",
|
||||
origin: "example.com.",
|
||||
wantError: true,
|
||||
validate: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := ParseRecord(tt.input, tt.origin)
|
||||
if tt.wantError {
|
||||
if err == nil {
|
||||
t.Error("Expected error, got nil")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if result == nil {
|
||||
t.Fatal("ParseRecord returned nil")
|
||||
}
|
||||
if tt.validate != nil {
|
||||
if dnsrr, ok := result.(dns.RR); ok {
|
||||
tt.validate(t, dnsrr)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRRRelative(t *testing.T) {
|
||||
origin := "example.com."
|
||||
|
||||
|
|
|
|||
162
internal/usecase/zone/delete_record.go
Normal file
162
internal/usecase/zone/delete_record.go
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2025 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 zone
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/helpers"
|
||||
"git.happydns.org/happyDomain/internal/usecase/service"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
"git.happydns.org/happyDomain/services"
|
||||
)
|
||||
|
||||
type DeleteRecordUsecase struct {
|
||||
serviceListRecordsUC *service.ListRecordsUsecase
|
||||
serviceSearchRecordUC *service.SearchRecordUsecase
|
||||
}
|
||||
|
||||
func NewDeleteRecordUsecase(serviceListRecordsUC *service.ListRecordsUsecase, serviceSearchRecordUC *service.SearchRecordUsecase) *DeleteRecordUsecase {
|
||||
return &DeleteRecordUsecase{
|
||||
serviceListRecordsUC: serviceListRecordsUC,
|
||||
serviceSearchRecordUC: serviceSearchRecordUC,
|
||||
}
|
||||
}
|
||||
|
||||
func (uc *DeleteRecordUsecase) delete(zone *happydns.Zone, origin string, record happydns.Record, svc *happydns.Service, dn happydns.Subdomain) error {
|
||||
// Export service related records
|
||||
svc_rrs, err := uc.serviceListRecordsUC.List(svc, origin, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record = helpers.RRAbsolute(record, origin)
|
||||
|
||||
// Drop given record
|
||||
rr_found := false
|
||||
for i, svc_rr := range svc_rrs {
|
||||
if svc_rr.String() == record.String() {
|
||||
svc_rrs = append(svc_rrs[:i], svc_rrs[i+1:]...)
|
||||
rr_found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !rr_found {
|
||||
return fmt.Errorf("unable to find record")
|
||||
}
|
||||
|
||||
var newsvc map[happydns.Subdomain][]*happydns.Service
|
||||
|
||||
if len(svc_rrs) > 0 {
|
||||
// Recreate the service
|
||||
newsvc, _, err = svcs.AnalyzeZone(origin, svc_rrs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Register in zone
|
||||
for i, s := range zone.Services[dn] {
|
||||
if s.Id.Equals(svc.Id) {
|
||||
nextsvcs := zone.Services[dn][i+1:]
|
||||
zone.Services[dn] = append(zone.Services[dn][:i], newsvc[dn]...)
|
||||
zone.Services[dn] = append(zone.Services[dn], nextsvcs...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (uc *DeleteRecordUsecase) Delete(zone *happydns.Zone, origin string, record happydns.Record) error {
|
||||
dn, svc, err := uc.serviceSearchRecordUC.Search(zone, record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if svc == nil {
|
||||
return fmt.Errorf("unable to delete record: record not found")
|
||||
}
|
||||
|
||||
err = uc.delete(zone, origin, record, svc, dn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if svc.Type == "svcs.Orphan" {
|
||||
err = uc.ReanalyzeOrphan(zone, origin, dn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (uc *DeleteRecordUsecase) ReanalyzeOrphan(zone *happydns.Zone, origin string, dn happydns.Subdomain) error {
|
||||
var records []happydns.Record
|
||||
|
||||
// Found all orphan records
|
||||
for _, svc := range zone.Services[dn] {
|
||||
if svc.Type == "svcs.Orphan" {
|
||||
svc_rrs, err := uc.serviceListRecordsUC.List(svc, origin, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
records = append(records, svc_rrs...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(records) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Redo analysis
|
||||
newsvcs, _, err := svcs.AnalyzeZone(origin, records)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for dn, nsvcs := range newsvcs {
|
||||
for _, svc := range nsvcs {
|
||||
if reflect.Indirect(reflect.ValueOf(svc)).Type().String() != reflect.ValueOf(svcs.Orphan{}).Type().String() {
|
||||
svc_rrs, err := uc.serviceListRecordsUC.List(svc, origin, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, record := range svc_rrs {
|
||||
err = uc.delete(zone, origin, record, svc, dn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
zone.Services[dn] = append(zone.Services[dn], svc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -27,12 +27,13 @@ import (
|
|||
)
|
||||
|
||||
type Service struct {
|
||||
CreateZoneUC *CreateZoneUsecase
|
||||
DeleteZoneUC *DeleteZoneUsecase
|
||||
DiffZoneUC *ZoneDifferUsecase
|
||||
GetZoneUC *GetZoneUsecase
|
||||
ListRecordsUC *ListRecordsUsecase
|
||||
UpdateZoneUC *UpdateZoneUsecase
|
||||
CreateZoneUC *CreateZoneUsecase
|
||||
DeleteRecordUC *DeleteRecordUsecase
|
||||
DeleteZoneUC *DeleteZoneUsecase
|
||||
DiffZoneUC *ZoneDifferUsecase
|
||||
GetZoneUC *GetZoneUsecase
|
||||
ListRecordsUC *ListRecordsUsecase
|
||||
UpdateZoneUC *UpdateZoneUsecase
|
||||
}
|
||||
|
||||
func NewZoneUsecases(store ZoneStorage, serviceUC *service.Service) *Service {
|
||||
|
|
@ -40,12 +41,13 @@ func NewZoneUsecases(store ZoneStorage, serviceUC *service.Service) *Service {
|
|||
listRecords := NewListRecordsUsecase(serviceUC.ListRecordsUC)
|
||||
|
||||
return &Service{
|
||||
CreateZoneUC: NewCreateZoneUsecase(store),
|
||||
DeleteZoneUC: NewDeleteZoneUsecase(store),
|
||||
DiffZoneUC: NewZoneDifferUsecase(getZone, listRecords),
|
||||
GetZoneUC: getZone,
|
||||
ListRecordsUC: listRecords,
|
||||
UpdateZoneUC: NewUpdateZoneUsease(store, getZone),
|
||||
CreateZoneUC: NewCreateZoneUsecase(store),
|
||||
DeleteRecordUC: NewDeleteRecordUsecase(serviceUC.ListRecordsUC, serviceUC.SearchRecordUC),
|
||||
DeleteZoneUC: NewDeleteZoneUsecase(store),
|
||||
DiffZoneUC: NewZoneDifferUsecase(getZone, listRecords),
|
||||
GetZoneUC: getZone,
|
||||
ListRecordsUC: listRecords,
|
||||
UpdateZoneUC: NewUpdateZoneUsease(store, getZone),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,6 +59,10 @@ func (s *Service) DeleteZone(zoneid happydns.Identifier) error {
|
|||
return s.DeleteZoneUC.Delete(zoneid)
|
||||
}
|
||||
|
||||
func (s *Service) DeleteRecord(zone *happydns.Zone, origin string, record happydns.Record) error {
|
||||
return s.DeleteRecordUC.Delete(zone, origin, record)
|
||||
}
|
||||
|
||||
func (s *Service) DiffZones(domain *happydns.Domain, newZone *happydns.Zone, oldZoneID happydns.Identifier) ([]*happydns.Correction, error) {
|
||||
return s.DiffZoneUC.Diff(domain, newZone, oldZoneID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ type ZoneServices struct {
|
|||
|
||||
type ZoneUsecase interface {
|
||||
CreateZone(*Zone) error
|
||||
DeleteRecord(*Zone, string, Record) error
|
||||
DeleteZone(Identifier) error
|
||||
DiffZones(*Domain, *Zone, Identifier) ([]*Correction, error)
|
||||
FlattenZoneFile(*Domain, *Zone) (string, error)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import { handleApiResponse } from "$lib/errors";
|
||||
import { printRR } from "$lib/dns";
|
||||
import type { dnsRR } from "$lib/dns_rr";
|
||||
import type { Correction } from "$lib/model/correction";
|
||||
import type { Domain } from "$lib/model/domain";
|
||||
import type { ServiceCombined, ServiceMeta } from "$lib/model/service";
|
||||
|
|
@ -154,3 +156,20 @@ export async function deleteZoneService(
|
|||
});
|
||||
return await handleApiResponse<Zone>(res);
|
||||
}
|
||||
|
||||
export async function deleteZoneRecord(
|
||||
domain: Domain,
|
||||
id: string,
|
||||
subdomain: string,
|
||||
record: dnsRR,
|
||||
): Promise<Zone> {
|
||||
const dnid = encodeURIComponent(domain.id);
|
||||
id = encodeURIComponent(id);
|
||||
|
||||
const res = await fetch(`/api/domains/${dnid}/zone/${id}/records/delete`, {
|
||||
method: "POST",
|
||||
headers: { Accept: "application/json" },
|
||||
body: JSON.stringify([printRR(record, subdomain)]),
|
||||
});
|
||||
return await handleApiResponse<Zone>(res);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,12 +47,14 @@
|
|||
Spinner,
|
||||
} from "@sveltestrap/sveltestrap";
|
||||
|
||||
import { addServiceRecord, deleteServiceRecord, updateServiceRecord } from "$lib/api/service";
|
||||
import { addServiceRecord, updateServiceRecord } from "$lib/api/service";
|
||||
import { deleteZoneRecord } from "$lib/api/zone";
|
||||
import { fqdn, nsclass, nsrrtype } from "$lib/dns";
|
||||
import { rdatafields } from "$lib/dns_rr";
|
||||
import type { Domain } from "$lib/model/domain";
|
||||
import type { ServiceCombined } from "$lib/model/service";
|
||||
import type { Zone } from "$lib/model/zone";
|
||||
import { thisZone } from "$lib/stores/thiszone";
|
||||
import { t } from "$lib/translations";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
|
@ -76,9 +78,9 @@
|
|||
function deleteRecord() {
|
||||
if (!record) return;
|
||||
deleteRecordInProgress = true;
|
||||
deleteServiceRecord(origin, zone.id, record).then(
|
||||
deleteZoneRecord(origin, zone.id, service._domain, record).then(
|
||||
(z: Zone) => {
|
||||
dispatch("update-zone-records", z);
|
||||
thisZone.set(z);
|
||||
deleteRecordInProgress = false;
|
||||
toggle();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -240,6 +240,11 @@ export function unreverseDomain(dn: string) {
|
|||
return ip.replace(/:(0000:)+/, "::").replace(/:0{1,3}/g, ":").replace(/^0+/, "").replace(/0+$/, "");
|
||||
}
|
||||
|
||||
export function printRR(rr: dnsRR, dn: string, origin: string): string {
|
||||
return fqdn(rr.Hdr.Name, fqdn(dn, origin)) + "\t" + rr.Hdr.Ttl + "\t" + nsclass(rr.Hdr.Class) + "\t" + nsrrtype(rr.Hdr.Rrtype) + "\t" + rdatatostr(rr);
|
||||
export function printRR(rr: dnsRR, dn?: string, origin?: string): string {
|
||||
let domain = rr.Hdr.Name || '@';
|
||||
if (dn && origin) domain = fqdn(domain, fqdn(dn, origin));
|
||||
else if (dn) domain = fqdn(domain, dn);
|
||||
else if (origin) domain = fqdn(domain, origin);
|
||||
|
||||
return domain + "\t" + rr.Hdr.Ttl + "\t" + nsclass(rr.Hdr.Class) + "\t" + nsrrtype(rr.Hdr.Rrtype) + "\t" + rdatatostr(rr);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue