Additional configuration from environment

This commit is contained in:
2025-12-15 13:53:03 +01:00
parent 05c315a56f
commit 9932a350cc
8 changed files with 117 additions and 63 deletions

View File

@@ -28,6 +28,18 @@ public class SystemEnvironmentValidator {
private String previewsPath;
@Value("${IMGFLOAT_DB_PATH}")
private String dbPath;
@Value("${IMGFLOAT_MAX_SPEED}")
private double maxSpeed;
@Value("${IMGFLOAT_MIN_AUDIO_SPEED}")
private double minAudioSpeed;
@Value("${IMGFLOAT_MAX_AUDIO_SPEED}")
private double maxAudioSpeed;
@Value("${IMGFLOAT_MIN_AUDIO_PITCH}")
private double minAudioPitch;
@Value("${IMGFLOAT_MAX_AUDIO_PITCH}")
private double maxAudioPitch;
@Value("${IMGFLOAT_MAX_AUDIO_VOLUME}")
private double maxAudioVolume;
private long maxUploadBytes;
private long maxRequestBytes;
@@ -38,8 +50,14 @@ public class SystemEnvironmentValidator {
maxUploadBytes = DataSize.parse(springMaxFileSize).toBytes();
maxRequestBytes = DataSize.parse(springMaxRequestSize).toBytes();
checkLong(maxUploadBytes, "SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE", missing);
checkLong(maxRequestBytes, "SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE", missing);
checkUnsignedNumeric(maxUploadBytes, "SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE", missing);
checkUnsignedNumeric(maxRequestBytes, "SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE", missing);
checkUnsignedNumeric(maxSpeed, "IMGFLOAT_MAX_SPEED", missing);;
checkUnsignedNumeric(minAudioSpeed, "IMGFLOAT_MIN_AUDIO_SPEED", missing);;
checkUnsignedNumeric(maxAudioSpeed, "IMGFLOAT_MAX_AUDIO_SPEED", missing);;
checkUnsignedNumeric(minAudioPitch, "IMGFLOAT_MIN_AUDIO_PITCH", missing);;
checkUnsignedNumeric(maxAudioPitch, "IMGFLOAT_MAX_AUDIO_PITCH", missing);;
checkUnsignedNumeric(maxAudioVolume, "IMGFLOAT_MAX_AUDIO_VOLUME", missing);;
checkString(twitchClientId, "TWITCH_CLIENT_ID", missing);
checkString(dbPath, "IMGFLOAT_DB_PATH", missing);
checkString(twitchClientSecret, "TWITCH_CLIENT_SECRET", missing);
@@ -57,15 +75,18 @@ public class SystemEnvironmentValidator {
log.info(" - TWITCH_CLIENT_ID: {}", redact(twitchClientId));
log.info(" - TWITCH_CLIENT_SECRET: {}", redact(twitchClientSecret));
log.info(" - SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE: {} ({} bytes)",
springMaxFileSize,
maxUploadBytes
);
springMaxFileSize, maxUploadBytes);
log.info(" - SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE: {} ({} bytes)",
springMaxRequestSize,
maxRequestBytes
);
springMaxRequestSize, maxRequestBytes);
log.info(" - IMGFLOAT_ASSETS_PATH: {}", assetsPath);
log.info(" - IMGFLOAT_PREVIEWS_PATH: {}", previewsPath);
log.info(" - IMGFLOAT_DB_PATH: {}", dbPath);
log.info(" - IMGFLOAT_MAX_SPEED: {}", maxSpeed);
log.info(" - IMGFLOAT_MIN_AUDIO_SPEED: {}", minAudioSpeed);
log.info(" - IMGFLOAT_MAX_AUDIO_SPEED: {}", maxAudioSpeed);
log.info(" - IMGFLOAT_MIN_AUDIO_PITCH: {}", minAudioPitch);
log.info(" - IMGFLOAT_MAX_AUDIO_PITCH: {}", maxAudioPitch);
log.info(" - IMGFLOAT_MAX_AUDIO_VOLUME: {}", maxAudioVolume);
}
private void checkString(String value, String name, StringBuilder missing) {
@@ -74,44 +95,15 @@ public class SystemEnvironmentValidator {
}
}
private void checkLong(Long value, String name, StringBuilder missing) {
if (value == null || value <= 0) {
missing.append(" - ").append(name).append("\n");
private <T extends Number> void checkUnsignedNumeric(T value, String name, StringBuilder missing) {
if (value == null || value.doubleValue() <= 0) {
missing.append(" - ").append(name).append('\n');
}
}
private String formatBytes(long bytes) {
if (bytes < 1024) return bytes + " B";
double kb = bytes / 1024.0;
if (kb < 1024) return String.format("%.2f KB", kb);
double mb = kb / 1024.0;
if (mb < 1024) return String.format("%.2f MB", mb);
double gb = mb / 1024.0;
return String.format("%.2f GB", gb);
}
private String redact(String value) {
if (!StringUtils.hasText(value)) return "(missing)";
if (value.length() <= 6) return "******";
return value.substring(0, 2) + "****" + value.substring(value.length() - 2);
}
private long parseSizeToBytes(String value) {
if (value == null) return -1;
String v = value.trim().toUpperCase(Locale.ROOT);
try {
if (v.endsWith("GB")) return Long.parseLong(v.replace("GB", "")) * 1024 * 1024 * 1024;
if (v.endsWith("MB")) return Long.parseLong(v.replace("MB", "")) * 1024 * 1024;
if (v.endsWith("KB")) return Long.parseLong(v.replace("KB", "")) * 1024;
if (v.endsWith("B")) return Long.parseLong(v.replace("B", ""));
return Long.parseLong(v);
} catch (NumberFormatException e) {
return -1;
}
}
}

View File

@@ -5,6 +5,7 @@ import dev.kruhlmann.imgfloat.service.VersionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@@ -22,9 +23,31 @@ public class ViewController {
@Autowired
private long uploadLimitBytes;
public ViewController(ChannelDirectoryService channelDirectoryService, VersionService versionService) {
private double maxSpeed;
private double minAudioSpeed;
private double maxAudioSpeed;
private double minAudioPitch;
private double maxAudioPitch;
private double maxAudioVolume;
public ViewController(
ChannelDirectoryService channelDirectoryService,
VersionService versionService,
@Value("${IMGFLOAT_MAX_SPEED}") double maxSpeed,
@Value("${IMGFLOAT_MIN_AUDIO_SPEED}") double minAudioSpeed,
@Value("${IMGFLOAT_MAX_AUDIO_SPEED}") double maxAudioSpeed,
@Value("${IMGFLOAT_MIN_AUDIO_PITCH}") double minAudioPitch,
@Value("${IMGFLOAT_MAX_AUDIO_PITCH}") double maxAudioPitch,
@Value("${IMGFLOAT_MAX_AUDIO_VOLUME}") double maxAudioVolume
) {
this.channelDirectoryService = channelDirectoryService;
this.versionService = versionService;
this.maxSpeed = maxSpeed;
this.minAudioSpeed = minAudioSpeed;
this.maxAudioSpeed = maxAudioSpeed;
this.minAudioPitch = minAudioPitch;
this.maxAudioPitch = maxAudioPitch;
this.maxAudioVolume = maxAudioVolume;
}
@org.springframework.web.bind.annotation.GetMapping("/")
@@ -62,6 +85,13 @@ public class ViewController {
model.addAttribute("username", login);
model.addAttribute("uploadLimitBytes", uploadLimitBytes);
model.addAttribute("maxSpeed", maxSpeed);
model.addAttribute("minAudioSpeed", minAudioSpeed);
model.addAttribute("maxAudioSpeed", maxAudioSpeed);
model.addAttribute("minAudioPitch", minAudioPitch);
model.addAttribute("maxAudioPitch", maxAudioPitch);
model.addAttribute("maxAudioVolume", maxAudioVolume);
return "admin";
}

View File

@@ -35,12 +35,6 @@ import static org.springframework.http.HttpStatus.PAYLOAD_TOO_LARGE;
@Service
public class ChannelDirectoryService {
private static final Logger logger = LoggerFactory.getLogger(ChannelDirectoryService.class);
private static final double MAX_SPEED = 4.0;
private static final double MIN_AUDIO_SPEED = 0.1;
private static final double MAX_AUDIO_SPEED = 4.0;
private static final double MIN_AUDIO_PITCH = 0.5;
private static final double MAX_AUDIO_PITCH = 2.0;
private static final double MAX_AUDIO_VOLUME = 1.0;
private static final Pattern SAFE_FILENAME = Pattern.compile("[^a-zA-Z0-9._ -]");
private final ChannelRepository channelRepository;
@@ -53,13 +47,26 @@ public class ChannelDirectoryService {
@Autowired
private long uploadLimitBytes;
private double maxSpeed;
private double minAudioSpeed;
private double maxAudioSpeed;
private double minAudioPitch;
private double maxAudioPitch;
private double maxAudioVolume;
public ChannelDirectoryService(
ChannelRepository channelRepository,
AssetRepository assetRepository,
SimpMessagingTemplate messagingTemplate,
AssetStorageService assetStorageService,
MediaDetectionService mediaDetectionService,
MediaOptimizationService mediaOptimizationService
MediaOptimizationService mediaOptimizationService,
@Value("${IMGFLOAT_MAX_SPEED}") double maxSpeed,
@Value("${IMGFLOAT_MIN_AUDIO_SPEED}") double minAudioSpeed,
@Value("${IMGFLOAT_MAX_AUDIO_SPEED}") double maxAudioSpeed,
@Value("${IMGFLOAT_MIN_AUDIO_PITCH}") double minAudioPitch,
@Value("${IMGFLOAT_MAX_AUDIO_PITCH}") double maxAudioPitch,
@Value("${IMGFLOAT_MAX_AUDIO_VOLUME}") double maxAudioVolume
) {
this.channelRepository = channelRepository;
this.assetRepository = assetRepository;
@@ -67,6 +74,12 @@ public class ChannelDirectoryService {
this.assetStorageService = assetStorageService;
this.mediaDetectionService = mediaDetectionService;
this.mediaOptimizationService = mediaOptimizationService;
this.maxSpeed = maxSpeed;
this.minAudioSpeed = minAudioSpeed;
this.maxAudioSpeed = maxAudioSpeed;
this.minAudioPitch = minAudioPitch;
this.maxAudioPitch = maxAudioPitch;
this.maxAudioVolume = maxAudioVolume;
}
@@ -244,17 +257,17 @@ public class ChannelDirectoryService {
private void validateTransform(TransformRequest req) {
if (req.getWidth() <= 0) throw new ResponseStatusException(BAD_REQUEST, "Width must be > 0");
if (req.getHeight() <= 0) throw new ResponseStatusException(BAD_REQUEST, "Height must be > 0");
if (req.getSpeed() != null && (req.getSpeed() < 0 || req.getSpeed() > MAX_SPEED))
throw new ResponseStatusException(BAD_REQUEST, "Speed must be between 0 and " + MAX_SPEED);
if (req.getSpeed() != null && (req.getSpeed() < 0 || req.getSpeed() > maxSpeed))
throw new ResponseStatusException(BAD_REQUEST, "Speed must be between 0 and " + maxSpeed);
if (req.getZIndex() != null && req.getZIndex() < 1)
throw new ResponseStatusException(BAD_REQUEST, "zIndex must be >= 1");
if (req.getAudioDelayMillis() != null && req.getAudioDelayMillis() < 0)
throw new ResponseStatusException(BAD_REQUEST, "Audio delay >= 0");
if (req.getAudioSpeed() != null && (req.getAudioSpeed() < MIN_AUDIO_SPEED || req.getAudioSpeed() > MAX_AUDIO_SPEED))
if (req.getAudioSpeed() != null && (req.getAudioSpeed() < minAudioSpeed || req.getAudioSpeed() > maxAudioSpeed))
throw new ResponseStatusException(BAD_REQUEST, "Audio speed out of range");
if (req.getAudioPitch() != null && (req.getAudioPitch() < MIN_AUDIO_PITCH || req.getAudioPitch() > MAX_AUDIO_PITCH))
if (req.getAudioPitch() != null && (req.getAudioPitch() < minAudioPitch || req.getAudioPitch() > maxAudioPitch))
throw new ResponseStatusException(BAD_REQUEST, "Audio pitch out of range");
if (req.getAudioVolume() != null && (req.getAudioVolume() < 0 || req.getAudioVolume() > MAX_AUDIO_VOLUME))
if (req.getAudioVolume() != null && (req.getAudioVolume() < 0 || req.getAudioVolume() > maxAudioVolume))
throw new ResponseStatusException(BAD_REQUEST, "Audio volume out of range");
}