From: Jonathan Eenkhoorn Date: Thu, 3 Jan 2019 15:19:00 +0000 (+0100) Subject: Add type filter to search-data api. Closes #5430 X-Git-Tag: auth-4.2.0-beta1~2^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45250285917ab1b7c298f8d64e644580b900f2b4;p=thirdparty%2Fpdns.git Add type filter to search-data api. Closes #5430 --- diff --git a/docs/http-api/swagger/authoritative-api-swagger.yaml b/docs/http-api/swagger/authoritative-api-swagger.yaml index b96dbe0558..ce9918adee 100644 --- a/docs/http-api/swagger/authoritative-api-swagger.yaml +++ b/docs/http-api/swagger/authoritative-api-swagger.yaml @@ -436,6 +436,11 @@ paths: required: true description: 'Maximum number of entries to return' type: integer + - name: type + in: query + required: false + description: 'Type of data to search for, one of “all”, “zone”, “record”, “comment”' + type: string responses: '200': description: Returns a JSON array with results diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index f822bdf27b..fbd5cb506f 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -2041,9 +2041,20 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { string q = req->getvars["q"]; string sMax = req->getvars["max"]; + string sType = req->getvars["type"]; + int maxEnts = 100; int ents = 0; + // the following types of data can be searched for using the api + enum class Type + { + ALL, + ZONE, + RECORD, + COMMENT + } type; + if (q.empty()) throw ApiException("Query q can't be blank"); if (!sMax.empty()) @@ -2051,6 +2062,19 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { if (maxEnts < 1) throw ApiException("Maximum entries must be larger than 0"); + if (sType.empty()) + type = Type::ALL; + else if (sType == "all") + type = Type::ALL; + else if (sType == "zone") + type = Type::ZONE; + else if (sType == "record") + type = Type::RECORD; + else if (sType == "comment") + type = Type::COMMENT; + else + throw ApiException("Type must be one of the following options: all, zone, record, comment"); + SimpleMatch sm(q,true); UeberBackend B; vector domains; @@ -2064,7 +2088,7 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { for(const DomainInfo di: domains) { - if (ents < maxEnts && sm.match(di.zone)) { + if ((type == Type::ALL || type == Type::ZONE) && ents < maxEnts && sm.match(di.zone)) { doc.push_back(Json::object { { "object_type", "zone" }, { "zone_id", apiZoneNameToId(di.zone) }, @@ -2075,7 +2099,7 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { zoneIdZone[di.id] = di; // populate cache } - if (B.searchRecords(q, maxEnts, result_rr)) + if ((type == Type::ALL || type == Type::RECORD) && B.searchRecords(q, maxEnts, result_rr)) { for(const DNSResourceRecord& rr: result_rr) { @@ -2098,7 +2122,7 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { } } - if (B.searchComments(q, maxEnts, result_c)) + if ((type == Type::ALL || type == Type::COMMENT) && B.searchComments(q, maxEnts, result_c)) { for(const Comment &c: result_c) { diff --git a/regression-tests.api/test_Zones.py b/regression-tests.api/test_Zones.py index a0e08f9b83..636ea439ea 100644 --- a/regression-tests.api/test_Zones.py +++ b/regression-tests.api/test_Zones.py @@ -1617,6 +1617,36 @@ fred IN A 192.168.0.4 u'ttl': 3600, u'type': u'SOA', u'name': name}, ]) + def test_search_rr_exact_zone_filter_type_zone(self): + name = unique_zone_name() + data_type = "zone" + self.create_zone(name=name, serial=22, soa_edit_api='') + r = self.session.get(self.url("/api/v1/servers/localhost/search-data?q=" + name.rstrip('.') + "&type=" + data_type)) + self.assert_success_json(r) + print(r.json()) + self.assertEquals(r.json(), [ + {u'object_type': u'zone', u'name': name, u'zone_id': name}, + ]) + + def test_search_rr_exact_zone_filter_type_record(self): + name = unique_zone_name() + data_type = "record" + self.create_zone(name=name, serial=22, soa_edit_api='') + r = self.session.get(self.url("/api/v1/servers/localhost/search-data?q=" + name.rstrip('.') + "&type=" + data_type)) + self.assert_success_json(r) + print(r.json()) + self.assertEquals(r.json(), [ + {u'content': u'ns1.example.com.', + u'zone_id': name, u'zone': name, u'object_type': u'record', u'disabled': False, + u'ttl': 3600, u'type': u'NS', u'name': name}, + {u'content': u'ns2.example.com.', + u'zone_id': name, u'zone': name, u'object_type': u'record', u'disabled': False, + u'ttl': 3600, u'type': u'NS', u'name': name}, + {u'content': u'a.misconfigured.powerdns.server. hostmaster.'+name+' 22 10800 3600 604800 3600', + u'zone_id': name, u'zone': name, u'object_type': u'record', u'disabled': False, + u'ttl': 3600, u'type': u'SOA', u'name': name}, + ]) + def test_search_rr_substring(self): name = unique_zone_name() search = name[5:-5]