From b3edb64e508f76b9b62ddccff46c2e8eebd21a70 Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Fri, 18 Jul 2025 09:07:18 +0200 Subject: [PATCH] Return record last modification time in API when known. Signed-off-by: Miod Vallat --- docs/http-api/swagger/authoritative-api-swagger.yaml | 5 ++++- pdns/dns.hh | 2 +- pdns/ws-auth.cc | 11 +++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/http-api/swagger/authoritative-api-swagger.yaml b/docs/http-api/swagger/authoritative-api-swagger.yaml index c80cbb2139..df1da4b79a 100644 --- a/docs/http-api/swagger/authoritative-api-swagger.yaml +++ b/docs/http-api/swagger/authoritative-api-swagger.yaml @@ -1,6 +1,6 @@ swagger: '2.0' info: - version: "0.0.16" + version: "0.0.17" title: PowerDNS Authoritative HTTP API license: name: MIT @@ -1289,6 +1289,9 @@ definitions: disabled: type: boolean description: 'Whether or not this record is disabled. When unset, the record is not disabled' + modified_at: + type: integer + description: 'Timestamp of the last change to the record' Comment: title: Comment diff --git a/pdns/dns.hh b/pdns/dns.hh index 1b55e859d0..e1be00222f 100644 --- a/pdns/dns.hh +++ b/pdns/dns.hh @@ -90,7 +90,7 @@ public: // Aligned on 8-byte boundaries on systems where time_t is 8 bytes and int // is 4 bytes, aka modern linux on x86_64 - time_t last_modified{}; //!< For autocalculating SOA serial numbers - the backend needs to fill this in + time_t last_modified{}; //!< Timestamp of last update, if known by the backend uint32_t ttl{}; //!< Time To Live of this record uint32_t signttl{}; //!< If non-zero, use this TTL as original TTL in the RRSIG diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index a72e5c057a..47ac61eecd 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -525,9 +525,13 @@ static void fillZone(UeberBackend& backend, const ZoneName& zonename, HttpRespon while (rit != records.end() && rit->qname == current_qname && rit->qtype == current_qtype) { ttl = min(ttl, rit->ttl); - rrset_records.push_back(Json::object{ + auto object = Json::object{ {"disabled", rit->disabled}, - {"content", makeApiRecordContent(rit->qtype, rit->content)}}); + {"content", makeApiRecordContent(rit->qtype, rit->content)}}; + if (rit->last_modified != 0) { + object["modified_at"] = (double)rit->last_modified; + } + rrset_records.push_back(object); rit++; } while (cit != comments.end() && cit->qname == current_qname && cit->qtype == current_qtype) { @@ -2596,6 +2600,9 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) {"ttl", (double)resourceRecord.ttl}, {"disabled", resourceRecord.disabled}, {"content", makeApiRecordContent(resourceRecord.qtype, resourceRecord.content)}}; + if (resourceRecord.last_modified != 0) { + object["modified_at"] = (double)resourceRecord.last_modified; + } val = zoneIdZone.find(resourceRecord.domain_id); if (val != zoneIdZone.end()) { -- 2.47.2