Skip to content

Commit 26c7074

Browse files
committed
#2270 added initDB script
1 parent 054cd3d commit 26c7074

File tree

8 files changed

+149
-86
lines changed

8 files changed

+149
-86
lines changed

build.gradle

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,11 @@ dependencies {
149149
implementation "org.springframework.session:spring-session-core:$springBootVersion"
150150
implementation "org.springframework:spring-jdbc"
151151

152-
implementation "com.unboundid.product.scim2:scim2-sdk-client:2.3.5"
153-
// Don't upgrade h2database
154152
runtimeOnly "org.postgresql:postgresql:42.7.4"
153+
// runtimeOnly 'com.mysql:mysql-connector-j:9.1.0'
154+
// runtimeOnly 'com.oracle.database.jdbc:ojdbc11:23.6.0.24.10'
155+
156+
implementation "com.unboundid.product.scim2:scim2-sdk-client:2.3.5"
155157
constraints {
156158
implementation "org.opensaml:opensaml-core:$openSamlVersion"
157159
implementation "org.opensaml:opensaml-saml-api:$openSamlVersion"
@@ -238,11 +240,33 @@ dependencies {
238240
tasks.withType(JavaCompile).configureEach {
239241
options.encoding = "UTF-8"
240242
dependsOn "spotlessApply"
243+
dependsOn "initDB"
241244
}
245+
242246
compileJava {
243247
options.compilerArgs << "-parameters"
244248
}
245249

250+
bootRun {
251+
if (project.hasProperty("args")) {
252+
args = project.args.split(" ")
253+
}
254+
}
255+
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+
246270
task writeVersion {
247271
def propsFile = file("src/main/resources/version.properties")
248272
def props = new Properties()

scripts/init_db.sh

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/bin/bash
2+
3+
# Enable robust error handling
4+
set -o errexit
5+
set -o nounset
6+
set -o pipefail
7+
8+
# Variables
9+
DB_NAME="stirling_pdf"
10+
DB_USER="admin"
11+
DB_PASSWORD="stirling"
12+
DB_TYPE=${1:-"postgresql"} # Default to PostgreSQL if not provided
13+
DB_HOST="localhost"
14+
DB_PORT=""
15+
16+
# Check database type and set defaults
17+
case "$DB_TYPE" in
18+
postgresql)
19+
DB_PORT="5432"
20+
;;
21+
mysql)
22+
DB_PORT="3306"
23+
;;
24+
oracle)
25+
DB_PORT="1521"
26+
;;
27+
*)
28+
echo "Unsupported database type: $DB_TYPE"
29+
exit 1
30+
;;
31+
esac
32+
33+
# Function to create PostgreSQL database and user
34+
create_postgres() {
35+
echo "Creating PostgreSQL database '$DB_NAME'..."
36+
37+
# Check if the database exists
38+
if psql -h "$DB_HOST" -p "$DB_PORT" -U postgres -lqt | cut -d \| -f 1 | grep -qw "$DB_NAME"; then
39+
echo "Database '$DB_NAME' already exists."
40+
else
41+
# Create user and database
42+
psql -h "$DB_HOST" -p "$DB_PORT" -U postgres -c "DO \$$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '$DB_USER') THEN CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_PASSWORD'; END IF; END \$$;"
43+
createdb -h "$DB_HOST" -p "$DB_PORT" -U postgres --owner="$DB_USER" "$DB_NAME"
44+
echo "Database '$DB_NAME' created successfully with owner '$DB_USER'."
45+
fi
46+
}
47+
48+
# Function to create MySQL database and user
49+
create_mysql() {
50+
echo "Creating MySQL database '$DB_NAME'..."
51+
52+
# Check if the database exists
53+
if mysql -h "$DB_HOST" -P "$DB_PORT" -u root -e "SHOW DATABASES LIKE '$DB_NAME';" | grep -qw "$DB_NAME"; then
54+
echo "Database '$DB_NAME' already exists."
55+
else
56+
# Create user and database
57+
mysql -h "$DB_HOST" -P "$DB_PORT" -u root -e "CREATE DATABASE IF NOT EXISTS $DB_NAME;"
58+
mysql -h "$DB_HOST" -P "$DB_PORT" -u root -e "CREATE USER IF NOT EXISTS '$DB_USER'@'%' IDENTIFIED BY '$DB_PASSWORD';"
59+
mysql -h "$DB_HOST" -P "$DB_PORT" -u root -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'%';"
60+
echo "Database '$DB_NAME' created successfully with owner '$DB_USER'."
61+
fi
62+
}
63+
64+
# Function to create Oracle database and user
65+
create_oracle() {
66+
echo "Creating Oracle database '$DB_NAME'..."
67+
# Check if the user exists
68+
EXISTS=$(sqlplus -s sys/oracle@//"$DB_HOST":"$DB_PORT"/orcl as sysdba <<EOF
69+
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
70+
SELECT COUNT(*) FROM dba_users WHERE username = UPPER('$DB_USER');
71+
EXIT;
72+
EOF
73+
)
74+
if [ "$EXISTS" -gt 0 ]; then
75+
echo "User '$DB_USER' already exists."
76+
else
77+
# Create user and schema
78+
sqlplus -s sys/oracle@//"$DB_HOST":"$DB_PORT"/orcl as sysdba <<EOF
79+
CREATE USER $DB_USER IDENTIFIED BY $DB_PASSWORD;
80+
GRANT CONNECT, RESOURCE TO $DB_USER;
81+
GRANT CREATE SESSION, CREATE TABLE TO $DB_USER;
82+
CREATE TABLESPACE $DB_NAME DATAFILE '$DB_NAME.dbf' SIZE 10M AUTOEXTEND ON NEXT 10M MAXSIZE 100M;
83+
ALTER USER $DB_USER DEFAULT TABLESPACE $DB_NAME;
84+
EXIT;
85+
EOF
86+
echo "User '$DB_USER' and tablespace '$DB_NAME' created successfully."
87+
fi
88+
}
89+
90+
# Execute the appropriate function based on the database type
91+
case "$DB_TYPE" in
92+
postgresql)
93+
create_postgres
94+
;;
95+
mysql)
96+
create_mysql
97+
;;
98+
oracle)
99+
create_oracle
100+
;;
101+
esac

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import stirling.software.SPDF.utils.FileInfo;
77

88
public interface DatabaseBackupInterface {
9-
void initDatabase();
10-
119
void exportDatabase() throws IOException;
1210

1311
void importDatabase();

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ public class InitialSecuritySetup {
2424

2525
@PostConstruct
2626
public void init() throws IllegalArgumentException, IOException {
27-
databaseBackupHelper.initDatabase();
28-
29-
if (databaseBackupHelper.hasBackup() && !userService.hasUsers()) {
27+
if (databaseBackupHelper.hasBackup() && userService.hasUsers()) {
3028
databaseBackupHelper.importDatabase();
3129
} else if (!userService.hasUsers()) {
3230
initializeAdminUser();

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

Lines changed: 10 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import java.nio.file.attribute.BasicFileAttributes;
99
import java.sql.Connection;
1010
import java.sql.DriverManager;
11-
import java.sql.PreparedStatement;
1211
import java.sql.ResultSet;
1312
import java.sql.SQLException;
1413
import java.sql.Statement;
@@ -40,75 +39,25 @@ public class DatabaseBackupHelper implements DatabaseBackupInterface {
4039
public static final String BACKUP_PREFIX = "backup_";
4140
public static final String SQL_SUFFIX = ".sql";
4241

42+
@Value("${dbType:postgresql}")
43+
private String dbType;
44+
4345
@Value("${spring.datasource.url}")
4446
private String url;
4547

4648
@Value("${spring.datasource.username}")
47-
private String databaseUsername;
49+
private String username;
4850

4951
@Value("${spring.datasource.password}")
50-
private String databasePassword;
51-
52-
@Value("${spring.datasource.stirling.url}")
53-
private String stirlingUrl;
54-
55-
@Value("${spring.datasource.stirling.username}")
56-
private String stirlingDatabaseUsername;
57-
58-
@Value("${spring.datasource.stirling.password}")
59-
private String stirlingDatabasePassword;
52+
private String password;
6053

6154
private final Path BACKUP_PATH = Paths.get("configs/db/backup/");
6255

63-
// fixMe: should check if backups exist without returning the whole list
64-
@Override
65-
public void initDatabase() {
66-
log.info("Creating database stirling-pdf-DB");
67-
68-
String initDBAndRoleScript =
69-
"""
70-
CREATE DATABASE "stirling-pdf-DB";
71-
CREATE USER %s WITH ENCRYPTED PASSWORD '%s';
72-
ALTER DATABASE "stirling-pdf-DB" OWNER TO %s;
73-
GRANT ALL PRIVILEGES ON DATABASE "stirling-pdf-DB" TO %s;
74-
"""
75-
.formatted(
76-
stirlingDatabaseUsername,
77-
stirlingDatabasePassword,
78-
stirlingDatabaseUsername,
79-
stirlingDatabaseUsername);
80-
try (Connection conn =
81-
DriverManager.getConnection(url, databaseUsername, databasePassword);
82-
PreparedStatement initStmt = conn.prepareStatement(initDBAndRoleScript)) {
83-
initStmt.execute();
84-
85-
String setRoleScript = "SET ROLE " + stirlingDatabaseUsername + ";";
86-
87-
try (Connection stirlingDBConn =
88-
DriverManager.getConnection(
89-
stirlingUrl,
90-
stirlingDatabaseUsername,
91-
stirlingDatabasePassword);
92-
PreparedStatement stmt = conn.prepareStatement(setRoleScript)) {
93-
stmt.execute();
94-
95-
log.info("Database stirling-pdf-DB created");
96-
log.info("User admin created");
97-
98-
ensureBackupDirectoryExists();
99-
} catch (SQLException e) {
100-
log.error("Failed to set admin to stirling-pdf-DB: {}", e.getMessage(), e);
101-
}
102-
} catch (SQLException e) {
103-
log.error("Failed to create stirling-pdf-DB: {}", e.getMessage(), e);
104-
}
105-
}
106-
10756
@Override
10857
public boolean hasBackup() {
10958
// Check if there is at least one backup
11059
try (Stream<Path> entries = Files.list(BACKUP_PATH)) {
111-
return entries.findFirst().isEmpty();
60+
return entries.findFirst().isPresent();
11261
} catch (IOException e) {
11362
log.error("Error reading backup directory: {}", e.getMessage(), e);
11463
throw new RuntimeException(e);
@@ -147,6 +96,7 @@ public List<FileInfo> getBackupList() {
14796
} catch (IOException e) {
14897
log.error("Error reading backup directory: {}", e.getMessage(), e);
14998
}
99+
150100
return backupFiles;
151101
}
152102

@@ -156,7 +106,6 @@ public boolean importDatabaseFromUI(String fileName) throws IOException {
156106
importDatabaseFromUI(getBackupFilePath(fileName));
157107
return true;
158108
} catch (IOException e) {
159-
// fixme: do we want to show the filename here?
160109
log.error(
161110
"Error importing database from file: {}, message: {}",
162111
fileName,
@@ -205,9 +154,7 @@ public void exportDatabase() {
205154
Path insertOutputFilePath =
206155
this.getBackupFilePath(BACKUP_PREFIX + dateNow.format(myFormatObj) + SQL_SUFFIX);
207156

208-
try (Connection conn =
209-
DriverManager.getConnection(
210-
stirlingUrl, stirlingDatabaseUsername, stirlingDatabasePassword)) {
157+
try (Connection conn = DriverManager.getConnection(url, username, password)) {
211158
ScriptUtils.executeSqlScript(
212159
conn, new EncodedResource(new PathResource(insertOutputFilePath)));
213160

@@ -236,8 +183,7 @@ private static void deleteOldestBackup(List<FileInfo> filteredBackupList) {
236183
// Retrieves the H2 database version.
237184
public String getH2Version() {
238185
String version = "Unknown";
239-
try (Connection conn =
240-
DriverManager.getConnection(stirlingUrl, stirlingDatabaseUsername, stirlingDatabasePassword)) {
186+
try (Connection conn = DriverManager.getConnection(url, username, password)) {
241187
try (Statement stmt = conn.createStatement();
242188
ResultSet rs = stmt.executeQuery("SELECT H2VERSION() AS version")) {
243189
if (rs.next()) {
@@ -277,8 +223,7 @@ public Path getBackupFilePath(String fileName) {
277223
}
278224

279225
private void executeDatabaseScript(Path scriptPath) {
280-
try (Connection conn =
281-
DriverManager.getConnection(stirlingUrl, stirlingDatabaseUsername, stirlingDatabasePassword)) {
226+
try (Connection conn = DriverManager.getConnection(url, username, password)) {
282227
ScriptUtils.executeSqlScript(conn, new EncodedResource(new PathResource(scriptPath)));
283228

284229
log.info("Database import completed: {}", scriptPath);

src/main/java/stirling/software/SPDF/model/User.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class User implements Serializable {
4747
@ElementCollection
4848
@MapKeyColumn(name = "setting_key")
4949
@Lob
50-
@Column(name = "setting_value", columnDefinition = "CLOB")
50+
@Column(name = "setting_value", columnDefinition = "text")
5151
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id"))
5252
private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings.
5353

src/main/resources/application.properties

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ logging.level.org.eclipse.jetty=WARN
99
#logging.level.stirling.software.SPDF.config.security: DEBUG
1010
logging.level.com.zaxxer.hikari=WARN
1111

12-
spring.jpa.open-in-view=false
13-
1412
server.forward-headers-strategy=NATIVE
1513

1614
server.error.path=/error
@@ -41,17 +39,16 @@ spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
4139
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
4240
#spring.thymeleaf.cache=false
4341

44-
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
45-
spring.datasource.platform=postgres
46-
spring.datasource.driver-class-name=org.postgresql.Driver
47-
spring.datasource.username=postgres
48-
spring.datasource.password=postgres
49-
spring.datasource.stirling.url=jdbc:postgresql://localhost:5432/stirling-pdf-DB
50-
spring.datasource.stirling.username=admin
51-
spring.datasource.stirling.password=stirling
42+
spring.datasource.url=jdbc:postgresql://localhost:5432/stirling_pdf
43+
# postgresql | oracle | mysql
44+
spring.datasource.driver=postgresql
45+
spring.datasource.username=admin
46+
spring.datasource.password=stirling
47+
spring.jpa.open-in-view=false
5248
spring.jpa.generate-ddl=true
5349
spring.jpa.hibernate.ddl-auto=update
5450
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
51+
spring.flyway.baselineOneMigrate=true
5552
server.servlet.session.timeout=30m
5653
# Change the default URL path for OpenAPI JSON
5754
springdoc.api-docs.path=/v1/api-docs

src/main/resources/settings.yml.template

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ system:
8686
tessdataDir: /usr/share/tessdata # path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored.
8787
enableAnalytics: undefined # set to 'true' to enable analytics, set to 'false' to disable analytics; for enterprise users, this is set to true
8888
datasource:
89-
url: jdbc:postgresql://localhost:5432/postgres
9089
driver: postgresql
91-
username: postgres
92-
password: postgres
90+
url: jdbc:postgresql://localhost:5432/stirling_pdf
91+
username: admin
92+
password: stirling
9393

9494
ui:
9595
appName: '' # application's visible name

0 commit comments

Comments
 (0)