]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Add type filter to search-data api. Closes #5430
authorJonathan Eenkhoorn <jonathan.eenkhoorn@antagonist.nl>
Thu, 3 Jan 2019 15:19:00 +0000 (16:19 +0100)
committerJonathan Eenkhoorn <jonathan.eenkhoorn@antagonist.nl>
Thu, 3 Jan 2019 16:29:59 +0000 (17:29 +0100)
docs/http-api/swagger/authoritative-api-swagger.yaml
pdns/ws-auth.cc
regression-tests.api/test_Zones.py

index b96dbe0558273c40e64fe1f532b5b04a4a782f67..ce9918adeeb0e8c0fdba3368bb695c9ff18d5c07 100644 (file)
@@ -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
index f822bdf27bd5b1732c57baa135383906dced5afe..fbd5cb506f80dcddaf642114aedfc34f85aaa0ac 100644 (file)
@@ -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<DomainInfo> 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)
     {
index a0e08f9b839cf73dd249c35286e485690286c0fc..636ea439ea93fae021e125d7a44ac582bf59b793 100644 (file)
@@ -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]