]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Fix transform schemas - inner schema describes result
authorVsevolod Stakhov <vsevolod@rspamd.com>
Wed, 19 Nov 2025 10:19:09 +0000 (10:19 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Wed, 19 Nov 2025 10:19:09 +0000 (10:19 +0000)
- Transform inner schema now describes the result type, not input
- Fixed lua_maps.lua: timeout transform
- Fixed lua_redis.lua: timeout, sentinel_watch_time, sentinel_master_maxerrors, redis_version
- Fixed rbl.lua: key transforms, return_bits number transforms
- Transform functions now handle type checking before conversion

lualib/lua_maps.lua
lualib/lua_redis.lua
lualib/plugins/rbl.lua

index a11e1d6a092038043e638c4bb1b68bdb5abddcb6..ccfa0ce088fd9caa7572a23cdeefa53a28b743d9 100644 (file)
@@ -92,10 +92,14 @@ local external_map_schema = T.table({
   cdb = T.string():optional(), -- path to CDB file, required for CDB
   method = T.enum({ "body", "header", "query" }):optional(), -- how to pass input
   encode = T.enum({ "json", "messagepack" }):optional(), -- how to encode input (if relevant)
-  timeout = T.transform(
-    T.one_of({T.number(), T.string()}),
-    lua_util.parse_time_interval
-  ):optional(),
+  timeout = T.transform(T.number({ min = 0 }), function(val)
+    if type(val) == "number" then
+      return val
+    elseif type(val) == "string" then
+      return lua_util.parse_time_interval(val)
+    end
+    return val
+  end):optional(),
 })
 
 -- Storage for CDB instances
@@ -672,7 +676,8 @@ local direct_map_schema = T.table({ -- complex object
 exports.map_schema = T.one_of({
   T.string(), -- 'http://some_map'
   T.array(T.string()), -- ['foo', 'bar']
-  T.one_of({ direct_map_schema, external_map_schema })
+  direct_map_schema, -- complex object with url/upstreams
+  external_map_schema -- external backend (HTTP API, etc)
 })
 
 return exports
index ddcb84c94b683f44a1a3faf7966e9f5a24367465..088965c9736b18a0ebf04ffbe7cf2944284756fe 100644 (file)
@@ -33,7 +33,12 @@ local db_schema = T.one_of({
 local common_schema = T.table({
   timeout = T.one_of({
     T.number(),
-    T.transform(T.string(), lutil.parse_time_interval)
+    T.transform(T.number({ min = 0 }), function(val)
+      if type(val) == "string" then
+        return lutil.parse_time_interval(val)
+      end
+      return val
+    end)
   }):optional():doc({ summary = "Connection timeout (seconds)" }),
   db = db_schema,
   database = db_schema,
@@ -56,18 +61,33 @@ local common_schema = T.table({
   }):optional():doc({ summary = "Sentinel servers" }),
   sentinel_watch_time = T.one_of({
     T.number(),
-    T.transform(T.string(), lutil.parse_time_interval)
+    T.transform(T.number({ min = 0 }), function(val)
+      if type(val) == "string" then
+        return lutil.parse_time_interval(val)
+      end
+      return val
+    end)
   }):optional():doc({ summary = "Sentinel watch time" }),
   sentinel_masters_pattern = T.string():optional():doc({ summary = "Sentinel masters pattern" }),
   sentinel_master_maxerrors = T.one_of({
     T.number(),
-    T.transform(T.string(), tonumber)
+    T.transform(T.number(), function(val)
+      if type(val) == "string" then
+        return tonumber(val)
+      end
+      return val
+    end)
   }):optional():doc({ summary = "Sentinel master max errors" }),
   sentinel_username = T.string():optional():doc({ summary = "Sentinel username" }),
   sentinel_password = T.string():optional():doc({ summary = "Sentinel password" }),
   redis_version = T.one_of({
     T.number(),
-    T.transform(T.string(), tonumber)
+    T.transform(T.number(), function(val)
+      if type(val) == "string" then
+        return tonumber(val)
+      end
+      return val
+    end)
   }):optional():doc({ summary = "Redis server version (6 or 7)" }),
 }, { open = true })
 
index c53c103bf940385de18a0faacf2e02ba1e862776..b7cc8fde7943a5db89ce96bd1dc2c892d6d749f0 100644 (file)
@@ -59,7 +59,12 @@ local default_options = {
 
 local return_codes_schema = T.table({}, {
   open = true,
-  key = T.transform(T.string(), string.upper),
+  key = T.transform(T.string(), function(val)
+    if type(val) == "string" then
+      return string.upper(val)
+    end
+    return val
+  end),
   extra = T.one_of({
     T.array(T.string()),
     -- Transform string to array, inner schema validates the result
@@ -74,11 +79,21 @@ local return_codes_schema = T.table({}, {
 
 local return_bits_schema = T.table({}, {
   open = true,
-  key = T.transform(T.string(), string.upper),
+  key = T.transform(T.string(), function(val)
+    if type(val) == "string" then
+      return string.upper(val)
+    end
+    return val
+  end),
   extra = T.one_of({
     T.array(T.one_of({
       T.number(),
-      T.transform(T.string(), tonumber)
+      T.transform(T.number(), function(val)
+        if type(val) == "string" then
+          return tonumber(val)
+        end
+        return val
+      end)
     })),
     -- Transform string or number to array, inner schema validates the result
     T.transform(T.array(T.number()), function(val)