You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ze...@apache.org on 2024/04/03 07:52:03 UTC

(streampipes) 03/03: fix(#2651): Refactor and deprecate AssetDashboardResource

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

zehnder pushed a commit to branch 2651-incorrect-redirect-to-dashboard-instead-of-app-module
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit 30c2f83f532e334302cbfe0a9e4ecceb4c1041cd
Author: Philipp Zehnder <te...@users.noreply.github.com>
AuthorDate: Wed Apr 3 09:51:51 2024 +0200

    fix(#2651): Refactor and deprecate AssetDashboardResource
---
 .../streampipes/manager/file/FileManager.java      |  5 ++
 .../streampipes/manager/file/TestFileManager.java  | 86 ++++++++++++++++------
 .../rest/impl/AssetDashboardResource.java          | 50 +++++++++----
 3 files changed, 106 insertions(+), 35 deletions(-)

diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/file/FileManager.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/file/FileManager.java
index 192d124bbe..5674aaa12e 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/file/FileManager.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/file/FileManager.java
@@ -64,6 +64,7 @@ public class FileManager {
 
     fileInputStream = cleanFile(fileInputStream, filetype);
 
+
     FileMetadata fileMetadata = makeFileMetadata(user, filename, filetype);
     new FileHandler().storeFile(filename, fileInputStream);
     storeFileMetadata(fileMetadata);
@@ -97,6 +98,10 @@ public class FileManager {
     return !fileHash.equals(hash);
   }
 
+  public static String sanitizeFilename(String filename) {
+    return filename.replaceAll("[^a-zA-Z0-9.\\-]", "_");
+  }
+
   private static void storeFileMetadata(FileMetadata fileMetadata) {
     getFileMetadataStorage().addFileMetadata(fileMetadata);
   }
diff --git a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/file/TestFileManager.java b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/file/TestFileManager.java
index 58553e72f6..59e96b1e8c 100644
--- a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/file/TestFileManager.java
+++ b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/file/TestFileManager.java
@@ -18,46 +18,88 @@
 package org.apache.streampipes.manager.file;
 
 import org.apache.commons.io.IOUtils;
-import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
 public class TestFileManager {
 
   @Test
   public void testCleanFileWithoutBom() throws IOException {
-    String expected = "test";
-    InputStream inputStream = IOUtils.toInputStream(expected, StandardCharsets.UTF_8);
-    InputStream resultStream = FileManager.cleanFile(inputStream, "CSV");
-    String resultString = IOUtils.toString(resultStream, StandardCharsets.UTF_8);
+    var expected = "test";
+    var inputStream = IOUtils.toInputStream(expected, StandardCharsets.UTF_8);
+    var resultStream = FileManager.cleanFile(inputStream, "CSV");
+    var resultString = IOUtils.toString(resultStream, StandardCharsets.UTF_8);
 
-    Assertions.assertEquals(expected, resultString);
+    assertEquals(expected, resultString);
   }
 
   @Test
   public void testCleanFileWithBom() throws IOException {
-    String expected = "test";
-    String utf8Bom = "\uFEFF";
-    String inputString = utf8Bom + expected;
-    InputStream inputStream = IOUtils.toInputStream(inputString, StandardCharsets.UTF_8);
-    InputStream resultStream = FileManager.cleanFile(inputStream, "CSV");
-    String resultString = IOUtils.toString(resultStream, StandardCharsets.UTF_8);
+    var expected = "test";
+    var utf8Bom = "\uFEFF";
+    var inputString = utf8Bom + expected;
+    var inputStream = IOUtils.toInputStream(inputString, StandardCharsets.UTF_8);
+    var resultStream = FileManager.cleanFile(inputStream, "CSV");
+    var resultString = IOUtils.toString(resultStream, StandardCharsets.UTF_8);
 
-    Assertions.assertEquals(expected, resultString);
+    assertEquals(expected, resultString);
   }
 
   @Test
   public void testCleanFileWithBomAndUmlauts() throws IOException {
-    String expected = "testäüö";
-    String utf8Bom = "\uFEFF";
-    String inputString = utf8Bom + expected;
-    InputStream inputStream = IOUtils.toInputStream(inputString, StandardCharsets.UTF_8);
-    InputStream resultStream = FileManager.cleanFile(inputStream, "CSV");
-    String resultString = IOUtils.toString(resultStream, StandardCharsets.UTF_8);
-
-    Assertions.assertEquals(expected, resultString);
+    var expected = "testäüö";
+    var utf8Bom = "\uFEFF";
+    var inputString = utf8Bom + expected;
+    var inputStream = IOUtils.toInputStream(inputString, StandardCharsets.UTF_8);
+    var resultStream = FileManager.cleanFile(inputStream, "CSV");
+    var resultString = IOUtils.toString(resultStream, StandardCharsets.UTF_8);
+
+    assertEquals(expected, resultString);
+  }
+
+  @Test
+  public void sanitizeFilename_replacesNonAlphanumericCharactersWithUnderscore() {
+    var filename = "file@name#with$special%characters";
+    var sanitizedFilename = FileManager.sanitizeFilename(filename);
+    assertEquals("file_name_with_special_characters", sanitizedFilename);
+  }
+
+  @Test
+  public void sanitizeFilename_keepsAlphanumericAndDotAndHyphenCharacters() {
+    var filename = "file.name-with_alphanumeric123";
+    var sanitizedFilename = FileManager.sanitizeFilename(filename);
+    assertEquals(filename, sanitizedFilename);
+  }
+
+  @Test
+  public void sanitizeFilename_returnsUnderscoreForFilenameWithAllSpecialCharacters() {
+    var filename = "@#$%^&*()";
+    var sanitizedFilename = FileManager.sanitizeFilename(filename);
+    assertEquals("_________", sanitizedFilename);
+  }
+
+  @Test
+  public void sanitizeFilename_returnsEmptyStringForEmptyFilename() {
+    var filename = "";
+    var sanitizedFilename = FileManager.sanitizeFilename(filename);
+    assertEquals("", sanitizedFilename);
+  }
+
+  @Test
+  public void sanitizeFilename_removesSingleParentDirectory() {
+    var filename = "../file";
+    var sanitizedFilename = FileManager.sanitizeFilename(filename);
+    assertEquals(".._file", sanitizedFilename);
+  }
+
+  @Test
+  public void sanitizeFilename_removesDoubleParentDirectoryy() {
+    var filename = "../../file";
+    var sanitizedFilename = FileManager.sanitizeFilename(filename);
+    assertEquals(".._.._file", sanitizedFilename);
   }
 }
\ No newline at end of file
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java
index 919bea60d9..111ea8ab14 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java
@@ -17,6 +17,7 @@
  */
 package org.apache.streampipes.rest.impl;
 
+import org.apache.streampipes.manager.file.FileManager;
 import org.apache.streampipes.model.client.assetdashboard.AssetDashboardConfig;
 import org.apache.streampipes.rest.core.base.impl.AbstractRestResource;
 import org.apache.streampipes.rest.shared.exception.SpMessageException;
@@ -43,6 +44,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.FileNameMap;
 import java.net.URLConnection;
 import java.nio.file.Files;
@@ -51,6 +53,7 @@ import java.util.List;
 
 @RestController
 @RequestMapping("/api/v2/asset-dashboards")
+@Deprecated(forRemoval = true, since = "0.95.0")
 public class AssetDashboardResource extends AbstractRestResource {
 
   private static final Logger LOG = LoggerFactory.getLogger(AssetDashboardResource.class);
@@ -59,44 +62,52 @@ public class AssetDashboardResource extends AbstractRestResource {
 
   @GetMapping(path = "/{dashboardId}", produces = MediaType.APPLICATION_JSON_VALUE)
   public ResponseEntity<AssetDashboardConfig> getAssetDashboard(@PathVariable("dashboardId") String dashboardId) {
-    return ok(getNoSqlStorage().getAssetDashboardStorage().getAssetDashboard(dashboardId));
+    return ok(getNoSqlStorage().getAssetDashboardStorage()
+                               .getAssetDashboard(dashboardId));
   }
 
   @PutMapping(
       path = "/{dashboardId}",
       produces = MediaType.APPLICATION_JSON_VALUE,
       consumes = MediaType.APPLICATION_JSON_VALUE)
-  public ResponseEntity<Void> updateAssetDashboard(@PathVariable("dashboardId") String dashboardId,
-                                                   @RequestBody AssetDashboardConfig dashboardConfig) {
+  public ResponseEntity<Void> updateAssetDashboard(
+      @PathVariable("dashboardId") String dashboardId,
+      @RequestBody AssetDashboardConfig dashboardConfig
+  ) {
     AssetDashboardConfig dashboard = getAssetDashboardStorage().getAssetDashboard(dashboardId);
     dashboardConfig.setRev(dashboard.getRev());
-    getNoSqlStorage().getAssetDashboardStorage().updateAssetDashboard(dashboardConfig);
+    getNoSqlStorage().getAssetDashboardStorage()
+                     .updateAssetDashboard(dashboardConfig);
     return ok();
   }
 
   @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
   public ResponseEntity<List<AssetDashboardConfig>> getAllDashboards() {
-    return ok(getNoSqlStorage().getAssetDashboardStorage().getAllAssetDashboards());
+    return ok(getNoSqlStorage().getAssetDashboardStorage()
+                               .getAllAssetDashboards());
   }
 
   @PostMapping(
       produces = MediaType.APPLICATION_JSON_VALUE,
       consumes = MediaType.APPLICATION_JSON_VALUE)
   public ResponseEntity<Void> storeAssetDashboard(@RequestBody AssetDashboardConfig dashboardConfig) {
-    getNoSqlStorage().getAssetDashboardStorage().storeAssetDashboard(dashboardConfig);
+    getNoSqlStorage().getAssetDashboardStorage()
+                     .storeAssetDashboard(dashboardConfig);
     return ok();
   }
 
   @DeleteMapping(path = "/{dashboardId}")
   public ResponseEntity<Void> deleteAssetDashboard(@PathVariable("dashboardId") String dashboardId) {
-    getNoSqlStorage().getAssetDashboardStorage().deleteAssetDashboard(dashboardId);
+    getNoSqlStorage().getAssetDashboardStorage()
+                     .deleteAssetDashboard(dashboardId);
     return ok();
   }
 
   @GetMapping(path = "/images/{imageName}")
   public ResponseEntity<byte[]> getDashboardImage(@PathVariable("imageName") String imageName) {
     try {
-      java.nio.file.Path path = Paths.get(getTargetFile(imageName));
+      var sanitizedFileName = FileManager.sanitizeFilename(imageName);
+      java.nio.file.Path path = Paths.get(getTargetFile(sanitizedFileName));
       File file = new File(path.toString());
       FileNameMap fileNameMap = URLConnection.getFileNameMap();
       String mimeType = fileNameMap.getContentTypeFor(file.getName());
@@ -114,16 +125,28 @@ public class AssetDashboardResource extends AbstractRestResource {
 
   @PostMapping(path = "/images", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
   public ResponseEntity<Void> storeDashboardImage(@RequestPart("file_upload") MultipartFile fileDetail) {
-    File targetDirectory = new File(getTargetDirectory());
+    try {
+      storeFile(fileDetail.getName(), fileDetail.getInputStream());
+      return ok();
+    } catch (IOException e) {
+      LOG.error("Could not extract image input stream from request", e);
+      return fail();
+    }
+  }
+
+  private void storeFile(String fileName, InputStream fileInputStream) {
+
+    var targetDirectory = new File(getTargetDirectory());
     if (!targetDirectory.exists()) {
       targetDirectory.mkdirs();
     }
 
-    File targetFile = new File(getTargetFile(fileDetail.getName()));
+    var sanitizedFileName = FileManager.sanitizeFilename(fileName);
+
+    var targetFile = new File(getTargetFile(sanitizedFileName));
 
     try {
-      FileUtils.copyInputStreamToFile(fileDetail.getInputStream(), targetFile);
-      return ok();
+      FileUtils.copyInputStreamToFile(fileInputStream, targetFile);
     } catch (IOException e) {
       LOG.error(e.getMessage(), e);
       throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e);
@@ -140,6 +163,7 @@ public class AssetDashboardResource extends AbstractRestResource {
   }
 
   private IAssetDashboardStorage getAssetDashboardStorage() {
-    return StorageDispatcher.INSTANCE.getNoSqlStore().getAssetDashboardStorage();
+    return StorageDispatcher.INSTANCE.getNoSqlStore()
+                                     .getAssetDashboardStorage();
   }
 }