This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 3f3c4604 fix(settings): harden Metrics data source validation (#1474)
3f3c4604 is described below

commit 3f3c4604bff3df8cf7b797e94bd4f8af67cce31e
Author: aias00 <[email protected]>
AuthorDate: Tue Aug 11 15:32:32 2026 +0800

    fix(settings): harden Metrics data source validation (#1474)
    
    * fix(settings): validate metrics data source types
    
    Signed-off-by: liuhy <[email protected]>
    
    * fix(settings): validate metrics data source authentication
    
    Signed-off-by: liuhy <[email protected]>
    
    * test: preserve missing data source name validation
    
    ---------
    
    Signed-off-by: liuhy <[email protected]>
---
 .../rocketmq/studio/settings/DataSourceDTO.java    | 11 ++-
 .../studio/settings/SettingsControllerTest.java    | 88 ++++++++++++++++++++--
 2 files changed, 91 insertions(+), 8 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/settings/DataSourceDTO.java 
b/server/src/main/java/org/apache/rocketmq/studio/settings/DataSourceDTO.java
index 61626ad9..bf9c5fb6 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/settings/DataSourceDTO.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/settings/DataSourceDTO.java
@@ -17,6 +17,7 @@
 package org.apache.rocketmq.studio.settings;
 
 import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
 import lombok.Data;
 
 @Data
@@ -28,20 +29,26 @@ public class DataSourceDTO {
     private String name;
 
     @NotBlank(message = "type is required")
+    @Pattern(
+            regexp = "(?i)\\s*(?:prometheus|victoria[ 
_]?metrics|thanos|mimir|cortex|arms)?\\s*",
+            message = "Unsupported metrics data source type")
     private String type;
 
     @NotBlank(message = "url is required")
     private String url;
 
+    @Pattern(
+            regexp = "(?i)\\s*(?:none|basic auth|bearer token)?\\s*",
+            message = "Unsupported metrics data source authentication")
     private String auth;
 
     public DataSourceVO toDataSourceVO() {
         return DataSourceVO.builder()
                 .key(key)
                 .name(name)
-                .type(type)
+                .type(type.trim())
                 .url(url)
-                .auth(auth)
+                .auth(auth == null ? null : auth.trim())
                 .build();
     }
 }
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsControllerTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsControllerTest.java
index 12f14191..094ee02e 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsControllerTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsControllerTest.java
@@ -160,9 +160,9 @@ class SettingsControllerTest {
 
     @Test
     void listDataSourcesShouldReturnAllSources() throws Exception {
-        DataSourceVO ds1 = 
DataSourceVO.builder().key("ds-1").name("Production").type("rocketmq")
+        DataSourceVO ds1 = 
DataSourceVO.builder().key("ds-1").name("Production").type("Prometheus")
                 .url("prod:9876").status("connected").build();
-        DataSourceVO ds2 = 
DataSourceVO.builder().key("ds-2").name("Staging").type("rocketmq")
+        DataSourceVO ds2 = 
DataSourceVO.builder().key("ds-2").name("Staging").type("Prometheus")
                 .url("staging:9876").status("disconnected").build();
         when(settingsService.listDataSources()).thenReturn(Arrays.asList(ds1, 
ds2));
 
@@ -189,9 +189,9 @@ class SettingsControllerTest {
 
     @Test
     void createDataSourceShouldReturnCreatedSource() throws Exception {
-        DataSourceVO input = DataSourceVO.builder().name("New 
DS").type("rocketmq")
+        DataSourceVO input = DataSourceVO.builder().name("New 
DS").type("Prometheus")
                 .url("new-host:9876").build();
-        DataSourceVO created = DataSourceVO.builder().key("ds-new").name("New 
DS").type("rocketmq")
+        DataSourceVO created = DataSourceVO.builder().key("ds-new").name("New 
DS").type("Prometheus")
                 .url("new-host:9876").status("connected").build();
         
when(settingsService.createDataSource(any(DataSourceVO.class))).thenReturn(created);
 
@@ -222,6 +222,43 @@ class SettingsControllerTest {
         verifyNoInteractions(settingsService);
     }
 
+    @Test
+    void createDataSourceShouldRejectUnsupportedMetricsType() throws Exception 
{
+        mockMvc.perform(post("/api/settings/datasources/create")
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content("""
+                                {
+                                  "name": "New DS",
+                                  "type": "unsupported",
+                                  "url": "http://metrics.example.test";
+                                }
+                                """))
+                .andExpect(status().isBadRequest())
+                .andExpect(jsonPath("$.code", is(400)))
+                .andExpect(jsonPath("$.message", is("Unsupported metrics data 
source type")));
+
+        verifyNoInteractions(settingsService);
+    }
+
+    @Test
+    void createDataSourceShouldRejectUnsupportedAuthentication() throws 
Exception {
+        mockMvc.perform(post("/api/settings/datasources/create")
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content("""
+                                {
+                                  "name": "New DS",
+                                  "type": "Prometheus",
+                                  "url": "http://metrics.example.test";,
+                                  "auth": "API Key"
+                                }
+                                """))
+                .andExpect(status().isBadRequest())
+                .andExpect(jsonPath("$.code", is(400)))
+                .andExpect(jsonPath("$.message", is("Unsupported metrics data 
source authentication")));
+
+        verifyNoInteractions(settingsService);
+    }
+
     @Test
     void createDataSourceShouldRejectNullRequestBody() throws Exception {
         mockMvc.perform(post("/api/settings/datasources/create")
@@ -236,7 +273,7 @@ class SettingsControllerTest {
 
     @Test
     void updateDataSourceShouldReturnUpdatedSource() throws Exception {
-        DataSourceVO input = DataSourceVO.builder().key("ds-1").name("Updated 
DS").type("rocketmq")
+        DataSourceVO input = DataSourceVO.builder().key("ds-1").name("Updated 
DS").type("Prometheus")
                 .url("updated:9876").build();
         
when(settingsService.updateDataSource(any(DataSourceVO.class))).thenReturn(input);
 
@@ -256,7 +293,7 @@ class SettingsControllerTest {
                         .content("""
                                 {
                                   "key": "ds-1",
-                                  "type": "rocketmq",
+                                  "type": "Prometheus",
                                   "url": "updated:9876"
                                 }
                                 """))
@@ -267,6 +304,45 @@ class SettingsControllerTest {
         verifyNoInteractions(settingsService);
     }
 
+    @Test
+    void updateDataSourceShouldRejectUnsupportedMetricsType() throws Exception 
{
+        mockMvc.perform(post("/api/settings/datasources/update")
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content("""
+                                {
+                                  "key": "ds-1",
+                                  "name": "Updated DS",
+                                  "type": "unsupported",
+                                  "url": "http://metrics.example.test";
+                                }
+                                """))
+                .andExpect(status().isBadRequest())
+                .andExpect(jsonPath("$.code", is(400)))
+                .andExpect(jsonPath("$.message", is("Unsupported metrics data 
source type")));
+
+        verifyNoInteractions(settingsService);
+    }
+
+    @Test
+    void updateDataSourceShouldRejectUnsupportedAuthentication() throws 
Exception {
+        mockMvc.perform(post("/api/settings/datasources/update")
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content("""
+                                {
+                                  "key": "ds-1",
+                                  "name": "Updated DS",
+                                  "type": "Prometheus",
+                                  "url": "http://metrics.example.test";,
+                                  "auth": "API Key"
+                                }
+                                """))
+                .andExpect(status().isBadRequest())
+                .andExpect(jsonPath("$.code", is(400)))
+                .andExpect(jsonPath("$.message", is("Unsupported metrics data 
source authentication")));
+
+        verifyNoInteractions(settingsService);
+    }
+
     @Test
     void updateDataSourceShouldRejectNullRequestBody() throws Exception {
         mockMvc.perform(post("/api/settings/datasources/update")

Reply via email to