mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 19:33:11 +02:00
open-saml bumps (#5805)
This commit is contained in:
@@ -8,7 +8,6 @@ spotless {
|
|||||||
googleJavaFormat(googleJavaFormatVersion).aosp().reorderImports(false)
|
googleJavaFormat(googleJavaFormatVersion).aosp().reorderImports(false)
|
||||||
|
|
||||||
importOrder("java", "javax", "org", "com", "net", "io", "jakarta", "lombok", "me", "stirling")
|
importOrder("java", "javax", "org", "com", "net", "io", "jakarta", "lombok", "me", "stirling")
|
||||||
toggleOffOn()
|
|
||||||
trimTrailingWhitespace()
|
trimTrailingWhitespace()
|
||||||
leadingTabsToSpaces()
|
leadingTabsToSpaces()
|
||||||
endWithNewline()
|
endWithNewline()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
repositories {
|
repositories {
|
||||||
maven { url = "https://build.shibboleth.net/maven/releases" }
|
maven { url = "https://build.shibboleth.net/maven/releases" }
|
||||||
|
maven { url = "https://repository.jboss.org/" }
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
@@ -63,12 +64,9 @@ dependencies {
|
|||||||
runtimeOnly "io.jsonwebtoken:jjwt-jackson:$jwtVersion"
|
runtimeOnly "io.jsonwebtoken:jjwt-jackson:$jwtVersion"
|
||||||
runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database
|
runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database
|
||||||
runtimeOnly 'org.postgresql:postgresql:42.7.10'
|
runtimeOnly 'org.postgresql:postgresql:42.7.10'
|
||||||
constraints {
|
implementation('com.coveo:saml-client:5.0.0') {
|
||||||
implementation "org.opensaml:opensaml-core:$openSamlVersion"
|
exclude group: 'org.opensaml', module: 'opensaml-core'
|
||||||
implementation "org.opensaml:opensaml-saml-api:$openSamlVersion"
|
|
||||||
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
|
|
||||||
}
|
}
|
||||||
implementation 'com.coveo:saml-client:5.0.0'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('prepareKotlinBuildScriptModel') {}
|
tasks.register('prepareKotlinBuildScriptModel') {}
|
||||||
|
|||||||
+14
@@ -191,6 +191,20 @@ public class DatabaseController {
|
|||||||
if (fileName == null || fileName.isEmpty()) {
|
if (fileName == null || fileName.isEmpty()) {
|
||||||
throw new IllegalArgumentException("File must not be null or empty");
|
throw new IllegalArgumentException("File must not be null or empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate that file is a legitimate backup file
|
||||||
|
// Only allow files matching the backup naming pattern
|
||||||
|
if (!fileName.startsWith("backup_") || !fileName.endsWith(".sql")) {
|
||||||
|
log.warn("Attempted download of non-backup file: {}", fileName);
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||||
|
.body(
|
||||||
|
java.util.Map.of(
|
||||||
|
"error",
|
||||||
|
"invalidFileName",
|
||||||
|
"message",
|
||||||
|
"Only backup files are allowed"));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Path filePath = databaseService.getBackupFilePath(fileName);
|
Path filePath = databaseService.getBackupFilePath(fileName);
|
||||||
InputStreamResource resource = new InputStreamResource(Files.newInputStream(filePath));
|
InputStreamResource resource = new InputStreamResource(Files.newInputStream(filePath));
|
||||||
|
|||||||
+108
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
@@ -47,6 +48,48 @@ public class DatabaseService implements DatabaseServiceInterface {
|
|||||||
public static final String SQL_SUFFIX = ".sql";
|
public static final String SQL_SUFFIX = ".sql";
|
||||||
private final Path BACKUP_DIR;
|
private final Path BACKUP_DIR;
|
||||||
|
|
||||||
|
// Whitelist of allowed SQL patterns for H2 database backups (generated by SCRIPT command)
|
||||||
|
// Only standard DDL/DML operations are permitted - anything else is rejected by default
|
||||||
|
private static final java.util.List<Pattern> ALLOWED_PATTERNS =
|
||||||
|
java.util.List.of(
|
||||||
|
Pattern.compile("(?i)\\bCREATE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bSET\\s+SCHEMA\\b"),
|
||||||
|
Pattern.compile("(?i)\\bALTER\\s+SEQUENCE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bDROP\\s+TABLE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bALTER\\s+TABLE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bADD\\s+COLUMN\\b"),
|
||||||
|
Pattern.compile("(?i)\\bINSERT\\s+INTO\\b"),
|
||||||
|
Pattern.compile("(?i)\\bVALUES\\b"),
|
||||||
|
Pattern.compile("(?i)\\bADD\\s+CONSTRAINT\\b"),
|
||||||
|
Pattern.compile("(?i)\\bPRIMARY\\s+KEY\\b"),
|
||||||
|
Pattern.compile("(?i)\\bFOREIGN\\s+KEY\\b"),
|
||||||
|
Pattern.compile("(?i)\\bCONSTRAINT\\b"),
|
||||||
|
Pattern.compile("(?i)\\bCHECK\\b"),
|
||||||
|
Pattern.compile(
|
||||||
|
"(?i)\\bGENERATED\\s+(BY\\s+DEFAULT|ALWAYS)\\s+AS\\s+IDENTITY\\b"),
|
||||||
|
Pattern.compile("(?i)\\bDEFAULT\\b"),
|
||||||
|
Pattern.compile(
|
||||||
|
"(?i)\\bSET\\s+(REFERENTIAL_INTEGRITY|MODE|DATABASE|IGNORECASE|AUTOINCREMENT|DB_CLOSE_DELAY)\\b"),
|
||||||
|
Pattern.compile("(?i)\\bIF\\s+EXISTS\\b"),
|
||||||
|
Pattern.compile("(?i)\\bIF\\s+NOT\\s+EXISTS\\b"),
|
||||||
|
Pattern.compile("(?i)\\bNULLS\\s+(FIRST|LAST)\\b"),
|
||||||
|
Pattern.compile("(?i)\\bREFERENCES\\b"),
|
||||||
|
Pattern.compile("(?i)\\bNOCHECK\\b"),
|
||||||
|
Pattern.compile("(?i)\\bRESTART\\s+WITH\\b"),
|
||||||
|
Pattern.compile("(?i)\\bCASCADE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bON\\b"),
|
||||||
|
Pattern.compile("(?i)\\bSTART\\s+WITH\\b"),
|
||||||
|
Pattern.compile("(?i)\\bAS\\b"),
|
||||||
|
Pattern.compile("(?i)\\bUNIQUE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bDISTINCT\\b"),
|
||||||
|
Pattern.compile("(?i)\\bWITH\\s+TIME\\s+ZONE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bTIMESTAMP\\b"),
|
||||||
|
Pattern.compile("(?i)\\bVARYING\\b"),
|
||||||
|
Pattern.compile("(?i)\\bNOT\\s+NULL\\b"),
|
||||||
|
Pattern.compile("(?i)\\bTRUE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bFALSE\\b"),
|
||||||
|
Pattern.compile("(?i)\\bNULL\\b"));
|
||||||
|
|
||||||
private final ApplicationProperties.Datasource datasourceProps;
|
private final ApplicationProperties.Datasource datasourceProps;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final DatabaseNotificationServiceInterface backupNotificationService;
|
private final DatabaseNotificationServiceInterface backupNotificationService;
|
||||||
@@ -450,6 +493,9 @@ public class DatabaseService implements DatabaseServiceInterface {
|
|||||||
throw new IllegalArgumentException("Backup verification failed for: " + scriptPath);
|
throw new IllegalArgumentException("Backup verification failed for: " + scriptPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate SQL content before execution to prevent injection attacks
|
||||||
|
validateSqlContent(scriptPath);
|
||||||
|
|
||||||
String query = "RUNSCRIPT from ?;";
|
String query = "RUNSCRIPT from ?;";
|
||||||
|
|
||||||
try (Connection conn = dataSource.getConnection();
|
try (Connection conn = dataSource.getConnection();
|
||||||
@@ -466,6 +512,68 @@ public class DatabaseService implements DatabaseServiceInterface {
|
|||||||
log.info("Database import completed: {}", scriptPath);
|
log.info("Database import completed: {}", scriptPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates SQL content to prevent execution of dangerous functions. Uses an allowlist approach
|
||||||
|
* - only allows standard DML/DDL operations generated by H2's SCRIPT command.
|
||||||
|
*
|
||||||
|
* @param scriptPath the path to the SQL file
|
||||||
|
* @throws IllegalArgumentException if dangerous SQL or disallowed patterns are detected
|
||||||
|
*/
|
||||||
|
private void validateSqlContent(Path scriptPath) {
|
||||||
|
try {
|
||||||
|
String content = Files.readString(scriptPath);
|
||||||
|
String normalizedContent = normalizeSqlContent(content);
|
||||||
|
|
||||||
|
// Validate that content only contains allowed operations (whitelist approach)
|
||||||
|
// Split by semicolons to check individual statements
|
||||||
|
String[] statements = normalizedContent.split(";");
|
||||||
|
for (String statement : statements) {
|
||||||
|
statement = statement.trim();
|
||||||
|
if (statement.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if statement matches any allowed pattern
|
||||||
|
boolean isAllowed = false;
|
||||||
|
for (Pattern allowedPattern : ALLOWED_PATTERNS) {
|
||||||
|
if (allowedPattern.matcher(statement).find()) {
|
||||||
|
isAllowed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAllowed) {
|
||||||
|
log.error(
|
||||||
|
"Unrecognized SQL statement in backup file: {}",
|
||||||
|
statement.substring(0, Math.min(50, statement.length())));
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"SQL script contains unrecognized or disallowed SQL statements. File may be"
|
||||||
|
+ " corrupted or tampered with.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error reading SQL script for validation: {}", e.getMessage());
|
||||||
|
throw new IllegalArgumentException("Failed to validate SQL script: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes SQL content by removing comments to prevent bypass attacks.
|
||||||
|
*
|
||||||
|
* @param sql the SQL content to normalize
|
||||||
|
* @return normalized SQL without comments
|
||||||
|
*/
|
||||||
|
private String normalizeSqlContent(String sql) {
|
||||||
|
// Remove block comments (/* ... */)
|
||||||
|
sql = sql.replaceAll("/\\*[\\s\\S]*?\\*/", " ");
|
||||||
|
// Remove line comments (--....)
|
||||||
|
sql = sql.replaceAll("--[^\r\n]*", " ");
|
||||||
|
// Collapse multiple whitespaces
|
||||||
|
sql = sql.replaceAll("\\s+", " ");
|
||||||
|
return sql.trim();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for invalid characters or sequences
|
* Checks for invalid characters or sequences
|
||||||
*
|
*
|
||||||
|
|||||||
+135
@@ -128,4 +128,139 @@ class DatabaseServiceTest {
|
|||||||
org.mockito.ArgumentMatchers.anyString(),
|
org.mockito.ArgumentMatchers.anyString(),
|
||||||
org.mockito.ArgumentMatchers.anyString());
|
org.mockito.ArgumentMatchers.anyString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void validateSqlContentAcceptsRealH2BackupFile() throws IOException {
|
||||||
|
String sqlContent =
|
||||||
|
"-- H2 2.4.240; \n"
|
||||||
|
+ "SET DB_CLOSE_DELAY -1; \n"
|
||||||
|
+ "; \n"
|
||||||
|
+ "CREATE USER IF NOT EXISTS \"SA\" SALT 'd4a7c2f9e1b5a8c3' HASH 'b8f3e6c1a9d2f7e4c5a8d1f6b3e7a2c9d0f5b8e1a4c7f2d9e6b3a1c8f5d2' ADMIN; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"AUDIT_EVENTS\" CASCADE; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"AUTHORITIES\" CASCADE; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"INVITE_TOKENS\" CASCADE; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"PERSISTENT_LOGINS\" CASCADE; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"SESSIONS\" CASCADE; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"TEAMS\" CASCADE; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"USER_LICENSE_SETTINGS\" CASCADE; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"USER_SETTINGS\" CASCADE; \n"
|
||||||
|
+ "DROP TABLE IF EXISTS \"PUBLIC\".\"USERS\" CASCADE; \n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"AUDIT_EVENTS\"(\n"
|
||||||
|
+ " \"ID\" BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL,\n"
|
||||||
|
+ " \"DATA\" CHARACTER VARYING,\n"
|
||||||
|
+ " \"PRINCIPAL\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"TIMESTAMP\" TIMESTAMP(6) WITH TIME ZONE,\n"
|
||||||
|
+ " \"TYPE\" CHARACTER VARYING(255)\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"AUDIT_EVENTS\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_C\" PRIMARY KEY(\"ID\"); \n"
|
||||||
|
+ "-- 0 +/- SELECT COUNT(*) FROM PUBLIC.AUDIT_EVENTS; \n"
|
||||||
|
+ "CREATE INDEX \"PUBLIC\".\"IDX_AUDIT_TIMESTAMP\" ON \"PUBLIC\".\"AUDIT_EVENTS\"(\"TIMESTAMP\" NULLS FIRST); \n"
|
||||||
|
+ "CREATE INDEX \"PUBLIC\".\"IDX_AUDIT_PRINCIPAL\" ON \"PUBLIC\".\"AUDIT_EVENTS\"(\"PRINCIPAL\" NULLS FIRST); \n"
|
||||||
|
+ "CREATE INDEX \"PUBLIC\".\"IDX_AUDIT_TYPE\" ON \"PUBLIC\".\"AUDIT_EVENTS\"(\"TYPE\" NULLS FIRST); \n"
|
||||||
|
+ "CREATE INDEX \"PUBLIC\".\"IDX_AUDIT_PRINCIPAL_TYPE\" ON \"PUBLIC\".\"AUDIT_EVENTS\"(\"PRINCIPAL\" NULLS FIRST, \"TYPE\" NULLS FIRST); \n"
|
||||||
|
+ "CREATE INDEX \"PUBLIC\".\"IDX_AUDIT_TYPE_TIMESTAMP\" ON \"PUBLIC\".\"AUDIT_EVENTS\"(\"TYPE\" NULLS FIRST, \"TIMESTAMP\" NULLS FIRST); \n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"AUTHORITIES\"(\n"
|
||||||
|
+ " \"ID\" BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1 RESTART WITH 3) NOT NULL,\n"
|
||||||
|
+ " \"AUTHORITY\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"USER_ID\" BIGINT\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"AUTHORITIES\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_A\" PRIMARY KEY(\"ID\"); \n"
|
||||||
|
+ "-- 2 +/- SELECT COUNT(*) FROM PUBLIC.AUTHORITIES; \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"AUTHORITIES\"(\"ID\", \"AUTHORITY\", \"USER_ID\") VALUES(1, 'ROLE_ADMIN', 1); \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"AUTHORITIES\"(\"ID\", \"AUTHORITY\", \"USER_ID\") VALUES(2, 'STIRLING-PDF-BACKEND-API-USER', 2);\n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"INVITE_TOKENS\"(\n"
|
||||||
|
+ " \"ID\" BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL,\n"
|
||||||
|
+ " \"CREATED_AT\" TIMESTAMP(6),\n"
|
||||||
|
+ " \"CREATED_BY\" CHARACTER VARYING(255) NOT NULL,\n"
|
||||||
|
+ " \"EMAIL\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"EXPIRES_AT\" TIMESTAMP(6) NOT NULL,\n"
|
||||||
|
+ " \"ROLE\" CHARACTER VARYING(50) NOT NULL,\n"
|
||||||
|
+ " \"TEAM_ID\" BIGINT,\n"
|
||||||
|
+ " \"TOKEN\" CHARACTER VARYING(100) NOT NULL,\n"
|
||||||
|
+ " \"USED\" BOOLEAN NOT NULL,\n"
|
||||||
|
+ " \"USED_AT\" TIMESTAMP(6)\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"INVITE_TOKENS\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_E\" PRIMARY KEY(\"ID\"); \n"
|
||||||
|
+ "-- 0 +/- SELECT COUNT(*) FROM PUBLIC.INVITE_TOKENS; \n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"PERSISTENT_LOGINS\"(\n"
|
||||||
|
+ " \"SERIES\" CHARACTER VARYING(255) NOT NULL,\n"
|
||||||
|
+ " \"LAST_USED\" TIMESTAMP(6) WITH TIME ZONE NOT NULL,\n"
|
||||||
|
+ " \"TOKEN\" CHARACTER VARYING(64) NOT NULL,\n"
|
||||||
|
+ " \"USERNAME\" CHARACTER VARYING(64) NOT NULL\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"PERSISTENT_LOGINS\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_A3\" PRIMARY KEY(\"SERIES\"); \n"
|
||||||
|
+ "-- 0 +/- SELECT COUNT(*) FROM PUBLIC.PERSISTENT_LOGINS; \n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"SESSIONS\"(\n"
|
||||||
|
+ " \"SESSION_ID\" CHARACTER VARYING(255) NOT NULL,\n"
|
||||||
|
+ " \"EXPIRED\" BOOLEAN NOT NULL,\n"
|
||||||
|
+ " \"LAST_REQUEST\" TIMESTAMP(6) WITH TIME ZONE,\n"
|
||||||
|
+ " \"PRINCIPAL_NAME\" CHARACTER VARYING(255)\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"SESSIONS\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_8\" PRIMARY KEY(\"SESSION_ID\"); \n"
|
||||||
|
+ "-- 0 +/- SELECT COUNT(*) FROM PUBLIC.SESSIONS; \n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"TEAMS\"(\n"
|
||||||
|
+ " \"TEAM_ID\" BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1 RESTART WITH 3) NOT NULL,\n"
|
||||||
|
+ " \"NAME\" CHARACTER VARYING(255) NOT NULL\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"TEAMS\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_4\" PRIMARY KEY(\"TEAM_ID\"); \n"
|
||||||
|
+ "-- 2 +/- SELECT COUNT(*) FROM PUBLIC.TEAMS; \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"TEAMS\"(\"TEAM_ID\", \"NAME\") VALUES(1, 'Default'); \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"TEAMS\"(\"TEAM_ID\", \"NAME\") VALUES(2, 'Internal'); \n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"USER_LICENSE_SETTINGS\"(\n"
|
||||||
|
+ " \"ID\" BIGINT NOT NULL,\n"
|
||||||
|
+ " \"GRANDFATHERED_USER_COUNT\" INTEGER NOT NULL,\n"
|
||||||
|
+ " \"GRANDFATHERED_USER_SIGNATURE\" CHARACTER VARYING(256) NOT NULL,\n"
|
||||||
|
+ " \"GRANDFATHERING_LOCKED\" BOOLEAN NOT NULL,\n"
|
||||||
|
+ " \"INTEGRITY_SALT\" CHARACTER VARYING(64) NOT NULL,\n"
|
||||||
|
+ " \"LICENSE_MAX_USERS\" INTEGER NOT NULL\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"USER_LICENSE_SETTINGS\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_9\" PRIMARY KEY(\"ID\"); \n"
|
||||||
|
+ "-- 0 +/- SELECT COUNT(*) FROM PUBLIC.USER_LICENSE_SETTINGS; \n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"USER_SETTINGS\"(\n"
|
||||||
|
+ " \"USER_ID\" BIGINT NOT NULL,\n"
|
||||||
|
+ " \"SETTING_VALUE\" CHARACTER VARYING,\n"
|
||||||
|
+ " \"SETTING_KEY\" CHARACTER VARYING(255) NOT NULL\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"USER_SETTINGS\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_9A\" PRIMARY KEY(\"USER_ID\", \"SETTING_KEY\"); \n"
|
||||||
|
+ "-- 4 +/- SELECT COUNT(*) FROM PUBLIC.USER_SETTINGS; \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"USER_SETTINGS\"(\"USER_ID\", \"SETTING_VALUE\", \"SETTING_KEY\") VALUES(1, 'false', 'mfaEnabled'); \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"USER_SETTINGS\"(\"USER_ID\", \"SETTING_VALUE\", \"SETTING_KEY\") VALUES(1, 'false', 'mfaRequired'); \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"USER_SETTINGS\"(\"USER_ID\", \"SETTING_VALUE\", \"SETTING_KEY\") VALUES(2, 'false', 'mfaEnabled'); \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"USER_SETTINGS\"(\"USER_ID\", \"SETTING_VALUE\", \"SETTING_KEY\") VALUES(2, 'false', 'mfaRequired'); \n"
|
||||||
|
+ "CREATE CACHED TABLE \"PUBLIC\".\"USERS\"(\n"
|
||||||
|
+ " \"USER_ID\" BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1 RESTART WITH 3) NOT NULL,\n"
|
||||||
|
+ " \"API_KEY\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"AUTHENTICATIONTYPE\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"CREATED_AT\" TIMESTAMP(6),\n"
|
||||||
|
+ " \"ENABLED\" BOOLEAN,\n"
|
||||||
|
+ " \"FORCE_PASSWORD_CHANGE\" BOOLEAN,\n"
|
||||||
|
+ " \"HAS_COMPLETED_INITIAL_SETUP\" BOOLEAN,\n"
|
||||||
|
+ " \"IS_FIRST_LOGIN\" BOOLEAN,\n"
|
||||||
|
+ " \"OAUTH_GRANDFATHERED\" BOOLEAN,\n"
|
||||||
|
+ " \"PASSWORD\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"ROLE_NAME\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"SSO_PROVIDER\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"SSO_PROVIDER_ID\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"UPDATED_AT\" TIMESTAMP(6),\n"
|
||||||
|
+ " \"USERNAME\" CHARACTER VARYING(255),\n"
|
||||||
|
+ " \"TEAM_ID\" BIGINT\n"
|
||||||
|
+ "); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"USERS\" ADD CONSTRAINT \"PUBLIC\".\"CONSTRAINT_4D\" PRIMARY KEY(\"USER_ID\"); \n"
|
||||||
|
+ "-- 2 +/- SELECT COUNT(*) FROM PUBLIC.USERS; \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"USERS\"(\"USER_ID\", \"API_KEY\", \"AUTHENTICATIONTYPE\", \"CREATED_AT\", \"ENABLED\", \"FORCE_PASSWORD_CHANGE\", \"HAS_COMPLETED_INITIAL_SETUP\", \"IS_FIRST_LOGIN\", \"OAUTH_GRANDFATHERED\", \"PASSWORD\", \"ROLE_NAME\", \"SSO_PROVIDER\", \"SSO_PROVIDER_ID\", \"UPDATED_AT\", \"USERNAME\", \"TEAM_ID\") VALUES(1, NULL, 'web', TIMESTAMP '2026-02-26 00:25:03.688329', TRUE, FALSE, FALSE, FALSE, FALSE, '$2a$10$k9mF3xL6pD8nB2v5rT1wSuZqJ4kP7mH8gN5aY3bX9cW2eR6fD9sY1', NULL, NULL, NULL, TIMESTAMP '2026-02-26 00:25:03.688365', 'ludy', 1); \n"
|
||||||
|
+ "INSERT INTO \"PUBLIC\".\"USERS\"(\"USER_ID\", \"API_KEY\", \"AUTHENTICATIONTYPE\", \"CREATED_AT\", \"ENABLED\", \"FORCE_PASSWORD_CHANGE\", \"HAS_COMPLETED_INITIAL_SETUP\", \"IS_FIRST_LOGIN\", \"OAUTH_GRANDFATHERED\", \"PASSWORD\", \"ROLE_NAME\", \"SSO_PROVIDER\", \"SSO_PROVIDER_ID\", \"UPDATED_AT\", \"USERNAME\", \"TEAM_ID\") VALUES(2, 'e3c7f1a9-6b2d-4f5e-8c3a-9d1b7e4f2c6a', 'web', TIMESTAMP '2026-02-26 00:25:03.845308', TRUE, FALSE, FALSE, FALSE, FALSE, '$2a$10$m7pB4qL9tF2jW5hX8vR3nUYsK1dE6cG9oP0jM3iC8lA7nZ4fT9xR2', NULL, NULL, NULL, TIMESTAMP '2026-02-26 00:25:03.914916', 'STIRLING-PDF-BACKEND-API-USER', 2); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"USERS\" ADD CONSTRAINT \"PUBLIC\".\"UKR43AF9AP4EDM43MMTQ01ODDJ6\" UNIQUE NULLS DISTINCT (\"USERNAME\"); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"TEAMS\" ADD CONSTRAINT \"PUBLIC\".\"UKA510NO6SJWQCX153YD5SM4JRR\" UNIQUE NULLS DISTINCT (\"NAME\"); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"INVITE_TOKENS\" ADD CONSTRAINT \"PUBLIC\".\"UKEWCI50C0NCFIIHR2TC41NFBNF\" UNIQUE NULLS DISTINCT (\"TOKEN\"); \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"AUTHORITIES\" ADD CONSTRAINT \"PUBLIC\".\"FKK91UPMBUEYIM93V469WJ7B2QH\" FOREIGN KEY(\"USER_ID\") REFERENCES \"PUBLIC\".\"USERS\"(\"USER_ID\") NOCHECK;\n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"USER_SETTINGS\" ADD CONSTRAINT \"PUBLIC\".\"FK8V82NJ88RMAI0NYCK19F873DW\" FOREIGN KEY(\"USER_ID\") REFERENCES \"PUBLIC\".\"USERS\"(\"USER_ID\") NOCHECK; \n"
|
||||||
|
+ "ALTER TABLE \"PUBLIC\".\"USERS\" ADD CONSTRAINT \"PUBLIC\".\"FKFJWS1RDRUAB2BQG7QIPOQF65R\" FOREIGN KEY(\"TEAM_ID\") REFERENCES \"PUBLIC\".\"TEAMS\"(\"TEAM_ID\") NOCHECK; \n"
|
||||||
|
+ "";
|
||||||
|
|
||||||
|
Path script = Files.createTempFile("backup", ".sql");
|
||||||
|
Files.writeString(script, sqlContent);
|
||||||
|
|
||||||
|
boolean result = databaseService.importDatabaseFromUI(script);
|
||||||
|
assertThat(result).isTrue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -26,7 +26,7 @@ ext {
|
|||||||
lombokVersion = "1.18.42"
|
lombokVersion = "1.18.42"
|
||||||
bouncycastleVersion = "1.83"
|
bouncycastleVersion = "1.83"
|
||||||
springSecuritySamlVersion = "7.0.2"
|
springSecuritySamlVersion = "7.0.2"
|
||||||
openSamlVersion = "4.3.2"
|
openSamlVersion = "5.2.1"
|
||||||
commonmarkVersion = "0.27.1"
|
commonmarkVersion = "0.27.1"
|
||||||
googleJavaFormatVersion = "1.34.1"
|
googleJavaFormatVersion = "1.34.1"
|
||||||
logback = "1.5.32"
|
logback = "1.5.32"
|
||||||
@@ -176,6 +176,7 @@ subprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
maven { url = "https://build.shibboleth.net/maven/releases" }
|
maven { url = "https://build.shibboleth.net/maven/releases" }
|
||||||
|
maven { url = "https://repository.jboss.org/" }
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user