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 07ebe442 fix: reject updates for missing data sources (#581)
07ebe442 is described below

commit 07ebe4428e04f86d29bbe19bcb432384121f68b2
Author: yx9o <[email protected]>
AuthorDate: Wed Jul 29 10:08:17 2026 +0800

    fix: reject updates for missing data sources (#581)
---
 .../settings/InMemorySettingsRepository.java       |  5 ++++
 .../studio/settings/SettingsRepository.java        |  2 ++
 .../rocketmq/studio/settings/SettingsService.java  |  6 +++-
 .../settings/InMemorySettingsRepositoryTest.java   | 32 ++++++++++++++++------
 .../studio/settings/SettingsServiceTest.java       | 20 ++++++++++++--
 5 files changed, 53 insertions(+), 12 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepository.java
 
b/server/src/main/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepository.java
index 46a1366b..ae72350e 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepository.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepository.java
@@ -65,6 +65,11 @@ public class InMemorySettingsRepository implements 
SettingsRepository {
         return dataSource;
     }
 
+    @Override
+    public boolean replaceDataSource(DataSourceVO dataSource) {
+        return dataSources.replace(dataSource.getKey(), dataSource) != null;
+    }
+
     @Override
     public void deleteDataSource(String key) {
         dataSources.remove(key);
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsRepository.java
 
b/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsRepository.java
index 0e6e2b9b..ecf24bf5 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsRepository.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsRepository.java
@@ -30,6 +30,8 @@ public interface SettingsRepository {
 
     DataSourceVO saveDataSource(DataSourceVO dataSource);
 
+    boolean replaceDataSource(DataSourceVO dataSource);
+
     void deleteDataSource(String key);
 
     Optional<DataSourceVO> findDataSourceByKey(String key);
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsService.java 
b/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsService.java
index d98a1cc5..6a49836d 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsService.java
@@ -19,6 +19,7 @@ package org.apache.rocketmq.studio.settings;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.studio.common.exception.BusinessException;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.client.SimpleClientHttpRequestFactory;
@@ -101,7 +102,10 @@ public class SettingsService {
 
     public DataSourceVO updateDataSource(DataSourceVO dataSource) {
         log.info("Updating data source: {}", dataSource.getKey());
-        return settingsRepository.saveDataSource(dataSource);
+        if (!settingsRepository.replaceDataSource(dataSource)) {
+            throw new BusinessException(404, "Data source not found: " + 
dataSource.getKey());
+        }
+        return dataSource;
     }
 
 
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepositoryTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepositoryTest.java
index 7a30002f..373d3753 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepositoryTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepositoryTest.java
@@ -25,7 +25,7 @@ class InMemorySettingsRepositoryTest {
     private final InMemorySettingsRepository repository = new 
InMemorySettingsRepository();
 
     @Test
-    void saveDataSourceShouldSupportCreateUpdateAndDeleteByKey() {
+    void saveDataSourceShouldSupportCreateAndDeleteByKey() {
         DataSourceVO dataSource = DataSourceVO.builder()
                 .key("source-1")
                 .name("Prometheus")
@@ -38,17 +38,31 @@ class InMemorySettingsRepositoryTest {
         
assertThat(repository.findDataSourceByKey("source-1")).containsSame(dataSource);
         
assertThat(repository.findAllDataSources()).containsExactly(dataSource);
 
-        dataSource.setName("Updated Prometheus");
-        repository.saveDataSource(dataSource);
-
-        assertThat(repository.findDataSourceByKey("source-1"))
-                .get()
-                .extracting(DataSourceVO::getName)
-                .isEqualTo("Updated Prometheus");
-
         repository.deleteDataSource("source-1");
 
         assertThat(repository.findDataSourceByKey("source-1")).isEmpty();
         assertThat(repository.findAllDataSources()).isEmpty();
     }
+
+    @Test
+    void replaceDataSourceShouldUpdateExistingEntry() {
+        DataSourceVO existing = 
DataSourceVO.builder().key("source-1").name("Prometheus").build();
+        DataSourceVO replacement = 
DataSourceVO.builder().key("source-1").name("Updated Prometheus").build();
+        repository.saveDataSource(existing);
+
+        boolean replaced = repository.replaceDataSource(replacement);
+
+        assertThat(replaced).isTrue();
+        
assertThat(repository.findAllDataSources()).containsExactly(replacement);
+    }
+
+    @Test
+    void replaceDataSourceShouldNotInsertUnknownEntry() {
+        DataSourceVO replacement = 
DataSourceVO.builder().key("missing").name("Unexpected DS").build();
+
+        boolean replaced = repository.replaceDataSource(replacement);
+
+        assertThat(replaced).isFalse();
+        assertThat(repository.findAllDataSources()).isEmpty();
+    }
 }
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsServiceTest.java
index ba5f4d45..b7d09c82 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsServiceTest.java
@@ -19,6 +19,7 @@ package org.apache.rocketmq.studio.settings;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.sun.net.httpserver.HttpExchange;
 import com.sun.net.httpserver.HttpServer;
+import org.apache.rocketmq.studio.common.exception.BusinessException;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -37,6 +38,7 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.verify;
@@ -213,13 +215,27 @@ class SettingsServiceTest {
     void updateDataSourceShouldDelegateToRepository() {
         DataSourceVO input = DataSourceVO.builder().key("ds-1").name("Updated 
DS").type("rocketmq")
                 .url("updated-host:9876").build();
-        
when(settingsRepository.saveDataSource(any(DataSourceVO.class))).thenReturn(input);
+        when(settingsRepository.replaceDataSource(input)).thenReturn(true);
 
         DataSourceVO result = settingsService.updateDataSource(input);
 
         assertThat(result.getKey()).isEqualTo("ds-1");
         assertThat(result.getName()).isEqualTo("Updated DS");
-        verify(settingsRepository).saveDataSource(input);
+        verify(settingsRepository).replaceDataSource(input);
+    }
+
+    @Test
+    void updateDataSourceShouldRejectUnknownKey() {
+        SettingsService service = new SettingsService(new 
InMemorySettingsRepository(), RestClient.builder(), new ObjectMapper());
+        DataSourceVO input = 
DataSourceVO.builder().key("missing").name("Unexpected DS").type("rocketmq")
+                .url("unexpected-host:9876").build();
+
+        assertThatThrownBy(() -> service.updateDataSource(input))
+                .isInstanceOf(BusinessException.class)
+                .hasMessage("Data source not found: missing")
+                .extracting("code")
+                .isEqualTo(404);
+        assertThat(service.listDataSources()).isEmpty();
     }
 
     @Test

Reply via email to