Revert "Revert "CB-1467 fix: properly persist preconfigured values into runtime config.""

This reverts commit 8796e04ff6.
This commit is contained in:
Nikita Makarov
2021-12-13 11:27:37 +03:00
parent 8eaa494660
commit 0380824a12
5 changed files with 258 additions and 78 deletions
@@ -226,6 +226,11 @@ public class CBAppConfig {
return plugins;
}
public void setPlugins(@NotNull Map<String, Object> plugins) {
this.plugins.clear();
this.plugins.putAll(plugins);
}
public Map<String, Object> getPluginConfig(@NotNull String pluginId) {
return getPluginConfig(pluginId, false);
}
@@ -284,6 +289,13 @@ public class CBAppConfig {
}
}
public void setAuthProvidersConfiguration(@NotNull Map<String, AuthProviderConfig> authProviders) {
synchronized (authConfiguration) {
authConfiguration.clear();
authConfiguration.putAll(authProviders);
}
}
public boolean deleteAuthProviderConfiguration(@NotNull String id) {
synchronized (authConfiguration) {
return authConfiguration.remove(id) != null;
@@ -23,6 +23,7 @@ import com.google.gson.stream.JsonWriter;
import io.cloudbeaver.DBWConnectionGrant;
import io.cloudbeaver.DBWSecurityController;
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.auth.provider.AuthProviderConfig;
import io.cloudbeaver.model.session.WebAuthInfo;
import io.cloudbeaver.registry.WebServiceRegistry;
import io.cloudbeaver.server.jetty.CBJettyServer;
@@ -173,7 +174,7 @@ public class CBApplication extends BaseApplicationImpl {
String[] args = Platform.getCommandLineArgs();
for (int i = 0; i < args.length; i++) {
if (args[i].equals(CBConstants.CLI_PARAM_WEB_CONFIG) & args.length > i + 1) {
if (args[i].equals(CBConstants.CLI_PARAM_WEB_CONFIG) && args.length > i + 1) {
configPath = args[i + 1];
break;
}
@@ -302,6 +303,7 @@ public class CBApplication extends BaseApplicationImpl {
/**
* Configures server automatically.
* Called on startup
*
* @param configPath
*/
protected void performAutoConfiguration(File configPath) {
@@ -368,7 +370,7 @@ public class CBApplication extends BaseApplicationImpl {
}
boolean hasLoopbackAddress = false;
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress localInetAddress = enumIpAddr.nextElement();
@@ -487,26 +489,40 @@ public class CBApplication extends BaseApplicationImpl {
develMode = JSONUtils.getBoolean(serverConfig, CBConstants.PARAM_DEVEL_MODE, develMode);
// App config
gson.fromJson(
gson.toJsonTree(JSONUtils.getObject(configProps, "app")), CBAppConfig.class);
Map<String, Object> appConfig = JSONUtils.getObject(configProps, "app");
gson.fromJson(gson.toJsonTree(appConfig), CBAppConfig.class);
// Database config
gson.fromJson(
gson.toJsonTree(JSONUtils.getObject(serverConfig, "database")), CBDatabaseConfig.class);
Map<String, Object> databaseConfig = JSONUtils.getObject(serverConfig, CBDatabase.PARAM_DB_CONFIGURATION);
gson.fromJson(gson.toJsonTree(databaseConfig), CBDatabaseConfig.class);
productConfigPath = getRelativePath(
JSONUtils.getString(serverConfig, CBConstants.PARAM_PRODUCT_CONFIGURATION, CBConstants.DEFAULT_PRODUCT_CONFIGURATION), homeFolder);
JSONUtils.getString(
serverConfig,
CBConstants.PARAM_PRODUCT_CONFIGURATION,
CBConstants.DEFAULT_PRODUCT_CONFIGURATION
),
homeFolder
);
} catch (IOException e) {
log.error("Error parsing server configuration", e);
}
// Merge new config with old one
{
Map<String, Object> mergedPlugins = Stream.concat(prevConfig.getPlugins().entrySet().stream(),
appConfiguration.getPlugins().entrySet().stream()).collect(
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (o, o2) -> o2));
appConfiguration.getPlugins().clear();
appConfiguration.getPlugins().putAll(mergedPlugins);
Map<String, Object> mergedPlugins = Stream.concat(
prevConfig.getPlugins().entrySet().stream(),
appConfiguration.getPlugins().entrySet().stream()
)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (o, o2) -> o2));
appConfiguration.setPlugins(mergedPlugins);
Map<String, AuthProviderConfig> mergedAuthProviders = Stream.concat(
prevConfig.getAuthProviderConfigurations().entrySet().stream(),
appConfiguration.getAuthProviderConfigurations().entrySet().stream()
)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (o, o2) -> o2));
appConfiguration.setAuthProvidersConfiguration(mergedAuthProviders);
}
if (!CommonUtils.isEmpty(productConfigPath)) {
@@ -605,8 +621,7 @@ public class CBApplication extends BaseApplicationImpl {
@Nullable String adminPassword,
@NotNull List<WebAuthInfo> authInfoList,
long sessionExpireTime,
@NotNull CBAppConfig appConfig) throws DBException
{
@NotNull CBAppConfig appConfig) throws DBException {
if (!RECONFIGURATION_ALLOWED && !isConfigurationMode()) {
throw new DBException("Application must be in configuration mode");
}
@@ -653,7 +668,7 @@ public class CBApplication extends BaseApplicationImpl {
if (ArrayUtils.isEmpty(grants)) {
securityController.setConnectionSubjectAccess(
ds.getId(),
new String[] { anonymousRoleId },
new String[]{anonymousRoleId},
adminName);
}
}
@@ -662,8 +677,10 @@ public class CBApplication extends BaseApplicationImpl {
}
}
private void saveRuntimeConfig(String newServerName, String newServerURL, long sessionExpireTime, CBAppConfig appConfig) throws DBException {
private void saveRuntimeConfig(String newServerName,
String newServerURL,
long sessionExpireTime,
CBAppConfig appConfig) throws DBException {
File runtimeConfigFile = getRuntimeAppConfigFile();
try (Writer out = new OutputStreamWriter(new FileOutputStream(runtimeConfigFile), StandardCharsets.UTF_8)) {
Gson gson = new GsonBuilder()
@@ -673,71 +690,24 @@ public class CBApplication extends BaseApplicationImpl {
try (JsonWriter json = gson.newJsonWriter(out)) {
json.setLenient(true);
json.beginObject();
{
json.name("server");
json.beginObject();
if (!CommonUtils.isEmpty(newServerName)) {
JSONUtils.field(json, CBConstants.PARAM_SERVER_NAME, newServerName);
}
if (!CommonUtils.isEmpty(newServerURL)) {
JSONUtils.field(json, CBConstants.PARAM_SERVER_URL, newServerURL);
}
if (sessionExpireTime > 0) {
JSONUtils.field(json, CBConstants.PARAM_SESSION_EXPIRE_PERIOD, sessionExpireTime);
}
json.endObject();
Map<String, Object> serverMap = ConfigurationUtils.serverConfigToMap(
newServerName,
newServerURL,
sessionExpireTime,
databaseConfiguration
);
if (!CommonUtils.isEmpty(serverMap)) {
JSONUtils.serializeProperties(json, "server", serverMap);
}
{
json.name("app");
json.beginObject();
JSONUtils.field(json, "anonymousAccessEnabled", appConfig.isAnonymousAccessEnabled());
JSONUtils.field(json, "supportsCustomConnections", appConfig.isSupportsCustomConnections());
JSONUtils.field(json, "publicCredentialsSaveEnabled", appConfig.isPublicCredentialsSaveEnabled());
JSONUtils.field(json, "adminCredentialsSaveEnabled", appConfig.isAdminCredentialsSaveEnabled());
{
// Save only differences in def navigator settings
DBNBrowseSettings navSettings = appConfig.getDefaultNavigatorSettings();
json.name("defaultNavigatorSettings");
json.beginObject();
if (navSettings.isShowSystemObjects() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isShowSystemObjects())
JSONUtils.field(json, "showSystemObjects", navSettings.isShowSystemObjects());
if (navSettings.isShowUtilityObjects() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isShowUtilityObjects())
JSONUtils.field(json, "showUtilityObjects", navSettings.isShowUtilityObjects());
if (navSettings.isShowOnlyEntities() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isShowOnlyEntities())
JSONUtils.field(json, "showOnlyEntities", navSettings.isShowOnlyEntities());
if (navSettings.isMergeEntities() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isMergeEntities())
JSONUtils.field(json, "mergeEntities", navSettings.isMergeEntities());
if (navSettings.isHideFolders() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isHideFolders())
JSONUtils.field(json, "hideFolders", navSettings.isHideFolders());
if (navSettings.isHideSchemas() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isHideSchemas())
JSONUtils.field(json, "hideSchemas", navSettings.isHideSchemas());
if (navSettings.isHideVirtualModel() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isHideVirtualModel())
JSONUtils.field(json, "hideVirtualModel", navSettings.isHideVirtualModel());
json.endObject();
}
if (appConfig.getEnabledFeatures() != null) {
JSONUtils.serializeStringList(json, "enabledFeatures", Arrays.asList(appConfig.getEnabledFeatures()), true);
}
if (appConfig.getEnabledAuthProviders() != null) {
JSONUtils.serializeStringList(json, "enabledAuthProviders", Arrays.asList(appConfig.getEnabledAuthProviders()), true);
}
if (!CommonUtils.isEmpty(appConfig.getPlugins())) {
JSONUtils.serializeProperties(json, "plugins", appConfig.getPlugins());
}
if (!CommonUtils.isEmpty(appConfig.getAuthProviderConfigurations())) {
json.name("authConfiguration");
gson.toJson(appConfig.getAuthProviderConfigurations(), Map.class, json);
}
json.endObject();
Map<String, Object> appMap = ConfigurationUtils.appConfigToMap(appConfig);
if (!CommonUtils.isEmpty(appMap)) {
JSONUtils.serializeProperties(json, "app", appMap);
}
json.endObject();
}
} catch (IOException e) {
throw new DBException("Error writing runtime configuration", e);
}
@@ -45,6 +45,8 @@ public class CBConstants {
public static final String PARAM_DRIVERS_LOCATION = "driversLocation";
public static final String PARAM_WORKSPACE_LOCATION = "workspaceLocation";
public static final String PARAM_PRODUCT_CONFIGURATION = "productConfiguration";
public static final String PARAM_RESOURCE_QUOTAS = "resourceQuotas";
public static final String PARAM_AUTH_PROVIDERS = "authConfiguration";
public static final String PARAM_SESSION_EXPIRE_PERIOD = "expireSessionAfterPeriod";
@@ -82,5 +84,5 @@ public class CBConstants {
public static final String CB_SESSION_COOKIE_NAME = "cb-session-id";
public static final String APPLICATION_JSON = "application/json";
public static final String APPLICATION_JSON = "application/json";
}
@@ -72,6 +72,20 @@ public class CBDatabase {
private static final String DEFAULT_DB_USER_NAME = "cb-data";
private static final String DEFAULT_DB_PWD_FILE = ".database-credentials.dat";
static final String PARAM_DB_CONFIGURATION = "database";
static final String PARAM_DB_DRIVER_CONFIGURATION = "driver";
static final String PARAM_DB_URL_CONFIGURATION = "url";
static final String PARAM_DB_USER_CONFIGURATION = "user";
static final String PARAM_DB_PW_CONFIGURATION = "password";
static final String PARAM_DB_CREATE_DATABASE_CONFIGURATION = "createDatabase";
static final String PARAM_DB_ALLOW_PUBLIC_ACCESS_CONFIGURATION = "allowPublicAccess";
static final String PARAM_DB_INITIAL_DATA_CONFIGURATION_CONFIGURATION = "initialDataConfiguration";
static final String PARAM_DB_POOL_CONFIGURATION = "pool";
static final String PARAM_DB_POOL_MIN_IDLE_CONNECTIONS_CONFIGURATION = "minIdleConnections";
static final String PARAM_DB_POOL_MAX_IDLE_CONNECTIONS_CONFIGURATION = "maxIdleConnections";
static final String PARAM_DB_POOL_MAX_CONNECTIONS_CONFIGURATION = "maxConnections";
static final String PARAM_DB_POOL_VALIDATION_QUERY_CONFIGURATION = "validationQuery";
private final CBApplication application;
private final CBDatabaseConfig databaseConfiguration;
private PoolingDataSource<PoolableConnection> cbDataSource;
@@ -0,0 +1,182 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudbeaver.server;
import io.cloudbeaver.auth.provider.AuthProviderConfig;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.data.json.JSONUtils;
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
import org.jkiss.utils.CommonUtils;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
public class ConfigurationUtils {
private static final Log log = Log.getLog(JSONUtils.class);
private ConfigurationUtils() {
}
public static Map<String, Object> appConfigToMap(@Nullable CBAppConfig appConfig) {
Map<String, Object> res = new LinkedHashMap<>();
if (appConfig == null) {
return res;
}
res.put("anonymousAccessEnabled", appConfig.isAnonymousAccessEnabled());
res.put("supportsCustomConnections", appConfig.isSupportsCustomConnections());
res.put("publicCredentialsSaveEnabled", appConfig.isPublicCredentialsSaveEnabled());
res.put("adminCredentialsSaveEnabled", appConfig.isAdminCredentialsSaveEnabled());
Map<String, Object> resourceQuotas = appConfig.getResourceQuotas();
if (!CommonUtils.isEmpty(resourceQuotas)) {
res.put(CBConstants.PARAM_RESOURCE_QUOTAS, resourceQuotas);
}
Map<String, AuthProviderConfig> authProviders = appConfig.getAuthProviderConfigurations();
if (!CommonUtils.isEmpty(authProviders)) {
res.put(CBConstants.PARAM_AUTH_PROVIDERS, authProviders);
}
Map<String, Object> navSettingsMap = ConfigurationUtils.defaultNavigatorSettingsConfigToMap(
appConfig.getDefaultNavigatorSettings()
);
if (!CommonUtils.isEmpty(navSettingsMap)) {
res.put("defaultNavigatorSettings", navSettingsMap);
}
if (appConfig.getEnabledFeatures() != null) {
res.put("enabledFeatures", Arrays.asList(appConfig.getEnabledFeatures()));
}
if (appConfig.getEnabledAuthProviders() != null) {
res.put("enabledAuthProviders", Arrays.asList(appConfig.getEnabledAuthProviders()));
}
if (!CommonUtils.isEmpty(appConfig.getPlugins())) {
res.put("plugins", appConfig.getPlugins());
}
return res;
}
public static Map<String, Object> defaultNavigatorSettingsConfigToMap(@Nullable DBNBrowseSettings navSettings) {
Map<String, Object> res = new LinkedHashMap<>();
if (navSettings == null) {
return res;
}
// Save only differences in def navigator settings
if (navSettings.isShowSystemObjects() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isShowSystemObjects()) {
res.put("showSystemObjects", navSettings.isShowSystemObjects());
}
if (navSettings.isShowUtilityObjects() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isShowUtilityObjects()) {
res.put("showUtilityObjects", navSettings.isShowUtilityObjects());
}
if (navSettings.isShowOnlyEntities() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isShowOnlyEntities()) {
res.put("showOnlyEntities", navSettings.isShowOnlyEntities());
}
if (navSettings.isMergeEntities() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isMergeEntities()) {
res.put("mergeEntities", navSettings.isMergeEntities());
}
if (navSettings.isHideFolders() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isHideFolders()) {
res.put("hideFolders", navSettings.isHideFolders());
}
if (navSettings.isHideSchemas() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isHideSchemas()) {
res.put("hideSchemas", navSettings.isHideSchemas());
}
if (navSettings.isHideVirtualModel() != CBAppConfig.DEFAULT_VIEW_SETTINGS.isHideVirtualModel()) {
res.put("hideVirtualModel", navSettings.isHideVirtualModel());
}
return res;
}
public static Map<String, Object> serverConfigToMap(String newServerName,
String newServerURL,
long sessionExpireTime,
CBDatabaseConfig databaseConfiguration) {
Map<String, Object> serverMap = new LinkedHashMap<>();
if (!CommonUtils.isEmpty(newServerName)) {
serverMap.put(CBConstants.PARAM_SERVER_NAME, newServerName);
}
if (!CommonUtils.isEmpty(newServerURL)) {
serverMap.put(CBConstants.PARAM_SERVER_URL, newServerURL);
}
if (sessionExpireTime > 0) {
serverMap.put(CBConstants.PARAM_SESSION_EXPIRE_PERIOD, sessionExpireTime);
}
Map<String, Object> dbMap = ConfigurationUtils.databaseConfigToMap(databaseConfiguration);
if (!CommonUtils.isEmpty(dbMap)) {
serverMap.put(CBDatabase.PARAM_DB_CONFIGURATION, dbMap);
}
return serverMap;
}
public static Map<String, Object> databaseConfigToMap(@Nullable CBDatabaseConfig databaseConfiguration) {
Map<String, Object> res = new LinkedHashMap<>();
if (databaseConfiguration == null) {
return res;
}
res.computeIfAbsent(
CBDatabase.PARAM_DB_DRIVER_CONFIGURATION,
v -> databaseConfiguration.getDriver()
);
res.computeIfAbsent(
CBDatabase.PARAM_DB_URL_CONFIGURATION,
v -> databaseConfiguration.getUrl()
);
res.computeIfAbsent(
CBDatabase.PARAM_DB_USER_CONFIGURATION,
v -> databaseConfiguration.getUser()
);
res.computeIfAbsent(
CBDatabase.PARAM_DB_PW_CONFIGURATION,
v -> databaseConfiguration.getPassword()
);
res.put(CBDatabase.PARAM_DB_CREATE_DATABASE_CONFIGURATION, databaseConfiguration.isCreateDatabase());
res.put(CBDatabase.PARAM_DB_ALLOW_PUBLIC_ACCESS_CONFIGURATION, databaseConfiguration.isAllowPublicAccess());
res.computeIfAbsent(
CBDatabase.PARAM_DB_INITIAL_DATA_CONFIGURATION_CONFIGURATION,
v -> databaseConfiguration.getInitialDataConfiguration()
);
Map<String, Object> poolMap = ConfigurationUtils.poolDatabaseConfigToMap(databaseConfiguration);
if (!CommonUtils.isEmpty(poolMap)) {
res.put(CBDatabase.PARAM_DB_POOL_CONFIGURATION, poolMap);
}
return res;
}
public static Map<String, Object> poolDatabaseConfigToMap(@Nullable CBDatabaseConfig databaseConfiguration) {
Map<String, Object> res = new LinkedHashMap<>();
if (databaseConfiguration == null) {
return res;
}
CBDatabaseConfig.Pool pool = databaseConfiguration.getPool();
if (pool == null) {
return res;
} else {
res.put(CBDatabase.PARAM_DB_POOL_MIN_IDLE_CONNECTIONS_CONFIGURATION, pool.getMinIdleConnections());
res.put(CBDatabase.PARAM_DB_POOL_MAX_IDLE_CONNECTIONS_CONFIGURATION, pool.getMaxIdleConnections());
res.put(CBDatabase.PARAM_DB_POOL_MAX_CONNECTIONS_CONFIGURATION, pool.getMaxConnections());
res.computeIfAbsent(
CBDatabase.PARAM_DB_POOL_VALIDATION_QUERY_CONFIGURATION,
v -> pool.getValidationQuery()
);
}
return res;
}
}