mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-25 13:49:23 +00:00
feat(database,Jwt): relocate backups and Jwt-keys to config/backup
and add Enterprise cleanup endpoints (#4225)
# Description of Changes - **What was changed** - Centralized installation paths: - Introduced `BACKUP_PATH`, `BACKUP_DB_PATH`, and `BACKUP_PRIVATE_KEY_PATH` in `InstallationPathConfig`; `getPrivateKeyPath()` now resolves to `backup/keys` and new `getBackupPath()` returns `backup/db`. - Removed old `PRIVATE_KEY_PATH` and switched all usages to the new locations. - Database service enhancements: - `DatabaseService` now uses `InstallationPathConfig.getBackupPath()` and includes a one-time migration to move existing backups from `config/db/backup` to `config/backup/db` (**@Deprecated(since = "2.0.0", forRemoval = true)**). - Added `deleteAllBackups()` and `deleteLastBackup()` methods and exposed them via a new Enterprise controller. - New Enterprise-only API: - Added `DatabaseControllerEnterprise` with: - `DELETE /api/v1/database/deleteAll` — delete all backup files. - `DELETE /api/v1/database/deleteLast` — delete the most recent backup. - Endpoints gated by `@EnterpriseEndpoint` and `@Conditional(H2SQLCondition.class)`. - Key persistence adjustments: - `KeyPersistenceService` now migrates keys from `config/db/keys` to `config/backup/keys` on startup (**@Deprecated(since = "2.0.0", forRemoval = true)**). - Miscellaneous refactors/fixes: - Switched driver resolution in `DatabaseConfig` to a switch expression. - Corrected HTTP status usage to `HttpStatus.SEE_OTHER`. - Removed constructor `runningEE` flag from `AccountWebController` and replaced EE checks with `@EnterpriseEndpoint`. - Minor test and annotation improvements (e.g., `@Deprecated(since = "0.45.0")`, method references, equals order). - **Why the change was made** - To standardize and future-proof storage locations for both backups and keys under a clear `config/backup` hierarchy. - To give Enterprise admins first-class, safe cleanup endpoints for managing backup retention without manual file operations. - To reduce conditional logic in controllers and rely on declarative EE gating. - To improve maintainability and correctness (status codes, switch expression, null-safety patterns). --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
40cf337b23
commit
3af93f0adb
@ -14,18 +14,22 @@ public class InstallationPathConfig {
|
||||
private static final String CONFIG_PATH;
|
||||
private static final String CUSTOM_FILES_PATH;
|
||||
private static final String CLIENT_WEBUI_PATH;
|
||||
private static final String SCRIPTS_PATH;
|
||||
private static final String PIPELINE_PATH;
|
||||
|
||||
// Config paths
|
||||
private static final String SETTINGS_PATH;
|
||||
private static final String CUSTOM_SETTINGS_PATH;
|
||||
private static final String SCRIPTS_PATH;
|
||||
private static final String BACKUP_PATH;
|
||||
|
||||
// Backup paths
|
||||
private static final String BACKUP_DB_PATH;
|
||||
private static final String BACKUP_PRIVATE_KEY_PATH;
|
||||
|
||||
// Custom file paths
|
||||
private static final String STATIC_PATH;
|
||||
private static final String TEMPLATES_PATH;
|
||||
private static final String SIGNATURES_PATH;
|
||||
private static final String PRIVATE_KEY_PATH;
|
||||
|
||||
static {
|
||||
BASE_PATH = initializeBasePath();
|
||||
@ -41,12 +45,16 @@ public class InstallationPathConfig {
|
||||
SETTINGS_PATH = CONFIG_PATH + "settings.yml";
|
||||
CUSTOM_SETTINGS_PATH = CONFIG_PATH + "custom_settings.yml";
|
||||
SCRIPTS_PATH = CONFIG_PATH + "scripts" + File.separator;
|
||||
BACKUP_PATH = CONFIG_PATH + "backup" + File.separator;
|
||||
|
||||
// Initialize backup paths
|
||||
BACKUP_DB_PATH = BACKUP_PATH + "db" + File.separator;
|
||||
BACKUP_PRIVATE_KEY_PATH = BACKUP_PATH + "keys" + File.separator;
|
||||
|
||||
// Initialize custom file paths
|
||||
STATIC_PATH = CUSTOM_FILES_PATH + "static" + File.separator;
|
||||
TEMPLATES_PATH = CUSTOM_FILES_PATH + "templates" + File.separator;
|
||||
SIGNATURES_PATH = CUSTOM_FILES_PATH + "signatures" + File.separator;
|
||||
PRIVATE_KEY_PATH = CONFIG_PATH + "db" + File.separator + "keys" + File.separator;
|
||||
}
|
||||
|
||||
private static String initializeBasePath() {
|
||||
@ -124,6 +132,10 @@ public class InstallationPathConfig {
|
||||
}
|
||||
|
||||
public static String getPrivateKeyPath() {
|
||||
return PRIVATE_KEY_PATH;
|
||||
return BACKUP_PRIVATE_KEY_PATH;
|
||||
}
|
||||
|
||||
public static String getBackupPath() {
|
||||
return BACKUP_DB_PATH;
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ class ApplicationPropertiesLogicTest {
|
||||
assertEquals(30, t.getOcrMyPdfTimeoutMinutes());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Deprecated(since = "0.45.0")
|
||||
@Test
|
||||
void enterprise_metadata_defaults() {
|
||||
ApplicationProperties.EnterpriseEdition ee = new ApplicationProperties.EnterpriseEdition();
|
||||
|
@ -11,7 +11,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
@ -59,19 +58,16 @@ public class AccountWebController {
|
||||
private final SessionPersistentRegistry sessionPersistentRegistry;
|
||||
// Assuming you have a repository for user operations
|
||||
private final UserRepository userRepository;
|
||||
private final boolean runningEE;
|
||||
private final TeamRepository teamRepository;
|
||||
|
||||
public AccountWebController(
|
||||
ApplicationProperties applicationProperties,
|
||||
SessionPersistentRegistry sessionPersistentRegistry,
|
||||
UserRepository userRepository,
|
||||
TeamRepository teamRepository,
|
||||
@Qualifier("runningEE") boolean runningEE) {
|
||||
TeamRepository teamRepository) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.sessionPersistentRegistry = sessionPersistentRegistry;
|
||||
this.userRepository = userRepository;
|
||||
this.runningEE = runningEE;
|
||||
this.teamRepository = teamRepository;
|
||||
}
|
||||
|
||||
@ -207,11 +203,9 @@ public class AccountWebController {
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@EnterpriseEndpoint
|
||||
@GetMapping("/usage")
|
||||
public String showUsage() {
|
||||
if (!runningEE) {
|
||||
return "error";
|
||||
}
|
||||
return "usage";
|
||||
}
|
||||
|
||||
@ -243,7 +237,7 @@ public class AccountWebController {
|
||||
|
||||
// Also check if user is part of the Internal team
|
||||
if (user.getTeam() != null
|
||||
&& user.getTeam().getName().equals(TeamService.INTERNAL_TEAM_NAME)) {
|
||||
&& TeamService.INTERNAL_TEAM_NAME.equals(user.getTeam().getName())) {
|
||||
shouldRemove = true;
|
||||
}
|
||||
|
||||
@ -362,11 +356,9 @@ public class AccountWebController {
|
||||
teamRepository.findAll().stream()
|
||||
.filter(
|
||||
team ->
|
||||
!team.getName()
|
||||
.equals(
|
||||
stirling.software.proprietary.security
|
||||
.service.TeamService
|
||||
.INTERNAL_TEAM_NAME))
|
||||
!stirling.software.proprietary.security.service.TeamService
|
||||
.INTERNAL_TEAM_NAME
|
||||
.equals(team.getName()))
|
||||
.toList();
|
||||
model.addAttribute("teams", allTeams);
|
||||
|
||||
|
@ -134,21 +134,21 @@ public class DatabaseConfig {
|
||||
ApplicationProperties.Driver driver =
|
||||
ApplicationProperties.Driver.valueOf(driverName.toUpperCase());
|
||||
|
||||
switch (driver) {
|
||||
return switch (driver) {
|
||||
case H2 -> {
|
||||
log.debug("H2 driver selected");
|
||||
return DatabaseDriver.H2.getDriverClassName();
|
||||
yield DatabaseDriver.H2.getDriverClassName();
|
||||
}
|
||||
case POSTGRESQL -> {
|
||||
log.debug("Postgres driver selected");
|
||||
return DatabaseDriver.POSTGRESQL.getDriverClassName();
|
||||
yield DatabaseDriver.POSTGRESQL.getDriverClassName();
|
||||
}
|
||||
default -> {
|
||||
log.warn("{} driver selected", driverName);
|
||||
throw new UnsupportedProviderException(
|
||||
driverName + " is not currently supported");
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn("Unknown driver: {}", driverName);
|
||||
throw new UnsupportedProviderException(driverName + " is not currently supported");
|
||||
|
@ -7,10 +7,10 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@ -145,7 +145,7 @@ public class DatabaseController {
|
||||
.body(resource);
|
||||
} catch (IOException e) {
|
||||
log.error("Error downloading file: {}", e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.SEE_OTHER_303)
|
||||
return ResponseEntity.status(HttpStatus.SEE_OTHER)
|
||||
.location(URI.create("/database?error=downloadFailed"))
|
||||
.build();
|
||||
}
|
||||
|
@ -0,0 +1,101 @@
|
||||
package stirling.software.proprietary.security.controller.api.enterprise;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.common.model.FileInfo;
|
||||
import stirling.software.proprietary.security.config.EnterpriseEndpoint;
|
||||
import stirling.software.proprietary.security.database.H2SQLCondition;
|
||||
import stirling.software.proprietary.security.service.DatabaseService;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/api/v1/database")
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@EnterpriseEndpoint
|
||||
@Conditional(H2SQLCondition.class)
|
||||
@Tag(name = "Database", description = "Database APIs for backup, import, and management")
|
||||
@RequiredArgsConstructor
|
||||
public class DatabaseControllerEnterprise {
|
||||
|
||||
private final DatabaseService databaseService;
|
||||
|
||||
@Operation(
|
||||
summary = "Delete the last database backup file",
|
||||
description =
|
||||
"Only Enterprise - Deletes the last database backup file from the server.")
|
||||
@DeleteMapping("/deleteLast")
|
||||
public ResponseEntity<?> deleteLastFile() {
|
||||
log.info("Deleting last database backup file...");
|
||||
List<Pair<FileInfo, Boolean>> results = databaseService.deleteLastBackup();
|
||||
return getDeleteAllResults(results);
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "Delete all database backup files",
|
||||
description = "Only Enterprise - Deletes all database backup files from the server.")
|
||||
@DeleteMapping("/deleteAll")
|
||||
public ResponseEntity<?> deleteAllFiles() {
|
||||
log.info("Deleting all database backup files...");
|
||||
List<Pair<FileInfo, Boolean>> results = databaseService.deleteAllBackups();
|
||||
return getDeleteAllResults(results);
|
||||
}
|
||||
|
||||
private ResponseEntity<?> getDeleteAllResults(List<Pair<FileInfo, Boolean>> results) {
|
||||
if (results.isEmpty()) {
|
||||
log.info("No backup files found to delete.");
|
||||
return ResponseEntity.ok(new DeleteAllResult(List.of(), List.of(), "noContent"));
|
||||
}
|
||||
|
||||
List<String> deleted =
|
||||
results.stream()
|
||||
.filter(p -> Boolean.TRUE.equals(p.getRight()))
|
||||
.map(p -> p.getLeft().getFileName())
|
||||
.toList();
|
||||
|
||||
List<String> failed =
|
||||
results.stream()
|
||||
.filter(p -> !Boolean.TRUE.equals(p.getRight()))
|
||||
.map(p -> p.getLeft().getFileName())
|
||||
.toList();
|
||||
|
||||
log.info("Deleted backup files: {}", deleted);
|
||||
if (!failed.isEmpty()) {
|
||||
log.warn("Some backup files could not be deleted: {}", failed);
|
||||
return ResponseEntity.status(HttpStatus.MULTI_STATUS) // 207
|
||||
.body(new DeleteAllResult(deleted, failed, "partialFailure"));
|
||||
}
|
||||
DeleteAllResult result = new DeleteAllResult(deleted, failed, "ok");
|
||||
log.debug(
|
||||
"DeleteAllResult: deleted={}, failed={}, status={}",
|
||||
result.deleted,
|
||||
result.failed,
|
||||
result.status);
|
||||
return ResponseEntity.ok(result); // 200
|
||||
}
|
||||
|
||||
private static final class DeleteAllResult {
|
||||
public final List<String> deleted;
|
||||
public final List<String> failed;
|
||||
public final String status;
|
||||
|
||||
public DeleteAllResult(List<String> deleted, List<String> failed, String status) {
|
||||
this.deleted = deleted;
|
||||
this.failed = failed;
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
@ -21,6 +22,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.jdbc.datasource.init.CannotReadScriptException;
|
||||
import org.springframework.jdbc.datasource.init.ScriptException;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -45,10 +47,39 @@ public class DatabaseService implements DatabaseServiceInterface {
|
||||
|
||||
public DatabaseService(
|
||||
ApplicationProperties.Datasource datasourceProps, DataSource dataSource) {
|
||||
this.BACKUP_DIR =
|
||||
Paths.get(InstallationPathConfig.getConfigPath(), "db", "backup").normalize();
|
||||
this.BACKUP_DIR = Paths.get(InstallationPathConfig.getBackupPath()).normalize();
|
||||
this.datasourceProps = datasourceProps;
|
||||
this.dataSource = dataSource;
|
||||
moveBackupFiles();
|
||||
}
|
||||
|
||||
/** Move all backup files from db/backup to backup/db */
|
||||
@Deprecated(since = "2.0.0", forRemoval = true)
|
||||
private void moveBackupFiles() {
|
||||
Path sourceDir =
|
||||
Paths.get(InstallationPathConfig.getConfigPath(), "db", "backup").normalize();
|
||||
|
||||
if (!Files.exists(sourceDir)) {
|
||||
log.info("Source directory does not exist: {}", sourceDir);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Files.createDirectories(BACKUP_DIR);
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(sourceDir)) {
|
||||
for (Path entry : stream) {
|
||||
if (entry.getFileName().toString().startsWith(BACKUP_PREFIX)
|
||||
&& entry.getFileName().toString().endsWith(SQL_SUFFIX)) {
|
||||
Files.move(
|
||||
entry,
|
||||
BACKUP_DIR.resolve(entry.getFileName()),
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Error moving backup files: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,6 +229,46 @@ public class DatabaseService implements DatabaseServiceInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<FileInfo, Boolean>> deleteAllBackups() {
|
||||
List<FileInfo> backupList = this.getBackupList();
|
||||
List<Pair<FileInfo, Boolean>> deletedFiles = new ArrayList<>();
|
||||
|
||||
for (FileInfo backup : backupList) {
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(backup.getFilePath()));
|
||||
deletedFiles.add(Pair.of(backup, true));
|
||||
} catch (IOException e) {
|
||||
log.error("Error deleting backup file: {}", backup.getFileName(), e);
|
||||
deletedFiles.add(Pair.of(backup, false));
|
||||
}
|
||||
}
|
||||
return deletedFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<FileInfo, Boolean>> deleteLastBackup() {
|
||||
|
||||
List<FileInfo> backupList = this.getBackupList();
|
||||
List<Pair<FileInfo, Boolean>> deletedFiles = new ArrayList<>();
|
||||
if (!backupList.isEmpty()) {
|
||||
FileInfo lastBackup = backupList.get(backupList.size() - 1);
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(lastBackup.getFilePath()));
|
||||
deletedFiles.add(Pair.of(lastBackup, true));
|
||||
} catch (IOException e) {
|
||||
log.error("Error deleting last backup file: {}", lastBackup.getFileName(), e);
|
||||
deletedFiles.add(Pair.of(lastBackup, false));
|
||||
}
|
||||
}
|
||||
return deletedFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the oldest backup file from the specified list.
|
||||
*
|
||||
* @param filteredBackupList the list of backup files
|
||||
*/
|
||||
private static void deleteOldestBackup(List<FileInfo> filteredBackupList) {
|
||||
try {
|
||||
filteredBackupList.sort(
|
||||
@ -237,6 +308,11 @@ public class DatabaseService implements DatabaseServiceInterface {
|
||||
return version;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the current datasource is H2.
|
||||
*
|
||||
* @return true if the datasource is H2, false otherwise
|
||||
*/
|
||||
private boolean isH2Database() {
|
||||
boolean isTypeH2 =
|
||||
datasourceProps.getType().equalsIgnoreCase(ApplicationProperties.Driver.H2.name());
|
||||
@ -301,6 +377,11 @@ public class DatabaseService implements DatabaseServiceInterface {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a database script.
|
||||
*
|
||||
* @param scriptPath the path to the script file
|
||||
*/
|
||||
private void executeDatabaseScript(Path scriptPath) {
|
||||
if (isH2Database()) {
|
||||
String query = "RUNSCRIPT from ?;";
|
||||
|
@ -3,6 +3,8 @@ package stirling.software.proprietary.security.service;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import stirling.software.common.model.FileInfo;
|
||||
import stirling.software.common.model.exception.UnsupportedProviderException;
|
||||
|
||||
@ -14,4 +16,8 @@ public interface DatabaseServiceInterface {
|
||||
boolean hasBackup();
|
||||
|
||||
List<FileInfo> getBackupList();
|
||||
|
||||
List<Pair<FileInfo, Boolean>> deleteAllBackups();
|
||||
|
||||
List<Pair<FileInfo, Boolean>> deleteLastBackup();
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
package stirling.software.proprietary.security.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
@ -52,6 +54,34 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface {
|
||||
this.verifyingKeyCache = cacheManager.getCache("verifyingKeys");
|
||||
}
|
||||
|
||||
/** Move all key files from db/keys to backup/keys */
|
||||
@Deprecated(since = "2.0.0", forRemoval = true)
|
||||
private void moveKeysToBackup() {
|
||||
Path sourceDir =
|
||||
Paths.get(InstallationPathConfig.getConfigPath(), "db", "keys").normalize();
|
||||
|
||||
if (!Files.exists(sourceDir)) {
|
||||
log.info("Source directory does not exist: {}", sourceDir);
|
||||
return;
|
||||
}
|
||||
|
||||
Path targetDir = Paths.get(InstallationPathConfig.getPrivateKeyPath()).normalize();
|
||||
|
||||
try {
|
||||
Files.createDirectories(targetDir);
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(sourceDir)) {
|
||||
for (Path entry : stream) {
|
||||
Files.move(
|
||||
entry,
|
||||
targetDir.resolve(entry.getFileName()),
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Error moving key files to backup: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void initializeKeystore() {
|
||||
if (!isKeystoreEnabled()) {
|
||||
@ -59,6 +89,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface {
|
||||
}
|
||||
|
||||
try {
|
||||
moveKeysToBackup();
|
||||
ensurePrivateKeyDirectoryExists();
|
||||
loadKeyPair();
|
||||
} catch (Exception e) {
|
||||
|
@ -2,6 +2,7 @@ package stirling.software.proprietary.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.actuate.audit.AuditEvent;
|
||||
import org.springframework.boot.actuate.audit.AuditEventRepository;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -29,8 +30,7 @@ public class AuditService {
|
||||
public AuditService(
|
||||
AuditEventRepository repository,
|
||||
AuditConfigurationProperties auditConfig,
|
||||
@org.springframework.beans.factory.annotation.Qualifier("runningEE")
|
||||
boolean runningEE) {
|
||||
@Qualifier("runningEE") boolean runningEE) {
|
||||
this.repository = repository;
|
||||
this.auditConfig = auditConfig;
|
||||
this.runningEE = runningEE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user