diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/utils/WebAppUtils.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/utils/WebAppUtils.java index 8f1ecf3442..b9af9a72cc 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/utils/WebAppUtils.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/utils/WebAppUtils.java @@ -27,6 +27,7 @@ import org.jkiss.dbeaver.model.app.DBPProject; import org.jkiss.dbeaver.model.auth.SMAuthenticationManager; import org.jkiss.dbeaver.model.rm.RMProjectType; import org.jkiss.dbeaver.runtime.DBWorkbench; +import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.utils.CommonUtils; import javax.servlet.http.Cookie; @@ -92,6 +93,47 @@ public class WebAppUtils { return resultConfig; } + @SuppressWarnings("unchecked") + public static Map mergeConfigurationsWithVariables(Map origin, Map additional) { + var resultConfig = new HashMap(); + Set rootKeys = new HashSet<>(additional.keySet()); + + for (var rootKey : rootKeys) { + var originValue = origin.get(rootKey); + var additionalValue = additional.get(rootKey); + + if (additionalValue == null) { + continue; + } + + if (originValue instanceof Map) { + var resultValue = mergeConfigurationsWithVariables((Map) originValue, (Map) additionalValue); + resultConfig.put(rootKey, resultValue); + } else { + resultConfig.put(rootKey, getExtractedValue(originValue, additionalValue)); + } + + } + + return resultConfig; + } + + public static Object getExtractedValue(Object oldValue, Object newValue) { + if (!(oldValue instanceof String)) { + return newValue; + } + String value = (String) oldValue; + if (!GeneralUtils.isVariablePattern(value)) { + return newValue; + } + String extractedVariable = GeneralUtils.extractVariableName(value); + if (extractedVariable != null) { + return GeneralUtils.variablePattern(extractedVariable + ":" + newValue); + } else { + return newValue; + } + } + @NotNull public static String removeSideSlashes(String action) { diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java index 32028cfbcb..7682ae1a2f 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java @@ -218,12 +218,16 @@ public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthC } public T getResourceQuota(String quotaId) { - return (T) resourceQuotas.get(quotaId); + Object quota = resourceQuotas.get(quotaId); + if (quota instanceof String) { + quota = CommonUtils.toDouble(quota); + } + return (T) quota; } public T getResourceQuota(String quotaId, T defaultValue) { if (resourceQuotas.containsKey(quotaId)) { - return (T) resourceQuotas.get(quotaId); + return (T) getResourceQuota(quotaId); } else { return defaultValue; } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java index a3fea9cd20..c2f012aa40 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java @@ -112,6 +112,7 @@ public class CBApplication extends BaseWebApplication implements WebAuthApplicat protected final Map databaseConfiguration = new HashMap<>(); private final CBAppConfig appConfiguration = new CBAppConfig(); private Map externalProperties = new LinkedHashMap<>(); + private Map originalConfigurationProperties = new LinkedHashMap<>(); // Persistence private SMAdminController securityController; @@ -650,13 +651,11 @@ public class CBApplication extends BaseWebApplication implements WebAuthApplicat Map configProps = new LinkedHashMap<>(); if (configFile.exists()) { log.debug("Read configuration [" + configFile.getAbsolutePath() + "]"); - try (Reader reader = new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8)) { - configProps.putAll(JSONUtils.parseMap(getGson(), reader)); - patchConfigurationWithProperties(configProps); // patch original properties + // saves original configuration file + this.originalConfigurationProperties.putAll(readConfigurationFile(configFile)); - } catch (IOException e) { - throw new DBException("Error parsing server configuration", e); - } + configProps.putAll(readConfigurationFile(configFile)); + patchConfigurationWithProperties(configProps); // patch original properties } readAdditionalConfiguration(configProps); @@ -682,6 +681,14 @@ public class CBApplication extends BaseWebApplication implements WebAuthApplicat return configProps; } + public Map readConfigurationFile(File configFile) throws DBException { + try (Reader reader = new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8)) { + return JSONUtils.parseMap(getGson(), reader); + } catch (IOException e) { + throw new DBException("Error parsing server configuration", e); + } + } + private Gson getGson() { // Stupid way to populate existing objects but ok google (https://github.com/google/gson/issues/431) InstanceCreator appConfigCreator = type -> appConfiguration; @@ -875,36 +882,57 @@ public class CBApplication extends BaseWebApplication implements WebAuthApplicat Map rootConfig = new LinkedHashMap<>(); { var serverConfigProperties = new LinkedHashMap(); + var originServerConfig = getServerConfigProps(this.originalConfigurationProperties); // get server properties from original configuration file rootConfig.put("server", serverConfigProperties); if (!CommonUtils.isEmpty(newServerName)) { - serverConfigProperties.put(CBConstants.PARAM_SERVER_NAME, newServerName); + copyConfigValue(originServerConfig, serverConfigProperties, CBConstants.PARAM_SERVER_NAME, newServerName); } if (!CommonUtils.isEmpty(newServerURL)) { - serverConfigProperties.put(CBConstants.PARAM_SERVER_URL, newServerURL); + copyConfigValue( + originServerConfig, serverConfigProperties, CBConstants.PARAM_SERVER_URL, newServerURL); } if (sessionExpireTime > 0) { - serverConfigProperties.put(CBConstants.PARAM_SESSION_EXPIRE_PERIOD, sessionExpireTime); + copyConfigValue( + originServerConfig, serverConfigProperties, CBConstants.PARAM_SESSION_EXPIRE_PERIOD, sessionExpireTime); } - + var databaseConfigProperties = new LinkedHashMap(); + Map oldRuntimeDBConfig = JSONUtils.getObject(originServerConfig, CBConstants.PARAM_DB_CONFIGURATION); if (!CommonUtils.isEmpty(databaseConfiguration)) { - serverConfigProperties.put(CBConstants.PARAM_DB_CONFIGURATION, databaseConfiguration); + for (Map.Entry mp : databaseConfiguration.entrySet()) { + copyConfigValue(oldRuntimeDBConfig, databaseConfigProperties, mp.getKey(), mp.getValue()); + } + serverConfigProperties.put(CBConstants.PARAM_DB_CONFIGURATION, databaseConfigProperties); } } { var appConfigProperties = new LinkedHashMap(); + Map oldAppConfig = JSONUtils.getObject(this.originalConfigurationProperties, "app"); rootConfig.put("app", appConfigProperties); - appConfigProperties.put("anonymousAccessEnabled", appConfig.isAnonymousAccessEnabled()); - appConfigProperties.put("supportsCustomConnections", appConfig.isSupportsCustomConnections()); - appConfigProperties.put("publicCredentialsSaveEnabled", appConfig.isPublicCredentialsSaveEnabled()); - appConfigProperties.put("adminCredentialsSaveEnabled", appConfig.isAdminCredentialsSaveEnabled()); - appConfigProperties.put("enableReverseProxyAuth", appConfig.isEnabledReverseProxyAuth()); - appConfigProperties.put("forwardProxy", appConfig.isEnabledForwardProxy()); - appConfigProperties.put("linkExternalCredentialsWithUser", appConfig.isLinkExternalCredentialsWithUser()); - appConfigProperties.put("redirectOnFederatedAuth", appConfig.isRedirectOnFederatedAuth()); - appConfigProperties.put(CBConstants.PARAM_RESOURCE_MANAGER_ENABLED, appConfig.isResourceManagerEnabled()); + copyConfigValue( + oldAppConfig, appConfigProperties, "anonymousAccessEnabled", appConfig.isAnonymousAccessEnabled()); + copyConfigValue( + oldAppConfig, appConfigProperties, "supportsCustomConnections", appConfig.isSupportsCustomConnections()); + copyConfigValue( + oldAppConfig, appConfigProperties, "publicCredentialsSaveEnabled", appConfig.isPublicCredentialsSaveEnabled()); + copyConfigValue( + oldAppConfig, appConfigProperties, "adminCredentialsSaveEnabled", appConfig.isAdminCredentialsSaveEnabled()); + copyConfigValue( + oldAppConfig, appConfigProperties, "enableReverseProxyAuth", appConfig.isEnabledReverseProxyAuth()); + copyConfigValue( + oldAppConfig, appConfigProperties, "forwardProxy", appConfig.isEnabledForwardProxy()); + copyConfigValue( + oldAppConfig, appConfigProperties, "linkExternalCredentialsWithUser", appConfig.isLinkExternalCredentialsWithUser()); + copyConfigValue( + oldAppConfig, appConfigProperties, "redirectOnFederatedAuth", appConfig.isRedirectOnFederatedAuth()); + copyConfigValue( + oldAppConfig, appConfigProperties, CBConstants.PARAM_RESOURCE_MANAGER_ENABLED, appConfig.isResourceManagerEnabled()); - Map resourceQuotas = appConfig.getResourceQuotas(); + Map resourceQuotas = new LinkedHashMap<>(); + Map originResourceQuotas = JSONUtils.getObject(oldAppConfig, CBConstants.PARAM_RESOURCE_QUOTAS); + for (Map.Entry mp : appConfig.getResourceQuotas().entrySet()) { + copyConfigValue(originResourceQuotas, resourceQuotas, mp.getKey(), mp.getValue()); + } appConfigProperties.put(CBConstants.PARAM_RESOURCE_QUOTAS, resourceQuotas); { @@ -1012,4 +1040,20 @@ public class CBApplication extends BaseWebApplication implements WebAuthApplicat public Set getAvailableAuthRoles() { return Set.of(); } + + // gets info about patterns from original configuration file and saves it to runtime config + private void copyConfigValue(Map oldConfig, Map newConfig, String key, Object defaultValue) { + Object value = oldConfig.get(key); + if (value instanceof Map && defaultValue instanceof Map) { + Map subValue = new LinkedHashMap<>(); + Map oldConfigValue = JSONUtils.getObject(oldConfig, key); + for (Map.Entry entry : oldConfigValue.entrySet()) { + copyConfigValue(oldConfigValue, subValue, entry.getKey(), ((Map) defaultValue).get(entry.getKey())); + } + newConfig.put(key, subValue); + } else { + Object newConfigValue = WebAppUtils.getExtractedValue(oldConfig.get(key), defaultValue); + newConfig.put(key, newConfigValue); + } + } }