This is an automated email from the ASF dual-hosted git repository.
zehnder pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new 223aa0ad94 fix(#2651): incorrect redirect to dashboard instead of app
module (#2689)
223aa0ad94 is described below
commit 223aa0ad948103a6ce068bb9946df41599660b1a
Author: Philipp Zehnder <[email protected]>
AuthorDate: Fri Apr 5 17:02:46 2024 +0200
fix(#2651): incorrect redirect to dashboard instead of app module (#2689)
* fix(#2651): Fix app module and deactivate it for default installation
* fix(#2651): Refactor and deprecate AssetDashboardResource
* fix(#2651): Add sanitize file name to FileManger
* fix(#2651): Check for file type in file manager
* fix(#2651): Check for file type in AssetDashboardResource
* fix(#2651): Fix e2e test for user roles
---
.../streampipes/manager/file/FileManager.java | 55 ++++++++--
.../streampipes/manager/file/TestFileManager.java | 112 +++++++++++++++++----
.../rest/impl/AssetDashboardResource.java | 57 ++++++++---
.../apache/streampipes/sdk/helpers/Filetypes.java | 9 +-
.../streampipes/sdk/helpers/FiletypesTest.java} | 31 +++---
.../testVariousUserRoles.smoke.spec.ts | 2 +-
ui/deployment/dev/config.yml | 1 -
.../app-asset-monitoring.component.html | 2 +-
.../app-asset-monitoring.module.ts | 4 +-
ui/src/app/app-overview/app-overview.module.ts | 4 +-
10 files changed, 209 insertions(+), 68 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..5038ec3af0 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
@@ -60,22 +60,33 @@ public class FileManager {
String filename,
InputStream fileInputStream) throws
IOException {
- String filetype = filename.substring(filename.lastIndexOf(".") + 1);
+ var filetype = filename.substring(filename.lastIndexOf(".") + 1);
- fileInputStream = cleanFile(fileInputStream, filetype);
+ fileInputStream = validateFileNameAndCleanFile(filename, filetype,
fileInputStream);
- FileMetadata fileMetadata = makeFileMetadata(user, filename, filetype);
- new FileHandler().storeFile(filename, fileInputStream);
- storeFileMetadata(fileMetadata);
- return fileMetadata;
+ var sanitizedFilename = sanitizeFilename(filename);
+
+ writeToFile(sanitizedFilename, fileInputStream);
+
+ return makeAndStoreFileMetadata(user, sanitizedFilename, filetype);
}
+
public static void deleteFile(String id) {
FileMetadata fileMetadata = getFileMetadataStorage().getMetadataById(id);
new FileHandler().deleteFile(fileMetadata.getFilename());
getFileMetadataStorage().deleteFileMetadata(id);
}
+ private static InputStream validateFileNameAndCleanFile(String filename,
+ String filetype,
+ InputStream fileInputStream)
{
+ if (!validateFileType(filename)) {
+ throw new IllegalArgumentException("Filetype for file %s not
allowed".formatted(filename));
+ }
+
+ return cleanFile(fileInputStream, filetype);
+ }
/**
* Remove Byte Order Mark (BOM) from csv files
@@ -84,7 +95,7 @@ public class FileManager {
* @param filetype file of type
* @return input stream without BOM
*/
- public static InputStream cleanFile(InputStream fileInputStream, String
filetype) {
+ protected static InputStream cleanFile(InputStream fileInputStream, String
filetype) {
if (Filetypes.CSV.getFileExtensions().contains(filetype.toLowerCase())) {
fileInputStream = new BOMInputStream(fileInputStream);
}
@@ -97,10 +108,21 @@ public class FileManager {
return !fileHash.equals(hash);
}
- private static void storeFileMetadata(FileMetadata fileMetadata) {
- getFileMetadataStorage().addFileMetadata(fileMetadata);
+ public static String sanitizeFilename(String filename) {
+ return filename.replaceAll("[^a-zA-Z0-9.\\-]", "_");
+ }
+
+ public static boolean validateFileType(String filename) {
+ return Filetypes.getAllFileExtensions()
+ .stream()
+ .anyMatch(filename::endsWith);
+ }
+
+ protected static void writeToFile(String sanitizedFilename, InputStream
fileInputStream) throws IOException {
+ new FileHandler().storeFile(sanitizedFilename, fileInputStream);
}
+
private static IFileMetadataStorage getFileMetadataStorage() {
return StorageDispatcher
.INSTANCE
@@ -108,6 +130,15 @@ public class FileManager {
.getFileMetadataStorage();
}
+ protected static FileMetadata makeAndStoreFileMetadata(String user,
+ String
sanitizedFilename,
+ String filetype) {
+ var fileMetadata = makeFileMetadata(user, sanitizedFilename, filetype);
+ storeFileMetadata(fileMetadata);
+
+ return fileMetadata;
+ }
+
private static FileMetadata makeFileMetadata(String user,
String filename,
String filetype) {
@@ -121,6 +152,11 @@ public class FileManager {
return fileMetadata;
}
+ private static void storeFileMetadata(FileMetadata fileMetadata) {
+ getFileMetadataStorage().addFileMetadata(fileMetadata);
+ }
+
+
private static List<FileMetadata> filterFiletypes(List<FileMetadata>
allFiles, String filetypes) {
return allFiles
.stream()
@@ -129,4 +165,5 @@ public class FileManager {
.anyMatch(ft -> ft.equals(fileMetadata.getFiletype())))
.collect(Collectors.toList());
}
+
}
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..a02a309fa3 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,116 @@
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;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+
public class TestFileManager {
+ @Test
+ public void storeFile_throwsExceptionForInvalidFileType() {
+ var filename = "testFile.invalid";
+
+ assertThrows(IllegalArgumentException.class, () ->
+ FileManager.storeFile("", filename, mock(InputStream.class)));
+ }
+
@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.csv";
+ var sanitizedFilename = FileManager.sanitizeFilename(filename);
+ assertEquals(".._file.csv", sanitizedFilename);
+ }
+
+ @Test
+ public void sanitizeFilename_removesDoubleParentDirectoryy() {
+ var filename = "../../file";
+ var sanitizedFilename = FileManager.sanitizeFilename(filename);
+ assertEquals(".._.._file", sanitizedFilename);
+ }
+
+ @Test
+ public void validateFileName_returnsTrueForCsv() {
+ assertTrue(FileManager.validateFileType("file.csv"));
+ }
+
+ @Test
+ public void validateFileName_returnsTrueForJson() {
+ assertTrue(FileManager.validateFileType("file.json"));
+ }
+
+ @Test
+ public void validateFileName_returnsFalseForSh() {
+ assertFalse(FileManager.validateFileType("file.sh"));
}
}
\ 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..4433d51ae4 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,35 @@ 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 {
+ var fileName = fileDetail.getName();
+
+ if (!FileManager.validateFileType(fileName)) {
+ LOG.error("File type of file " + fileName + " is not supported");
+ fail();
+ }
+
+ 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 +170,7 @@ public class AssetDashboardResource extends
AbstractRestResource {
}
private IAssetDashboardStorage getAssetDashboardStorage() {
- return
StorageDispatcher.INSTANCE.getNoSqlStore().getAssetDashboardStorage();
+ return StorageDispatcher.INSTANCE.getNoSqlStore()
+ .getAssetDashboardStorage();
}
}
diff --git
a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/Filetypes.java
b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/Filetypes.java
index 2ac00e6c45..681b180983 100644
---
a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/Filetypes.java
+++
b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/Filetypes.java
@@ -19,6 +19,7 @@ package org.apache.streampipes.sdk.helpers;
import java.util.Arrays;
import java.util.List;
+import java.util.stream.Stream;
public enum Filetypes {
@@ -30,7 +31,7 @@ public enum Filetypes {
XML("xml"),
ZIP("zip");
- private List<String> fileExtensions;
+ private final List<String> fileExtensions;
Filetypes(String... fileExtensions) {
this.fileExtensions = Arrays.asList(fileExtensions);
@@ -39,4 +40,10 @@ public enum Filetypes {
public List<String> getFileExtensions() {
return fileExtensions;
}
+
+ public static List<String> getAllFileExtensions() {
+ return Stream.of(Filetypes.values())
+ .flatMap(filetype -> filetype.getFileExtensions().stream())
+ .toList();
+ }
}
diff --git
a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/Filetypes.java
b/streampipes-sdk/src/test/java/org/apache/streampipes/sdk/helpers/FiletypesTest.java
similarity index 62%
copy from
streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/Filetypes.java
copy to
streampipes-sdk/src/test/java/org/apache/streampipes/sdk/helpers/FiletypesTest.java
index 2ac00e6c45..8c287f2cbc 100644
---
a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/Filetypes.java
+++
b/streampipes-sdk/src/test/java/org/apache/streampipes/sdk/helpers/FiletypesTest.java
@@ -15,28 +15,23 @@
* limitations under the License.
*
*/
-package org.apache.streampipes.sdk.helpers;
-import java.util.Arrays;
-import java.util.List;
+package org.apache.streampipes.sdk.helpers;
-public enum Filetypes {
+import org.junit.jupiter.api.Test;
- CSV("csv"),
- JPG("jpg", "jpeg"),
- JSON("json"),
- XLS("xls"),
- XLSX("xlsx"),
- XML("xml"),
- ZIP("zip");
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
- private List<String> fileExtensions;
+class FiletypesTest {
- Filetypes(String... fileExtensions) {
- this.fileExtensions = Arrays.asList(fileExtensions);
- }
+ @Test
+ public void getAllFileExtensions_returnsAllExtensions() {
+ var actualExtensions = Filetypes.getAllFileExtensions();
- public List<String> getFileExtensions() {
- return fileExtensions;
+ assertEquals(8, actualExtensions.size());
+ assertTrue(actualExtensions.contains("jpg"));
+ assertTrue(actualExtensions.contains("jpeg"));
+ assertTrue(actualExtensions.contains("csv"));
}
-}
+}
\ No newline at end of file
diff --git a/ui/cypress/tests/userManagement/testVariousUserRoles.smoke.spec.ts
b/ui/cypress/tests/userManagement/testVariousUserRoles.smoke.spec.ts
index 1d5195b1da..d64bfef8d7 100644
--- a/ui/cypress/tests/userManagement/testVariousUserRoles.smoke.spec.ts
+++ b/ui/cypress/tests/userManagement/testVariousUserRoles.smoke.spec.ts
@@ -40,7 +40,7 @@ for (var i = 0; i < testedRoles.length; i++) {
UserUtils.goToUserConfiguration();
cy.dataCy('navigation-icon', { timeout: 10000 }).should(
'have.length',
- 11,
+ 10,
);
cy.dataCy('user-accounts-table-row', { timeout: 10000 }).should(
diff --git a/ui/deployment/dev/config.yml b/ui/deployment/dev/config.yml
index d3980f177b..4edd9074ee 100644
--- a/ui/deployment/dev/config.yml
+++ b/ui/deployment/dev/config.yml
@@ -23,7 +23,6 @@ modules:
- spConnect
- spDashboard
- spDataExplorer
- - spAppOverview
- spAdd
- spAssets
- spFiles
diff --git
a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
index 4ec241b38a..7fe7439dc4 100644
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
+++ b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
@@ -16,7 +16,7 @@
~
-->
-<sp-basic-view showBackLink="true" [backLinkTarget]="['apps']">
+<sp-basic-view showBackLink="true" [backLinkTarget]="['apps', 'overview']">
<ng-container nav>
<mat-tab-group
[selectedIndex]="selectedIndex"
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
b/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
index cac83cb9cd..df9d4bfe46 100644
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
+++ b/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
@@ -33,12 +33,12 @@ import { ColorPickerModule } from 'ngx-color-picker';
import { SaveDashboardDialogComponent } from
'./dialog/save-dashboard/save-dashboard-dialog.component';
import { AssetDashboardOverviewComponent } from
'./components/dashboard-overview/dashboard-overview.component';
import { AddLinkDialogComponent } from
'./dialog/add-link/add-link-dialog.component';
-import { DashboardModule } from '../dashboard/dashboard.module';
import { RouterModule } from '@angular/router';
import { SharedUiModule } from '@streampipes/shared-ui';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { MatTabsModule } from '@angular/material/tabs';
+import { MatButtonModule } from '@angular/material/button';
@NgModule({
imports: [
@@ -48,11 +48,11 @@ import { MatTabsModule } from '@angular/material/tabs';
MatGridListModule,
MatIconModule,
MatTabsModule,
+ MatButtonModule,
MatInputModule,
MatFormFieldModule,
FormsModule,
ColorPickerModule,
- DashboardModule,
RouterModule.forChild([
{
path: '',
diff --git a/ui/src/app/app-overview/app-overview.module.ts
b/ui/src/app/app-overview/app-overview.module.ts
index 2b98e9afd6..eef43de838 100644
--- a/ui/src/app/app-overview/app-overview.module.ts
+++ b/ui/src/app/app-overview/app-overview.module.ts
@@ -30,6 +30,7 @@ import { RouterModule } from '@angular/router';
import { AvailableAppsService } from './apps';
import { PageName } from '../_enums/page-name.enum';
import { SharedUiModule } from '@streampipes/shared-ui';
+import { MatButtonModule } from '@angular/material/button';
@NgModule({
imports: [
@@ -39,13 +40,14 @@ import { SharedUiModule } from '@streampipes/shared-ui';
FormsModule,
MatGridListModule,
MatInputModule,
+ MatButtonModule,
MatFormFieldModule,
SharedUiModule,
RouterModule.forChild([
{
path: '',
children: [
- { path: '', component: AppOverviewComponent },
+ { path: 'overview', component: AppOverviewComponent },
...(AvailableAppsService.apps.map(app => {
return {
path: app.appLink,