diff --git a/src/components/domains/ARow.svelte b/src/components/domains/ARow.svelte index d01b334..732b2f4 100644 --- a/src/components/domains/ARow.svelte +++ b/src/components/domains/ARow.svelte @@ -1,5 +1,6 @@ - {item.data.name} + {dnsSubdomain(item.data.name)} {item.data.value} {item.data.ttl} diff --git a/src/components/domains/CaaRow.svelte b/src/components/domains/CaaRow.svelte index e7e2ae9..7bf519a 100644 --- a/src/components/domains/CaaRow.svelte +++ b/src/components/domains/CaaRow.svelte @@ -1,5 +1,6 @@ - {item.data.name} + {dnsSubdomain(item.data.name)} {item.data.value.tag} {item.data.value.value} {item.data.ttl} diff --git a/src/components/domains/CnameRow.svelte b/src/components/domains/CnameRow.svelte index 7fbe737..6593d91 100644 --- a/src/components/domains/CnameRow.svelte +++ b/src/components/domains/CnameRow.svelte @@ -1,5 +1,6 @@ - {item.data.name} + {dnsSubdomain(item.data.name)} {item.data.value} {item.data.ttl} diff --git a/src/components/domains/MxRow.svelte b/src/components/domains/MxRow.svelte index d5559e5..25007b8 100644 --- a/src/components/domains/MxRow.svelte +++ b/src/components/domains/MxRow.svelte @@ -1,5 +1,6 @@ - {item.data.name} + {dnsSubdomain(item.data.name)} {item.data.value.mx} {item.data.value.preference} {item.data.ttl} diff --git a/src/components/domains/NsRow.svelte b/src/components/domains/NsRow.svelte index 34cd1c6..146a9d2 100644 --- a/src/components/domains/NsRow.svelte +++ b/src/components/domains/NsRow.svelte @@ -1,5 +1,6 @@ - {item.data.name} + {dnsSubdomain(item.data.name)} {item.data.value} {item.data.ttl} diff --git a/src/components/domains/SoaRow.svelte b/src/components/domains/SoaRow.svelte index ea2cc10..6534b72 100644 --- a/src/components/domains/SoaRow.svelte +++ b/src/components/domains/SoaRow.svelte @@ -6,6 +6,7 @@ export let item: RestItem>; let editItem: ApiRecordFormat = { + id: 0, name: item.data.name, type: item.data.type, ttl: item.data.ttl, diff --git a/src/components/domains/SrvRow.svelte b/src/components/domains/SrvRow.svelte index 0d3d129..87fd937 100644 --- a/src/components/domains/SrvRow.svelte +++ b/src/components/domains/SrvRow.svelte @@ -1,5 +1,6 @@ - {item.data.name} + {dnsSubdomain(item.data.name)} {item.data.value.priority} {item.data.value.weight} {item.data.value.port} diff --git a/src/components/domains/TxtRow.svelte b/src/components/domains/TxtRow.svelte index b21d21c..8cd023e 100644 --- a/src/components/domains/TxtRow.svelte +++ b/src/components/domains/TxtRow.svelte @@ -1,5 +1,6 @@ - {item.data.name} + {dnsSubdomain(item.data.name)} {item.data.value} {item.data.ttl} diff --git a/src/types/records.ts b/src/types/records.ts index aefba63..d825ac3 100644 --- a/src/types/records.ts +++ b/src/types/records.ts @@ -1,5 +1,3 @@ -import type {IPv4, IPv6} from "ipaddr.js"; - export const DnsTypeSOA = 6; export const DnsTypeNS = 2; export const DnsTypeMX = 15; @@ -14,6 +12,7 @@ export type AnyValue = SoaValue | NsValue | MxValue | AValue | AaaaValue | Cname export type AnyRecord = ApiRecordFormat; export interface ApiRecordFormat { + id: number; name: string; type: number; ttl: number | null; diff --git a/src/utils/dns-subdomain.ts b/src/utils/dns-subdomain.ts new file mode 100644 index 0000000..90340c5 --- /dev/null +++ b/src/utils/dns-subdomain.ts @@ -0,0 +1,24 @@ +import {get} from "svelte/store"; +import {domainOption} from "../stores/domain-option"; + +export function dnsFqdn(domain: string): string { + if (domain.endsWith(".")) return domain; + return domain + "."; +} + +export function dnsSubdomain(value: string): string { + let baseDomain = dnsFqdn(get(domainOption)); + console.log(value, baseDomain, value == baseDomain); + + if (value == baseDomain) value = ""; + else if (value.endsWith("." + baseDomain)) value = value.substring(0, value.length - baseDomain.length - 1); + + switch (value) { + case "": + return "."; + case "*": + return "*"; + default: + return value; + } +} diff --git a/src/utils/temp-saving.ts b/src/utils/temp-saving.ts new file mode 100644 index 0000000..3c8c10c --- /dev/null +++ b/src/utils/temp-saving.ts @@ -0,0 +1,13 @@ +export function tempSave(key: string, value: object) { + localStorage.setItem("temp-" + key, JSON.stringify(value)); +} + +export function tempGet(key: string): T | null { + let v = localStorage.getItem("temp-" + key); + if (v == null) return null; + return JSON.parse(v) as T; +} + +export function tempClear(key: string) { + localStorage.removeItem("temp-" + key); +} diff --git a/src/views/DomainsView.svelte b/src/views/DomainsView.svelte index b733a99..3802be4 100644 --- a/src/views/DomainsView.svelte +++ b/src/views/DomainsView.svelte @@ -44,10 +44,11 @@ import CnameCreate from "../components/create-domains/CnameCreate.svelte"; import CaaCreate from "../components/create-domains/CaaCreate.svelte"; import TxtCreate from "../components/create-domains/TxtCreate.svelte"; + import {dnsFqdn} from "../utils/dns-subdomain"; const apiAzalea = import.meta.env.VITE_API_AZALEA; - const table = new RestTable(apiAzalea + "/domains/" + $domainOption + "/records", (item: AnyRecord) => item.id); + const table = new RestTable(apiAzalea + "/domains/" + $domainOption + "/records", (item: AnyRecord) => `${item.id}`); domainOption.subscribe(x => { table.changeUrl(apiAzalea + "/domains/" + x + "/records"); @@ -66,7 +67,7 @@ } function domainFilter(src: string, domain: string) { - domain = fqdn(domain); + domain = dnsFqdn(domain); if (domain == "*") return true; let n = src.indexOf("/"); if (n == -1) n = src.length; @@ -84,13 +85,11 @@ return name; } - function fqdn(domain: string): string { - if (domain.endsWith(".")) return domain; - return domain + "."; - } - let domainTitle: string = ""; - $: (domainTitle = table.rows.length === 0 ? "Unknown" : getTitleDomain(table.rows[0].data.name)), $table; + $: try { + console.log("a:", table.rows[0].data.name); + } catch {} + $: (domainTitle = table.rows.length === 0 ? "Unknown" : (getTitleDomain(table.rows[0].data.name) ?? "")), $table; let zoneFileUrl: string; zoneFileUrl = domainTitle ? `${import.meta.env.VITE_API_AZALEA}/domains/${domainTitle}/zone-file` : ""; @@ -113,6 +112,7 @@ render: NsRow, create: NsCreate, empty: (): ApiRecordFormat => ({ + id: 0, name: "", type: DnsTypeNS, ttl: null, @@ -127,6 +127,7 @@ render: MxRow, create: MxCreate, empty: (): ApiRecordFormat => ({ + id: 0, name: "", type: DnsTypeMX, ttl: null, @@ -144,6 +145,7 @@ render: ARow, create: ACreate, empty: (): ApiRecordFormat => ({ + id: 0, name: "", type: 0, // this is on purpose ttl: null, @@ -158,6 +160,7 @@ render: CnameRow, create: CnameCreate, empty: (): ApiRecordFormat => ({ + id: 0, name: "", type: DnsTypeCNAME, ttl: null, @@ -172,6 +175,7 @@ render: TxtRow, create: TxtCreate, empty: (): ApiRecordFormat => ({ + id: 0, name: "", type: DnsTypeTXT, ttl: null, @@ -186,6 +190,7 @@ render: SrvRow, create: null, empty: (): ApiRecordFormat => ({ + id: 0, name: "", type: DnsTypeSRV, ttl: null, @@ -205,6 +210,7 @@ render: CaaRow, create: CaaCreate, empty: (): ApiRecordFormat => ({ + id: 0, name: "", type: DnsTypeCAA, ttl: null, diff --git a/src/views/RedirectsView.svelte b/src/views/RedirectsView.svelte index f432028..9b73254 100644 --- a/src/views/RedirectsView.svelte +++ b/src/views/RedirectsView.svelte @@ -1,27 +1,56 @@
diff --git a/src/views/RoutesView.svelte b/src/views/RoutesView.svelte index d8dafe6..2e725f7 100644 --- a/src/views/RoutesView.svelte +++ b/src/views/RoutesView.svelte @@ -4,25 +4,50 @@ import TargetManagementView from "./TargetManagementView.svelte"; import {routeKeys, type Route} from "../types/target"; import Flags from "../components/Flags.svelte"; + import {tempClear, tempGet, tempSave} from "../utils/temp-saving"; + import {onMount} from "svelte"; const apiViolet = import.meta.env.VITE_API_VIOLET; let targetManagement: TargetManagementView; - let createItem: Route = { - src: "", - dst: "", - flags: 0, - active: false, - }; + let createItem: Route = defaultCreateItem(); let createPopup: boolean = false; let createErrorMessage = ""; + function defaultCreateItem(): Route { + return { + src: "", + dst: "", + flags: 0, + active: false, + }; + } + + const createItemStore: string = "routes-view-create-item"; + function createRoute() { createErrorMessage = ""; - targetManagement.createItem(createItem).catch(x => { - createErrorMessage = x; - }); + tempSave(createItemStore, createItem); + targetManagement + .createItem(createItem) + .then(() => { + createPopup = false; + createItem = defaultCreateItem(); + tempClear(createItemStore); + }) + .catch(x => { + createErrorMessage = x; + }); } + + onMount(() => { + let start = tempGet(createItemStore); + if (start != null) { + createPopup = true; + createErrorMessage = "You have been logged in"; + createItem = start; + } + });
diff --git a/test-server/go.mod b/test-server/go.mod index 2d961f9..1749cd7 100644 --- a/test-server/go.mod +++ b/test-server/go.mod @@ -7,12 +7,14 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 github.com/google/uuid v1.6.0 github.com/rs/cors v1.11.1 + golang.org/x/net v0.21.0 ) require ( - github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/1f349/rsa-helper v0.0.2 // indirect + github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/go-jose/go-jose/v4 v4.0.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/spf13/afero v1.11.0 // indirect golang.org/x/crypto v0.25.0 // indirect diff --git a/test-server/go.sum b/test-server/go.sum index 7e254f1..1ed3ebd 100644 --- a/test-server/go.sum +++ b/test-server/go.sum @@ -1,41 +1,46 @@ -github.com/1f349/mjwt v0.2.1 h1:REdiM/MaNjYQwHvI39LaMPhlvMg4Vy9SgomWMsKTNz8= -github.com/1f349/mjwt v0.2.1/go.mod h1:KEs6jd9JjWrQW+8feP2pGAU7pdA3aYTqjkT/YQr73PU= github.com/1f349/mjwt v0.4.1 h1:ooCroMMw2kcL5c9L3sLbdtxI0H4/QC8RfTxiloKr+4Y= github.com/1f349/mjwt v0.4.1/go.mod h1:qwnzokkqc7Z9YmKA1m9beI3OZL1GvGYHOQU2rOwoV1M= github.com/1f349/rsa-helper v0.0.2 h1:N/fLQqg5wrjIzG6G4zdwa5Xcv9/jIPutCls9YekZr9U= github.com/1f349/rsa-helper v0.0.2/go.mod h1:VUQ++1tYYhYrXeOmVFkQ82BegR24HQEJHl5lHbjg7yg= github.com/becheran/wildmatch-go v1.0.0 h1:mE3dGGkTmpKtT4Z+88t8RStG40yN9T+kFEGj2PZFSzA= github.com/becheran/wildmatch-go v1.0.0/go.mod h1:gbMvj0NtVdJ15Mg/mH9uxk2R1QCistMyU7d9KFzroX4= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/test-server/main.go b/test-server/main.go index 870db4f..4da3f94 100644 --- a/test-server/main.go +++ b/test-server/main.go @@ -14,6 +14,7 @@ import ( "github.com/golang-jwt/jwt/v4" "github.com/google/uuid" "github.com/rs/cors" + "golang.org/x/net/publicsuffix" ) func main() { @@ -137,13 +138,23 @@ func apiServer(verify *mjwt.KeyStore) { })) r.Handle("POST /v1/violet/route", hasPerm(verify, "violet:route", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) { j := make(map[string]any) - json.NewDecoder(req.Body).Decode(&j) - keys:= b.Claims.Perms.Search("domain:owns=*") + err := json.NewDecoder(req.Body).Decode(&j) + if err != nil { + http.Error(rw, "Failed to parse JSON", http.StatusBadRequest) + return + } - strings.Split() j.src - fmt.Printf("%#v\n", j) - fmt.Printf("%#v\n", b.Claims.Perms.Dump()) - b.Claims.Perms. + etld, err := publicsuffix.EffectiveTLDPlusOne(j["src"].(string)) + if err != nil { + http.Error(rw, "Internal Server Error", http.StatusInternalServerError) + return + } + if !b.Claims.Perms.Has("domain:owns=" + etld) { + http.Error(rw, "User does not own this domain", http.StatusBadRequest) + return + } + + fmt.Printf("Would create database row: %#v\n", j) })) r.Handle("/v1/violet/redirect", hasPerm(verify, "violet:redirect", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) { m := make([]map[string]any, 0, len(subdomains)*2) @@ -201,7 +212,7 @@ func apiServer(verify *mjwt.KeyStore) { } json.NewEncoder(rw).Encode(m) })) - r.Handle("/v1/azalea/domains", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) { + r.Handle("/v1/azalea/domains", hasPerm(verify, "azalea:domains", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) { type Zone struct { ID int64 `json:"id"` Name string `json:"name"` @@ -211,134 +222,105 @@ func apiServer(verify *mjwt.KeyStore) { {ID: 2, Name: "example.org."}, }) })) - r.Handle("/v1/azalea/domains/example.com/records", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) { + r.Handle("/v1/azalea/domains/example.com/records", hasPerm(verify, "azalea:domains", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) { fmt.Fprintln(rw, `[ { - "Hdr": { - "Name": "example.com.", - "Rrtype": 6, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "Ns": "ns1.example.com.", - "Mbox": "hostmaster.example.com.", - "Serial": 2024062001, - "Refresh": 7200, - "Retry": 1800, - "Expire": 1209600, - "Minttl": 300 + "id": -1, + "name": "example.com.", + "type": 6, + "ttl": 300, + "value": { + "ns": "ns1.example.com.", + "mbox": "hostmaster.example.com.", + "serial": 2024111901, + "refresh": 7200, + "retry": 1800, + "expire": 1209600, + "minttl": 300 + } }, { - "Hdr": { - "Name": "example.com.", - "Rrtype": 2, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "Ns": "ns1.example.com." + "id": -2, + "name": "example.com.", + "type": 2, + "ttl": 300, + "value": "ns1.example.com." }, { - "Hdr": { - "Name": "example.com.", - "Rrtype": 2, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "Ns": "ns2.example.com." + "id": -2, + "name": "example.com.", + "type": 2, + "ttl": 300, + "value": "ns2.example.com." }, { - "Hdr": { - "Name": "example.com.", - "Rrtype": 2, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "Ns": "ns3.example.com." + "id": -2, + "name": "example.com.", + "type": 2, + "ttl": 300, + "value": "ns3.example.com." }, { - "Hdr": { - "Name": "ns1.example.com.", - "Rrtype": 1, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "A": "10.54.0.1" + "id": 1, + "name": "ns1.example.com.", + "type": 1, + "ttl": 300, + "value": "10.20.0.1" } ]`) })) - r.Handle("/v1/azalea/domains/example.org/records", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) { + r.Handle("/v1/azalea/domains/example.org/records", hasPerm(verify, "azalea:domains", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) { fmt.Fprintln(rw, `[ - { - "Hdr": { - "Name": "example.org.", - "Rrtype": 6, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "Ns": "ns1.example.com.", - "Mbox": "hostmaster.example.com.", - "Serial": 2024062001, - "Refresh": 7200, - "Retry": 1800, - "Expire": 1209600, - "Minttl": 300 + { + "id": -1, + "name": "example.org.", + "type": 6, + "ttl": 300, + "value": { + "ns": "ns1.example.com.", + "mbox": "hostmaster.example.com.", + "serial": 2024062001, + "refresh": 7200, + "retry": 1800, + "expire": 1209600, + "minttl": 300 + } }, { - "Hdr": { - "Name": "example.org.", - "Rrtype": 2, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "Ns": "ns1.example.com." + "id": -2, + "name": "example.org.", + "type": 2, + "ttl": 300, + "value": "ns1.example.com." }, { - "Hdr": { - "Name": "example.org.", - "Rrtype": 2, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "Ns": "ns2.example.com." + "id": -2, + "name": "example.org.", + "type": 2, + "ttl": 300, + "value": "ns2.example.com." }, { - "Hdr": { - "Name": "example.org.", - "Rrtype": 2, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "Ns": "ns3.example.com." + "id": -2, + "name": "example.org.", + "type": 2, + "ttl": 300, + "value": "ns3.example.com." }, { - "Hdr": { - "Name": "example.org.", - "Rrtype": 1, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "A": "10.36.0.1" + "id": 1, + "name": "example.org.", + "type": 1, + "ttl": 300, + "value": "10.36.0.1" }, - { - "Hdr": { - "Name": "example.org.", - "Rrtype": 28, - "Class": 1, - "Ttl": 300, - "Rdlength": 0 - }, - "AAAA": "2001:db8::15" - } + { + "id": 2, + "name": "example.org.", + "type": 28, + "ttl": 300, + "value": "2001:db8::15" + } ]`) })) r.Handle("/v1/sites", hasPerm(verify, "sites:manage", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {