Merge remote-tracking branch 'origin/V2' into mainToV2

This commit is contained in:
Anthony Stirling
2025-11-03 23:01:41 +00:00
833 changed files with 28948 additions and 4804 deletions

View File

@@ -74,8 +74,7 @@ public class AppConfig {
@Bean(name = "appName")
public String appName() {
String homeTitle = applicationProperties.getUi().getAppName();
return (homeTitle != null) ? homeTitle : "Stirling PDF";
return "Stirling PDF";
}
@Bean(name = "appVersion")
@@ -93,9 +92,7 @@ public class AppConfig {
@Bean(name = "homeText")
public String homeText() {
return (applicationProperties.getUi().getHomeDescription() != null)
? applicationProperties.getUi().getHomeDescription()
: "null";
return "null";
}
@Bean(name = "languages")
@@ -110,11 +107,8 @@ public class AppConfig {
@Bean(name = "navBarText")
public String navBarText() {
String defaultNavBar =
applicationProperties.getUi().getAppNameNavbar() != null
? applicationProperties.getUi().getAppNameNavbar()
: applicationProperties.getUi().getAppName();
return (defaultNavBar != null) ? defaultNavBar : "Stirling PDF";
String navBar = applicationProperties.getUi().getAppNameNavbar();
return (navBar != null) ? navBar : "Stirling PDF";
}
@Bean(name = "enableAlphaFunctionality")

View File

@@ -121,6 +121,7 @@ public class ApplicationProperties {
private String loginMethod = "all";
private String customGlobalAPIKey;
private Jwt jwt = new Jwt();
private Validation validation = new Validation();
public Boolean isAltLogin() {
return saml2.getEnabled() || oauth2.getEnabled();
@@ -307,7 +308,41 @@ public class ApplicationProperties {
private boolean enableKeyRotation = false;
private boolean enableKeyCleanup = true;
private int keyRetentionDays = 7;
private boolean secureCookie;
}
@Data
public static class Validation {
private Trust trust = new Trust();
private boolean allowAIA = false;
private Aatl aatl = new Aatl();
private Eutl eutl = new Eutl();
private Revocation revocation = new Revocation();
@Data
public static class Trust {
private boolean serverAsAnchor = true;
private boolean useSystemTrust = false;
private boolean useMozillaBundle = false;
private boolean useAATL = false;
private boolean useEUTL = false;
}
@Data
public static class Aatl {
private String url = "https://trustlist.adobe.com/tl.pdf";
}
@Data
public static class Eutl {
private String lotlUrl = "https://ec.europa.eu/tools/lotl/eu-lotl.xml";
private boolean acceptTransitional = false;
}
@Data
public static class Revocation {
private String mode = "none";
private boolean hardFail = false;
}
}
}
@@ -321,6 +356,8 @@ public class ApplicationProperties {
private String tessdataDir;
private Boolean enableAlphaFunctionality;
private Boolean enableAnalytics;
private Boolean enablePosthog;
private Boolean enableScarf;
private Datasource datasource;
private Boolean disableSanitize;
private int maxDPI;
@@ -330,10 +367,23 @@ public class ApplicationProperties {
private String fileUploadLimit;
private TempFileManagement tempFileManagement = new TempFileManagement();
private DatabaseBackup databaseBackup = new DatabaseBackup();
private List<String> corsAllowedOrigins = new ArrayList<>();
public boolean isAnalyticsEnabled() {
return this.getEnableAnalytics() != null && this.getEnableAnalytics();
}
public boolean isPosthogEnabled() {
// Treat null as enabled when analytics is enabled
return this.isAnalyticsEnabled()
&& (this.getEnablePosthog() == null || this.getEnablePosthog());
}
public boolean isScarfEnabled() {
// Treat null as enabled when analytics is enabled
return this.isAnalyticsEnabled()
&& (this.getEnableScarf() == null || this.getEnableScarf());
}
}
@Data
@@ -449,21 +499,9 @@ public class ApplicationProperties {
@Data
public static class Ui {
private String appName;
private String homeDescription;
private String appNameNavbar;
private List<String> languages;
public String getAppName() {
return appName != null && !appName.trim().isEmpty() ? appName : null;
}
public String getHomeDescription() {
return homeDescription != null && !homeDescription.trim().isEmpty()
? homeDescription
: null;
}
public String getAppNameNavbar() {
return appNameNavbar != null && !appNameNavbar.trim().isEmpty() ? appNameNavbar : null;
}
@@ -517,6 +555,7 @@ public class ApplicationProperties {
@Data
public static class Mail {
private boolean enabled;
private boolean enableInvites = false;
private String host;
private int port;
private String username;

View File

@@ -56,7 +56,7 @@ public class PostHogService {
}
private void captureSystemInfo() {
if (!applicationProperties.getSystem().isAnalyticsEnabled()) {
if (!applicationProperties.getSystem().isPosthogEnabled()) {
return;
}
try {
@@ -67,7 +67,7 @@ public class PostHogService {
}
public void captureEvent(String eventName, Map<String, Object> properties) {
if (!applicationProperties.getSystem().isAnalyticsEnabled()) {
if (!applicationProperties.getSystem().isPosthogEnabled()) {
return;
}
@@ -325,13 +325,16 @@ public class PostHogService {
properties,
"system_enableAnalytics",
applicationProperties.getSystem().isAnalyticsEnabled());
// Capture UI properties
addIfNotEmpty(properties, "ui_appName", applicationProperties.getUi().getAppName());
addIfNotEmpty(
properties,
"ui_homeDescription",
applicationProperties.getUi().getHomeDescription());
"system_enablePosthog",
applicationProperties.getSystem().isPosthogEnabled());
addIfNotEmpty(
properties,
"system_enableScarf",
applicationProperties.getSystem().isScarfEnabled());
// Capture UI properties
addIfNotEmpty(
properties, "ui_appNameNavbar", applicationProperties.getUi().getAppNameNavbar());

View File

@@ -6,4 +6,6 @@ public interface UserServiceInterface {
String getCurrentUsername();
long getTotalUsersCount();
boolean isCurrentUserAdmin();
}

View File

@@ -0,0 +1,29 @@
package stirling.software.common.util;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
/**
* Captures application command-line arguments at startup so they can be reused for restart
* operations. This allows the application to restart with the same configuration.
*/
@Slf4j
@Component
public class AppArgsCapture implements ApplicationRunner {
public static final AtomicReference<List<String>> APP_ARGS = new AtomicReference<>(List.of());
@Override
public void run(ApplicationArguments args) {
APP_ARGS.set(List.of(args.getSourceArgs()));
log.debug(
"Captured {} application arguments for restart capability",
args.getSourceArgs().length);
}
}

View File

@@ -0,0 +1,84 @@
package stirling.software.common.util;
import java.io.File;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import lombok.extern.slf4j.Slf4j;
/** Utility class to locate JAR files at runtime for restart operations */
@Slf4j
public class JarPathUtil {
/**
* Gets the path to the currently running JAR file
*
* @return Path to the current JAR, or null if not running from a JAR
*/
public static Path currentJar() {
try {
Path jar =
Paths.get(
JarPathUtil.class
.getProtectionDomain()
.getCodeSource()
.getLocation()
.toURI())
.toAbsolutePath();
// Check if we're actually running from a JAR (not from IDE/classes directory)
if (jar.toString().endsWith(".jar")) {
log.debug("Current JAR located at: {}", jar);
return jar;
} else {
log.warn("Not running from JAR, current location: {}", jar);
return null;
}
} catch (URISyntaxException e) {
log.error("Failed to determine current JAR location", e);
return null;
}
}
/**
* Gets the path to the restart-helper.jar file Expected to be in the same directory as the main
* JAR
*
* @return Path to restart-helper.jar, or null if not found
*/
public static Path restartHelperJar() {
Path appJar = currentJar();
if (appJar == null) {
return null;
}
Path helperJar = appJar.getParent().resolve("restart-helper.jar");
if (Files.isRegularFile(helperJar)) {
log.debug("Restart helper JAR located at: {}", helperJar);
return helperJar;
} else {
log.warn("Restart helper JAR not found at: {}", helperJar);
return null;
}
}
/**
* Gets the java binary path for the current JVM
*
* @return Path to java executable
*/
public static String javaExecutable() {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
// On Windows, add .exe extension
if (System.getProperty("os.name").toLowerCase().contains("win")) {
javaBin += ".exe";
}
return javaBin;
}
}