Skip to content

Commit 519e4ff

Browse files
committed
#2270 config for DB variants
1 parent 6255177 commit 519e4ff

21 files changed

+198
-74
lines changed

build.gradle

+1-15
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ dependencies {
240240
tasks.withType(JavaCompile).configureEach {
241241
options.encoding = "UTF-8"
242242
dependsOn "spotlessApply"
243-
dependsOn "initDB"
243+
// dependsOn "initDB"
244244
}
245245

246246
compileJava {
@@ -253,20 +253,6 @@ bootRun {
253253
}
254254
}
255255

256-
257-
tasks.register("initDB", Exec) {
258-
description = "Creates a database of the specified type (postgresql, mysql, oracle)."
259-
def scriptPath = "$projectDir/scripts/init_db.sh"
260-
// Set the database type argument
261-
def dbType = project.hasProperty('dbType') ? project.property('dbType') : "postgresql"
262-
263-
if (!["postgresql", "mysql", "oracle"].contains(dbType)) {
264-
throw new GradleException("Invalid database type: $dbType. Valid types are: postgresql, mysql, oracle.")
265-
} else {
266-
commandLine "bash", scriptPath, dbType
267-
}
268-
}
269-
270256
task writeVersion {
271257
def propsFile = file("src/main/resources/version.properties")
272258
def props = new Properties()

src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public LicenseKeyChecker(
2828
this.checkLicense();
2929
}
3030

31-
@Scheduled(initialDelay = 604800000,fixedRate = 604800000) // 7 days in milliseconds
31+
@Scheduled(initialDelay = 604800000, fixedRate = 604800000) // 7 days in milliseconds
3232
public void checkLicensePeriodically() {
3333
checkLicense();
3434
}

src/main/java/stirling/software/SPDF/config/interfaces/DatabaseBackupInterface.java

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import stirling.software.SPDF.utils.FileInfo;
77

88
public interface DatabaseBackupInterface {
9+
void setAdminUser();
10+
911
void exportDatabase() throws IOException;
1012

1113
void importDatabase();

src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java

+12-8
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,26 @@
1616
@Slf4j
1717
public class InitialSecuritySetup {
1818

19+
public static final String POSTGRES = "postgres";
20+
1921
@Autowired private UserService userService;
2022

2123
@Autowired private ApplicationProperties applicationProperties;
2224

23-
@Autowired private DatabaseBackupInterface databaseBackupHelper;
25+
@Autowired private DatabaseBackupInterface databaseBackupService;
2426

2527
@PostConstruct
2628
public void init() throws IllegalArgumentException, IOException {
27-
if (databaseBackupHelper.hasBackup() && userService.hasUsers()) {
28-
databaseBackupHelper.importDatabase();
29-
} else if (!userService.hasUsers()) {
29+
if (applicationProperties.getSystem().getEnvironmentName().equals(POSTGRES)) {
30+
log.debug("PostgreSQL configuration settings detected. Creating admin user");
31+
databaseBackupService.setAdminUser();
32+
}
33+
34+
if (!userService.hasUsers()) {
3035
initializeAdminUser();
31-
} else {
32-
databaseBackupHelper.exportDatabase();
33-
userService.migrateOauth2ToSSO();
3436
}
37+
38+
userService.migrateOauth2ToSSO();
3539
initializeInternalApiUser();
3640
}
3741

@@ -73,7 +77,7 @@ private void initializeInternalApiUser() throws IllegalArgumentException, IOExce
7377
UUID.randomUUID().toString(),
7478
Role.INTERNAL_API_USER.getRoleId());
7579
userService.addApiKeyToUser(Role.INTERNAL_API_USER.getRoleId());
76-
log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
80+
log.info("Internal API user created: {}", Role.INTERNAL_API_USER.getRoleId());
7781
}
7882
}
7983
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package stirling.software.SPDF.config.security.database;
2+
3+
import javax.sql.DataSource;
4+
5+
import org.springframework.boot.context.properties.ConfigurationProperties;
6+
import org.springframework.boot.jdbc.DataSourceBuilder;
7+
import org.springframework.context.annotation.Configuration;
8+
9+
import lombok.Data;
10+
11+
@Data
12+
@Configuration
13+
@ConfigurationProperties(prefix = "spring.datasource")
14+
public class DataSourceConfig {
15+
16+
private String driverClassName;
17+
private String url;
18+
private String username;
19+
private String password;
20+
21+
public DataSource dataSource() {
22+
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
23+
dataSourceBuilder.driverClassName(driverClassName);
24+
dataSourceBuilder.url(url);
25+
dataSourceBuilder.username(username);
26+
dataSourceBuilder.password(password);
27+
return dataSourceBuilder.build();
28+
}
29+
}

src/main/java/stirling/software/SPDF/config/security/database/DatabaseBackupHelper.java src/main/java/stirling/software/SPDF/config/security/database/DatabaseBackupService.java

+42-19
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import java.nio.file.Paths;
88
import java.nio.file.attribute.BasicFileAttributes;
99
import java.sql.Connection;
10-
import java.sql.DriverManager;
1110
import java.sql.ResultSet;
1211
import java.sql.SQLException;
1312
import java.sql.Statement;
@@ -20,38 +19,62 @@
2019
import java.util.stream.Collectors;
2120
import java.util.stream.Stream;
2221

23-
import org.springframework.beans.factory.annotation.Value;
24-
import org.springframework.context.annotation.Configuration;
22+
import org.springframework.beans.factory.annotation.Autowired;
2523
import org.springframework.core.io.PathResource;
2624
import org.springframework.core.io.support.EncodedResource;
2725
import org.springframework.jdbc.datasource.init.ScriptException;
2826
import org.springframework.jdbc.datasource.init.ScriptUtils;
27+
import org.springframework.stereotype.Service;
2928

3029
import lombok.extern.slf4j.Slf4j;
3130
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
3231
import stirling.software.SPDF.model.exception.BackupNotFoundException;
3332
import stirling.software.SPDF.utils.FileInfo;
3433

3534
@Slf4j
36-
@Configuration
37-
public class DatabaseBackupHelper implements DatabaseBackupInterface {
35+
@Service
36+
public class DatabaseBackupService implements DatabaseBackupInterface {
3837

3938
public static final String BACKUP_PREFIX = "backup_";
4039
public static final String SQL_SUFFIX = ".sql";
40+
private static final Path BACKUP_PATH = Paths.get("configs/db/backup/");
4141

42-
@Value("${dbType:postgresql}")
43-
private String dbType;
42+
@Autowired private DatabaseConfig databaseConfig;
4443

45-
@Value("${spring.datasource.url}")
46-
private String url;
47-
48-
@Value("${spring.datasource.username}")
49-
private String username;
50-
51-
@Value("${spring.datasource.password}")
52-
private String password;
44+
@Override
45+
public void setAdminUser() {
46+
String adminScript =
47+
"""
48+
DO
49+
$do$
50+
BEGIN
51+
IF EXISTS (
52+
SELECT FROM pg_catalog.pg_roles
53+
WHERE rolname = 'admin') THEN
54+
55+
RAISE NOTICE 'Role "admin" already exists. Skipping.';
56+
ELSE
57+
CREATE USER admin WITH ENCRYPTED PASSWORD 'stirling';
58+
END IF;
59+
END
60+
$do$;
61+
62+
CREATE SCHEMA IF NOT EXISTS stirling_pdf AUTHORIZATION admin;
63+
GRANT ALL PRIVILEGES ON DATABASE postgres TO admin;
64+
ALTER DATABASE postgres SET search_path TO stirling_pdf;
65+
ALTER USER admin SET search_path TO stirling_pdf;
66+
"""
67+
.trim();
68+
69+
try (Connection connection = databaseConfig.connection();
70+
Statement statement = connection.createStatement()) {
71+
statement.execute(adminScript);
72+
} catch (SQLException e) {
73+
log.error("Error: Failed to create admin user for database", e);
74+
}
5375

54-
private final Path BACKUP_PATH = Paths.get("configs/db/backup/");
76+
log.info("Created admin user for database");
77+
}
5578

5679
@Override
5780
public boolean hasBackup() {
@@ -154,7 +177,7 @@ public void exportDatabase() {
154177
Path insertOutputFilePath =
155178
this.getBackupFilePath(BACKUP_PREFIX + dateNow.format(myFormatObj) + SQL_SUFFIX);
156179

157-
try (Connection conn = DriverManager.getConnection(url, username, password)) {
180+
try (Connection conn = databaseConfig.connection()) {
158181
ScriptUtils.executeSqlScript(
159182
conn, new EncodedResource(new PathResource(insertOutputFilePath)));
160183

@@ -183,7 +206,7 @@ private static void deleteOldestBackup(List<FileInfo> filteredBackupList) {
183206
// Retrieves the H2 database version.
184207
public String getH2Version() {
185208
String version = "Unknown";
186-
try (Connection conn = DriverManager.getConnection(url, username, password)) {
209+
try (Connection conn = databaseConfig.connection()) {
187210
try (Statement stmt = conn.createStatement();
188211
ResultSet rs = stmt.executeQuery("SELECT H2VERSION() AS version")) {
189212
if (rs.next()) {
@@ -223,7 +246,7 @@ public Path getBackupFilePath(String fileName) {
223246
}
224247

225248
private void executeDatabaseScript(Path scriptPath) {
226-
try (Connection conn = DriverManager.getConnection(url, username, password)) {
249+
try (Connection conn = databaseConfig.connection()) {
227250
ScriptUtils.executeSqlScript(conn, new EncodedResource(new PathResource(scriptPath)));
228251

229252
log.info("Database import completed: {}", scriptPath);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package stirling.software.SPDF.config.security.database;
2+
3+
import java.sql.Connection;
4+
import java.sql.DriverManager;
5+
import java.sql.SQLException;
6+
7+
import javax.sql.DataSource;
8+
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
13+
import lombok.Getter;
14+
15+
@Getter
16+
@Configuration
17+
public class DatabaseConfig {
18+
19+
@Autowired private DataSourceConfig dataSourceConfig;
20+
21+
@Autowired private JpaConfig jpaConfig;
22+
23+
@Bean
24+
public DataSource dataSource() {
25+
return dataSourceConfig.dataSource();
26+
}
27+
28+
@Bean
29+
public Connection connection() throws SQLException {
30+
return DriverManager.getConnection(
31+
dataSourceConfig.getUrl(),
32+
dataSourceConfig.getUsername(),
33+
dataSourceConfig.getPassword());
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package stirling.software.SPDF.config.security.database;
2+
3+
import org.springframework.beans.factory.annotation.Value;
4+
import org.springframework.boot.context.properties.ConfigurationProperties;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
import lombok.Data;
8+
9+
@Data
10+
@Configuration
11+
@ConfigurationProperties(prefix = "spring.jpa")
12+
public class JpaConfig {
13+
14+
@Value("${environment.name}")
15+
private String environmentName;
16+
17+
private String databasePlatform;
18+
private String openInView;
19+
private String generateDDL;
20+
}

src/main/java/stirling/software/SPDF/config/security/database/ScheduledTasks.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
@Component
1010
public class ScheduledTasks {
1111

12-
@Autowired private DatabaseBackupHelper databaseBackupService;
12+
@Autowired private DatabaseBackupService databaseBackupService;
1313

1414
@Scheduled(cron = "0 0 0 * * ?")
1515
public void performBackup() throws IOException {

src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import io.swagger.v3.oas.annotations.tags.Tag;
2929

3030
import lombok.extern.slf4j.Slf4j;
31-
import stirling.software.SPDF.config.security.database.DatabaseBackupHelper;
31+
import stirling.software.SPDF.config.security.database.DatabaseBackupService;
3232

3333
@Slf4j
3434
@Controller
@@ -37,7 +37,7 @@
3737
@Tag(name = "Database", description = "Database APIs")
3838
public class DatabaseController {
3939

40-
@Autowired DatabaseBackupHelper databaseBackupHelper;
40+
@Autowired DatabaseBackupService databaseBackupService;
4141

4242
@Hidden
4343
@PostMapping(consumes = "multipart/form-data", value = "import-database")
@@ -56,7 +56,7 @@ public String importDatabase(
5656
try (InputStream in = file.getInputStream()) {
5757
Files.copy(in, tempTemplatePath, StandardCopyOption.REPLACE_EXISTING);
5858
boolean importSuccess =
59-
databaseBackupHelper.importDatabaseFromUI(tempTemplatePath.toString());
59+
databaseBackupService.importDatabaseFromUI(tempTemplatePath.toString());
6060
if (importSuccess) {
6161
redirectAttributes.addAttribute("infoMessage", "importIntoDatabaseSuccessed");
6262
} else {
@@ -79,14 +79,14 @@ public String importDatabaseFromBackupUI(@PathVariable String fileName)
7979

8080
// Check if the file exists in the backup list
8181
boolean fileExists =
82-
databaseBackupHelper.getBackupList().stream()
82+
databaseBackupService.getBackupList().stream()
8383
.anyMatch(backup -> backup.getFileName().equals(fileName));
8484
if (!fileExists) {
8585
log.error("File {} not found in backup list", fileName);
8686
return "redirect:/database?error=fileNotFound";
8787
}
8888
log.info("Received file: {}", fileName);
89-
if (databaseBackupHelper.importDatabaseFromUI(fileName)) {
89+
if (databaseBackupService.importDatabaseFromUI(fileName)) {
9090
log.info("File {} imported to database", fileName);
9191
return "redirect:/database?infoMessage=importIntoDatabaseSuccessed";
9292
}
@@ -104,7 +104,7 @@ public String deleteFile(@PathVariable String fileName) {
104104
throw new IllegalArgumentException("File must not be null or empty");
105105
}
106106
try {
107-
if (databaseBackupHelper.deleteBackupFile(fileName)) {
107+
if (databaseBackupService.deleteBackupFile(fileName)) {
108108
log.info("Deleted file: {}", fileName);
109109
} else {
110110
log.error("Failed to delete file: {}", fileName);
@@ -128,7 +128,7 @@ public ResponseEntity<?> downloadFile(@PathVariable String fileName) {
128128
throw new IllegalArgumentException("File must not be null or empty");
129129
}
130130
try {
131-
Path filePath = databaseBackupHelper.getBackupFilePath(fileName);
131+
Path filePath = databaseBackupService.getBackupFilePath(fileName);
132132
InputStreamResource resource = new InputStreamResource(Files.newInputStream(filePath));
133133
return ResponseEntity.ok()
134134
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)

src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
import io.swagger.v3.oas.annotations.tags.Tag;
1313

1414
import jakarta.servlet.http.HttpServletRequest;
15-
import stirling.software.SPDF.config.security.database.DatabaseBackupHelper;
15+
import stirling.software.SPDF.config.security.database.DatabaseBackupService;
1616
import stirling.software.SPDF.utils.FileInfo;
1717

1818
@Controller
1919
@Tag(name = "Database Management", description = "Database management and security APIs")
2020
public class DatabaseWebController {
2121

22-
@Autowired private DatabaseBackupHelper databaseBackupHelper;
22+
@Autowired private DatabaseBackupService databaseBackupService;
2323

2424
@PreAuthorize("hasRole('ROLE_ADMIN')")
2525
@GetMapping("/database")
@@ -33,10 +33,10 @@ public String database(HttpServletRequest request, Model model, Authentication a
3333
model.addAttribute("infoMessage", confirmed);
3434
}
3535

36-
List<FileInfo> backupList = databaseBackupHelper.getBackupList();
36+
List<FileInfo> backupList = databaseBackupService.getBackupList();
3737
model.addAttribute("backupFiles", backupList);
3838

39-
model.addAttribute("databaseVersion", databaseBackupHelper.getH2Version());
39+
model.addAttribute("databaseVersion", databaseBackupService.getH2Version());
4040

4141
return "database";
4242
}

0 commit comments

Comments
 (0)