Compare commits
2 Commits
a60df48774
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a0c810214 | |||
| 1c6b127543 |
@@ -24,24 +24,21 @@ public class AdventAccessService implements AccessService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkAccess(Path path) {
|
public boolean checkAccess(Path path) {
|
||||||
Optional<String> pathUriOptional = this.fileURIResolver.resolve(path);
|
Optional<String> pathUri = this.fileURIResolver.resolve(path);
|
||||||
|
|
||||||
String pathUri;
|
if (pathUri.isEmpty()) {
|
||||||
if (pathUriOptional.isEmpty()) {
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
pathUri = pathUriOptional.get().replaceAll("^.file", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<AdventConfiguration.AdventEvent> matchingAdvent = adventConfiguration.events().stream()
|
Optional<AdventConfiguration.AdventEvent> matchingAdvent = adventConfiguration.events().stream()
|
||||||
.filter(e -> pathUri.startsWith(e.path()))
|
.filter(e -> pathUri.get().startsWith(e.path()))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
|
|
||||||
if (matchingAdvent.isEmpty()) {
|
if (matchingAdvent.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String dayString = pathUri.replaceAll(
|
String dayString = pathUri.get().replaceAll(
|
||||||
"^" + Pattern.quote(matchingAdvent.get().path()) + "/?([^.]+)\\.?[^.]*$",
|
"^" + Pattern.quote(matchingAdvent.get().path()) + "/?([^.]+)\\.?[^.]*$",
|
||||||
"$1");
|
"$1");
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class AdventThumbnailPathURIResolver extends PathAccessor implements Path
|
|||||||
|
|
||||||
private Optional<java.nio.file.Path> getDefaultThumbnailPath(Path path) {
|
private Optional<java.nio.file.Path> getDefaultThumbnailPath(Path path) {
|
||||||
try {
|
try {
|
||||||
return Files.list(getAbsolutePath(path).getParent().resolve(".thumbnails"))
|
return Files.list(getAbsolutePath(path).get().getParent().resolve(".thumbnails"))
|
||||||
.filter(f -> f.getFileName().toString().matches("^00(\\.[^.]+)*$"))
|
.filter(f -> f.getFileName().toString().matches("^00(\\.[^.]+)*$"))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
|
|||||||
28
src/main/java/sh/rhiobet/lalafin/core/cache/Cache.java
vendored
Normal file
28
src/main/java/sh/rhiobet/lalafin/core/cache/Cache.java
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package sh.rhiobet.lalafin.core.cache;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.Dependent;
|
||||||
|
|
||||||
|
@Dependent
|
||||||
|
public class Cache<K, V> {
|
||||||
|
private final Map<K, V> cache = new HashMap<>();
|
||||||
|
|
||||||
|
public V computeIfAbsent(K key, ThrowingFunction<K, V> loader) throws IOException {
|
||||||
|
if (!cache.containsKey(key)) {
|
||||||
|
cache.put(key, loader.apply(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public V get(K key) {
|
||||||
|
return this.cache.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidate(K key) {
|
||||||
|
cache.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/main/java/sh/rhiobet/lalafin/core/cache/ThrowingFunction.java
vendored
Normal file
8
src/main/java/sh/rhiobet/lalafin/core/cache/ThrowingFunction.java
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package sh.rhiobet.lalafin.core.cache;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ThrowingFunction<K, V> {
|
||||||
|
V apply(K key) throws IOException;
|
||||||
|
}
|
||||||
@@ -2,17 +2,18 @@ package sh.rhiobet.lalafin.core.path.model;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public abstract class PathAccessor {
|
public abstract class PathAccessor {
|
||||||
protected java.nio.file.Path getAbsolutePath(Path path) {
|
protected Optional<java.nio.file.Path> getAbsolutePath(Path path) {
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case FileSystemPath fsp:
|
case FileSystemPath fsp:
|
||||||
return fsp.absolutePath;
|
return Optional.of(fsp.absolutePath);
|
||||||
|
|
||||||
case ZipEntryPath zep:
|
case ZipEntryPath zep:
|
||||||
return zep.zipFilePath.absolutePath;
|
return Optional.of(zep.zipFilePath.absolutePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package sh.rhiobet.lalafin.core.thumbnail;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.RequestScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import sh.rhiobet.lalafin.core.cache.Cache;
|
||||||
|
|
||||||
|
@RequestScoped
|
||||||
|
public class ThumbnailCacheManager {
|
||||||
|
@Inject
|
||||||
|
private Cache<Path, Map<String, Path>> thumbnailCache;
|
||||||
|
|
||||||
|
public Cache<Path, Map<String, Path>> getCache() {
|
||||||
|
return this.thumbnailCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,40 +2,55 @@ package sh.rhiobet.lalafin.core.thumbnail;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Pattern;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import jakarta.inject.Inject;
|
||||||
import sh.rhiobet.lalafin.core.path.model.FileSystemPath;
|
import sh.rhiobet.lalafin.core.path.model.FileSystemPath;
|
||||||
import sh.rhiobet.lalafin.core.path.model.Path;
|
import sh.rhiobet.lalafin.core.path.model.Path;
|
||||||
import sh.rhiobet.lalafin.core.path.model.PathAccessor;
|
import sh.rhiobet.lalafin.core.path.model.PathAccessor;
|
||||||
import sh.rhiobet.lalafin.core.path.model.ZipEntryPath;
|
import sh.rhiobet.lalafin.core.path.model.ZipEntryPath;
|
||||||
|
|
||||||
public abstract class ThumbnailPathAccessor extends PathAccessor {
|
public abstract class ThumbnailPathAccessor extends PathAccessor {
|
||||||
|
@Inject
|
||||||
|
protected ThumbnailCacheManager thumbnailCacheManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected java.nio.file.Path getAbsolutePath(Path path) {
|
protected Optional<java.nio.file.Path> getAbsolutePath(Path path) {
|
||||||
try {
|
try {
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case FileSystemPath fsp:
|
case FileSystemPath fsp:
|
||||||
java.nio.file.Path thumbnailsFolder =
|
java.nio.file.Path thumbnailsFolder = getThumbnailRootPath(path);
|
||||||
super.getAbsolutePath(path).getParent().resolve(".thumbnails");
|
|
||||||
|
|
||||||
Optional<java.nio.file.Path> foundPath = Optional.empty();
|
Map<String, java.nio.file.Path> thumbnails =
|
||||||
|
this.thumbnailCacheManager.getCache().computeIfAbsent(thumbnailsFolder, p -> {
|
||||||
if (Files.exists(thumbnailsFolder)) {
|
if (Files.exists(thumbnailsFolder)) {
|
||||||
foundPath = Files.list(thumbnailsFolder)
|
return Files.list(thumbnailsFolder)
|
||||||
.filter(f -> f.getFileName().toString()
|
.collect(Collectors.toMap(
|
||||||
.matches("^" + Pattern.quote(path.getFilename()) + "(\\.[^.]+)*$"))
|
f -> f.getFileName().toString().replaceAll("\\.[^.]+$", ""),
|
||||||
.findFirst();
|
f -> f,
|
||||||
|
(a, b) -> a,
|
||||||
|
HashMap::new
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return foundPath.isPresent() ?
|
return Optional.of(thumbnails.getOrDefault(path.getFilename(),
|
||||||
foundPath.get() :
|
thumbnailsFolder.resolve(path.getFilename() + ".png")));
|
||||||
thumbnailsFolder.resolve(path.getFilename() + ".png");
|
|
||||||
|
|
||||||
case ZipEntryPath zep:
|
case ZipEntryPath zep:
|
||||||
return null;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
return null;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected java.nio.file.Path getThumbnailRootPath(Path path) {
|
||||||
|
return super.getAbsolutePath(path).get().getParent().resolve(".thumbnails");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,17 +26,14 @@ public class FileRoleAccessService implements AccessService {
|
|||||||
PathURIResolver fileURIResolver;
|
PathURIResolver fileURIResolver;
|
||||||
|
|
||||||
public boolean checkAccess(Path path) {
|
public boolean checkAccess(Path path) {
|
||||||
Optional<String> pathUriOptional = this.fileURIResolver.resolve(path);
|
Optional<String> pathUri = this.fileURIResolver.resolve(path);
|
||||||
|
|
||||||
String pathUri;
|
if (pathUri.isEmpty()) {
|
||||||
if (pathUriOptional.isEmpty()) {
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
pathUri = pathUriOptional.get().replaceAll("^.file", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<FileConfiguration.Route> matchingRoutes = fileConfiguration.routes().stream()
|
List<FileConfiguration.Route> matchingRoutes = fileConfiguration.routes().stream()
|
||||||
.filter(r -> pathUri.startsWith(r.path()))
|
.filter(r -> pathUri.get().startsWith(r.path()))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (matchingRoutes.isEmpty()) {
|
if (matchingRoutes.isEmpty()) {
|
||||||
|
|||||||
20
src/main/java/sh/rhiobet/lalafin/file/access/FileToken.java
Normal file
20
src/main/java/sh/rhiobet/lalafin/file/access/FileToken.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package sh.rhiobet.lalafin.file.access;
|
||||||
|
|
||||||
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
|
|
||||||
|
@RegisterForReflection
|
||||||
|
public class FileToken {
|
||||||
|
public String user;
|
||||||
|
public long timestamp;
|
||||||
|
public String ip;
|
||||||
|
public String file;
|
||||||
|
|
||||||
|
public FileToken() {}
|
||||||
|
|
||||||
|
public FileToken(String user, long timestamp, String ip, String file) {
|
||||||
|
this.user = user;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.ip = ip;
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package sh.rhiobet.lalafin.file.access;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import io.quarkus.redis.datasource.RedisDataSource;
|
||||||
|
import io.quarkus.redis.datasource.value.SetArgs;
|
||||||
|
import io.quarkus.security.identity.SecurityIdentity;
|
||||||
|
import io.vertx.core.http.HttpServerRequest;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class FileTokenProvider {
|
||||||
|
@Inject
|
||||||
|
RedisDataSource redisDataSource;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SecurityIdentity securityIdentity;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
HttpServerRequest request;
|
||||||
|
|
||||||
|
public String getFileToken(String fileUri) {
|
||||||
|
FileToken token = new FileToken(this.securityIdentity.getPrincipal().getName(),
|
||||||
|
System.currentTimeMillis(), this.request.remoteAddress().host(), fileUri);
|
||||||
|
|
||||||
|
String uniqueID = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
this.redisDataSource.value(FileToken.class).set(
|
||||||
|
"fileToken-" + uniqueID, token, new SetArgs().pxAt(System.currentTimeMillis() + 86400000));
|
||||||
|
|
||||||
|
return uniqueID;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ public class FileInfo extends FileInfoBase {
|
|||||||
this.publicApiUrl = publicApiUrl;
|
this.publicApiUrl = publicApiUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileInfo(String filename, String directUrl) {
|
public FileInfo(String filename, String directUrl, String publicApiUrl) {
|
||||||
this(filename, "", directUrl, "");
|
this(filename, "", directUrl, publicApiUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package sh.rhiobet.lalafin.file.model;
|
package sh.rhiobet.lalafin.file.model;
|
||||||
|
|
||||||
|
import io.quarkus.logging.Log;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Named;
|
import jakarta.inject.Named;
|
||||||
import sh.rhiobet.lalafin.LalafinConfiguration;
|
import sh.rhiobet.lalafin.LalafinConfiguration;
|
||||||
import sh.rhiobet.lalafin.api.internal.redis.FileTokenProvider;
|
|
||||||
import sh.rhiobet.lalafin.core.path.model.Path;
|
import sh.rhiobet.lalafin.core.path.model.Path;
|
||||||
import sh.rhiobet.lalafin.core.path.resolver.PathURIResolver;
|
import sh.rhiobet.lalafin.core.path.resolver.PathURIResolver;
|
||||||
import sh.rhiobet.lalafin.core.thumbnail.ThumbnailGenerator;
|
import sh.rhiobet.lalafin.core.thumbnail.ThumbnailGenerator;
|
||||||
@@ -28,11 +28,15 @@ public class FileMetadataService {
|
|||||||
@Named("file/resolver/thumbnail")
|
@Named("file/resolver/thumbnail")
|
||||||
PathURIResolver fileThumbnailURIResolver;
|
PathURIResolver fileThumbnailURIResolver;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Named("file/resolver/token")
|
||||||
|
PathURIResolver fileTokenURIResolver;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Named("file/thumbnail")
|
@Named("file/thumbnail")
|
||||||
ThumbnailGenerator fileThumbnailGenerator;
|
ThumbnailGenerator fileThumbnailGenerator;
|
||||||
|
|
||||||
public FileInfoBase getInfo(Path filePath, FileTokenProvider fileTokenProvider) {
|
public FileInfoBase getInfo(Path filePath) {
|
||||||
if (filePath.exists()) {
|
if (filePath.exists()) {
|
||||||
Optional<String> fileUrl = this.fileURIResolver.resolve(filePath);
|
Optional<String> fileUrl = this.fileURIResolver.resolve(filePath);
|
||||||
Optional<String> thumbUrl = this.fileThumbnailURIResolver.resolve(filePath);
|
Optional<String> thumbUrl = this.fileThumbnailURIResolver.resolve(filePath);
|
||||||
@@ -42,7 +46,7 @@ public class FileMetadataService {
|
|||||||
this.fileThumbnailGenerator.generate(filePath);
|
this.fileThumbnailGenerator.generate(filePath);
|
||||||
thumbUrl = this.fileThumbnailURIResolver.resolve(filePath);
|
thumbUrl = this.fileThumbnailURIResolver.resolve(filePath);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.warn("Failed to generate thumbnail for " + filePath + ".", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,16 +60,13 @@ public class FileMetadataService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
for (Path child : filePath.getChildren()) {
|
for (Path child : filePath.getChildren()) {
|
||||||
if (child.getFilename().startsWith(".")) {
|
if (child.getFilename().startsWith(".") ||
|
||||||
|
fileConfiguration.ignored().isPresent() &&
|
||||||
|
fileConfiguration.ignored().get().stream()
|
||||||
|
.anyMatch(i -> child.getFilename().endsWith(i)))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fileConfiguration.ignored().isPresent()) {
|
|
||||||
for (String ignoreString : fileConfiguration.ignored().get()) {
|
|
||||||
if (child.getFilename().endsWith(ignoreString)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<String> childFileUrl = this.fileURIResolver.resolve(child);
|
Optional<String> childFileUrl = this.fileURIResolver.resolve(child);
|
||||||
Optional<String> childThumbUrl = this.fileThumbnailURIResolver.resolve(child);
|
Optional<String> childThumbUrl = this.fileThumbnailURIResolver.resolve(child);
|
||||||
@@ -75,7 +76,7 @@ public class FileMetadataService {
|
|||||||
this.fileThumbnailGenerator.generate(child);
|
this.fileThumbnailGenerator.generate(child);
|
||||||
childThumbUrl = this.fileThumbnailURIResolver.resolve(child);
|
childThumbUrl = this.fileThumbnailURIResolver.resolve(child);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.warn("Failed to generate thumbnail for " + child + ".", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +85,12 @@ public class FileMetadataService {
|
|||||||
contentInfo = new FolderInfo(child.getFilename(),
|
contentInfo = new FolderInfo(child.getFilename(),
|
||||||
childFileUrl.isPresent() ? childFileUrl.get() : "");
|
childFileUrl.isPresent() ? childFileUrl.get() : "");
|
||||||
} else {
|
} else {
|
||||||
contentInfo = new FileInfo(child.getFilename(),
|
Optional<String> childTokenUrl = this.fileTokenURIResolver.resolve(child);
|
||||||
childFileUrl.isPresent() ? childFileUrl.get() : "");
|
contentInfo = new FileInfo(
|
||||||
|
child.getFilename(),
|
||||||
|
childFileUrl.isPresent() ? childFileUrl.get() : "",
|
||||||
|
childTokenUrl.isPresent() ? childTokenUrl.get() : ""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (childThumbUrl.isPresent()) {
|
if (childThumbUrl.isPresent()) {
|
||||||
@@ -95,16 +100,17 @@ public class FileMetadataService {
|
|||||||
folderInfo.content.add(contentInfo);
|
folderInfo.content.add(contentInfo);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.warn("Failed to walk through children of " + filePath + ".", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return folderInfo;
|
return folderInfo;
|
||||||
} else {
|
} else {
|
||||||
|
Optional<String> tokenUrl = this.fileTokenURIResolver.resolve(filePath);
|
||||||
FileInfo fileInfo = new FileInfo(
|
FileInfo fileInfo = new FileInfo(
|
||||||
filePath.getFilename(),
|
filePath.getFilename(),
|
||||||
thumbUrl.isPresent() ? thumbUrl.get() : "",
|
thumbUrl.isPresent() ? thumbUrl.get() : "",
|
||||||
fileUrl.isPresent() ? fileUrl.get() : "",
|
fileUrl.isPresent() ? fileUrl.get() : "",
|
||||||
""
|
tokenUrl.isPresent() ? tokenUrl.get() : ""
|
||||||
);
|
);
|
||||||
|
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
|
|||||||
@@ -23,10 +23,6 @@ public class FilePathURIResolver extends PathAccessor implements PathURIResolver
|
|||||||
public Optional<String> resolve(Path path) {
|
public Optional<String> resolve(Path path) {
|
||||||
List<String> segments = getSegments(path);
|
List<String> segments = getSegments(path);
|
||||||
|
|
||||||
if (segments.isEmpty()) {
|
|
||||||
return Optional.of("/file/");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Optional.of(segments.stream()
|
return Optional.of(segments.stream()
|
||||||
.map(s -> "/" + Encode.encodePathSegment(s))
|
.map(s -> "/" + Encode.encodePathSegment(s))
|
||||||
.reduce("/file", String::concat));
|
.reduce("/file", String::concat));
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import org.jboss.resteasy.reactive.common.util.Encode;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.RequestScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Named;
|
import jakarta.inject.Named;
|
||||||
import sh.rhiobet.lalafin.file.configuration.FileConfiguration;
|
import sh.rhiobet.lalafin.file.configuration.FileConfiguration;
|
||||||
@@ -14,7 +16,7 @@ import sh.rhiobet.lalafin.core.path.model.ZipEntryPath;
|
|||||||
import sh.rhiobet.lalafin.core.path.resolver.PathURIResolver;
|
import sh.rhiobet.lalafin.core.path.resolver.PathURIResolver;
|
||||||
import sh.rhiobet.lalafin.core.thumbnail.ThumbnailPathAccessor;
|
import sh.rhiobet.lalafin.core.thumbnail.ThumbnailPathAccessor;
|
||||||
|
|
||||||
@ApplicationScoped
|
@RequestScoped
|
||||||
@Named("file/resolver/thumbnail")
|
@Named("file/resolver/thumbnail")
|
||||||
public class FileThumbnailPathURIResolver extends ThumbnailPathAccessor implements PathURIResolver {
|
public class FileThumbnailPathURIResolver extends ThumbnailPathAccessor implements PathURIResolver {
|
||||||
@Inject
|
@Inject
|
||||||
@@ -24,13 +26,12 @@ public class FileThumbnailPathURIResolver extends ThumbnailPathAccessor implemen
|
|||||||
public Optional<String> resolve(Path path) {
|
public Optional<String> resolve(Path path) {
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case FileSystemPath fsp:
|
case FileSystemPath fsp:
|
||||||
java.nio.file.Path thumbnailAbsolutePath = getAbsolutePath(path);
|
Optional<java.nio.file.Path> thumbnailAbsolutePath = getAbsolutePath(path);
|
||||||
|
|
||||||
if (thumbnailAbsolutePath != null && Files.exists(thumbnailAbsolutePath)) {
|
if (thumbnailAbsolutePath.isPresent() && Files.exists(thumbnailAbsolutePath.get())) {
|
||||||
java.nio.file.Path rootFolderPath = Paths.get(this.fileConfiguration.directory());
|
java.nio.file.Path rootFolderPath = Paths.get(this.fileConfiguration.directory());
|
||||||
return Optional.of(
|
return Optional.of("/file/" + Encode.encodePath(
|
||||||
"/file/" + rootFolderPath.resolve("file").relativize(thumbnailAbsolutePath)
|
rootFolderPath.resolve("file").relativize(thumbnailAbsolutePath.get()).toString()));
|
||||||
.toString());
|
|
||||||
} else {
|
} else {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package sh.rhiobet.lalafin.file.resolver;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.reactive.common.util.Encode;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.inject.Named;
|
||||||
|
import sh.rhiobet.lalafin.core.path.model.Path;
|
||||||
|
import sh.rhiobet.lalafin.core.path.resolver.PathURIResolver;
|
||||||
|
import sh.rhiobet.lalafin.file.access.FileTokenProvider;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
@Named("file/resolver/token")
|
||||||
|
public class FileTokenURIResolver implements PathURIResolver {
|
||||||
|
@Inject
|
||||||
|
@Named("file/resolver")
|
||||||
|
PathURIResolver fileURIResolver;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
FileTokenProvider fileTokenProvider;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> resolve(Path path) {
|
||||||
|
Optional<String> fileURI = this.fileURIResolver.resolve(path);
|
||||||
|
|
||||||
|
if (fileURI.isPresent()) {
|
||||||
|
return Optional.of(
|
||||||
|
"/v1/api/public/file/token/" + this.fileTokenProvider.getFileToken(fileURI.get()) + "/"
|
||||||
|
+ Encode.encodePathSegment(path.getFilename()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,7 +59,7 @@ public class FilePrivateAPI {
|
|||||||
return Response.status(Response.Status.FORBIDDEN).build();
|
return Response.status(Response.Status.FORBIDDEN).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfoBase fileInfo = this.fileMetadataService.getInfo(path, null);
|
FileInfoBase fileInfo = this.fileMetadataService.getInfo(path);
|
||||||
|
|
||||||
if (fileInfo == null) {
|
if (fileInfo == null) {
|
||||||
return Response.status(Response.Status.NOT_FOUND).build();
|
return Response.status(Response.Status.NOT_FOUND).build();
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package sh.rhiobet.lalafin.file.thumbnail;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.im4java.core.ConvertCmd;
|
import org.im4java.core.ConvertCmd;
|
||||||
import org.im4java.core.IM4JavaException;
|
import org.im4java.core.IM4JavaException;
|
||||||
@@ -26,17 +28,17 @@ public class FileThumbnailGenerator extends ThumbnailPathAccessor implements Thu
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(Path path) throws IOException {
|
public void generate(Path path) throws IOException {
|
||||||
java.nio.file.Path thumbnailAbsolutePath = getAbsolutePath(path);
|
Optional<java.nio.file.Path> thumbnailAbsolutePath = getAbsolutePath(path);
|
||||||
|
|
||||||
if (!path.canHaveChildren() || thumbnailAbsolutePath == null) {
|
if (!path.canHaveChildren() || thumbnailAbsolutePath.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Files.exists(thumbnailAbsolutePath)) {
|
if (Files.exists(thumbnailAbsolutePath.get())) {
|
||||||
Files.delete(thumbnailAbsolutePath);
|
Files.delete(thumbnailAbsolutePath.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
Files.createDirectories(thumbnailAbsolutePath.getParent());
|
Files.createDirectories(thumbnailAbsolutePath.get().getParent());
|
||||||
|
|
||||||
for (Path childPath : path.getChildren()) {
|
for (Path childPath : path.getChildren()) {
|
||||||
String mimetype = MimeType.getMimeType(childPath.getFilename());
|
String mimetype = MimeType.getMimeType(childPath.getFilename());
|
||||||
@@ -54,10 +56,14 @@ public class FileThumbnailGenerator extends ThumbnailPathAccessor implements Thu
|
|||||||
Pipe inputPipe = new Pipe(pathInputStream, null);
|
Pipe inputPipe = new Pipe(pathInputStream, null);
|
||||||
op.addImage(extension + ":-");
|
op.addImage(extension + ":-");
|
||||||
op.resize(200, null);
|
op.resize(200, null);
|
||||||
op.addImage(thumbnailAbsolutePath.toString());
|
op.addImage(thumbnailAbsolutePath.get().toString());
|
||||||
convert.setInputProvider(inputPipe);
|
convert.setInputProvider(inputPipe);
|
||||||
convert.run(op);
|
convert.run(op);
|
||||||
|
|
||||||
|
Map<String, java.nio.file.Path> thumbnailCache =
|
||||||
|
this.thumbnailCacheManager.getCache().get(getThumbnailRootPath(path));
|
||||||
|
thumbnailCache.put(path.getFilename(), thumbnailAbsolutePath.get());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} catch (InterruptedException | IM4JavaException e) {
|
} catch (InterruptedException | IM4JavaException e) {
|
||||||
throw new IOException("Error when generating thumbnail with IM4J.", e);
|
throw new IOException("Error when generating thumbnail with IM4J.", e);
|
||||||
|
|||||||
Reference in New Issue
Block a user