This commit is contained in:
@@ -3,6 +3,8 @@ package com.kaidi.oa.install;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.flywaydb.core.api.output.MigrateResult;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -36,6 +38,8 @@ import java.util.Set;
|
||||
@Service
|
||||
public class InstallerService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(InstallerService.class);
|
||||
|
||||
private static final Set<PosixFilePermission> OWNER_ONLY = EnumSet.of(
|
||||
PosixFilePermission.OWNER_READ,
|
||||
PosixFilePermission.OWNER_WRITE);
|
||||
@@ -117,6 +121,11 @@ public class InstallerService {
|
||||
.load()
|
||||
.migrate();
|
||||
} catch (RuntimeException exception) {
|
||||
log.error(
|
||||
"PostgreSQL migration failed for database {} as user {}",
|
||||
request.database().database().strip(),
|
||||
request.database().username().strip(),
|
||||
exception);
|
||||
throw new InstallApiException(
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
42203,
|
||||
@@ -170,6 +179,7 @@ public class InstallerService {
|
||||
42201,
|
||||
"PostgreSQL 版本过低,需要 15 或更高版本");
|
||||
}
|
||||
requireDatabaseOwnership(connection);
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute("SELECT 1");
|
||||
statement.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm");
|
||||
@@ -181,10 +191,16 @@ public class InstallerService {
|
||||
throw new SQLException("pg_trgm is unavailable");
|
||||
}
|
||||
}
|
||||
requirePgTrgmOwnership(connection);
|
||||
return new DatabaseCheck(major, connection.getMetaData().getDatabaseProductVersion());
|
||||
} catch (InstallApiException exception) {
|
||||
throw exception;
|
||||
} catch (SQLException | NumberFormatException exception) {
|
||||
log.warn(
|
||||
"PostgreSQL verification failed for database {} as user {}: {}",
|
||||
database.database().strip(),
|
||||
database.username().strip(),
|
||||
exception.getMessage());
|
||||
throw new InstallApiException(
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
42202,
|
||||
@@ -192,6 +208,40 @@ public class InstallerService {
|
||||
}
|
||||
}
|
||||
|
||||
private void requireDatabaseOwnership(Connection connection) throws SQLException {
|
||||
try (Statement statement = connection.createStatement();
|
||||
ResultSet result = statement.executeQuery(
|
||||
"SELECT "
|
||||
+ "pg_get_userbyid(datdba) = current_user AS owns_database, "
|
||||
+ "has_schema_privilege(current_user, 'public', 'USAGE') AS can_use_schema, "
|
||||
+ "has_schema_privilege(current_user, 'public', 'CREATE') AS can_create_in_schema "
|
||||
+ "FROM pg_database WHERE datname = current_database()")) {
|
||||
if (!result.next()
|
||||
|| !result.getBoolean("owns_database")
|
||||
|| !result.getBoolean("can_use_schema")
|
||||
|| !result.getBoolean("can_create_in_schema")) {
|
||||
throw new InstallApiException(
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
42206,
|
||||
"数据库账号必须是该空数据库的所有者,并拥有 public schema 建表权限");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void requirePgTrgmOwnership(Connection connection) throws SQLException {
|
||||
try (Statement statement = connection.createStatement();
|
||||
ResultSet result = statement.executeQuery(
|
||||
"SELECT pg_get_userbyid(extowner) = current_user "
|
||||
+ "FROM pg_extension WHERE extname = 'pg_trgm'")) {
|
||||
if (!result.next() || !result.getBoolean(1)) {
|
||||
throw new InstallApiException(
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
42207,
|
||||
"数据库账号必须拥有 pg_trgm 扩展;请由管理员删除预建扩展后重新测试");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void rejectExistingInstallation(InstallRequest.Database database) {
|
||||
try (Connection connection = openConnection(database);
|
||||
PreparedStatement tableQuery = connection.prepareStatement(
|
||||
@@ -272,6 +322,11 @@ public class InstallerService {
|
||||
} catch (InstallApiException exception) {
|
||||
throw exception;
|
||||
} catch (Exception exception) {
|
||||
log.error(
|
||||
"Administrator initialization failed for database {} as user {}",
|
||||
database.database().strip(),
|
||||
database.username().strip(),
|
||||
exception);
|
||||
throw new InstallApiException(HttpStatus.UNPROCESSABLE_ENTITY, 42205, "管理员账号初始化失败");
|
||||
}
|
||||
}
|
||||
@@ -326,6 +381,8 @@ public class InstallerService {
|
||||
values.put("ERP_INSTALL_PENDING_FILE", properties.pendingFile().toAbsolutePath().normalize().toString());
|
||||
values.put("ERP_INSTALL_LOCK_FILE", properties.lockFile().toAbsolutePath().normalize().toString());
|
||||
values.put("ERP_INSTALL_OPERATION_LOCK_FILE", properties.operationLockFile().toAbsolutePath().normalize().toString());
|
||||
values.put("ERP_INSTALL_LOG_FILE", stateRoot.resolve("install-formal.log").toString());
|
||||
values.put("ERP_INSTALL_HEALTH_TIMEOUT_SECONDS", environment("ERP_INSTALL_HEALTH_TIMEOUT_SECONDS", "240"));
|
||||
values.put("ERP_SETUP_TOKEN", properties.token());
|
||||
values.put("ERP_INSTALLER_JAR", installRoot.resolve("installer/kaidi-erp-installer.jar").toString());
|
||||
values.put("ERP_JAR_PATH", installRoot.resolve("current/app/kaidi-erp.jar").toString());
|
||||
|
||||
Reference in New Issue
Block a user