diff --git a/dashboard/pom.xml b/dashboard/pom.xml
index 0084017..0fac68e 100644
--- a/dashboard/pom.xml
+++ b/dashboard/pom.xml
@@ -31,6 +31,10 @@
spring-boot-starter-web
provided
+
+ de.77zzcx7.nbs-cloud
+ files-api
+
\ No newline at end of file
diff --git a/dashboard/src/main/java/de/nbscloud/dashboard/controller/DashboardWidgetController.java b/dashboard/src/main/java/de/nbscloud/dashboard/controller/DashboardWidgetController.java
index 7e92181..16e2e5b 100644
--- a/dashboard/src/main/java/de/nbscloud/dashboard/controller/DashboardWidgetController.java
+++ b/dashboard/src/main/java/de/nbscloud/dashboard/controller/DashboardWidgetController.java
@@ -26,6 +26,7 @@ public class DashboardWidgetController {
@GetMapping("dashboard/widgets/machineMetrics")
public String getDiskUsage(HttpServletRequest request, HttpServletResponse response, Model model) {
+
model.addAttribute("interfaces", metricService.getInterfaces());
model.addAttribute("updates", metricService.getUpdates());
diff --git a/files-api/pom.xml b/files-api/pom.xml
new file mode 100644
index 0000000..858b058
--- /dev/null
+++ b/files-api/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+
+ de.77zzcx7.nbs-cloud
+ nbs-cloud-aggregator
+ 18-SNAPSHOT
+
+
+ de.77zzcx7.nbs-cloud
+ files-api
+ jar
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ provided
+
+
+ de.77zzcx7.nbs-cloud
+ web-container-registry
+
+
+
+
diff --git a/files-api/src/main/java/de/nbscloud/files/api/FilesService.java b/files-api/src/main/java/de/nbscloud/files/api/FilesService.java
new file mode 100644
index 0000000..403498f
--- /dev/null
+++ b/files-api/src/main/java/de/nbscloud/files/api/FilesService.java
@@ -0,0 +1,33 @@
+package de.nbscloud.files.api;
+
+import de.nbscloud.webcontainer.registry.App;
+
+import java.nio.file.Path;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+public interface FilesService {
+ record ContentContainer(boolean directory, Path path, String name, long size,
+ LocalDateTime lastModified) {
+ }
+
+ public void createAppDirectory(App app);
+
+ public void createDirectory(App app, Path path);
+
+ public void createFile(App app, Path path, byte[] content);
+
+ public void delete(App app, Path path);
+
+ public void get(App app, Path path);
+
+ /**
+ * Paths in return list are always relative to the appDir.
+ *
+ * @param app to list the files for
+ * @param path in case of {@link Optional#EMPTY} the appDir is used as start dir. If not empty, path has to be relative
+ * to the appDir
+ */
+ public List list(App app, Optional path);
+}
diff --git a/files/pom.xml b/files/pom.xml
index 41c6170..e73b5d4 100644
--- a/files/pom.xml
+++ b/files/pom.xml
@@ -21,6 +21,10 @@
de.77zzcx7.nbs-cloud
web-container-config
+
+ de.77zzcx7.nbs-cloud
+ files-api
+
org.springframework.boot
diff --git a/files/src/main/java/de/nbscloud/files/AppLocationTracker.java b/files/src/main/java/de/nbscloud/files/AppLocationTracker.java
new file mode 100644
index 0000000..c84b62d
--- /dev/null
+++ b/files/src/main/java/de/nbscloud/files/AppLocationTracker.java
@@ -0,0 +1,54 @@
+package de.nbscloud.files;
+
+import de.nbscloud.files.config.FilesConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.nio.file.Path;
+
+@Component
+public class AppLocationTracker implements InitializingBean {
+ private static final Logger logger = LoggerFactory.getLogger(AppLocationTracker.class);
+
+ @Autowired
+ private FilesConfig filesConfig;
+ @Autowired
+ private LocationTracker locationTracker;
+
+ private Path baseDirPath;
+
+ public Path resolve(String appId, Path path) {
+ validate(Path.of(appId));
+ validate(path);
+
+ final Path appPath = this.baseDirPath.resolve(appId);
+
+ return appPath.resolve(path);
+ }
+
+ private void validate(Path path) {
+ if(path == null) {
+ throw new IllegalStateException("Null");
+ }
+
+ if(path.toString().contains("..")) {
+ throw new IllegalStateException("Relative path");
+ }
+
+ if (path.isAbsolute()) {
+ throw new IllegalStateException("Absolute path: " + path);
+ }
+
+ if(!this.baseDirPath.resolve(path).normalize().startsWith(this.baseDirPath)) {
+ throw new IllegalStateException("Illegal path: " + path);
+ }
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ this.baseDirPath = this.locationTracker.getAppDir();
+ }
+}
diff --git a/files/src/main/java/de/nbscloud/files/FileSystemService.java b/files/src/main/java/de/nbscloud/files/FileSystemService.java
index d698d75..988f2fb 100644
--- a/files/src/main/java/de/nbscloud/files/FileSystemService.java
+++ b/files/src/main/java/de/nbscloud/files/FileSystemService.java
@@ -1,5 +1,6 @@
package de.nbscloud.files;
+import de.nbscloud.files.api.FilesService.ContentContainer;
import de.nbscloud.files.config.FilesConfig;
import de.nbscloud.files.exception.FileSystemServiceException;
import org.apache.commons.io.FileUtils;
@@ -20,6 +21,7 @@ import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
+import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -29,10 +31,6 @@ public class FileSystemService {
private static final Logger logger = LoggerFactory.getLogger(FileSystemService.class);
- public static record ContentContainer(boolean directory, Path path, String name, long size,
- LocalDateTime lastModified) {
- }
-
public enum SortOrder {
/**
* First by type (directories first), then by name ignoring case
@@ -95,6 +93,14 @@ public class FileSystemService {
}
}
+ void createDirectory(Path path) {
+ try {
+ Files.createDirectories(path);
+ } catch (IOException e) {
+ throw new FileSystemServiceException("Could not create directory", e);
+ }
+ }
+
public void createFile(String name, byte[] content) {
try {
Files.write(this.locationTracker.resolve(name), content, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
@@ -278,7 +284,7 @@ public class FileSystemService {
}
}
- public List list(SortOrder sortOrder) {
+ List list(Path startPath, SortOrder sortOrder, Function relativizer) {
try {
List contentList = Files.list(this.locationTracker.getCurrentLocation())
.filter(path -> {
@@ -295,7 +301,7 @@ public class FileSystemService {
final boolean isDir = Files.isDirectory(path);
return new ContentContainer(isDir,
- this.locationTracker.getRelativeToBaseDir(path),
+ relativizer.apply(path),
path.getFileName().toString(),
isDir ? FileUtils.sizeOfDirectory(path.toFile()) : Files.size(path),
LocalDateTime.ofInstant(Files.getLastModifiedTime(path)
@@ -313,6 +319,10 @@ public class FileSystemService {
}
}
+ public List list(SortOrder sortOrder) {
+ return list(this.locationTracker.getCurrentLocation(), sortOrder, path -> this.locationTracker.getRelativeToBaseDir(path));
+ }
+
public List collectDirs(String sourceFile) {
try {
final List resultList = new ArrayList<>();
diff --git a/files/src/main/java/de/nbscloud/files/FilesServiceImpl.java b/files/src/main/java/de/nbscloud/files/FilesServiceImpl.java
new file mode 100644
index 0000000..1375683
--- /dev/null
+++ b/files/src/main/java/de/nbscloud/files/FilesServiceImpl.java
@@ -0,0 +1,61 @@
+package de.nbscloud.files;
+
+import de.nbscloud.files.api.FilesService;
+import de.nbscloud.files.exception.FileSystemServiceException;
+import de.nbscloud.webcontainer.registry.App;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class FilesServiceImpl implements FilesService {
+ @Autowired
+ private FileSystemService fileSystemService;
+ @Autowired
+ private AppLocationTracker locationTracker;
+
+ private Path resolve(App app, Path path) {
+ return this.locationTracker.resolve(app.getId(), path);
+ }
+
+ @Override
+ public void createAppDirectory(App app) {
+ try {
+ this.fileSystemService.createDirectory(resolve(app, Path.of("")));
+ }
+ catch(FileSystemServiceException e) {
+ // Ignore, may happen if the dir already exists
+ }
+ }
+
+ @Override
+ public void createDirectory(App app, Path path) {
+ this.fileSystemService.createDirectory(resolve(app, path));
+ }
+
+ @Override
+ public void createFile(App app, Path path, byte[] content) {
+ this.fileSystemService.createFile(resolve(app, path), content);
+ }
+
+ @Override
+ public void delete(App app, Path path) {
+ this.fileSystemService.delete(resolve(app, path));
+ }
+
+ @Override
+ public void get(App app, Path path) {
+ this.fileSystemService.get(resolve(app, path));
+ }
+
+ @Override
+ public List list(App app, Optional path) {
+ final Path appPath = resolve(app, Path.of(""));
+ final Path p = path.map(tmpPath -> resolve(app, tmpPath)).orElse(appPath);
+
+ return this.fileSystemService.list(p, FileSystemService.SortOrder.NATURAL, callbackPath -> appPath.relativize(callbackPath));
+ }
+}
diff --git a/files/src/main/java/de/nbscloud/files/LocationTracker.java b/files/src/main/java/de/nbscloud/files/LocationTracker.java
index 824d928..078e077 100644
--- a/files/src/main/java/de/nbscloud/files/LocationTracker.java
+++ b/files/src/main/java/de/nbscloud/files/LocationTracker.java
@@ -3,6 +3,7 @@ package de.nbscloud.files;
import de.nbscloud.files.config.FilesConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -10,7 +11,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
@Component
-public class LocationTracker {
+public class LocationTracker implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(LocationTracker.class);
@Autowired
@@ -25,7 +26,8 @@ public class LocationTracker {
this.currentLocation = this.baseDirPath.resolve("");
}
- public void init() {
+ @Override
+ public void afterPropertiesSet() throws Exception {
this.baseDirPath = Paths.get(this.filesConfig.getBaseDir());
this.currentLocation = this.baseDirPath.resolve("");
@@ -35,7 +37,11 @@ public class LocationTracker {
public void reset() {
logger.debug("Reset location");
- init();
+ try {
+ afterPropertiesSet();
+ } catch (Exception e) {
+ // Cannot happen
+ }
}
Path getCurrentLocation() {
@@ -50,6 +56,10 @@ public class LocationTracker {
return this.baseDirPath.relativize(other);
}
+ public Path getAppDir() {
+ return this.baseDirPath.resolve(this.filesConfig.getAppDir());
+ }
+
private Path getTrashBin() {
return this.baseDirPath.resolve(this.filesConfig.getTrashBinName());
}
@@ -72,24 +82,6 @@ public class LocationTracker {
this.currentLocation = this.baseDirPath.resolve(navigateTo);
}
- public void validate(String path) {
- // Absolut paths are allowed, however, they have to be under baseDir
-
- if(path == null) {
- throw new IllegalStateException("Null");
- }
-
- if(path.contains("..")) {
- throw new IllegalStateException("Relative path");
- }
-
- final Path tmpPath = Path.of(path);
-
- if(!tmpPath.normalize().startsWith(this.baseDirPath)) {
- throw new IllegalStateException("Illegal path: " + path);
- }
- }
-
private void validate_internal(String navigateTo) {
if(navigateTo == null) {
throw new IllegalStateException("Null");
diff --git a/files/src/main/java/de/nbscloud/files/config/FilesConfig.java b/files/src/main/java/de/nbscloud/files/config/FilesConfig.java
index d59806e..f30e090 100644
--- a/files/src/main/java/de/nbscloud/files/config/FilesConfig.java
+++ b/files/src/main/java/de/nbscloud/files/config/FilesConfig.java
@@ -14,6 +14,7 @@ public class FilesConfig {
private String trashBinName;
private int truncateFileNameChars;
private String sharesName;
+ private String appDir;
public String getBaseDir() {
return baseDir;
@@ -62,4 +63,12 @@ public class FilesConfig {
public void setSharesName(String sharesName) {
this.sharesName = sharesName;
}
+
+ public String getAppDir() {
+ return appDir;
+ }
+
+ public void setAppDir(String appDir) {
+ this.appDir = appDir;
+ }
}
diff --git a/files/src/main/java/de/nbscloud/files/controller/FilesController.java b/files/src/main/java/de/nbscloud/files/controller/FilesController.java
index ddee2a3..6585c62 100644
--- a/files/src/main/java/de/nbscloud/files/controller/FilesController.java
+++ b/files/src/main/java/de/nbscloud/files/controller/FilesController.java
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import de.nbscloud.files.FileSystemService;
import de.nbscloud.files.LocationTracker;
import de.nbscloud.files.Share;
+import de.nbscloud.files.api.FilesService.ContentContainer;
import de.nbscloud.files.config.FilesConfig;
import de.nbscloud.files.exception.FileSystemServiceException;
import de.nbscloud.files.form.RenameForm;
@@ -338,12 +339,12 @@ public class FilesController implements InitializingBean {
return retList;
}
- private List getContent(FileSystemService.SortOrder order) {
- final List contentList = this.fileSystemService.list(order);
+ private List getContent(FileSystemService.SortOrder order) {
+ final List contentList = this.fileSystemService.list(order);
if (!this.locationTracker.isBasePath()) {
contentList.add(0,
- new FileSystemService.ContentContainer(true,
+ new ContentContainer(true,
this.locationTracker.getParent(),
"..",
0L,
@@ -382,8 +383,6 @@ public class FilesController implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
- this.locationTracker.init();
-
if (this.filesConfig.isUseTrashBin()) {
try {
this.fileSystemService.createDirectory(this.filesConfig.getTrashBinName());
diff --git a/files/src/main/resources/config/files-application.properties b/files/src/main/resources/config/files-application.properties
index 91e5e8b..219e3b5 100644
--- a/files/src/main/resources/config/files-application.properties
+++ b/files/src/main/resources/config/files-application.properties
@@ -25,4 +25,7 @@ nbs-cloud.files.trashBinName=nbs.internal/nbs.trashbin
nbs-cloud.files.truncateFileNameChars=130
# Knob to configure the name of the shares directory
-nbs-cloud.files.sharesName=nbs.internal/nbs.shares
\ No newline at end of file
+nbs-cloud.files.sharesName=nbs.internal/nbs.shares
+
+# Knob to configure the name of the app directory
+nbs-cloud.files.appDir=nbs.internal/apps
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 36f7179..8e43bf0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,7 @@
files
+ files-api
web-container
web-container-registry
notes
@@ -63,6 +64,11 @@
files
${project.version}
+
+ de.77zzcx7.nbs-cloud
+ files-api
+ ${project.version}
+
de.77zzcx7.nbs-cloud
web-container-registry
@@ -199,4 +205,4 @@
-
\ No newline at end of file
+