diff --git a/server/bundles/io.cloudbeaver.connect.provider.sample/src/io/cloudbeaver/connect/provider/sample/SampleDataSourceConfigurationStorage.java b/server/bundles/io.cloudbeaver.connect.provider.sample/src/io/cloudbeaver/connect/provider/sample/SampleDataSourceConfigurationStorage.java index 3b80569972..c3ec2cb7e5 100644 --- a/server/bundles/io.cloudbeaver.connect.provider.sample/src/io/cloudbeaver/connect/provider/sample/SampleDataSourceConfigurationStorage.java +++ b/server/bundles/io.cloudbeaver.connect.provider.sample/src/io/cloudbeaver/connect/provider/sample/SampleDataSourceConfigurationStorage.java @@ -66,9 +66,9 @@ public class SampleDataSourceConfigurationStorage implements DBPDataSourceConfig if (sampleConfigFile.exists()) { log.debug("Loading provided connections from [" + sampleConfigFile.getFullPath().toString() + "]"); List dsList = registry.loadDataSourcesFromFile(this, sampleConfigFile); - for (DBPDataSourceContainer ds : dsList) { - log.debug("\tProvided connection: " + ds.getName()); - } +// for (DBPDataSourceContainer ds : dsList) { +// log.debug("\tProvided connection: " + ds.getName()); +// } return dsList; } } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatabaseDriverConfig.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatabaseDriverConfig.java index 7ca4561388..9782adfe43 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatabaseDriverConfig.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatabaseDriverConfig.java @@ -152,6 +152,9 @@ public class WebDatabaseDriverConfig { cfg.setHostPort(driver.getDefaultPort()); cfg.setUrl(driver.getDataSourceProvider().getConnectionURL(driver, cfg)); DBPPropertyDescriptor[] properties = driver.getDataSourceProvider().getConnectionProperties(webSession.getProgressMonitor(), driver, cfg); + if (properties == null) { + return new WebPropertyInfo[0]; + } PropertySourceCustom propertySource = new PropertySourceCustom( properties, diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/session/WebSession.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/session/WebSession.java index 78b26a2b20..3c47a6efe8 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/session/WebSession.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/session/WebSession.java @@ -73,7 +73,7 @@ public class WebSession { private String locale; private boolean cacheExpired; - private final List connections = new ArrayList<>(); + private final Map connections = new HashMap<>(); private final List progressMessages = new ArrayList<>(); private final Map asyncTasks = new HashMap<>(); @@ -83,6 +83,7 @@ public class WebSession { private DBNModel navigatorModel; private DBNProjectDatabases databases; private DBRProgressMonitor progressMonitor = new SessionProgressMonitor(); + private DBNProject projectNode; public WebSession(HttpSession httpSession) { this.id = httpSession.getId(); @@ -175,7 +176,7 @@ public class WebSession { this.navigatorModel.initialize(); DBPProject project = platform.getWorkspace().getActiveProject(); - DBNProject projectNode = this.navigatorModel.getRoot().getProjectNode(project); + this.projectNode = this.navigatorModel.getRoot().getProjectNode(project); this.databases = projectNode.getDatabases(); this.locale = Locale.getDefault().getLanguage(); @@ -184,7 +185,7 @@ public class WebSession { for (DBPDataSourceContainer ds : databases.getDataSourceRegistry().getDataSources()) { if (ds.isProvided()) { WebConnectionInfo connectionInfo = new WebConnectionInfo(this, ds); - connections.add(connectionInfo); + connections.put(connectionInfo.getId(), connectionInfo); } } } @@ -201,13 +202,13 @@ public class WebSession { attributes.clear(); } - List conCopy; + Map conCopy; synchronized (this.connections) { - conCopy = new ArrayList<>(this.connections); + conCopy = new HashMap<>(this.connections); this.connections.clear(); } - for (WebConnectionInfo connectionInfo : conCopy) { + for (WebConnectionInfo connectionInfo : conCopy.values()) { if (connectionInfo.isConnected()) { new DisconnectJob(connectionInfo.getDataSourceContainer()).schedule(); } @@ -247,7 +248,11 @@ public class WebSession { return navigatorModel; } - public DBNProjectDatabases getDatabases() { + public DBNProject getProjectNode() { + return projectNode; + } + + public DBNProjectDatabases getDatabasesNode() { return databases; } @@ -293,23 +298,26 @@ public class WebSession { @Association public List getConnections() { synchronized (connections) { - return new ArrayList<>(connections); + return new ArrayList<>(connections.values()); } } @NotNull public WebConnectionInfo getWebConnectionInfo(String connectionID) throws DBWebException { - WebConnectionInfo connectionInfo = null; + WebConnectionInfo connectionInfo; synchronized (connections) { - for (WebConnectionInfo ci : connections) { - if (ci.getId().equals(connectionID)) { - connectionInfo = ci; - break; - } - } + connectionInfo = connections.get(connectionID); } if (connectionInfo == null) { - throw new DBWebException("Connection '" + connectionID + "' not found"); + DBPDataSourceContainer dataSource = databases.getDataSourceRegistry().getDataSource(connectionID); + if (dataSource != null) { + connectionInfo = new WebConnectionInfo(this, dataSource); + synchronized (connections) { + connections.put(connectionID, connectionInfo); + } + } else { + throw new DBWebException("Connection '" + connectionID + "' not found"); + } } return connectionInfo; } @@ -317,13 +325,13 @@ public class WebSession { public void addConnection(WebConnectionInfo connectionInfo) { synchronized (connections) { - connections.add(connectionInfo); + connections.put(connectionInfo.getId(), connectionInfo); } } public void removeConnection(WebConnectionInfo connectionInfo) { synchronized (connections) { - connections.remove(connectionInfo); + connections.remove(connectionInfo.getId()); } } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java index 5dbfe65bae..7cbf858089 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java @@ -33,10 +33,10 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.DBConstants; +import org.jkiss.dbeaver.model.connection.DBPDriver; import org.jkiss.dbeaver.model.exec.DBCException; import org.jkiss.dbeaver.model.runtime.LoggingProgressMonitor; import org.jkiss.dbeaver.registry.DataSourceProviderRegistry; -import org.jkiss.dbeaver.registry.driver.DriverDescriptor; import org.jkiss.dbeaver.utils.ContentUtils; import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.dbeaver.utils.SystemVariablesResolver; @@ -82,9 +82,9 @@ public class CBDatabase { void initialize() throws DBException { if (CommonUtils.isEmpty(databaseConfiguration.getDriver())) { - throw new DBException("Database driver not specified"); + throw new DBException("No database driver configured for CloudBeaver database"); } - DriverDescriptor driver = DataSourceProviderRegistry.getInstance().findDriver(databaseConfiguration.getDriver()); + DBPDriver driver = DataSourceProviderRegistry.getInstance().findDriver(databaseConfiguration.getDriver()); if (driver == null) { throw new DBException("Driver '" + databaseConfiguration.getDriver() + "' not found"); } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java index ac28c49583..020626f844 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java @@ -155,7 +155,7 @@ public class CBPlatform extends BasePlatformImpl { continue; } List libraries = driver.getDriverLibraries(); - if (!libraries.isEmpty()) { + { boolean hasAllFiles = true; for (DBPDriverLibrary lib : libraries) { if (!lib.isOptional() && lib.getType() != DBPDriverLibrary.FileType.license && @@ -172,7 +172,7 @@ public class CBPlatform extends BasePlatformImpl { } } } - log.info("Available drivers: " + applicableDrivers.stream().map(DBPDriver::getId).collect(Collectors.joining(","))); + log.info("Available drivers: " + applicableDrivers.stream().map(DBPDriver::getFullName).collect(Collectors.joining(","))); sessionManager = WebSessionManager.getInstance(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBSecurityController.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBSecurityController.java index 0b15e2353b..4d328b09b1 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBSecurityController.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBSecurityController.java @@ -148,7 +148,7 @@ class CBSecurityController implements DBWSecurityController { String propertyName = cred.getKey(); WebAuthProviderPropertyDescriptor property = authProvider.getCredentialParameter(propertyName); if (property == null) { - throw new IllegalArgumentException("Invalid auth provider '" + authProvider.getId() + "' property '" + propertyName + "'"); + return null; } String encodedValue = CommonUtils.toString(cred.getValue()); encodedValue = property.getEncryption().encrypt(userId, encodedValue); @@ -162,6 +162,9 @@ class CBSecurityController implements DBWSecurityController { if (!CommonUtils.isEmpty(credentials)) { try (PreparedStatement dbStat = dbCon.prepareStatement("INSERT INTO CB_USER_CREDENTIALS(USER_ID,PROVIDER_ID,CRED_ID,CRED_VALUE) VALUES(?,?,?,?)")) { for (String[] cred : transformedCredentials) { + if (cred == null) { + continue; + } dbStat.setString(1, userId); dbStat.setString(2, authProvider.getId()); dbStat.setString(3, cred[0]); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/impl/WebServiceCore.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/impl/WebServiceCore.java index 52149d8c76..b1c0f28116 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/impl/WebServiceCore.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/impl/WebServiceCore.java @@ -135,7 +135,7 @@ public class WebServiceCore implements DBWServiceCore { throw new DBWebException("Datasource '" + dataSourceId + "' not found"); } - DBPDataSourceRegistry sessionRegistry = webSession.getDatabases().getDataSourceRegistry(); + DBPDataSourceRegistry sessionRegistry = webSession.getDatabasesNode().getDataSourceRegistry(); DBPDataSourceContainer newDataSource = sessionRegistry.createDataSource(dataSourceTemplate); newDataSource.setSavePassword(true); ((DataSourceDescriptor)newDataSource).setTemporary(true); @@ -164,7 +164,7 @@ public class WebServiceCore implements DBWServiceCore { @Override public WebConnectionInfo createConnection(WebSession webSession, WebConnectionConfig connectionConfig) throws DBWebException { - DBPDataSourceRegistry sessionRegistry = webSession.getDatabases().getDataSourceRegistry(); + DBPDataSourceRegistry sessionRegistry = webSession.getDatabasesNode().getDataSourceRegistry(); DBPDataSourceContainer newDataSource = makeConnectionInstance(connectionConfig, sessionRegistry); if (CommonUtils.isEmpty(newDataSource.getName())) { @@ -181,7 +181,7 @@ public class WebServiceCore implements DBWServiceCore { @Override public WebConnectionInfo testConnection(WebSession webSession, WebConnectionConfig connectionConfig) throws DBWebException { - DBPDataSourceRegistry sessionRegistry = webSession.getDatabases().getDataSourceRegistry(); + DBPDataSourceRegistry sessionRegistry = webSession.getDatabasesNode().getDataSourceRegistry(); DBPDataSourceContainer newDataSource = makeConnectionInstance(connectionConfig, sessionRegistry); try { @@ -216,7 +216,7 @@ public class WebServiceCore implements DBWServiceCore { // Disconnect in async mode? //new DisconnectJob(connectionInfo.getDataSource()).schedule(); } - webSession.getDatabases().getDataSourceRegistry().removeDataSource(connectionInfo.getDataSourceContainer()); + webSession.getDatabasesNode().getDataSourceRegistry().removeDataSource(connectionInfo.getDataSourceContainer()); webSession.removeConnection(connectionInfo); return disconnected; diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/impl/WebServiceNavigator.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/impl/WebServiceNavigator.java index a0119551f6..3adf6c5214 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/impl/WebServiceNavigator.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/impl/WebServiceNavigator.java @@ -35,6 +35,7 @@ import org.jkiss.dbeaver.model.navigator.DBNNode; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.struct.DBSObject; import org.jkiss.dbeaver.model.struct.rdb.DBSCatalog; +import org.jkiss.utils.ArrayUtils; import org.jkiss.utils.CommonUtils; import java.lang.reflect.InvocationTargetException; @@ -56,7 +57,12 @@ public class WebServiceNavigator implements DBWServiceNavigator { DBNNode[] nodeChildren; boolean isRootPath = CommonUtils.isEmpty(parentPath) || "/".equals(parentPath); if (isRootPath) { - nodeChildren = session.getDatabases().getChildren(monitor); + nodeChildren = session.getDatabasesNode().getChildren(monitor); + // Inject extra nodes + List extraNodes = session.getProjectNode().getExtraNodes(); + if (!extraNodes.isEmpty()) { + nodeChildren = ArrayUtils.concatArrays(extraNodes.toArray(new DBNNode[0]), nodeChildren); + } } else { DBNNode parentNode = session.getNavigatorModel().getNodeByPath(monitor, parentPath); if (parentNode == null) { diff --git a/server/product/web-server/CloudbeaverServer.product.launch b/server/product/web-server/CloudbeaverServer.product.launch index 7b4e4a0f78..a23f453f50 100644 --- a/server/product/web-server/CloudbeaverServer.product.launch +++ b/server/product/web-server/CloudbeaverServer.product.launch @@ -12,16 +12,18 @@ + - + + - + @@ -34,13 +36,212 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/webapp/packages/authentication/src/UserInfo.tsx b/webapp/packages/authentication/src/UserInfo.tsx index dfabf6b880..d5cb9c0da7 100644 --- a/webapp/packages/authentication/src/UserInfo.tsx +++ b/webapp/packages/authentication/src/UserInfo.tsx @@ -52,7 +52,7 @@ export const UserInfo = observer(function UserInfo() { - {authInfoService.userInfo.userId} + {authInfoService.userInfo.displayName || authInfoService.userInfo.userId} ); });