]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3/mdssvc: add option "elasticsearch:force_substring_search = yes | no" (default...
authorRalph Boehme <slow@samba.org>
Thu, 16 Jan 2025 11:15:37 +0000 (12:15 +0100)
committerVolker Lendecke <vl@samba.org>
Fri, 24 Jan 2025 10:52:33 +0000 (10:52 +0000)
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Fri Jan 24 10:52:33 UTC 2025 on atb-devel-224

docs-xml/smbdotconf/misc/elasticsearchforcesubstringsearch.xml [new file with mode: 0644]
python/samba/tests/dcerpc/mdssvc.py
source3/rpc_server/mdssvc/es_parser.y

diff --git a/docs-xml/smbdotconf/misc/elasticsearchforcesubstringsearch.xml b/docs-xml/smbdotconf/misc/elasticsearchforcesubstringsearch.xml
new file mode 100644 (file)
index 0000000..b5df5d1
--- /dev/null
@@ -0,0 +1,16 @@
+<samba:parameter name="elasticsearch:force substring search"
+                 context="G"
+                 type="boolean"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+  <description>
+    <para>
+      Force string searches in string attributes likes paths to be prefix
+      searches by prefixing a *. Example: a Spotlight search for '*=="samba*"'
+      would be mapped to "'query': '(*samba*)'" instead of "'query':
+      '(samba*)'".
+    </para>
+  </description>
+
+  <value type="default">no</value>
+  <value type="example">yes</value>
+</samba:parameter>
index 1d53676dea3415895c9298fa0f485325c5622572..cd256548b91d7c04d379f2772d071813ad291e30 100644 (file)
@@ -24,6 +24,7 @@ import threading
 import logging
 import json
 from http.server import HTTPServer, BaseHTTPRequestHandler
+import samba
 from samba.dcerpc import mdssvc
 from samba.tests import RpcInterfaceTestCase
 from samba.samba3 import mdscli
@@ -75,6 +76,11 @@ class MdssvcTests(RpcInterfaceTestCase):
     def setUp(self):
         super().setUp()
 
+        # Build the global inject file path
+        server_conf = samba.tests.env_get_var_value("SERVERCONFFILE")
+        server_conf_dir = os.path.dirname(server_conf)
+        self.global_inject = os.path.join(server_conf_dir, "global_inject.conf")
+
         self.pipe = mdssvc.mdssvc('ncacn_np:fileserver[/pipe/mdssvc]', self.get_loadparm())
 
         self.server = HTTPServer(('10.53.57.35', 8080),
@@ -192,3 +198,31 @@ class MdssvcTests(RpcInterfaceTestCase):
             r"x\x",
         ]
         self.run_test(sl_query, exp_results, exp_json_query, fake_json_response)
+
+    def test_mdscli_search_force_substring(self):
+        with open(self.global_inject, 'w') as f:
+            f.write("elasticsearch:force substring search = yes\n")
+        os.system("killall -SIGHUP rpcd_mdssvc")
+
+        exp_json_query = r'''{
+          "from": 0, "size": 50, "_source": ["path.real"],
+          "query": {
+            "query_string": {
+              "query": "(*samba*) AND path.real.fulltext:\"%BASEPATH%\""
+            }
+          }
+        }'''
+        fake_json_response = '''{
+          "hits" : {
+            "total" : { "value" : 2},
+            "hits" : [
+              {"_source" : {"path" : {"real" : "%BASEPATH%/foo"}}},
+              {"_source" : {"path" : {"real" : "%BASEPATH%/bar"}}}
+            ]
+          }
+        }'''
+        exp_results = ["foo", "bar"]
+        self.run_test('*=="samba*"', exp_results, exp_json_query, fake_json_response)
+
+        os.remove(self.global_inject)
+        os.system("killall -SIGHUP rpcd_mdssvc")
index 023f8790a148f3e0dfbfd09d2395ae54cbeb56b4..7f3275d3d9292810c9d548c2caeec33c981354c1 100644 (file)
@@ -67,6 +67,7 @@
                json_t *mime_map;
                bool ignore_unknown_attribute;
                bool ignore_unknown_type;
+               bool force_substring_search;
                bool type_error;
                YY_BUFFER_STATE s;
                const char *result;
@@ -392,6 +393,7 @@ static char *map_fts(const struct es_attr_map *attr,
        struct es_parser_state *s = global_es_parser_state;
        const char *not = NULL;
        const char *end = NULL;
+       const char *force_substring = "";
        char *esval = NULL;
        char *es = NULL;
 
@@ -414,9 +416,15 @@ static char *map_fts(const struct es_attr_map *attr,
                DBG_ERR("Mapping fts [%s] unexpected op [%c]\n", val, op);
                return NULL;
        }
+
+       if (s->force_substring_search) {
+               force_substring = "*";
+       }
+
        es = talloc_asprintf(s->frame,
-                            "%s%s%s",
+                            "%s%s%s%s",
                             not,
+                            force_substring,
                             esval,
                             end);
        if (es == NULL) {
@@ -432,6 +440,7 @@ static char *map_str(const struct es_attr_map *attr,
        struct es_parser_state *s = global_es_parser_state;
        char *esval = NULL;
        char *es = NULL;
+       const char *force_substring = "";
        const char *not = NULL;
        const char *end = NULL;
 
@@ -455,10 +464,15 @@ static char *map_str(const struct es_attr_map *attr,
                return NULL;
        }
 
+       if (s->force_substring_search) {
+               force_substring = "*";
+       }
+
        es = talloc_asprintf(s->frame,
-                            "%s%s:%s%s",
+                            "%s%s:%s%s%s",
                             not,
                             attr->name,
+                            force_substring,
                             esval,
                             end);
        if (es == NULL) {
@@ -662,6 +676,10 @@ bool map_spotlight_to_es_query(TALLOC_CTX *mem_ctx,
                                             "elasticsearch",
                                             "ignore unknown type",
                                             false);
+       s.force_substring_search = lp_parm_bool(GLOBAL_SECTION_SNUM,
+                                            "elasticsearch",
+                                            "force substring search",
+                                            false);
 
        global_es_parser_state = &s;
        result = mdsyylparse();