mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-16 14:50:15 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d71a77a48 |
Vendored
+1
-1
@@ -48,7 +48,7 @@
|
||||
"-Declipse.pde.launch=true",
|
||||
"-XstartOnFirstThread",
|
||||
"-Dfile.encoding=UTF-8",
|
||||
"--add-modules=ALL-DEFAULT",
|
||||
"--add-modules=ALL-SYSTEM",
|
||||
"--add-opens=java.base/java.io=ALL-UNNAMED",
|
||||
"--add-opens=java.base/java.lang=ALL-UNNAMED",
|
||||
"--add-opens=java.base/java.lang.reflect=ALL-UNNAMED",
|
||||
|
||||
Vendored
+2
-11
@@ -92,10 +92,10 @@
|
||||
"label": "Run Backend CE",
|
||||
"type": "shell",
|
||||
"windows": {
|
||||
"command": "./run-cloudbeaver-server.bat"
|
||||
"command": "./run-server.bat"
|
||||
},
|
||||
"osx": {
|
||||
"command": "./run-cloudbeaver-server.sh"
|
||||
"command": "./run-server.sh"
|
||||
},
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/deploy/cloudbeaver"
|
||||
@@ -136,15 +136,6 @@
|
||||
"cwd": "${workspaceFolder}/webapp/common-react/@dbeaver/ui-kit"
|
||||
},
|
||||
"args": ["docs"]
|
||||
},
|
||||
{
|
||||
"label": "Run Storybook",
|
||||
"type": "shell",
|
||||
"command": "yarn",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/webapp/packages/storybook"
|
||||
},
|
||||
"args": ["storybook"]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
|
||||
@@ -25,11 +25,6 @@ You can see a live demo of CloudBeaver here: https://demo.cloudbeaver.io
|
||||
|
||||
## Changelog
|
||||
|
||||
### 25.2.1 2025-09-22
|
||||
- Autocomplete values in SQL Editor are ordered alphabetically to simplify object search.
|
||||
- "Show all databases" setting was added on the connection page for MySQL and MariaDB.
|
||||
- Different bug fixes and enhancements have been made.
|
||||
|
||||
### 25.2.0 2025-09-01
|
||||
### Changes since 25.1.0:
|
||||
- Administration:
|
||||
|
||||
@@ -28,4 +28,4 @@ echo "Copy static content"
|
||||
|
||||
cp -rp ../webapp/packages/product-default/lib/* cloudbeaver/web
|
||||
|
||||
echo "Cloudbeaver is ready. Run run-cloudbeaver-server.sh in cloudbeaver folder to start the server."
|
||||
echo "Cloudbeaver is ready. Run run-server.sh in cloudbeaver folder to start the server."
|
||||
|
||||
+1
-1
@@ -72,6 +72,6 @@ echo "Copy static content"
|
||||
|
||||
xcopy /E /Q ..\webapp\packages\product-default\lib cloudbeaver\web >NUL
|
||||
|
||||
echo "Cloudbeaver is ready. Run run-cloudbeaver-server.bat in cloudbeaver folder to start the server."
|
||||
echo "Cloudbeaver is ready. Run run-server.bat in cloudbeaver folder to start the server."
|
||||
|
||||
pause
|
||||
|
||||
@@ -16,6 +16,6 @@ EXPOSE 8978
|
||||
RUN find /opt/cloudbeaver -type d -exec chmod 775 {} \;
|
||||
WORKDIR /opt/cloudbeaver/
|
||||
|
||||
RUN chmod +x "run-cloudbeaver-server.sh" "/opt/cloudbeaver/launch-product.sh"
|
||||
RUN chmod +x "run-server.sh" "/opt/cloudbeaver/launch-product.sh"
|
||||
|
||||
ENTRYPOINT ["./launch-product.sh"]
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -Eeo pipefail
|
||||
if [[ $# -eq 0 ]] ;
|
||||
then
|
||||
set -- "$@" -help
|
||||
fi
|
||||
set -- "$@" -cli-mode
|
||||
|
||||
source run-cloudbeaver-server.sh "$@"
|
||||
@@ -12,8 +12,8 @@ if [ "$(id -u)" -eq 0 ]; then
|
||||
TARGET_GID=${TARGET_GID:-$DBEAVER_GID}
|
||||
|
||||
chown -R $DBEAVER_UID:$DBEAVER_GID $PWD/workspace
|
||||
# Execute run-cloudbeaver-server.sh as the dbeaver user with the JAVA_HOME and PATH environment variables
|
||||
exec su "$TARGET_USER" -c "JAVA_HOME=$JAVA_HOME PATH=$PATH ./run-cloudbeaver-server.sh"
|
||||
# Execute run-server.sh as the dbeaver user with the JAVA_HOME and PATH environment variables
|
||||
exec su "$TARGET_USER" -c "JAVA_HOME=$JAVA_HOME PATH=$PATH ./run-server.sh"
|
||||
else
|
||||
exec ./run-cloudbeaver-server.sh
|
||||
exec ./run-server.sh
|
||||
fi
|
||||
@@ -17,7 +17,7 @@ If Not Defined JAVA_OPTS (
|
||||
|
||||
java %JAVA_OPTS% ^
|
||||
-Dfile.encoding=UTF-8 ^
|
||||
--add-modules=ALL-DEFAULT ^
|
||||
--add-modules=ALL-SYSTEM ^
|
||||
--add-opens=java.base/java.io=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.lang=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED ^
|
||||
@@ -11,7 +11,7 @@ echo "Starting Cloudbeaver Server"
|
||||
|
||||
exec java ${JAVA_OPTS} \
|
||||
-Dfile.encoding=UTF-8 \
|
||||
--add-modules=ALL-DEFAULT \
|
||||
--add-modules=ALL-SYSTEM \
|
||||
--add-opens=java.base/java.io=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.lang=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
|
||||
@@ -36,6 +36,6 @@ exec java ${JAVA_OPTS} \
|
||||
-jar ${launcherJar} \
|
||||
-product io.cloudbeaver.product.ce.product \
|
||||
-web-config conf/cloudbeaver.conf \
|
||||
"$@" \
|
||||
${CLI_OPTS} \
|
||||
-nl en \
|
||||
-registryMultiLanguage
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -Eeo pipefail
|
||||
CLI_OPTS="$@"
|
||||
if [[ $# -eq 0 ]] ;
|
||||
then
|
||||
CLI_OPTS='-help'
|
||||
fi
|
||||
source run-server.sh
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Model
|
||||
Bundle-SymbolicName: io.cloudbeaver.model;singleton:=true
|
||||
Bundle-Version: 1.0.86.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.85.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: org.jkiss.dbeaver.data.gis;visibility:=reexport,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.model</artifactId>
|
||||
<version>1.0.86-SNAPSHOT</version>
|
||||
<version>1.0.85-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -17,14 +17,18 @@
|
||||
package io.cloudbeaver;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.model.app.DBPWorkspace;
|
||||
import org.jkiss.dbeaver.model.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.impl.app.BaseProjectImpl;
|
||||
import org.jkiss.dbeaver.model.rm.*;
|
||||
import org.jkiss.dbeaver.model.rm.RMController;
|
||||
import org.jkiss.dbeaver.model.rm.RMControllerProvider;
|
||||
import org.jkiss.dbeaver.model.rm.RMProject;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.Pair;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class BaseWebProjectImpl extends BaseProjectImpl implements RMControllerProvider {
|
||||
|
||||
@@ -77,12 +81,6 @@ public abstract class BaseWebProjectImpl extends BaseProjectImpl implements RMCo
|
||||
return project.getId();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Path getAbsolutePath() {
|
||||
@@ -104,25 +102,52 @@ public abstract class BaseWebProjectImpl extends BaseProjectImpl implements RMCo
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for Bulk Update of resources properties paths
|
||||
*
|
||||
* @param oldToNewPaths collection of OldPath to NewPath pairs
|
||||
*/
|
||||
public void moveResourcePropertiesBatch(@NotNull Collection<Pair<String, String>> oldToNewPaths) {
|
||||
loadMetadata();
|
||||
synchronized (metadataSync) {
|
||||
for (var pathsPair : oldToNewPaths) {
|
||||
final var oldResourcePath = CommonUtils.normalizeResourcePath(pathsPair.getFirst());
|
||||
final var newResourcePath = CommonUtils.normalizeResourcePath(pathsPair.getSecond());
|
||||
final var resProps = resourceProperties.remove(oldResourcePath);
|
||||
if (resProps != null) {
|
||||
resourceProperties.put(newResourcePath, resProps);
|
||||
}
|
||||
}
|
||||
}
|
||||
flushMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for Bulk Remove of resources properties
|
||||
*/
|
||||
public boolean resetResourcesPropertiesBatch(@NotNull Collection<String> resourcesPaths) {
|
||||
loadMetadata();
|
||||
boolean propertiesChanged = false;
|
||||
synchronized (metadataSync) {
|
||||
for (var resourcePath : resourcesPaths) {
|
||||
var removedProperties = resourceProperties.remove(CommonUtils.normalizeResourcePath(resourcePath));
|
||||
if (removedProperties != null) {
|
||||
propertiesChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (propertiesChanged) {
|
||||
flushMetadata();
|
||||
}
|
||||
return propertiesChanged;
|
||||
}
|
||||
|
||||
public Path getMetadataFilePath() {
|
||||
return getMetadataPath().resolve(METADATA_STORAGE_FILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrivateProject() {
|
||||
return RMProjectType.USER.equals(getRMProject().getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateProject(@Nullable String newName, @Nullable String description) throws DBException {
|
||||
RMProject rmProject = getResourceController().updateProject(this.getId(), new RMProjectInfo(newName, description));
|
||||
updateProjectInfo(rmProject.getName(), rmProject.getDescription());
|
||||
}
|
||||
|
||||
public void updateProjectInfo(@Nullable String newName, @Nullable String description) {
|
||||
this.project.setName(newName);
|
||||
this.project.setDescription(description);
|
||||
RMEventManager.fireEvent(
|
||||
new RMEvent(
|
||||
RMEvent.Action.PROJECT_UPDATE,
|
||||
project
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2024 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;
|
||||
|
||||
import io.cloudbeaver.model.WebConnectionConfig;
|
||||
import io.cloudbeaver.model.app.WebAppConfiguration;
|
||||
import io.cloudbeaver.utils.ServletAppUtils;
|
||||
import io.cloudbeaver.utils.WebDataSourceUtils;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
public class WebConnectionConfigInputHandler<T extends WebConnectionConfig, C extends DataSourceDescriptor> {
|
||||
private static final Log log = Log.getLog(WebConnectionConfigInputHandler.class);
|
||||
protected final T input;
|
||||
protected final DBPDataSourceRegistry registry;
|
||||
|
||||
public WebConnectionConfigInputHandler(@NotNull DBPDataSourceRegistry registry, T configInput) {
|
||||
this.registry = registry;
|
||||
this.input = configInput;
|
||||
}
|
||||
|
||||
public C createDataSourceContainer() throws DBWebException {
|
||||
String driverId = input.getDriverId();
|
||||
if (CommonUtils.isEmpty(driverId)) {
|
||||
throw new DBWebException("Driver must be specified");
|
||||
}
|
||||
DBPDriver driver = WebDataSourceUtils.getDriverById(driverId);
|
||||
|
||||
C newDataSource = createDataSourceContainerFromInput(driver);
|
||||
|
||||
if (ServletAppUtils.getServletApplication().getAppConfiguration() instanceof WebAppConfiguration webAppConfiguration) {
|
||||
newDataSource.setNavigatorSettings(webAppConfiguration.getDefaultNavigatorSettings());
|
||||
}
|
||||
|
||||
WebDataSourceUtils.saveAuthProperties(
|
||||
newDataSource,
|
||||
newDataSource.getConnectionConfiguration(),
|
||||
input.getCredentials(),
|
||||
input.isSaveCredentials(),
|
||||
input.isSharedCredentials()
|
||||
);
|
||||
return newDataSource;
|
||||
}
|
||||
|
||||
public void updateDataSource(@NotNull C dataSource) throws DBWebException {
|
||||
dataSource.setId(dataSource.getId());
|
||||
if (!CommonUtils.isEmpty(input.getName())) {
|
||||
dataSource.setName(input.getName());
|
||||
}
|
||||
|
||||
if (input.getDescription() != null) {
|
||||
dataSource.setDescription(input.getDescription());
|
||||
}
|
||||
|
||||
dataSource.setFolder(input.getFolder() != null ? registry.getFolder(input.getFolder()) : null);
|
||||
if (input.isDefaultAutoCommit() != null) {
|
||||
dataSource.setDefaultAutoCommit(input.isDefaultAutoCommit());
|
||||
}
|
||||
WebDataSourceUtils.setConnectionConfiguration(
|
||||
dataSource.getDriver(),
|
||||
dataSource.getConnectionConfiguration(),
|
||||
input
|
||||
);
|
||||
WebDataSourceUtils.saveAuthProperties(
|
||||
dataSource,
|
||||
dataSource.getConnectionConfiguration(),
|
||||
input.getCredentials(),
|
||||
input.isSaveCredentials(),
|
||||
input.isSharedCredentials()
|
||||
);
|
||||
dataSource.setConnectionReadOnly(input.isReadOnly());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected C createDataSourceContainerFromInput(@NotNull DBPDriver driver) {
|
||||
DBPConnectionConfiguration dsConfig = new DBPConnectionConfiguration();
|
||||
WebDataSourceUtils.setConnectionConfiguration(driver, dsConfig, input);
|
||||
C newDataSource = registry.createDataSource(driver, dsConfig);
|
||||
|
||||
newDataSource.setSavePassword(true);
|
||||
newDataSource.setName(CommonUtils.notNull(input.getName(), "NewConnection"));
|
||||
newDataSource.setDescription(input.getDescription());
|
||||
newDataSource.setConnectionReadOnly(input.isReadOnly());
|
||||
if (input.getFolder() != null) {
|
||||
newDataSource.setFolder(registry.getFolder(input.getFolder()));
|
||||
}
|
||||
return newDataSource;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -16,13 +16,11 @@
|
||||
*/
|
||||
package io.cloudbeaver;
|
||||
|
||||
import io.cloudbeaver.model.WebConnectionConfig;
|
||||
import io.cloudbeaver.model.WebConnectionInfo;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.utils.WebDataSourceUtils;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
|
||||
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
@@ -30,26 +28,22 @@ import org.jkiss.dbeaver.model.app.DBPDataSourceRegistryCache;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNModel;
|
||||
import org.jkiss.dbeaver.model.rm.RMProject;
|
||||
import org.jkiss.dbeaver.model.rm.RMUtils;
|
||||
import org.jkiss.dbeaver.model.security.SMObjectType;
|
||||
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceEvent;
|
||||
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
|
||||
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
|
||||
import org.jkiss.dbeaver.registry.DataSourceRegistry;
|
||||
import org.jkiss.dbeaver.runtime.jobs.DisconnectJob;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class WebSessionProjectImpl extends WebProjectImpl {
|
||||
private static final Log log = Log.getLog(WebSessionProjectImpl.class);
|
||||
protected final WebSession webSession;
|
||||
private final Map<String, WebConnectionInfo> connections = new HashMap<>();
|
||||
private final Map<String, Object> projectSettings = new ConcurrentHashMap<>();
|
||||
private boolean registryIsLoaded = false;
|
||||
|
||||
public WebSessionProjectImpl(
|
||||
@@ -165,7 +159,7 @@ public class WebSessionProjectImpl extends WebProjectImpl {
|
||||
*/
|
||||
@NotNull
|
||||
public synchronized WebConnectionInfo addConnection(@NotNull DBPDataSourceContainer dataSourceContainer) {
|
||||
WebConnectionInfo connection = createConnectionInfo(dataSourceContainer);
|
||||
WebConnectionInfo connection = new WebConnectionInfo(webSession, dataSourceContainer);
|
||||
synchronized (connections) {
|
||||
connections.put(dataSourceContainer.getId(), connection);
|
||||
}
|
||||
@@ -243,124 +237,4 @@ public class WebSessionProjectImpl extends WebProjectImpl {
|
||||
}
|
||||
return sendDataSourceUpdatedEvent;
|
||||
}
|
||||
|
||||
public void refreshProjectSettings() throws DBException {
|
||||
if (webSession.getUser() == null) {
|
||||
projectSettings.clear();
|
||||
return;
|
||||
}
|
||||
Map<String, Object> loadedSettings = webSession.getSecurityController().getObjectSettings(
|
||||
getId(),
|
||||
SMObjectType.project,
|
||||
null
|
||||
);
|
||||
projectSettings.clear();
|
||||
projectSettings.putAll(loadedSettings);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WebConnectionInfo createConnectionInfo(@NotNull DBPDataSourceContainer dataSourceDescriptor) {
|
||||
return new WebConnectionInfo(webSession, dataSourceDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WebConnectionInfo createConnection(@NotNull Map<String, Object> configMap) throws DBWebException {
|
||||
if (CommonUtils.isEmpty(configMap)) {
|
||||
throw new DBWebException("Connection configuration parameters are missing");
|
||||
}
|
||||
DBPDataSourceContainer newDataSource = getDataSourceContainerFromInput(configMap);
|
||||
return addDataSourceToProject(newDataSource);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WebConnectionInfo addDataSourceToProject(@NotNull DBPDataSourceContainer newDataSource) throws DBWebException {
|
||||
DBPDataSourceRegistry registry = getDataSourceRegistry();
|
||||
try {
|
||||
registry.addDataSource(newDataSource);
|
||||
registry.checkForErrors();
|
||||
} catch (DBException e) {
|
||||
registry.removeDataSource(newDataSource);
|
||||
throw new DBWebException("Failed to create connection", e);
|
||||
}
|
||||
|
||||
WebConnectionInfo connectionInfo = addConnection(newDataSource);
|
||||
webSession.addInfoMessage("New connection was created - " + WebDataSourceUtils.getConnectionContainerInfo(
|
||||
newDataSource));
|
||||
log.info(String.format(
|
||||
"New connection was created: [info=%s, user=%s]",
|
||||
WebDataSourceUtils.getConnectionContainerInfo(newDataSource),
|
||||
webSession.getUserId()
|
||||
));
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WebConnectionInfo updateConnection(@Nullable Map<String, Object> configMap) throws DBWebException {
|
||||
WebConnectionConfig config = getConnectionConfigInput(configMap);
|
||||
WebConnectionInfo connectionInfo = getWebConnectionInfo(config.getConnectionId());
|
||||
DataSourceDescriptor dataSource = (DataSourceDescriptor) connectionInfo.getDataSourceContainer();
|
||||
webSession.addInfoMessage("Update connection - " + WebDataSourceUtils.getConnectionContainerInfo(dataSource));
|
||||
|
||||
DBPDataSourceRegistry registry = getDataSourceRegistry();
|
||||
getInputConfigHandler(configMap).updateDataSource(dataSource);
|
||||
connectionInfo.setCredentialsSavedInSession(null);
|
||||
try {
|
||||
registry.updateDataSource(dataSource);
|
||||
registry.checkForErrors();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Failed to update connection", e);
|
||||
}
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
public boolean deleteConnection(@NotNull String connectionId) throws DBWebException {
|
||||
WebConnectionInfo connectionInfo = getWebConnectionInfo(connectionId);
|
||||
webSession.addInfoMessage("Delete connection - " +
|
||||
WebDataSourceUtils.getConnectionContainerInfo(connectionInfo.getDataSourceContainer()));
|
||||
closeAndDeleteConnection(connectionInfo);
|
||||
|
||||
log.info(String.format(
|
||||
"Connection deleted: [info=%s, userId=%s]",
|
||||
WebDataSourceUtils.getConnectionContainerInfo(connectionInfo.getDataSourceContainer()),
|
||||
webSession.getUserId()
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private WebConnectionInfo closeAndDeleteConnection(@NotNull WebConnectionInfo connectionInfo) throws DBWebException {
|
||||
DBPDataSourceContainer dataSourceContainer = connectionInfo.getDataSourceContainer();
|
||||
boolean disconnected = WebDataSourceUtils.disconnectDataSource(webSession, dataSourceContainer);
|
||||
DBPDataSourceRegistry registry = getDataSourceRegistry();
|
||||
registry.removeDataSource(dataSourceContainer);
|
||||
try {
|
||||
registry.checkForErrors();
|
||||
} catch (DBException e) {
|
||||
try {
|
||||
registry.addDataSource(dataSourceContainer);
|
||||
} catch (DBException ex) {
|
||||
log.error("Error re-adding after delete attempt", e);
|
||||
}
|
||||
throw new DBWebException("Failed to delete connection", e);
|
||||
}
|
||||
removeConnection(dataSourceContainer);
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DataSourceDescriptor getDataSourceContainerFromInput(@NotNull Map<String, Object> configMap) throws DBWebException {
|
||||
return getInputConfigHandler(configMap).createDataSourceContainer();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WebConnectionConfig getConnectionConfigInput(@Nullable Map<String, Object> configMap) {
|
||||
return new WebConnectionConfig(configMap == null ? Map.of() : configMap);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected WebConnectionConfigInputHandler getInputConfigHandler(@NotNull Map<String, Object> configMap) {
|
||||
return new WebConnectionConfigInputHandler<>(getDataSourceRegistry(), getConnectionConfigInput(configMap));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+47
-40
@@ -16,11 +16,11 @@
|
||||
*/
|
||||
package io.cloudbeaver.model;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriverConfigurationType;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.model.meta.Property;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -58,6 +58,7 @@ public class WebConnectionConfig {
|
||||
private Map<String, Object> mainPropertyValues;
|
||||
private Map<String, Object> expertSettingsValues;
|
||||
private Map<String, Object> providerProperties;
|
||||
private Map<String, Object> externalParameters;
|
||||
private List<WebNetworkHandlerConfigInput> networkHandlersConfig;
|
||||
private DBPDriverConfigurationType configurationType;
|
||||
private String selectedSecretId;
|
||||
@@ -68,52 +69,54 @@ public class WebConnectionConfig {
|
||||
public WebConnectionConfig() {
|
||||
}
|
||||
|
||||
public WebConnectionConfig(@NotNull Map<String, Object> params) {
|
||||
connectionId = JSONUtils.getString(params, "connectionId");
|
||||
driverId = JSONUtils.getString(params, "driverId");
|
||||
public WebConnectionConfig(Map<String, Object> params) {
|
||||
if (!CommonUtils.isEmpty(params)) {
|
||||
connectionId = JSONUtils.getString(params, "connectionId");
|
||||
driverId = JSONUtils.getString(params, "driverId");
|
||||
|
||||
host = JSONUtils.getString(params, "host");
|
||||
port = JSONUtils.getString(params, "port");
|
||||
serverName = JSONUtils.getString(params, "serverName");
|
||||
databaseName = JSONUtils.getString(params, "databaseName");
|
||||
url = JSONUtils.getString(params, "url");
|
||||
host = JSONUtils.getString(params, "host");
|
||||
port = JSONUtils.getString(params, "port");
|
||||
serverName = JSONUtils.getString(params, "serverName");
|
||||
databaseName = JSONUtils.getString(params, "databaseName");
|
||||
url = JSONUtils.getString(params, "url");
|
||||
|
||||
name = JSONUtils.getString(params, "name");
|
||||
description = JSONUtils.getString(params, "description");
|
||||
folder = JSONUtils.getString(params, "folder");
|
||||
name = JSONUtils.getString(params, "name");
|
||||
description = JSONUtils.getString(params, "description");
|
||||
folder = JSONUtils.getString(params, "folder");
|
||||
|
||||
properties = JSONUtils.getObjectOrNull(params, "properties");
|
||||
userName = JSONUtils.getString(params, "userName");
|
||||
userPassword = JSONUtils.getString(params, "userPassword");
|
||||
selectedSecretId = JSONUtils.getString(params, "selectedSecretId");
|
||||
properties = JSONUtils.getObjectOrNull(params, "properties");
|
||||
userName = JSONUtils.getString(params, "userName");
|
||||
userPassword = JSONUtils.getString(params, "userPassword");
|
||||
selectedSecretId = JSONUtils.getString(params, "selectedSecretId");
|
||||
|
||||
authModelId = JSONUtils.getString(params, "authModelId");
|
||||
credentials = JSONUtils.getObjectOrNull(params, "credentials");
|
||||
saveCredentials = JSONUtils.getBoolean(params, "saveCredentials");
|
||||
sharedCredentials = JSONUtils.getBoolean(params, "sharedCredentials");
|
||||
authModelId = JSONUtils.getString(params, "authModelId");
|
||||
credentials = JSONUtils.getObjectOrNull(params, "credentials");
|
||||
saveCredentials = JSONUtils.getBoolean(params, "saveCredentials");
|
||||
sharedCredentials = JSONUtils.getBoolean(params, "sharedCredentials");
|
||||
|
||||
mainPropertyValues = JSONUtils.getObjectOrNull(params, "mainPropertyValues");
|
||||
providerProperties = JSONUtils.getObjectOrNull(params, "providerProperties");
|
||||
expertSettingsValues = JSONUtils.getObjectOrNull(params, "expertSettingsValues");
|
||||
keepAliveInterval = JSONUtils.getInteger(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_KEEP_ALIVE_INTERVAL, -1);
|
||||
readOnly = JSONUtils.getBoolean(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_READ_ONLY);
|
||||
defaultAutoCommit = JSONUtils.getBoolean(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_AUTO_COMMIT, true);
|
||||
defaultCatalogName = JSONUtils.getString(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_DEFAULT_CATALOG);
|
||||
defaultSchemaName = JSONUtils.getString(
|
||||
expertSettingsValues != null ? expertSettingsValues : params,
|
||||
WebExpertSettingsProperties.PROP_DEFAULT_SCHEMA
|
||||
);
|
||||
mainPropertyValues = JSONUtils.getObjectOrNull(params, "mainPropertyValues");
|
||||
providerProperties = JSONUtils.getObjectOrNull(params, "providerProperties");
|
||||
|
||||
String configType = JSONUtils.getString(params, "configurationType");
|
||||
configurationType = configType == null ? null : DBPDriverConfigurationType.valueOf(configType);
|
||||
expertSettingsValues = JSONUtils.getObjectOrNull(params, "expertSettingsValues");
|
||||
keepAliveInterval = JSONUtils.getInteger(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_KEEP_ALIVE_INTERVAL, -1);
|
||||
readOnly = JSONUtils.getBoolean(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_READ_ONLY);
|
||||
defaultAutoCommit = JSONUtils.getBoolean(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_AUTO_COMMIT, true);
|
||||
defaultCatalogName = JSONUtils.getString(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_DEFAULT_CATALOG);
|
||||
defaultSchemaName = JSONUtils.getString(
|
||||
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_DEFAULT_SCHEMA);
|
||||
|
||||
networkHandlersConfig = new ArrayList<>();
|
||||
for (Map<String, Object> nhc : JSONUtils.getObjectList(params, "networkHandlersConfig")) {
|
||||
networkHandlersConfig.add(new WebNetworkHandlerConfigInput(nhc));
|
||||
String configType = JSONUtils.getString(params, "configurationType");
|
||||
configurationType = configType == null ? null : DBPDriverConfigurationType.valueOf(configType);
|
||||
externalParameters = JSONUtils.getObjectOrNull(params, "externalParameters");
|
||||
|
||||
networkHandlersConfig = new ArrayList<>();
|
||||
for (Map<String, Object> nhc : JSONUtils.getObjectList(params, "networkHandlersConfig")) {
|
||||
networkHandlersConfig.add(new WebNetworkHandlerConfigInput(nhc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,4 +262,8 @@ public class WebConnectionConfig {
|
||||
public String getDefaultSchemaName() {
|
||||
return defaultSchemaName;
|
||||
}
|
||||
|
||||
public Map<String, Object> getExternalParameters() {
|
||||
return externalParameters;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package io.cloudbeaver.model;
|
||||
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebProjectImpl;
|
||||
import io.cloudbeaver.model.app.BaseWebAppConfiguration;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
@@ -320,10 +319,6 @@ public class WebConnectionInfo {
|
||||
!dataSourceContainer.getDriver().isAnonymousAccess();
|
||||
}
|
||||
|
||||
public void validateConnection() throws DBWebException {
|
||||
|
||||
}
|
||||
|
||||
// we don't show non-secured properties in FE when connecting to DB without saved credentials
|
||||
private boolean isAuthPropertiesEmpty() {
|
||||
return Arrays.stream(getAuthProperties()).allMatch(f -> f.hasFeature(DBConstants.PROP_FEATURE_NON_SECURED));
|
||||
|
||||
+1
-8
@@ -198,7 +198,6 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object start(IApplicationContext context) {
|
||||
initializeApplicationServices();
|
||||
@@ -211,9 +210,8 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
|
||||
startServer();
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return EXIT_ERROR_UNSPECIFIED;
|
||||
}
|
||||
return EXIT_OK;
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract void startServer() throws DBException;
|
||||
@@ -281,9 +279,4 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
|
||||
public ApplicationInstanceController getInstanceServer() {
|
||||
return instanceServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnonymousAccessEnabled() {
|
||||
return getAppConfiguration().isAnonymousAccessEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -100,6 +100,4 @@ public interface ServletApplication extends DBPApplication {
|
||||
default void getStatusInfo(Map<String, Object> infoMap) {
|
||||
|
||||
}
|
||||
|
||||
boolean isAnonymousAccessEnabled();
|
||||
}
|
||||
|
||||
+3
-4
@@ -20,7 +20,7 @@ import org.apache.commons.cli.CommandLine;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.model.cli.ApplicationInstanceController;
|
||||
import org.jkiss.dbeaver.model.cli.ApplicationInstanceServer;
|
||||
import org.jkiss.dbeaver.model.cli.CLIProcessResult;
|
||||
import org.jkiss.dbeaver.model.cli.CliProcessResult;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -31,17 +31,16 @@ public class CloudBeaverInstanceServer extends ApplicationInstanceServer<Applica
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CLIProcessResult handleCommandLine(@NotNull String[] args) {
|
||||
public CliProcessResult handleCommandLine(@NotNull String[] args) {
|
||||
CommandLine cmd = CloudBeaverCommandLine.getInstance().getCommandLine(args);
|
||||
try {
|
||||
return CloudBeaverCommandLine.getInstance().executeCommandLineCommands(
|
||||
cmd,
|
||||
this,
|
||||
false,
|
||||
false
|
||||
);
|
||||
} catch (Exception e) {
|
||||
return new CLIProcessResult(CLIProcessResult.PostAction.ERROR, "Error executing command: " + e.getMessage());
|
||||
return new CliProcessResult(CliProcessResult.PostAction.ERROR, "Error executing command: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-13
@@ -19,6 +19,7 @@ package io.cloudbeaver.model.rm;
|
||||
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.DBPHiddenObject;
|
||||
@@ -140,9 +141,6 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
case PROJECT_ADD:
|
||||
addProjectNode(event.getProject());
|
||||
break;
|
||||
case PROJECT_UPDATE:
|
||||
updateProjectNode(event.getProject());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,14 +187,4 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
private void addProjectNode(RMProject project) {
|
||||
projects = ArrayUtils.add(DBNResourceManagerProject.class, projects, new DBNResourceManagerProject(this, project));
|
||||
}
|
||||
|
||||
private void updateProjectNode(@NotNull RMProject project) {
|
||||
var projectNode = getProjectNode(project);
|
||||
projectNode.ifPresent(
|
||||
dbnResourceManagerProject -> {
|
||||
dbnResourceManagerProject.getProject().setName(project.getName());
|
||||
dbnResourceManagerProject.getProject().setDescription(project.getDescription());
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -99,7 +99,7 @@ public abstract class BaseLocalResourceController implements RMController {
|
||||
@NotNull String propName,
|
||||
@NotNull Object propValue
|
||||
) throws DBException {
|
||||
RMLocalProject webProject = getWebProject(projectId, false);
|
||||
BaseWebProjectImpl webProject = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, webProject.getMetadataFilePath(),
|
||||
() -> {
|
||||
log.debug("Updating value for property '" + propName + "' in project '" + projectId + "'");
|
||||
@@ -284,7 +284,7 @@ public abstract class BaseLocalResourceController implements RMController {
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract RMLocalProject getWebProject(String projectId, boolean refresh) throws DBException;
|
||||
protected abstract BaseWebProjectImpl getWebProject(String projectId, boolean refresh) throws DBException;
|
||||
|
||||
protected abstract <T> T doFileWriteOperation(String projectId, Path file, RMFileOperation<T> operation)
|
||||
throws DBException;
|
||||
|
||||
+100
-77
@@ -16,12 +16,12 @@
|
||||
*/
|
||||
package io.cloudbeaver.model.rm.local;
|
||||
|
||||
import io.cloudbeaver.BaseWebProjectImpl;
|
||||
import io.cloudbeaver.DBWConstants;
|
||||
import io.cloudbeaver.model.app.ServletApplication;
|
||||
import io.cloudbeaver.service.security.SMUtils;
|
||||
import io.cloudbeaver.service.sql.WebSQLConstants;
|
||||
import io.cloudbeaver.utils.ServletAppUtils;
|
||||
import io.cloudbeaver.utils.WebRMUtils;
|
||||
import io.cloudbeaver.utils.file.UniversalFileVisitor;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.jkiss.code.NotNull;
|
||||
@@ -81,7 +81,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
private Supplier<SMController> smControllerSupplier;
|
||||
protected final List<RMFileOperationHandler> fileHandlers;
|
||||
|
||||
private final Map<String, RMLocalProject> projectRegistries = new LinkedHashMap<>();
|
||||
private final Map<String, BaseWebProjectImpl> projectRegistries = new LinkedHashMap<>();
|
||||
|
||||
public LocalResourceController(
|
||||
DBPWorkspace workspace,
|
||||
@@ -116,11 +116,13 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
return userId == null ? null : this.userProjectsPath.resolve(userId);
|
||||
}
|
||||
|
||||
protected RMLocalProject getWebProject(String projectId, boolean refresh) throws DBException {
|
||||
protected BaseWebProjectImpl getWebProject(String projectId, boolean refresh) throws DBException {
|
||||
synchronized (projectRegistries) {
|
||||
RMLocalProject project = projectRegistries.get(projectId);
|
||||
BaseWebProjectImpl project = projectRegistries.get(projectId);
|
||||
if (project == null || refresh) {
|
||||
project = createWebProjectImpl(projectId, new SessionContextImpl(null));
|
||||
SessionContextImpl sessionContext = new SessionContextImpl(null);
|
||||
RMProject rmProject = makeProjectFromId(projectId, false);
|
||||
project = createWebProjectImpl(projectId, sessionContext, rmProject);
|
||||
projectRegistries.put(projectId, project);
|
||||
}
|
||||
return project;
|
||||
@@ -128,11 +130,12 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected RMLocalProject createWebProjectImpl(
|
||||
@NotNull String projectId,
|
||||
@NotNull SessionContextImpl sessionContext
|
||||
protected InternalWebProjectImpl createWebProjectImpl(
|
||||
String projectId,
|
||||
SessionContextImpl sessionContext,
|
||||
RMProject rmProject
|
||||
) throws DBException {
|
||||
return new RMLocalProject(workspace, sessionContext, getProjectPath(projectId), WebRMUtils.parseProjectName(projectId).getType());
|
||||
return new InternalWebProjectImpl(sessionContext, rmProject, getProjectPath(projectId));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -187,7 +190,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
.stream()
|
||||
.filter(smObjectPermissions -> CommonUtils.isNotEmpty(smObjectPermissions.getObjectId()))
|
||||
.map(projectPermission -> makeProjectFromPath(
|
||||
sharedProjectsPath.resolve(WebRMUtils.parseProjectNameUnsafe(projectPermission.getObjectId()).getName()),
|
||||
sharedProjectsPath.resolve(parseProjectNameUnsafe(projectPermission.getObjectId()).getName()),
|
||||
Arrays.stream(projectPermission.getPermissions()).map(RMProjectPermission::fromPermission).collect(Collectors.toSet()),
|
||||
RMProjectType.SHARED, true)
|
||||
)
|
||||
@@ -253,7 +256,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
var allPaths = list.toList();
|
||||
for (Path path : allPaths) {
|
||||
var projectPerms = getProjectPermissions(
|
||||
RMUtils.makeProjectIdFromPath(path, RMProjectType.SHARED),
|
||||
makeProjectIdFromPath(path, RMProjectType.SHARED),
|
||||
RMProjectType.SHARED
|
||||
);
|
||||
var rmProject = makeProjectFromPath(path, projectPerms, RMProjectType.SHARED, false);
|
||||
@@ -278,54 +281,28 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
}
|
||||
}
|
||||
validateResourcePath(name);
|
||||
validateProjectName(null, name);
|
||||
RMProject project;
|
||||
var projectPath = sharedProjectsPath.resolve(name);
|
||||
if (Files.exists(projectPath)) {
|
||||
throw new DBException("Project '" + name + "' already exists");
|
||||
}
|
||||
RMLocalProject webProject = new RMLocalProject(workspace, new SessionContextImpl(null), projectPath, RMProjectType.SHARED);
|
||||
webProject.updateProject(name, description);
|
||||
RMProject rmProject = createRmProjectFromWebProject(projectPath, webProject, new String[0]);
|
||||
project = makeProjectFromPath(projectPath, Set.of(), RMProjectType.SHARED, false);
|
||||
if (project == null) {
|
||||
throw new DBException("Project '" + name + "' not created");
|
||||
}
|
||||
try {
|
||||
log.debug("Creating project '" + rmProject.getId() + "'");
|
||||
log.debug("Creating project '" + project.getId() + "'");
|
||||
Files.createDirectories(projectPath);
|
||||
if (ServletAppUtils.getServletApplication().isMultiNode()) {
|
||||
createResourceTypeFolders(projectPath);
|
||||
}
|
||||
fireRmProjectAddEvent(rmProject);
|
||||
return rmProject;
|
||||
fireRmProjectAddEvent(project);
|
||||
return project;
|
||||
} catch (IOException e) {
|
||||
throw new DBException("Error creating project path", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RMProject updateProject(@NotNull String projectId, @NotNull RMProjectInfo projectInfo) throws DBException {
|
||||
validateProjectName(projectId, projectInfo.getName());
|
||||
try (var projectLock = lockController.lock(projectId, "updateProject")) {
|
||||
RMLocalProject project = getWebProject(projectId, false);
|
||||
Path targetPath = getProjectPath(projectId);
|
||||
if (!Files.exists(targetPath)) {
|
||||
throw new DBException("Project folder '" + projectId + "' not found");
|
||||
}
|
||||
if (!project.canUpdateProjectName()) {
|
||||
throw new DBException("Project '" + projectId + "' is not shared");
|
||||
}
|
||||
project.updateProject(projectInfo.getName(), projectInfo.getDescription());
|
||||
return WebRMUtils.createRmProjectFromWebProject(project);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateProjectName(@Nullable String projectId, @Nullable String name) throws DBException {
|
||||
boolean duplicatedName = Arrays.stream(listAllSharedProjects())
|
||||
.filter(p -> !p.getId().equals(projectId))
|
||||
.map(RMProject::getName)
|
||||
.noneMatch(n -> n.equalsIgnoreCase(name));
|
||||
if (!duplicatedName) {
|
||||
throw new DBException("Project name '" + name + "' is already used");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProject(@NotNull String projectId) throws DBException {
|
||||
try (var projectLock = lockController.lock(projectId, "deleteProject")) {
|
||||
@@ -898,7 +875,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "resourcePropertyUpdate")) {
|
||||
validateResourcePath(resourcePath);
|
||||
RMLocalProject webProject = getWebProject(projectId, false);
|
||||
BaseWebProjectImpl webProject = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, webProject.getMetadataFilePath(),
|
||||
() -> {
|
||||
log.debug("Updating resource property '" + propertyName + "' in project '" + projectId + "'");
|
||||
@@ -919,7 +896,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "resourcePropertyUpdate")) {
|
||||
validateResourcePath(resourcePath);
|
||||
RMLocalProject webProject = getWebProject(projectId, false);
|
||||
BaseWebProjectImpl webProject = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, webProject.getMetadataFilePath(),
|
||||
() -> {
|
||||
log.debug("Updating resource '" + resourcePath + "' properties in project '" + projectId + "'");
|
||||
@@ -953,9 +930,15 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String makeProjectIdFromPath(Path path, RMProjectType type) {
|
||||
String projectName = path.getFileName().toString();
|
||||
return type.getPrefix() + "_" + projectName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected RMProject makeProjectFromId(String projectId, boolean loadPermissions) throws DBException {
|
||||
var projectName = WebRMUtils.parseProjectName(projectId);
|
||||
var projectName = parseProjectName(projectId);
|
||||
var projectPath = getProjectPath(projectId);
|
||||
if (!Files.exists(projectPath)) {
|
||||
if (isPrivateProject(projectId) && isProjectOwner(projectId)) {
|
||||
@@ -992,8 +975,28 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
.flatMap(rmProjectPermission -> rmProjectPermission.getAllPermissions().stream())
|
||||
.toArray(String[]::new);
|
||||
|
||||
RMLocalProject webProject = new RMLocalProject(workspace, new SessionContextImpl(null), path, type);
|
||||
return createRmProjectFromWebProject(path, webProject, allProjectPermissions);
|
||||
RMProject project = new RMProject();
|
||||
String projectName = path.getFileName().toString();
|
||||
project.setName(projectName);
|
||||
project.setId(makeProjectIdFromPath(path, type));
|
||||
project.setType(type);
|
||||
project.setProjectPermissions(allProjectPermissions);
|
||||
if (Files.exists(path)) {
|
||||
try {
|
||||
project.setCreateTime(
|
||||
OffsetDateTime.ofInstant(Files.getLastModifiedTime(path).toInstant(), ZoneId.of("UTC")).toInstant().toEpochMilli());
|
||||
} catch (IOException e) {
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
// Resource types
|
||||
project.setResourceTypes(ResourceTypeRegistry.getInstance().getResourceTypes()
|
||||
.stream()
|
||||
.filter(ResourceTypeDescriptor::isManagable)
|
||||
.map(RMResourceType::new)
|
||||
.toArray(RMResourceType[]::new));
|
||||
|
||||
return project;
|
||||
}
|
||||
|
||||
private void createResourceTypeFolders(Path path) {
|
||||
@@ -1072,7 +1075,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
}
|
||||
|
||||
protected Path getProjectPath(String projectId) throws DBException {
|
||||
RMProjectName project = WebRMUtils.parseProjectName(projectId);
|
||||
RMProjectName project = parseProjectName(projectId);
|
||||
RMProjectType type = project.getType();
|
||||
String projectName = project.getName();
|
||||
switch (type) {
|
||||
@@ -1234,13 +1237,56 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
}
|
||||
}
|
||||
|
||||
public static class RMProjectName {
|
||||
String prefix;
|
||||
String name;
|
||||
|
||||
private RMProjectName(String prefix, String name) {
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public RMProjectType getType() {
|
||||
return RMProjectType.getByPrefix(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
public static RMProjectName parseProjectName(String projectId) throws DBException {
|
||||
if (CommonUtils.isEmpty(projectId)) {
|
||||
throw new DBException("Project id is empty");
|
||||
}
|
||||
return parseProjectNameUnsafe(projectId);
|
||||
}
|
||||
|
||||
private static RMProjectName parseProjectNameUnsafe(String projectId) {
|
||||
String prefix;
|
||||
String name;
|
||||
int divPos = projectId.indexOf("_");
|
||||
if (divPos < 0) {
|
||||
prefix = RMProjectType.USER.getPrefix();
|
||||
name = projectId;
|
||||
} else {
|
||||
prefix = projectId.substring(0, divPos);
|
||||
name = projectId.substring(divPos + 1);
|
||||
}
|
||||
return new RMProjectName(prefix, name);
|
||||
}
|
||||
|
||||
public static boolean isGlobalProject(String projectId) {
|
||||
RMProjectName rmProjectName = WebRMUtils.parseProjectNameUnsafe(projectId);
|
||||
RMProjectName rmProjectName = parseProjectNameUnsafe(projectId);
|
||||
return RMProjectType.GLOBAL.getPrefix().equals(rmProjectName.getPrefix());
|
||||
}
|
||||
|
||||
public static boolean isPrivateProject(String projectId) {
|
||||
RMProjectName rmProjectName = WebRMUtils.parseProjectNameUnsafe(projectId);
|
||||
RMProjectName rmProjectName = parseProjectNameUnsafe(projectId);
|
||||
return RMProjectType.USER.getPrefix().equals(rmProjectName.getPrefix());
|
||||
}
|
||||
|
||||
@@ -1251,32 +1297,9 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
}
|
||||
|
||||
public static boolean isProjectOwner(String projectId, String userId) {
|
||||
RMProjectName rmProjectName = WebRMUtils.parseProjectNameUnsafe(projectId);
|
||||
RMProjectName rmProjectName = parseProjectNameUnsafe(projectId);
|
||||
return RMProjectType.USER.getPrefix().equals(rmProjectName.getPrefix()) &&
|
||||
rmProjectName.name.equals(userId);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static RMProject createRmProjectFromWebProject(Path path, RMLocalProject webProject, String[] allProjectPermissions) {
|
||||
RMProject project = WebRMUtils.createRmProjectFromWebProject(webProject);
|
||||
project.setProjectPermissions(allProjectPermissions);
|
||||
if (Files.exists(path)) {
|
||||
try {
|
||||
project.setCreateTime(
|
||||
OffsetDateTime.ofInstant(Files.getLastModifiedTime(path).toInstant(), ZoneId.of("UTC")).toInstant().toEpochMilli());
|
||||
} catch (IOException e) {
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
// Resource types
|
||||
project.setResourceTypes(ResourceTypeRegistry.getInstance().getResourceTypes()
|
||||
.stream()
|
||||
.filter(ResourceTypeDescriptor::isManagable)
|
||||
.map(RMResourceType::new)
|
||||
.toArray(RMResourceType[]::new));
|
||||
|
||||
return project;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 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.model.rm.local;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
import org.jkiss.dbeaver.model.app.DBPWorkspace;
|
||||
import org.jkiss.dbeaver.model.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.impl.app.BaseProjectImpl;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
import org.jkiss.dbeaver.model.rm.RMUtils;
|
||||
import org.jkiss.dbeaver.registry.DataSourceRegistry;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.Pair;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
public class RMLocalProject extends BaseProjectImpl {
|
||||
@NotNull
|
||||
private final Path projectPath;
|
||||
@NotNull
|
||||
private final RMProjectType projectType;
|
||||
|
||||
public RMLocalProject(
|
||||
@NotNull DBPWorkspace workspace,
|
||||
@Nullable SMSessionContext sessionContext,
|
||||
@NotNull Path projectPath,
|
||||
@NotNull RMProjectType type
|
||||
) {
|
||||
super(workspace, sessionContext);
|
||||
this.projectPath = projectPath;
|
||||
this.projectType = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getId() {
|
||||
return RMUtils.makeProjectIdFromPath(projectPath, projectType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
Object projectName = this.getProjectProperty(PROP_PROJECT_NAME);
|
||||
if (projectName != null) {
|
||||
return projectName.toString();
|
||||
}
|
||||
return projectPath.getFileName().toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Path getAbsolutePath() {
|
||||
return projectPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensureOpen() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseSecretStorage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Path getMetadataFilePath() {
|
||||
return getMetadataPath().resolve(METADATA_STORAGE_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for Bulk Update of resources properties paths
|
||||
*
|
||||
* @param oldToNewPaths collection of OldPath to NewPath pairs
|
||||
*/
|
||||
public void moveResourcePropertiesBatch(@NotNull Collection<Pair<String, String>> oldToNewPaths) {
|
||||
loadMetadata();
|
||||
synchronized (metadataSync) {
|
||||
for (var pathsPair : oldToNewPaths) {
|
||||
final var oldResourcePath = CommonUtils.normalizeResourcePath(pathsPair.getFirst());
|
||||
final var newResourcePath = CommonUtils.normalizeResourcePath(pathsPair.getSecond());
|
||||
final var resProps = resourceProperties.remove(oldResourcePath);
|
||||
if (resProps != null) {
|
||||
resourceProperties.put(newResourcePath, resProps);
|
||||
}
|
||||
}
|
||||
}
|
||||
flushMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for Bulk Remove of resources properties
|
||||
*/
|
||||
public boolean resetResourcesPropertiesBatch(@NotNull Collection<String> resourcesPaths) {
|
||||
loadMetadata();
|
||||
boolean propertiesChanged = false;
|
||||
synchronized (metadataSync) {
|
||||
for (var resourcePath : resourcesPaths) {
|
||||
var removedProperties = resourceProperties.remove(CommonUtils.normalizeResourcePath(resourcePath));
|
||||
if (removedProperties != null) {
|
||||
propertiesChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (propertiesChanged) {
|
||||
flushMetadata();
|
||||
}
|
||||
return propertiesChanged;
|
||||
}
|
||||
|
||||
public boolean canUpdateProjectName() {
|
||||
return RMProjectType.SHARED.equals(projectType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected DBPDataSourceRegistry createDataSourceRegistry() {
|
||||
return new DataSourceRegistry<>(this);
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 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.model.rm.local;
|
||||
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
|
||||
public class RMProjectName {
|
||||
String prefix;
|
||||
String name;
|
||||
|
||||
public RMProjectName(String prefix, String name) {
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public RMProjectType getType() {
|
||||
return RMProjectType.getByPrefix(prefix);
|
||||
}
|
||||
}
|
||||
+1
-8
@@ -30,7 +30,6 @@ import org.jkiss.dbeaver.model.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.auth.impl.AbstractSessionPersistent;
|
||||
import org.jkiss.dbeaver.model.meta.Property;
|
||||
import org.jkiss.dbeaver.model.security.user.SMTeam;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectInfo;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSEvent;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSEventDeleteTempFile;
|
||||
import org.jkiss.dbeaver.model.websocket.event.session.WSSessionExpiredEvent;
|
||||
@@ -58,7 +57,7 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
|
||||
protected volatile long lastAccessTime;
|
||||
|
||||
private final List<CBWebSessionEventHandler> sessionEventHandlers = new CopyOnWriteArrayList<>();
|
||||
private WebSessionEventsFilter eventsFilter;
|
||||
private WebSessionEventsFilter eventsFilter = new WebSessionEventsFilter();
|
||||
private final WebSessionWorkspace workspace;
|
||||
|
||||
public BaseWebSession(@NotNull String id, @NotNull ServletApplication application) throws DBException {
|
||||
@@ -69,7 +68,6 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
|
||||
this.workspace = createWebWorkspace();
|
||||
this.workspace.getAuthContext().addSession(this);
|
||||
this.userContext = createUserContext();
|
||||
this.eventsFilter = new WebSessionEventsFilter(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -235,11 +233,6 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
|
||||
userContext.getAccessibleProjectIds().add(projectId);
|
||||
}
|
||||
|
||||
public void updateSessionProject(@NotNull String projectId, @NotNull RMProjectInfo rmProjectInfo) throws DBException {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void removeSessionProject(@Nullable String projectId) throws DBException {
|
||||
userContext.getAccessibleProjectIds().remove(projectId);
|
||||
}
|
||||
|
||||
+1
-2
@@ -18,10 +18,9 @@ package io.cloudbeaver.model.session;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.utils.HttpConstants;
|
||||
|
||||
public class WebHttpRequestInfo {
|
||||
public static final String USER_AGENT = HttpConstants.HEADER_USER_AGENT;
|
||||
public static final String USER_AGENT = "User-Agent";
|
||||
|
||||
@Nullable
|
||||
private final String id;
|
||||
|
||||
+8
-21
@@ -49,7 +49,10 @@ import org.jkiss.dbeaver.model.fs.DBFFileSystemManager;
|
||||
import org.jkiss.dbeaver.model.meta.Association;
|
||||
import org.jkiss.dbeaver.model.meta.Property;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNModel;
|
||||
import org.jkiss.dbeaver.model.rm.*;
|
||||
import org.jkiss.dbeaver.model.rm.RMController;
|
||||
import org.jkiss.dbeaver.model.rm.RMProject;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
import org.jkiss.dbeaver.model.rm.RMUtils;
|
||||
import org.jkiss.dbeaver.model.runtime.AbstractJob;
|
||||
import org.jkiss.dbeaver.model.runtime.BaseProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
@@ -304,7 +307,7 @@ public class WebSession extends BaseWebSession
|
||||
for (RMProject project : rmProjects) {
|
||||
createWebProject(project);
|
||||
}
|
||||
if (user == null && application.isAnonymousAccessEnabled()) {
|
||||
if (user == null && application.getAppConfiguration().isAnonymousAccessEnabled()) {
|
||||
WebProjectImpl anonymousProject = createWebProject(RMUtils.createAnonymousProject());
|
||||
anonymousProject.setInMemory(true);
|
||||
}
|
||||
@@ -324,7 +327,6 @@ public class WebSession extends BaseWebSession
|
||||
} else {
|
||||
sessionProject = createSessionProject(project);
|
||||
}
|
||||
sessionProject.refreshProjectSettings();
|
||||
// do not load data sources for anonymous project
|
||||
if (project.getType() == RMProjectType.USER && userContext.getUser() == null) {
|
||||
sessionProject.setInMemory(true);
|
||||
@@ -397,10 +399,9 @@ public class WebSession extends BaseWebSession
|
||||
|
||||
|
||||
private synchronized void authAsAnonymousUser() throws DBException {
|
||||
if (!application.isAnonymousAccessEnabled()) {
|
||||
if (!application.getAppConfiguration().isAnonymousAccessEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SMAuthInfo authInfo = getSecurityController().authenticateAnonymousUser(this.id, getSessionParameters(), CB_SESSION_TYPE);
|
||||
updateSMSession(authInfo);
|
||||
notifySessionAuthChange();
|
||||
@@ -793,7 +794,7 @@ public class WebSession extends BaseWebSession
|
||||
}
|
||||
}
|
||||
|
||||
public List<WebAuthInfo> removeAuthInfo(String providerId, boolean needResetUserState) throws DBException {
|
||||
public List<WebAuthInfo> removeAuthInfo(String providerId) throws DBException {
|
||||
List<WebAuthInfo> oldInfo;
|
||||
if (providerId == null) {
|
||||
oldInfo = clearAuthTokens();
|
||||
@@ -806,16 +807,12 @@ public class WebSession extends BaseWebSession
|
||||
oldInfo = List.of();
|
||||
}
|
||||
}
|
||||
if (authTokens.isEmpty() && needResetUserState) {
|
||||
if (authTokens.isEmpty()) {
|
||||
resetUserState();
|
||||
}
|
||||
return oldInfo;
|
||||
}
|
||||
|
||||
public List<WebAuthInfo> removeAuthInfo(String providerId) throws DBException {
|
||||
return removeAuthInfo(providerId, true);
|
||||
}
|
||||
|
||||
public List<DBACredentialsProvider> getContextCredentialsProviders() {
|
||||
return getAdapters(DBACredentialsProvider.class);
|
||||
}
|
||||
@@ -984,16 +981,6 @@ public class WebSession extends BaseWebSession
|
||||
createWebProject(rmProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSessionProject(@NotNull String projectId, @NotNull RMProjectInfo rmProjectInfo) throws DBException {
|
||||
super.updateSessionProject(projectId, rmProjectInfo);
|
||||
var project = getProjectById(projectId);
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
project.updateProjectInfo(rmProjectInfo.getName(), rmProjectInfo.getDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSessionProject(@Nullable String projectId) throws DBException {
|
||||
super.removeSessionProject(projectId);
|
||||
|
||||
+1
-3
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2010-2024 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.
|
||||
@@ -118,8 +118,6 @@ public class WebSessionAuthProcessor {
|
||||
// We may need to associate new credentials with active user
|
||||
if (linkWithActiveUser) {
|
||||
securityController.setCurrentUserCredentials(authProviderDescriptor.getId(), authAttrs);
|
||||
//link only first(main) credentials
|
||||
alreadyLoggedIn = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-25
@@ -21,37 +21,18 @@ import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSEvent;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSProjectResourceEvent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class WebSessionEventsFilter {
|
||||
private final BaseWebSession session;
|
||||
private final Set<String> subscribedEventTopics = new CopyOnWriteArraySet<>();
|
||||
private final Set<String> subscribedProjectIds = new CopyOnWriteArraySet<>();
|
||||
private final Map<String, List<WebTopicActivityListener>> topicActivityListeners = new ConcurrentHashMap<>();
|
||||
private final Set<String> handledStartTopics = new CopyOnWriteArraySet<>();
|
||||
|
||||
public WebSessionEventsFilter(BaseWebSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public void subscribeOnEventTopic(@Nullable String topic) {
|
||||
if (topic == null) {
|
||||
return;
|
||||
}
|
||||
subscribedEventTopics.add(topic);
|
||||
|
||||
topicActivityListeners
|
||||
.getOrDefault(topic, List.of()).stream()
|
||||
.filter(listener -> !handledStartTopics.contains(listener.getTopicName()))
|
||||
.forEach(listener -> {
|
||||
listener.handelStartSubscriptionTopic(session);
|
||||
handledStartTopics.add(topic);
|
||||
});
|
||||
}
|
||||
|
||||
public void unsubscribeFromEventTopic(@Nullable String topic) {
|
||||
@@ -86,10 +67,4 @@ public class WebSessionEventsFilter {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addTopicSubscribeListener(WebTopicActivityListener listener) {
|
||||
topicActivityListeners
|
||||
.computeIfAbsent(listener.getTopicName(), k -> new CopyOnWriteArrayList<>())
|
||||
.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -62,12 +62,12 @@ public class WebSessionPreferenceStore extends AbstractUserPreferenceStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultString(@NotNull String name) {
|
||||
public String getDefaultString(String name) {
|
||||
return parentStore.getDefaultString(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault(@NotNull String name) {
|
||||
public boolean isDefault(String name) {
|
||||
return !userPreferences.containsKey(name) && parentStore.isDefault(name);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class WebSessionPreferenceStore extends AbstractUserPreferenceStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToDefault(@NotNull String name) {
|
||||
public void setToDefault(String name) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -239,7 +239,7 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
}
|
||||
|
||||
private Set<String> getDefaultPermissions() {
|
||||
return application.isAnonymousAccessEnabled() ? null : Set.of();
|
||||
return application.getAppConfiguration().isAnonymousAccessEnabled() ? null : Set.of();
|
||||
}
|
||||
|
||||
public RMController getRmController() {
|
||||
|
||||
@@ -98,5 +98,4 @@ public class CBConstants {
|
||||
|
||||
public static final String BIND_SESSION_ENABLE = "enable";
|
||||
public static final String BIND_SESSION_DISABLE = "disable";
|
||||
public static final String DEFAULT_CLOUD_PROJECT_NAME = "GlobalConfiguration";
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2010-2024 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.
|
||||
@@ -14,11 +14,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudbeaver.model.session;
|
||||
package io.cloudbeaver.server;
|
||||
|
||||
public interface WebTopicActivityListener {
|
||||
public interface HttpConstants {
|
||||
String CONTENT_TYPE = "Content-Type";
|
||||
|
||||
void handelStartSubscriptionTopic(BaseWebSession session);
|
||||
|
||||
String getTopicName();
|
||||
String TYPE_JSON = "application/json";
|
||||
String HEADER_AUTHORIZATION = "Authorization";
|
||||
}
|
||||
+27
-28
@@ -18,7 +18,6 @@ package io.cloudbeaver.server;
|
||||
|
||||
import io.cloudbeaver.utils.ServletAppUtils;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.impl.preferences.AbstractPreferenceStore;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
|
||||
|
||||
@@ -35,37 +34,37 @@ public class WebServerPreferenceStore extends AbstractPreferenceStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull String name) {
|
||||
public boolean contains(String name) {
|
||||
return productConf().containsKey(name) || parentStore.contains(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(@NotNull String name) {
|
||||
public boolean getBoolean(String name) {
|
||||
return toBoolean(getString(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(@NotNull String name) {
|
||||
public double getDouble(String name) {
|
||||
return toDouble(getString(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(@NotNull String name) {
|
||||
public float getFloat(String name) {
|
||||
return toFloat(getString(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(@NotNull String name) {
|
||||
public int getInt(String name) {
|
||||
return toInt(getString(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(@NotNull String name) {
|
||||
public long getLong(String name) {
|
||||
return toLong(getString(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(@NotNull String name) {
|
||||
public String getString(String name) {
|
||||
Object value = productConf().get(name);
|
||||
if (value == null) {
|
||||
return parentStore.getString(name);
|
||||
@@ -74,38 +73,38 @@ public class WebServerPreferenceStore extends AbstractPreferenceStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDefaultBoolean(@NotNull String name) {
|
||||
public boolean getDefaultBoolean(String name) {
|
||||
return getBoolean(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDefaultDouble(@NotNull String name) {
|
||||
public double getDefaultDouble(String name) {
|
||||
return getDouble(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDefaultFloat(@NotNull String name) {
|
||||
public float getDefaultFloat(String name) {
|
||||
return getFloat(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultInt(@NotNull String name) {
|
||||
public int getDefaultInt(String name) {
|
||||
return getInt(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDefaultLong(@NotNull String name) {
|
||||
public long getDefaultLong(String name) {
|
||||
return getLong(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultString(@NotNull String name) {
|
||||
public String getDefaultString(String name) {
|
||||
// TODO: split product.conf and runtime.product.conf
|
||||
return getString(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault(@NotNull String name) {
|
||||
public boolean isDefault(String name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -115,68 +114,68 @@ public class WebServerPreferenceStore extends AbstractPreferenceStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(@NotNull String name, double value) {
|
||||
public void setDefault(String name, double value) {
|
||||
setDefault(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(@NotNull String name, float value) {
|
||||
public void setDefault(String name, float value) {
|
||||
setDefault(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(@NotNull String name, int value) {
|
||||
public void setDefault(String name, int value) {
|
||||
setDefault(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(@NotNull String name, long value) {
|
||||
public void setDefault(String name, long value) {
|
||||
setDefault(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(@NotNull String name, @Nullable String defaultObject) {
|
||||
public void setDefault(String name, String defaultObject) {
|
||||
// do not store global default properties in product.conf
|
||||
this.parentStore.setDefault(name, defaultObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(@NotNull String name, boolean value) {
|
||||
public void setDefault(String name, boolean value) {
|
||||
setDefault(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToDefault(@NotNull String name) {
|
||||
public void setToDefault(String name) {
|
||||
parentStore.setToDefault(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@NotNull String name, double value) {
|
||||
public void setValue(String name, double value) {
|
||||
parentStore.setValue(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@NotNull String name, float value) {
|
||||
public void setValue(String name, float value) {
|
||||
parentStore.setValue(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@NotNull String name, int value) {
|
||||
public void setValue(String name, int value) {
|
||||
parentStore.setValue(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@NotNull String name, long value) {
|
||||
public void setValue(String name, long value) {
|
||||
parentStore.setValue(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@NotNull String name, @Nullable String value) {
|
||||
public void setValue(String name, String value) {
|
||||
parentStore.setValue(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@NotNull String name, boolean value) {
|
||||
public void setValue(String name, boolean value) {
|
||||
parentStore.setValue(name, value);
|
||||
}
|
||||
|
||||
|
||||
+3
-185
@@ -23,7 +23,6 @@ import com.google.gson.Strictness;
|
||||
import io.cloudbeaver.DBWConstants;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebSessionProjectImpl;
|
||||
import io.cloudbeaver.model.WebConnectionConfig;
|
||||
import io.cloudbeaver.model.WebConnectionInfo;
|
||||
import io.cloudbeaver.model.WebNetworkHandlerConfigInput;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
@@ -31,25 +30,21 @@ import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.DBConstants;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
|
||||
import org.jkiss.dbeaver.model.access.DBAAuthCredentials;
|
||||
import org.jkiss.dbeaver.model.access.DBAAuthCredentialsWithComplexProperties;
|
||||
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
import org.jkiss.dbeaver.model.app.DBPProject;
|
||||
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDataSourceProviderDescriptor;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
import org.jkiss.dbeaver.model.impl.auth.AuthModelDatabaseNativeCredentials;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration;
|
||||
import org.jkiss.dbeaver.model.net.ssh.SSHConstants;
|
||||
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceDisconnectEvent;
|
||||
import org.jkiss.dbeaver.registry.network.NetworkHandlerDescriptor;
|
||||
import org.jkiss.dbeaver.registry.network.NetworkHandlerRegistry;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class WebDataSourceUtils {
|
||||
|
||||
@@ -224,181 +219,4 @@ public class WebDataSourceUtils {
|
||||
}
|
||||
credGson.fromJson(credGson.toJsonTree(properties), credentials.getClass());
|
||||
}
|
||||
|
||||
public static void saveAuthProperties(
|
||||
@NotNull DBPDataSourceContainer dataSourceContainer,
|
||||
@NotNull DBPConnectionConfiguration configuration,
|
||||
@Nullable Map<String, Object> authProperties,
|
||||
boolean saveCredentials,
|
||||
boolean sharedCredentials
|
||||
) {
|
||||
saveAuthProperties(dataSourceContainer, configuration, authProperties, saveCredentials, sharedCredentials, false);
|
||||
}
|
||||
|
||||
public static void saveAuthProperties(
|
||||
@NotNull DBPDataSourceContainer dataSourceContainer,
|
||||
@NotNull DBPConnectionConfiguration configuration,
|
||||
@Nullable Map<String, Object> authProperties,
|
||||
boolean saveCredentials,
|
||||
boolean sharedCredentials,
|
||||
boolean isTest
|
||||
) {
|
||||
dataSourceContainer.setSavePassword(saveCredentials);
|
||||
dataSourceContainer.setSharedCredentials(sharedCredentials);
|
||||
if (!saveCredentials) {
|
||||
// Reset credentials
|
||||
if (authProperties == null) {
|
||||
authProperties = new LinkedHashMap<>();
|
||||
}
|
||||
authProperties.replace(AuthModelDatabaseNativeCredentials.PROP_USER_PASSWORD, null);
|
||||
dataSourceContainer.resetPassword();
|
||||
} else {
|
||||
if (authProperties == null) {
|
||||
// No changes
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
// Read save credentials
|
||||
DBAAuthCredentials credentials = configuration.getAuthModel().loadCredentials(dataSourceContainer, configuration);
|
||||
|
||||
if (isTest) {
|
||||
var currentAuthProps = new HashMap<String, String>();
|
||||
for (Map.Entry<String, Object> stringObjectEntry : authProperties.entrySet()) {
|
||||
var value = stringObjectEntry.getValue() == null ? null : stringObjectEntry.getValue().toString();
|
||||
currentAuthProps.put(stringObjectEntry.getKey(), value);
|
||||
}
|
||||
configuration.setAuthProperties(currentAuthProps);
|
||||
}
|
||||
if (!authProperties.isEmpty()) {
|
||||
updateCredentialsFromProperties(credentials, authProperties);
|
||||
}
|
||||
|
||||
configuration.getAuthModel().saveCredentials(dataSourceContainer, configuration, credentials);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setConnectionConfiguration(
|
||||
@NotNull DBPDriver driver,
|
||||
@NotNull DBPConnectionConfiguration dsConfig,
|
||||
@NotNull WebConnectionConfig config
|
||||
) {
|
||||
setMainProperties(dsConfig, config);
|
||||
if (config.getProperties() != null) {
|
||||
Map<String, String> newProps = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> pe : config.getProperties().entrySet()) {
|
||||
newProps.put(pe.getKey(), CommonUtils.toString(pe.getValue()));
|
||||
}
|
||||
dsConfig.setProperties(newProps);
|
||||
}
|
||||
if (config.getUserName() != null) {
|
||||
dsConfig.setUserName(config.getUserName());
|
||||
}
|
||||
if (config.getUserPassword() != null) {
|
||||
dsConfig.setUserPassword(config.getUserPassword());
|
||||
}
|
||||
if (config.getAuthModelId() != null) {
|
||||
dsConfig.setAuthModelId(config.getAuthModelId());
|
||||
}
|
||||
if (config.getKeepAliveInterval() >= 0) {
|
||||
dsConfig.setKeepAliveInterval(config.getKeepAliveInterval());
|
||||
}
|
||||
if (config.isDefaultAutoCommit() != null) {
|
||||
dsConfig.getBootstrap().setDefaultAutoCommit(config.isDefaultAutoCommit());
|
||||
}
|
||||
dsConfig.getBootstrap().setDefaultCatalogName(config.getDefaultCatalogName());
|
||||
dsConfig.getBootstrap().setDefaultSchemaName(config.getDefaultSchemaName());
|
||||
// Save provider props
|
||||
if (config.getProviderProperties() != null) {
|
||||
dsConfig.setProviderProperties(new LinkedHashMap<>());
|
||||
for (Map.Entry<String, Object> e : config.getProviderProperties().entrySet()) {
|
||||
dsConfig.setProviderProperty(e.getKey(), CommonUtils.toString(e.getValue()));
|
||||
}
|
||||
}
|
||||
if (config.getConfigurationType() != null) {
|
||||
dsConfig.setConfigurationType(config.getConfigurationType());
|
||||
}
|
||||
if (CommonUtils.isEmpty(config.getUrl())) {
|
||||
dsConfig.setUrl(driver.getConnectionURL(dsConfig));
|
||||
}
|
||||
// Save network handlers
|
||||
if (config.getNetworkHandlersConfig() != null) {
|
||||
for (WebNetworkHandlerConfigInput nhc : config.getNetworkHandlersConfig()) {
|
||||
DBWHandlerConfiguration handlerConfig = dsConfig.getHandler(nhc.getId());
|
||||
if (handlerConfig == null) {
|
||||
NetworkHandlerDescriptor handlerDescriptor = NetworkHandlerRegistry.getInstance().getDescriptor(nhc.getId());
|
||||
if (handlerDescriptor == null) {
|
||||
log.warn("Can't find network handler '" + nhc.getId() + "'");
|
||||
continue;
|
||||
} else {
|
||||
handlerConfig = new DBWHandlerConfiguration(handlerDescriptor, null);
|
||||
WebDataSourceUtils.updateHandlerConfig(handlerConfig, nhc);
|
||||
}
|
||||
} else {
|
||||
WebDataSourceUtils.updateHandlerConfig(handlerConfig, nhc);
|
||||
}
|
||||
dsConfig.updateHandler(handlerConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setMainProperties(@NotNull DBPConnectionConfiguration dsConfig, @NotNull WebConnectionConfig config) {
|
||||
if (CommonUtils.isNotEmpty(config.getUrl())) {
|
||||
dsConfig.setUrl(config.getUrl());
|
||||
return;
|
||||
}
|
||||
if (config.getMainPropertyValues() != null) {
|
||||
for (Map.Entry<String, Object> e : config.getMainPropertyValues().entrySet()) {
|
||||
if (e.getValue() == null) {
|
||||
continue;
|
||||
}
|
||||
switch (e.getKey()) {
|
||||
case DBConstants.PROP_HOST -> dsConfig.setHostName(CommonUtils.toString(e.getValue()));
|
||||
case DBConstants.PROP_PORT -> dsConfig.setHostPort(CommonUtils.toString(e.getValue()));
|
||||
case DBConstants.PROP_DATABASE -> dsConfig.setDatabaseName(CommonUtils.toString(e.getValue()));
|
||||
case DBConstants.PROP_SERVER -> dsConfig.setServerName(CommonUtils.toString(e.getValue()));
|
||||
default -> throw new IllegalStateException("Unexpected value: " + e.getKey());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (config.getHost() != null) {
|
||||
dsConfig.setHostName(config.getHost());
|
||||
}
|
||||
if (config.getPort() != null) {
|
||||
dsConfig.setHostPort(config.getPort());
|
||||
}
|
||||
if (config.getDatabaseName() != null) {
|
||||
dsConfig.setDatabaseName(config.getDatabaseName());
|
||||
}
|
||||
if (config.getServerName() != null) {
|
||||
dsConfig.setServerName(config.getServerName());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DBPDriver getDriverById(String id) throws DBWebException {
|
||||
int divPos = id.indexOf(':');
|
||||
if (divPos < 0) {
|
||||
throw new DBWebException("Bad driver id [" + id + "]");
|
||||
}
|
||||
String dsId = id.substring(0, divPos);
|
||||
String driverId = id.substring(divPos + 1);
|
||||
DBPDataSourceProviderDescriptor dsProvider = DBWorkbench.getPlatform().getDataSourceProviderRegistry().getDataSourceProvider(dsId);
|
||||
if (dsProvider == null) {
|
||||
throw new DBWebException("Data source provider '" + dsId + "' not found");
|
||||
}
|
||||
DBPDriver driver = dsProvider.getDriver(driverId);
|
||||
if (driver == null) {
|
||||
throw new DBWebException("Driver '" + driverId + "' not found in provider '" + dsId + "'");
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
|
||||
public static String getConnectionContainerInfo(@Nullable DBPDataSourceContainer container) {
|
||||
if (container == null) {
|
||||
return null;
|
||||
}
|
||||
return container.getName() + " [" + container.getId() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package io.cloudbeaver.utils;
|
||||
|
||||
import io.cloudbeaver.model.rm.local.RMProjectName;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.model.app.DBPProject;
|
||||
import org.jkiss.dbeaver.model.rm.RMProject;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
public class WebRMUtils {
|
||||
|
||||
public static RMProject createRmProjectFromWebProject(@NotNull DBPProject project) {
|
||||
RMProject rmProject = new RMProject();
|
||||
rmProject.setId(project.getId());
|
||||
rmProject.setName(project.getName());
|
||||
rmProject.setDescription(project.getDescription());
|
||||
rmProject.setType(parseProjectNameUnsafe(rmProject.getId()).getType());
|
||||
return rmProject;
|
||||
}
|
||||
|
||||
public static RMProjectName parseProjectName(@NotNull String projectId) throws DBException {
|
||||
if (CommonUtils.isEmpty(projectId)) {
|
||||
throw new DBException("Project id is empty");
|
||||
}
|
||||
return parseProjectNameUnsafe(projectId);
|
||||
}
|
||||
|
||||
public static RMProjectName parseProjectNameUnsafe(String projectId) {
|
||||
String prefix;
|
||||
String name;
|
||||
int divPos = projectId.indexOf("_");
|
||||
if (divPos < 0) {
|
||||
prefix = RMProjectType.USER.getPrefix();
|
||||
name = projectId;
|
||||
} else {
|
||||
prefix = projectId.substring(0, divPos);
|
||||
name = projectId.substring(divPos + 1);
|
||||
}
|
||||
return new RMProjectName(prefix, name);
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 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.websocket;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.websocket.WSConstants;
|
||||
import org.jkiss.dbeaver.model.websocket.event.session.WSAbstractSessionEvent;
|
||||
|
||||
public class WSServerNotificationEvent extends WSAbstractSessionEvent {
|
||||
|
||||
public static final String EVENT_ID = "cb_server_notification";
|
||||
private String title;
|
||||
private String message;
|
||||
private WSServerNotificationEventType notificationType;
|
||||
|
||||
public WSServerNotificationEvent(
|
||||
@Nullable String title,
|
||||
@Nullable String message,
|
||||
@NotNull WSServerNotificationEventType notificationType
|
||||
) {
|
||||
super(EVENT_ID, WSConstants.TOPIC_USER_NOTIFICATION);
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
this.notificationType = notificationType;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public WSServerNotificationEventType getNotificationType() {
|
||||
return notificationType;
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 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.websocket;
|
||||
|
||||
public enum WSServerNotificationEventType {
|
||||
INFO,
|
||||
ERROR,
|
||||
LOADING,
|
||||
CUSTOM
|
||||
}
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Community Product
|
||||
Bundle-SymbolicName: io.cloudbeaver.product.ce;singleton:=true
|
||||
Bundle-Version: 25.2.2.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 25.2.1.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: io.cloudbeaver.server.ce
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.product.ce</artifactId>
|
||||
<version>25.2.2-SNAPSHOT</version>
|
||||
<version>25.2.1-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -2,8 +2,8 @@ Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Cloudbeaver Base JDBC drivers
|
||||
Bundle-SymbolicName: io.cloudbeaver.resources.drivers.base;singleton:=true
|
||||
Bundle-Version: 1.0.131.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.130.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Automatic-Module-Name: io.cloudbeaver.resources.drivers.base
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.resources.drivers.base</artifactId>
|
||||
<version>1.0.131-SNAPSHOT</version>
|
||||
<version>1.0.130-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</project>
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver CE Server
|
||||
Bundle-SymbolicName: io.cloudbeaver.server.ce;singleton:=true
|
||||
Bundle-Version: 25.2.2.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 25.2.1.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Activator: io.cloudbeaver.server.CBPlatformActivator
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.server.ce</artifactId>
|
||||
<version>25.2.2-SNAPSHOT</version>
|
||||
<version>25.2.1-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+8
-2
@@ -30,6 +30,8 @@ import io.cloudbeaver.registry.WebDriverRegistry;
|
||||
import io.cloudbeaver.registry.WebFeatureRegistry;
|
||||
import io.cloudbeaver.registry.WebServiceRegistry;
|
||||
import io.cloudbeaver.server.jetty.CBJettyServer;
|
||||
import io.cloudbeaver.service.ConnectionController;
|
||||
import io.cloudbeaver.service.ConnectionControllerCE;
|
||||
import io.cloudbeaver.service.DBWServiceInitializer;
|
||||
import io.cloudbeaver.service.DBWServiceServerConfigurator;
|
||||
import io.cloudbeaver.service.session.CBSessionManager;
|
||||
@@ -503,10 +505,9 @@ public abstract class CBApplication<T extends CBServerConfig>
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDefaultProjectName() {
|
||||
return CBConstants.DEFAULT_CLOUD_PROJECT_NAME;
|
||||
return "GlobalConfiguration";
|
||||
}
|
||||
|
||||
public boolean isDevelMode() {
|
||||
@@ -783,6 +784,11 @@ public abstract class CBApplication<T extends CBServerConfig>
|
||||
return new CBWebServerConfig(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionController getConnectionController() {
|
||||
return new ConnectionControllerCE();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ServletSystemInformationCollector<?> getSystemInformationCollector() {
|
||||
|
||||
+3
-7
@@ -36,6 +36,8 @@ import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.auth.SMAuthInfo;
|
||||
import org.jkiss.dbeaver.model.security.user.SMAuthPermissions;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSAbstractEvent;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSUserDeletedEvent;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSUserDisabledEvent;
|
||||
import org.jkiss.dbeaver.model.websocket.event.session.WSSessionStateEvent;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
@@ -70,19 +72,13 @@ public class CBSessionManager implements WebAppSessionManager {
|
||||
|
||||
@Override
|
||||
public BaseWebSession closeSession(@NotNull String sessionId) {
|
||||
return closeSession(sessionId, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseWebSession closeSession(@NotNull String sessionId, boolean sendSessionExpiredEvent) {
|
||||
BaseWebSession webSession;
|
||||
synchronized (sessionMap) {
|
||||
webSession = sessionMap.remove(sessionId);
|
||||
}
|
||||
if (webSession != null) {
|
||||
log.debug("> Close session '" + sessionId + "'");
|
||||
webSession.close(true, sendSessionExpiredEvent);
|
||||
|
||||
webSession.close();
|
||||
return webSession;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Server
|
||||
Bundle-SymbolicName: io.cloudbeaver.server;singleton:=true
|
||||
Bundle-Version: 25.2.2.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 25.2.1.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: org.eclipse.core.runtime;visibility:=reexport,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.server</artifactId>
|
||||
<version>25.2.2-SNAPSHOT</version>
|
||||
<version>25.2.1-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -45,8 +45,6 @@ enum CBServerEventId {
|
||||
|
||||
"Resource manager project added"
|
||||
cb_rm_project_added,
|
||||
"Resource manager project added"
|
||||
cb_rm_project_updated,
|
||||
"Resource manager project removed"
|
||||
cb_rm_project_removed,
|
||||
|
||||
@@ -66,9 +64,7 @@ enum CBServerEventId {
|
||||
"Session async task info updated"
|
||||
cb_session_task_info_updated @since(version: "24.3.1"),
|
||||
"Workspace configuration updated"
|
||||
cb_workspace_config_changed @since(version: "25.1.1"),
|
||||
"Server notification"
|
||||
cb_server_notification@since(version: "25.2.1")
|
||||
cb_workspace_config_changed @since(version: "25.1.1")
|
||||
}
|
||||
|
||||
"Events sent by client"
|
||||
@@ -100,7 +96,6 @@ enum CBEventTopic {
|
||||
cb_transaction @since(version: "24.3.3"),
|
||||
cb_workspace_configuration @since(version: "25.1.1")
|
||||
cb_ai @since(version: "25.1.1")
|
||||
cb_notification @since(version: "25.2.1")
|
||||
}
|
||||
|
||||
"Base server event interface"
|
||||
@@ -279,21 +274,6 @@ type WSAIChatMessageErrorEvent implements CBServerEvent @since(version: "25.1.1"
|
||||
errorMessage: String
|
||||
}
|
||||
|
||||
enum WSServerNotificationEventType {
|
||||
INFO
|
||||
ERROR
|
||||
LOADING
|
||||
CUSTOM
|
||||
}
|
||||
"General event for showing user notification"
|
||||
type WSServerNotificationEvent implements CBServerEvent @since(version: "25.2.1") {
|
||||
id: CBServerEventId!
|
||||
topicId: CBEventTopic!
|
||||
title: String
|
||||
message: String
|
||||
notificationType: WSServerNotificationEventType!
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
emptyEvent: Boolean
|
||||
}
|
||||
|
||||
@@ -119,8 +119,6 @@ type DatabaseStructContainers {
|
||||
schemaList: [ NavigatorNodeInfo! ]!
|
||||
supportsCatalogChange: Boolean!
|
||||
supportsSchemaChange: Boolean!
|
||||
defaultCatalog: String @since(version: "25.2.2")
|
||||
defaultSchema: String @since(version: "25.2.2")
|
||||
}
|
||||
|
||||
####################################################
|
||||
|
||||
@@ -18,7 +18,10 @@ package io.cloudbeaver;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.cloudbeaver.model.WebConnectionConfig;
|
||||
import io.cloudbeaver.model.WebNetworkHandlerConfigInput;
|
||||
import io.cloudbeaver.model.WebPropertyInfo;
|
||||
import io.cloudbeaver.model.app.ServletApplication;
|
||||
import io.cloudbeaver.model.app.WebAppConfiguration;
|
||||
import io.cloudbeaver.model.rm.DBNResourceManagerResource;
|
||||
import io.cloudbeaver.model.session.WebActionParameters;
|
||||
@@ -27,6 +30,7 @@ import io.cloudbeaver.model.utils.ConfigurationUtils;
|
||||
import io.cloudbeaver.registry.WebAuthProviderDescriptor;
|
||||
import io.cloudbeaver.registry.WebAuthProviderRegistry;
|
||||
import io.cloudbeaver.server.WebAppUtils;
|
||||
import io.cloudbeaver.server.WebApplication;
|
||||
import io.cloudbeaver.service.navigator.WebPropertyFilter;
|
||||
import io.cloudbeaver.utils.ServletAppUtils;
|
||||
import io.cloudbeaver.utils.WebCommonUtils;
|
||||
@@ -35,14 +39,25 @@ import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.DBConstants;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
|
||||
import org.jkiss.dbeaver.model.access.DBAAuthCredentials;
|
||||
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
import org.jkiss.dbeaver.model.app.DBPProject;
|
||||
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
import org.jkiss.dbeaver.model.impl.auth.AuthModelDatabaseNativeCredentials;
|
||||
import org.jkiss.dbeaver.model.navigator.*;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
|
||||
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
|
||||
import org.jkiss.dbeaver.registry.DataSourceProviderDescriptor;
|
||||
import org.jkiss.dbeaver.registry.DataSourceProviderRegistry;
|
||||
import org.jkiss.dbeaver.registry.driver.DriverDescriptor;
|
||||
import org.jkiss.dbeaver.registry.network.NetworkHandlerDescriptor;
|
||||
import org.jkiss.dbeaver.registry.network.NetworkHandlerRegistry;
|
||||
import org.jkiss.dbeaver.runtime.properties.PropertyCollector;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
@@ -59,6 +74,25 @@ public class WebServiceUtils extends WebCommonUtils {
|
||||
|
||||
private static final Gson gson = new GsonBuilder().create();
|
||||
|
||||
@NotNull
|
||||
public static DBPDriver getDriverById(String id) throws DBWebException {
|
||||
int divPos = id.indexOf(':');
|
||||
if (divPos < 0) {
|
||||
throw new DBWebException("Bad driver id [" + id + "]");
|
||||
}
|
||||
String dsId = id.substring(0, divPos);
|
||||
String driverId = id.substring(divPos + 1);
|
||||
DataSourceProviderDescriptor dsProvider = DataSourceProviderRegistry.getInstance().getDataSourceProvider(dsId);
|
||||
if (dsProvider == null) {
|
||||
throw new DBWebException("Data source provider '" + dsId + "' not found");
|
||||
}
|
||||
DriverDescriptor driver = dsProvider.getDriver(driverId);
|
||||
if (driver == null) {
|
||||
throw new DBWebException("Driver '" + driverId + "' not found in provider '" + dsId + "'");
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DBPDataSourceRegistry getGlobalDataSourceRegistry() throws DBWebException {
|
||||
return WebDataSourceUtils.getGlobalDataSourceRegistry();
|
||||
@@ -68,6 +102,198 @@ public class WebServiceUtils extends WebCommonUtils {
|
||||
return WebServiceUtils.class.getClassLoader().getResourceAsStream(path);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DBPDataSourceContainer createConnectionFromConfig(WebConnectionConfig config, DBPDataSourceRegistry registry) throws DBWebException {
|
||||
DBPDataSourceContainer newDataSource;
|
||||
if (!CommonUtils.isEmpty(config.getDriverId())) {
|
||||
String driverId = config.getDriverId();
|
||||
if (CommonUtils.isEmpty(driverId)) {
|
||||
throw new DBWebException("Driver not specified");
|
||||
}
|
||||
DBPDriver driver = getDriverById(driverId);
|
||||
|
||||
DBPConnectionConfiguration dsConfig = new DBPConnectionConfiguration();
|
||||
|
||||
setConnectionConfiguration(driver, dsConfig, config);
|
||||
|
||||
newDataSource = registry.createDataSource(driver, dsConfig);
|
||||
} else {
|
||||
throw new DBWebException("Template connection or driver must be specified");
|
||||
}
|
||||
|
||||
newDataSource.setSavePassword(true);
|
||||
newDataSource.setName(config.getName());
|
||||
newDataSource.setDescription(config.getDescription());
|
||||
newDataSource.setConnectionReadOnly(config.isReadOnly());
|
||||
if (config.getFolder() != null) {
|
||||
newDataSource.setFolder(registry.getFolder(config.getFolder()));
|
||||
}
|
||||
|
||||
ServletApplication app = ServletAppUtils.getServletApplication();
|
||||
if (app instanceof WebApplication webApplication) {
|
||||
((DataSourceDescriptor) newDataSource).setNavigatorSettings(
|
||||
webApplication.getAppConfiguration().getDefaultNavigatorSettings());
|
||||
}
|
||||
|
||||
saveAuthProperties(
|
||||
newDataSource,
|
||||
newDataSource.getConnectionConfiguration(),
|
||||
config.getCredentials(),
|
||||
config.isSaveCredentials(),
|
||||
config.isSharedCredentials()
|
||||
);
|
||||
|
||||
|
||||
return newDataSource;
|
||||
}
|
||||
|
||||
public static void setConnectionConfiguration(DBPDriver driver, DBPConnectionConfiguration dsConfig, WebConnectionConfig config) {
|
||||
setMainProperties(dsConfig, config);
|
||||
if (config.getProperties() != null) {
|
||||
Map<String, String> newProps = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> pe : config.getProperties().entrySet()) {
|
||||
newProps.put(pe.getKey(), CommonUtils.toString(pe.getValue()));
|
||||
}
|
||||
dsConfig.setProperties(newProps);
|
||||
}
|
||||
if (config.getUserName() != null) {
|
||||
dsConfig.setUserName(config.getUserName());
|
||||
}
|
||||
if (config.getUserPassword() != null) {
|
||||
dsConfig.setUserPassword(config.getUserPassword());
|
||||
}
|
||||
if (config.getAuthModelId() != null) {
|
||||
dsConfig.setAuthModelId(config.getAuthModelId());
|
||||
}
|
||||
if (config.getKeepAliveInterval() >= 0) {
|
||||
dsConfig.setKeepAliveInterval(config.getKeepAliveInterval());
|
||||
}
|
||||
if (config.isDefaultAutoCommit() != null) {
|
||||
dsConfig.getBootstrap().setDefaultAutoCommit(config.isDefaultAutoCommit());
|
||||
}
|
||||
dsConfig.getBootstrap().setDefaultCatalogName(config.getDefaultCatalogName());
|
||||
dsConfig.getBootstrap().setDefaultSchemaName(config.getDefaultSchemaName());
|
||||
// Save provider props
|
||||
if (config.getProviderProperties() != null) {
|
||||
dsConfig.setProviderProperties(new LinkedHashMap<>());
|
||||
for (Map.Entry<String, Object> e : config.getProviderProperties().entrySet()) {
|
||||
dsConfig.setProviderProperty(e.getKey(), CommonUtils.toString(e.getValue()));
|
||||
}
|
||||
}
|
||||
if (config.getConfigurationType() != null) {
|
||||
dsConfig.setConfigurationType(config.getConfigurationType());
|
||||
}
|
||||
if (CommonUtils.isEmpty(config.getUrl())) {
|
||||
dsConfig.setUrl(driver.getConnectionURL(dsConfig));
|
||||
}
|
||||
// Save network handlers
|
||||
if (config.getNetworkHandlersConfig() != null) {
|
||||
for (WebNetworkHandlerConfigInput nhc : config.getNetworkHandlersConfig()) {
|
||||
DBWHandlerConfiguration handlerConfig = dsConfig.getHandler(nhc.getId());
|
||||
if (handlerConfig == null) {
|
||||
NetworkHandlerDescriptor handlerDescriptor = NetworkHandlerRegistry.getInstance().getDescriptor(nhc.getId());
|
||||
if (handlerDescriptor == null) {
|
||||
log.warn("Can't find network handler '" + nhc.getId() + "'");
|
||||
continue;
|
||||
} else {
|
||||
handlerConfig = new DBWHandlerConfiguration(handlerDescriptor, null);
|
||||
WebDataSourceUtils.updateHandlerConfig(handlerConfig, nhc);
|
||||
}
|
||||
} else {
|
||||
WebDataSourceUtils.updateHandlerConfig(handlerConfig, nhc);
|
||||
}
|
||||
dsConfig.updateHandler(handlerConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setMainProperties(DBPConnectionConfiguration dsConfig, WebConnectionConfig config) {
|
||||
if (CommonUtils.isNotEmpty(config.getUrl())) {
|
||||
dsConfig.setUrl(config.getUrl());
|
||||
return;
|
||||
}
|
||||
if (config.getMainPropertyValues() != null) {
|
||||
for (Map.Entry<String, Object> e : config.getMainPropertyValues().entrySet()) {
|
||||
if (e.getValue() == null) {
|
||||
continue;
|
||||
}
|
||||
switch (e.getKey()) {
|
||||
case DBConstants.PROP_HOST -> dsConfig.setHostName(CommonUtils.toString(e.getValue()));
|
||||
case DBConstants.PROP_PORT -> dsConfig.setHostPort(CommonUtils.toString(e.getValue()));
|
||||
case DBConstants.PROP_DATABASE -> dsConfig.setDatabaseName(CommonUtils.toString(e.getValue()));
|
||||
case DBConstants.PROP_SERVER -> dsConfig.setServerName(CommonUtils.toString(e.getValue()));
|
||||
default -> throw new IllegalStateException("Unexpected value: " + e.getKey());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (config.getHost() != null) {
|
||||
dsConfig.setHostName(config.getHost());
|
||||
}
|
||||
if (config.getPort() != null) {
|
||||
dsConfig.setHostPort(config.getPort());
|
||||
}
|
||||
if (config.getDatabaseName() != null) {
|
||||
dsConfig.setDatabaseName(config.getDatabaseName());
|
||||
}
|
||||
if (config.getServerName() != null) {
|
||||
dsConfig.setServerName(config.getServerName());
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveAuthProperties(
|
||||
@NotNull DBPDataSourceContainer dataSourceContainer,
|
||||
@NotNull DBPConnectionConfiguration configuration,
|
||||
@Nullable Map<String, Object> authProperties,
|
||||
boolean saveCredentials,
|
||||
boolean sharedCredentials
|
||||
) {
|
||||
saveAuthProperties(dataSourceContainer, configuration, authProperties, saveCredentials, sharedCredentials, false);
|
||||
}
|
||||
|
||||
public static void saveAuthProperties(
|
||||
@NotNull DBPDataSourceContainer dataSourceContainer,
|
||||
@NotNull DBPConnectionConfiguration configuration,
|
||||
@Nullable Map<String, Object> authProperties,
|
||||
boolean saveCredentials,
|
||||
boolean sharedCredentials,
|
||||
boolean isTest
|
||||
) {
|
||||
dataSourceContainer.setSavePassword(saveCredentials);
|
||||
dataSourceContainer.setSharedCredentials(sharedCredentials);
|
||||
if (!saveCredentials) {
|
||||
// Reset credentials
|
||||
if (authProperties == null) {
|
||||
authProperties = new LinkedHashMap<>();
|
||||
}
|
||||
authProperties.replace(AuthModelDatabaseNativeCredentials.PROP_USER_PASSWORD, null);
|
||||
dataSourceContainer.resetPassword();
|
||||
} else {
|
||||
if (authProperties == null) {
|
||||
// No changes
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
// Read save credentials
|
||||
DBAAuthCredentials credentials = configuration.getAuthModel().loadCredentials(dataSourceContainer, configuration);
|
||||
|
||||
if (isTest) {
|
||||
var currentAuthProps = new HashMap<String, String>();
|
||||
for (Map.Entry<String, Object> stringObjectEntry : authProperties.entrySet()) {
|
||||
var value = stringObjectEntry.getValue() == null ? null : stringObjectEntry.getValue().toString();
|
||||
currentAuthProps.put(stringObjectEntry.getKey(), value);
|
||||
}
|
||||
configuration.setAuthProperties(currentAuthProps);
|
||||
}
|
||||
if (!authProperties.isEmpty()) {
|
||||
WebDataSourceUtils.updateCredentialsFromProperties(credentials, authProperties);
|
||||
}
|
||||
|
||||
configuration.getAuthModel().saveCredentials(dataSourceContainer, configuration, credentials);
|
||||
}
|
||||
}
|
||||
|
||||
public static DBNBrowseSettings parseNavigatorSettings(Map<String, Object> settingsMap) {
|
||||
return gson.fromJson(
|
||||
gson.toJsonTree(settingsMap), DataSourceNavigatorSettings.class);
|
||||
@@ -84,6 +310,13 @@ public class WebServiceUtils extends WebCommonUtils {
|
||||
WebActionParameters.saveToSession(webSession, actionParameters);
|
||||
}
|
||||
|
||||
public static String getConnectionContainerInfo(DBPDataSourceContainer container) {
|
||||
if (container == null) {
|
||||
return null;
|
||||
}
|
||||
return container.getName() + " [" + container.getId() + "]";
|
||||
}
|
||||
|
||||
public static void refreshDatabases(WebSession session, String projectId) throws DBWebException {
|
||||
DBNProject projectNode = session.getNavigatorModelOrThrow().getRoot().getProjectNode(session.getProjectById(projectId));
|
||||
if (projectNode != null) {
|
||||
|
||||
-2
@@ -34,8 +34,6 @@ public interface WebAppSessionManager {
|
||||
|
||||
BaseWebSession closeSession(@NotNull String sessionId);
|
||||
|
||||
BaseWebSession closeSession(@NotNull String sessionId, boolean sendSessionExpiredEvent);
|
||||
|
||||
@NotNull
|
||||
WebSession getWebSession(
|
||||
@NotNull HttpServletRequest request,
|
||||
|
||||
@@ -21,6 +21,7 @@ import io.cloudbeaver.model.app.ServletApplication;
|
||||
import io.cloudbeaver.model.app.WebAppConfiguration;
|
||||
import io.cloudbeaver.model.app.WebServerConfiguration;
|
||||
import io.cloudbeaver.registry.WebDriverRegistry;
|
||||
import io.cloudbeaver.service.ConnectionController;
|
||||
import org.jkiss.code.NotNull;
|
||||
|
||||
import java.net.InetAddress;
|
||||
@@ -52,4 +53,6 @@ public interface WebApplication extends ServletApplication {
|
||||
|
||||
WebServerConfig getWebServerConfig();
|
||||
|
||||
ConnectionController getConnectionController();
|
||||
|
||||
}
|
||||
|
||||
+1
-8
@@ -38,13 +38,6 @@ public class WSProjectUpdatedEventHandler extends WSAbstractProjectEventHandler<
|
||||
} else if (WSProjectUpdateEvent.REMOVED.equals(eventId)) {
|
||||
activeUserSession.removeSessionProject(projectId);
|
||||
log.info("Project '" + projectId + "' removed from '" + activeUserSession.getSessionId() + "' session");
|
||||
} else if (WSProjectUpdateEvent.UPDATED.equals(eventId)) {
|
||||
if (event.getProjectInfo() == null) {
|
||||
log.warn("No project info provided for update event: " + event);
|
||||
return;
|
||||
}
|
||||
activeUserSession.updateSessionProject(projectId, event.getProjectInfo());
|
||||
log.info("Project '" + projectId + "' updated in '" + activeUserSession.getSessionId() + "' session");
|
||||
}
|
||||
activeUserSession.addSessionEvent(event);
|
||||
} catch (DBException e) {
|
||||
@@ -55,7 +48,7 @@ public class WSProjectUpdatedEventHandler extends WSAbstractProjectEventHandler<
|
||||
@Override
|
||||
protected boolean isAcceptableInSession(@NotNull BaseWebSession activeUserSession, @NotNull WSProjectUpdateEvent event) {
|
||||
return !WSWebUtils.isSessionIdEquals(activeUserSession, event.getSessionId()) &&
|
||||
(!event.getId().equals(WSProjectUpdateEvent.ADDED) ||
|
||||
(event.getId().equals(WSProjectUpdateEvent.REMOVED) ||
|
||||
activeUserSession.getUserContext().hasPermission(DBWConstants.PERMISSION_ADMIN));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -32,6 +32,7 @@ import io.cloudbeaver.WebServiceUtils;
|
||||
import io.cloudbeaver.model.apilog.ApiCallInterceptor;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.registry.WebServiceRegistry;
|
||||
import io.cloudbeaver.server.HttpConstants;
|
||||
import io.cloudbeaver.server.WebAppUtils;
|
||||
import io.cloudbeaver.service.DBWBindingContext;
|
||||
import io.cloudbeaver.service.DBWServiceBindingGraphQL;
|
||||
@@ -45,7 +46,6 @@ import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.HttpConstants;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -146,7 +146,7 @@ public class GraphQLEndpoint extends HttpServlet {
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
String contentType = request.getContentType();
|
||||
if (CommonUtils.isEmpty(contentType) || !contentType.startsWith(HttpConstants.CONTENT_TYPE_JSON)) {
|
||||
if (CommonUtils.isEmpty(contentType) || !contentType.startsWith(HttpConstants.TYPE_JSON)) {
|
||||
String error = "Bad request," + (CommonUtils.isEmpty(contentType)
|
||||
? " content type is missing"
|
||||
: " incorrect content type:" + contentType);
|
||||
|
||||
+1
-1
@@ -18,6 +18,7 @@ package io.cloudbeaver.server.websockets;
|
||||
|
||||
import io.cloudbeaver.model.session.WebHeadlessSession;
|
||||
import io.cloudbeaver.model.session.WebHttpRequestInfo;
|
||||
import io.cloudbeaver.server.HttpConstants;
|
||||
import io.cloudbeaver.server.WebAppSessionManager;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import jakarta.websocket.HandshakeResponse;
|
||||
@@ -32,7 +33,6 @@ import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.security.exception.SMAccessTokenExpiredException;
|
||||
import org.jkiss.dbeaver.model.websocket.WSConstants;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.HttpConstants;
|
||||
import org.jkiss.utils.WSClientUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 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.service;
|
||||
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebObjectId;
|
||||
import io.cloudbeaver.model.WebConnectionConfig;
|
||||
import io.cloudbeaver.model.WebConnectionInfo;
|
||||
import io.cloudbeaver.model.WebNetworkHandlerConfigInput;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
|
||||
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public interface ConnectionController {
|
||||
|
||||
DBPDataSourceContainer createDataSourceContainer(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable @WebObjectId String projectId,
|
||||
@NotNull WebConnectionConfig connectionConfig
|
||||
) throws DBWebException;
|
||||
|
||||
WebConnectionInfo createConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
DBPDataSourceRegistry sessionRegistry,
|
||||
DBPDataSourceContainer newDataSource
|
||||
) throws DBWebException;
|
||||
|
||||
DBPDataSourceContainer getDatasourceConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable @WebObjectId String projectId,
|
||||
@NotNull WebConnectionConfig connectionConfig) throws DBWebException;
|
||||
|
||||
WebConnectionInfo updateConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull WebConnectionConfig config,
|
||||
DBPDataSourceContainer dataSource,
|
||||
DBPDataSourceRegistry sessionRegistry
|
||||
) throws DBWebException;
|
||||
|
||||
boolean deleteConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable @WebObjectId String projectId,
|
||||
@NotNull String connectionId) throws DBWebException;
|
||||
|
||||
DataSourceDescriptor prepareTestConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull WebConnectionConfig connectionConfig) throws DBWebException;
|
||||
|
||||
WebConnectionInfo testConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull WebConnectionConfig connectionConfig,
|
||||
DataSourceDescriptor dataSource
|
||||
) throws DBWebException;
|
||||
|
||||
WebConnectionInfo getConnectionState(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull String connectionId
|
||||
) throws DBWebException;
|
||||
|
||||
WebConnectionInfo initConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull String connectionId,
|
||||
@NotNull Map<String, Object> authProperties,
|
||||
@Nullable List<WebNetworkHandlerConfigInput> networkCredentials,
|
||||
boolean saveCredentials,
|
||||
boolean sharedCredentials,
|
||||
@Nullable String selectedSecretId
|
||||
) throws DBWebException;
|
||||
|
||||
void validateConnection(DBPDataSourceContainer dataSourceContainer) throws DBWebException;
|
||||
|
||||
}
|
||||
+496
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 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.service;
|
||||
|
||||
import io.cloudbeaver.*;
|
||||
import io.cloudbeaver.model.WebConnectionConfig;
|
||||
import io.cloudbeaver.model.WebConnectionInfo;
|
||||
import io.cloudbeaver.model.WebNetworkHandlerConfigInput;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.utils.ServletAppUtils;
|
||||
import io.cloudbeaver.utils.WebDataSourceUtils;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
|
||||
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
import org.jkiss.dbeaver.model.exec.DBCConnectException;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerType;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.secret.DBSSecretController;
|
||||
import org.jkiss.dbeaver.model.secret.DBSSecretValue;
|
||||
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.dbeaver.runtime.jobs.ConnectionTestJob;
|
||||
import org.jkiss.dbeaver.utils.RuntimeUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConnectionControllerCE implements ConnectionController {
|
||||
|
||||
private static final Log log = Log.getLog(ConnectionController.class);
|
||||
|
||||
|
||||
@Override
|
||||
public DBPDataSourceContainer createDataSourceContainer(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull WebConnectionConfig connectionConfig
|
||||
) throws DBWebException {
|
||||
WebSessionProjectImpl project = getProjectById(webSession, projectId);
|
||||
var rmProject = project.getRMProject();
|
||||
if (rmProject.getType() == RMProjectType.USER
|
||||
&& !webSession.hasPermission(DBWConstants.PERMISSION_ADMIN)
|
||||
&& !ServletAppUtils.getServletApplication().getAppConfiguration().isSupportsCustomConnections()
|
||||
) {
|
||||
throw new DBWebException("New connection create is restricted by server configuration");
|
||||
}
|
||||
webSession.addInfoMessage("Create new connection");
|
||||
DBPDataSourceRegistry sessionRegistry = project.getDataSourceRegistry();
|
||||
|
||||
DBPDataSourceContainer newDataSource = WebServiceUtils.createConnectionFromConfig(connectionConfig,
|
||||
sessionRegistry);
|
||||
if (CommonUtils.isEmpty(newDataSource.getName())) {
|
||||
newDataSource.setName(CommonUtils.notNull(connectionConfig.getName(), "NewConnection"));
|
||||
}
|
||||
return newDataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public WebConnectionInfo createConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
DBPDataSourceRegistry sessionRegistry,
|
||||
DBPDataSourceContainer newDataSource
|
||||
) throws DBWebException {
|
||||
WebSessionProjectImpl project = getProjectById(webSession, projectId);
|
||||
try {
|
||||
sessionRegistry.addDataSource(newDataSource);
|
||||
|
||||
sessionRegistry.checkForErrors();
|
||||
} catch (DBException e) {
|
||||
sessionRegistry.removeDataSource(newDataSource);
|
||||
throw new DBWebException("Failed to create connection", e);
|
||||
}
|
||||
|
||||
WebConnectionInfo connectionInfo = project.addConnection(newDataSource);
|
||||
webSession.addInfoMessage("New connection was created - " + WebServiceUtils.getConnectionContainerInfo(
|
||||
newDataSource));
|
||||
log.info(String.format(
|
||||
"New connection was created: [info=%s, user=%s]",
|
||||
WebServiceUtils.getConnectionContainerInfo(newDataSource),
|
||||
webSession.getUserId()
|
||||
));
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBPDataSourceContainer getDatasourceConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull WebConnectionConfig config
|
||||
) throws DBWebException {
|
||||
// Do not check for custom connection option. Already created connections can be edited.
|
||||
// Also template connections can be edited
|
||||
// if (!CBApplication.getInstance().getAppConfiguration().isSupportsCustomConnections()) {
|
||||
// throw new DBWebException("Connection edit is restricted by server configuration");
|
||||
// }
|
||||
|
||||
WebConnectionInfo connectionInfo = WebDataSourceUtils.getWebConnectionInfo(webSession, projectId, config.getConnectionId());
|
||||
DBPDataSourceContainer dataSource = connectionInfo.getDataSourceContainer();
|
||||
webSession.addInfoMessage("Update connection - " + WebServiceUtils.getConnectionContainerInfo(dataSource));
|
||||
getOldDataSource(dataSource);
|
||||
if (!CommonUtils.isEmpty(config.getName())) {
|
||||
dataSource.setName(config.getName());
|
||||
}
|
||||
|
||||
if (config.getDescription() != null) {
|
||||
dataSource.setDescription(config.getDescription());
|
||||
}
|
||||
|
||||
WebSessionProjectImpl project = getProjectById(webSession, projectId);
|
||||
DBPDataSourceRegistry sessionRegistry = project.getDataSourceRegistry();
|
||||
dataSource.setFolder(config.getFolder() != null ? sessionRegistry.getFolder(config.getFolder()) : null);
|
||||
if (config.isDefaultAutoCommit() != null) {
|
||||
dataSource.setDefaultAutoCommit(config.isDefaultAutoCommit());
|
||||
}
|
||||
dataSource.setConnectionReadOnly(config.isReadOnly());
|
||||
WebServiceUtils.setConnectionConfiguration(dataSource.getDriver(),
|
||||
dataSource.getConnectionConfiguration(),
|
||||
config);
|
||||
|
||||
// we should check that the config has changed but not check for password changes
|
||||
dataSource.setSharedCredentials(config.isSharedCredentials());
|
||||
dataSource.setSavePassword(config.isSaveCredentials());
|
||||
boolean sharedCredentials = isSharedCredentials(dataSource);
|
||||
if (sharedCredentials) {
|
||||
//we must notify about the shared password change
|
||||
WebServiceUtils.saveAuthProperties(
|
||||
dataSource,
|
||||
dataSource.getConnectionConfiguration(),
|
||||
config.getCredentials(),
|
||||
config.isSaveCredentials(),
|
||||
config.isSharedCredentials()
|
||||
);
|
||||
}
|
||||
connectionInfo.setCredentialsSavedInSession(null);
|
||||
// same here
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private static boolean isSharedCredentials(DBPDataSourceContainer dataSource) {
|
||||
return dataSource.isSharedCredentials() || !dataSource.getProject()
|
||||
.isUseSecretStorage() && dataSource.isSavePassword();
|
||||
}
|
||||
|
||||
private static DataSourceDescriptor getOldDataSource(DBPDataSourceContainer dataSource) {
|
||||
DataSourceDescriptor oldDataSource;
|
||||
oldDataSource = dataSource.getRegistry().createDataSource(dataSource);
|
||||
oldDataSource.setId(dataSource.getId());
|
||||
return oldDataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebConnectionInfo updateConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull WebConnectionConfig config,
|
||||
DBPDataSourceContainer dataSource,
|
||||
DBPDataSourceRegistry sessionRegistry
|
||||
) throws DBWebException {
|
||||
WebConnectionInfo connectionInfo = WebDataSourceUtils.getWebConnectionInfo(webSession, projectId, config.getConnectionId());
|
||||
if (!isSharedCredentials(dataSource)) {
|
||||
// secret controller is responsible for notification, password changes applied after checks
|
||||
WebServiceUtils.saveAuthProperties(
|
||||
dataSource,
|
||||
dataSource.getConnectionConfiguration(),
|
||||
config.getCredentials(),
|
||||
config.isSaveCredentials(),
|
||||
config.isSharedCredentials()
|
||||
);
|
||||
}
|
||||
try {
|
||||
sessionRegistry.updateDataSource(dataSource);
|
||||
sessionRegistry.checkForErrors();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Failed to update connection", e);
|
||||
}
|
||||
log.info(String.format(
|
||||
"Connection updated: [info=%s, userId=%s]",
|
||||
WebServiceUtils.getConnectionContainerInfo(dataSource),
|
||||
webSession.getUser()
|
||||
));
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteConnection(
|
||||
@NotNull WebSession webSession, @Nullable String projectId, @NotNull String connectionId
|
||||
) throws DBWebException {
|
||||
WebConnectionInfo connectionInfo = WebDataSourceUtils.getWebConnectionInfo(webSession, projectId, connectionId);
|
||||
if (connectionInfo.getDataSourceContainer().getProject() != getProjectById(webSession, projectId)) {
|
||||
throw new DBWebException("Global connection '" + connectionInfo.getName() + "' configuration cannot be deleted");
|
||||
}
|
||||
webSession.addInfoMessage("Delete connection - " +
|
||||
WebServiceUtils.getConnectionContainerInfo(connectionInfo.getDataSourceContainer()));
|
||||
closeAndDeleteConnection(webSession, projectId, connectionId, true);
|
||||
|
||||
log.info(String.format(
|
||||
"Connection deleted: [info=%s, userId=%s]",
|
||||
WebServiceUtils.getConnectionContainerInfo(connectionInfo.getDataSourceContainer()),
|
||||
webSession.getUserId()
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceDescriptor prepareTestConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull WebConnectionConfig connectionConfig
|
||||
) throws DBWebException {
|
||||
String connectionId = connectionConfig.getConnectionId();
|
||||
|
||||
connectionConfig.setSaveCredentials(true); // It is used in createConnectionFromConfig
|
||||
|
||||
DataSourceDescriptor dataSource = (DataSourceDescriptor) WebDataSourceUtils.getLocalOrGlobalDataSource(
|
||||
webSession, projectId, connectionId);
|
||||
|
||||
validateConnection(dataSource);
|
||||
|
||||
WebProjectImpl project = getProjectById(webSession, projectId);
|
||||
DBPDataSourceRegistry sessionRegistry = project.getDataSourceRegistry();
|
||||
DataSourceDescriptor testDataSource;
|
||||
if (dataSource != null) {
|
||||
try {
|
||||
// Check that creds are saved to trigger secrets resolve
|
||||
dataSource.isCredentialsSaved();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Can't determine whether datasource credentials are saved", e);
|
||||
}
|
||||
|
||||
testDataSource = (DataSourceDescriptor) dataSource.createCopy(dataSource.getRegistry());
|
||||
WebServiceUtils.setConnectionConfiguration(
|
||||
testDataSource.getDriver(),
|
||||
testDataSource.getConnectionConfiguration(),
|
||||
connectionConfig
|
||||
);
|
||||
if (connectionConfig.getSelectedSecretId() != null) {
|
||||
try {
|
||||
dataSource.listSharedCredentials()
|
||||
.stream()
|
||||
.filter(secret -> connectionConfig.getSelectedSecretId().equals(secret.getSubjectId()))
|
||||
.findFirst()
|
||||
.ifPresent(testDataSource::setSelectedSharedCredentials);
|
||||
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Failed to load secret value: " + connectionConfig.getSelectedSecretId());
|
||||
}
|
||||
}
|
||||
WebServiceUtils.saveAuthProperties(
|
||||
testDataSource,
|
||||
testDataSource.getConnectionConfiguration(),
|
||||
connectionConfig.getCredentials(),
|
||||
true,
|
||||
false,
|
||||
true
|
||||
);
|
||||
} else {
|
||||
testDataSource = (DataSourceDescriptor) WebServiceUtils.createConnectionFromConfig(connectionConfig,
|
||||
sessionRegistry);
|
||||
}
|
||||
return testDataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public WebConnectionInfo testConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull WebConnectionConfig connectionConfig,
|
||||
DataSourceDescriptor testDataSource
|
||||
) throws DBWebException {
|
||||
validateDriverLibrariesPresence(testDataSource);
|
||||
webSession.provideAuthParameters(webSession.getProgressMonitor(),
|
||||
testDataSource,
|
||||
testDataSource.getConnectionConfiguration());
|
||||
testDataSource.setSavePassword(true); // We need for test to avoid password callback
|
||||
if (DataSourceDescriptor.class.isAssignableFrom(testDataSource.getClass())) {
|
||||
testDataSource.setAccessCheckRequired(!webSession.hasPermission(DBWConstants.PERMISSION_ADMIN));
|
||||
}
|
||||
try {
|
||||
ConnectionTestJob ct = new ConnectionTestJob(testDataSource, param -> {
|
||||
});
|
||||
ct.run(webSession.getProgressMonitor());
|
||||
if (ct.getConnectError() != null) {
|
||||
if (ct.getConnectError() instanceof DBCConnectException error) {
|
||||
Throwable rootCause = CommonUtils.getRootCause(error);
|
||||
if (rootCause instanceof ClassNotFoundException) {
|
||||
throwDriverNotFoundException(testDataSource);
|
||||
}
|
||||
}
|
||||
throw new DBWebException("Connection failed", ct.getConnectError());
|
||||
}
|
||||
WebConnectionInfo connectionInfo = new WebConnectionInfo(webSession, testDataSource);
|
||||
connectionInfo.setConnectError(ct.getConnectError());
|
||||
connectionInfo.setServerVersion(ct.getServerVersion());
|
||||
connectionInfo.setClientVersion(ct.getClientVersion());
|
||||
connectionInfo.setConnectTime(RuntimeUtils.formatExecutionTime(ct.getConnectTime()));
|
||||
return connectionInfo;
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error connecting to database", e);
|
||||
}
|
||||
}
|
||||
|
||||
private WebSessionProjectImpl getProjectById(WebSession webSession, String projectId) throws DBWebException {
|
||||
WebSessionProjectImpl project = webSession.getProjectById(projectId);
|
||||
if (project == null) {
|
||||
throw new DBWebException("Project '" + projectId + "' not found");
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private WebConnectionInfo closeAndDeleteConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String projectId,
|
||||
@NotNull String connectionId,
|
||||
boolean forceDelete
|
||||
) throws DBWebException {
|
||||
WebSessionProjectImpl project = getProjectById(webSession, projectId);
|
||||
WebConnectionInfo connectionInfo = project.getWebConnectionInfo(connectionId);
|
||||
|
||||
DBPDataSourceContainer dataSourceContainer = connectionInfo.getDataSourceContainer();
|
||||
boolean disconnected = WebDataSourceUtils.disconnectDataSource(webSession, dataSourceContainer);
|
||||
if (forceDelete) {
|
||||
DBPDataSourceRegistry registry = project.getDataSourceRegistry();
|
||||
registry.removeDataSource(dataSourceContainer);
|
||||
try {
|
||||
registry.checkForErrors();
|
||||
} catch (DBException e) {
|
||||
try {
|
||||
registry.addDataSource(dataSourceContainer);
|
||||
} catch (DBException ex) {
|
||||
log.error("Error re-adding after delete attempt", e);
|
||||
}
|
||||
throw new DBWebException("Failed to delete connection", e);
|
||||
}
|
||||
project.removeConnection(dataSourceContainer);
|
||||
} else {
|
||||
// Just reset saved credentials
|
||||
connectionInfo.clearCache();
|
||||
}
|
||||
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebConnectionInfo getConnectionState(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull String connectionId
|
||||
) throws DBWebException {
|
||||
return WebDataSourceUtils.getWebConnectionInfo(webSession, projectId, connectionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebConnectionInfo initConnection(@NotNull WebSession webSession, @Nullable String projectId, @NotNull String connectionId, @NotNull Map<String, Object> authProperties, @Nullable List<WebNetworkHandlerConfigInput> networkCredentials, boolean saveCredentials, boolean sharedCredentials, @Nullable String selectedSecretId) throws DBWebException {
|
||||
WebConnectionInfo connectionInfo = WebDataSourceUtils.getWebConnectionInfo(webSession, projectId, connectionId);
|
||||
connectionInfo.setSavedCredentials(authProperties, networkCredentials);
|
||||
|
||||
var dataSourceContainer = connectionInfo.getDataSourceContainer();;
|
||||
validateConnection(dataSourceContainer);
|
||||
if (dataSourceContainer.isConnected()) {
|
||||
throw new DBWebException("Datasource '" + dataSourceContainer.getName() + "' is already connected");
|
||||
}
|
||||
if (dataSourceContainer.isSharedCredentials() && selectedSecretId != null) {
|
||||
List<DBSSecretValue> allSecrets;
|
||||
try {
|
||||
allSecrets = dataSourceContainer.listSharedCredentials();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error loading connection secret", e);
|
||||
}
|
||||
DBSSecretValue selectedSecret =
|
||||
allSecrets.stream()
|
||||
.filter(secret -> selectedSecretId.equals(secret.getUniqueId()))
|
||||
.findFirst().orElse(null);
|
||||
if (selectedSecret == null) {
|
||||
throw new DBWebException("Secret not found:" + selectedSecretId);
|
||||
}
|
||||
dataSourceContainer.setSelectedSharedCredentials(selectedSecret);
|
||||
}
|
||||
|
||||
boolean oldSavePassword = dataSourceContainer.isSavePassword();
|
||||
DBRProgressMonitor monitor = webSession.getProgressMonitor();
|
||||
validateDriverLibrariesPresence(dataSourceContainer);
|
||||
try {
|
||||
boolean connect = dataSourceContainer.connect(monitor, true, false);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof DBCConnectException) {
|
||||
Throwable rootCause = CommonUtils.getRootCause(e);
|
||||
if (rootCause instanceof ClassNotFoundException) {
|
||||
throwDriverNotFoundException(dataSourceContainer);
|
||||
}
|
||||
}
|
||||
throw new DBWebException("Error connecting to database", e);
|
||||
} finally {
|
||||
dataSourceContainer.setSavePassword(oldSavePassword);
|
||||
connectionInfo.clearCache();
|
||||
}
|
||||
// Mark all specified network configs as saved
|
||||
boolean[] saveConfig = new boolean[1];
|
||||
|
||||
if (networkCredentials != null) {
|
||||
networkCredentials.forEach(c -> {
|
||||
if (CommonUtils.toBoolean(c.isSavePassword())) {
|
||||
DBWHandlerConfiguration handlerCfg = dataSourceContainer.getConnectionConfiguration()
|
||||
.getHandler(c.getId());
|
||||
if (handlerCfg != null &&
|
||||
// check username param only for ssh config
|
||||
!(CommonUtils.isEmpty(c.getUserName()) && CommonUtils.equalObjects(handlerCfg.getType(),
|
||||
DBWHandlerType.TUNNEL))
|
||||
) {
|
||||
WebDataSourceUtils.updateHandlerCredentials(handlerCfg, c);
|
||||
handlerCfg.setSavePassword(true);
|
||||
saveConfig[0] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (saveCredentials) {
|
||||
// Save all passed credentials in the datasource container
|
||||
WebServiceUtils.saveAuthProperties(
|
||||
dataSourceContainer,
|
||||
dataSourceContainer.getConnectionConfiguration(),
|
||||
authProperties,
|
||||
true,
|
||||
sharedCredentials
|
||||
);
|
||||
|
||||
var project = dataSourceContainer.getProject();
|
||||
if (project.isUseSecretStorage()) {
|
||||
try {
|
||||
dataSourceContainer.persistSecrets(
|
||||
DBSSecretController.getProjectSecretController(dataSourceContainer.getProject())
|
||||
);
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Failed to save credentials", e);
|
||||
}
|
||||
}
|
||||
|
||||
WebDataSourceUtils.saveCredentialsInDataSource(connectionInfo,
|
||||
dataSourceContainer,
|
||||
dataSourceContainer.getConnectionConfiguration());
|
||||
saveConfig[0] = true;
|
||||
}
|
||||
if (WebServiceUtils.isGlobalProject(dataSourceContainer.getProject())) {
|
||||
// Do not flush config for global project (only admin can do it - CB-2415)
|
||||
if (saveCredentials) {
|
||||
connectionInfo.setCredentialsSavedInSession(true);
|
||||
}
|
||||
saveConfig[0] = false;
|
||||
}
|
||||
if (saveConfig[0]) {
|
||||
dataSourceContainer.persistConfiguration();
|
||||
}
|
||||
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateConnection(DBPDataSourceContainer dataSourceContainer) throws DBWebException {
|
||||
}
|
||||
|
||||
|
||||
private void validateDriverLibrariesPresence(@NotNull DBPDataSourceContainer container) throws DBWebException {
|
||||
if (!DBWorkbench.isDistributed() && container.getDriver().getDriverLoader(container).needsExternalDependencies()) {
|
||||
throwDriverNotFoundException(container);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String throwDriverNotFoundException(@NotNull DBPDataSourceContainer container) throws DBWebException {
|
||||
throw new DBWebException("Driver files for %s are not found. Please ask the administrator to download it."
|
||||
.formatted(container.getDriver().getName()));
|
||||
}
|
||||
}
|
||||
+5
-11
@@ -130,37 +130,31 @@ public interface DBWServiceCore extends DBWService {
|
||||
WebConnectionInfo createConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable @WebObjectId String projectId,
|
||||
@NotNull Map<String, Object> connectionConfig
|
||||
@NotNull WebConnectionConfig connectionConfig
|
||||
) throws DBWebException;
|
||||
|
||||
@WebProjectAction(requireProjectPermissions = {RMConstants.PERMISSION_PROJECT_DATASOURCES_EDIT})
|
||||
WebConnectionInfo updateConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable @WebObjectId String projectId,
|
||||
@NotNull Map<String, Object> connectionConfig
|
||||
) throws DBWebException;
|
||||
@NotNull WebConnectionConfig connectionConfig) throws DBWebException;
|
||||
|
||||
@WebProjectAction(requireProjectPermissions = {RMConstants.PERMISSION_PROJECT_DATASOURCES_EDIT})
|
||||
boolean deleteConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable @WebObjectId String projectId,
|
||||
@NotNull String connectionId
|
||||
) throws DBWebException;
|
||||
@NotNull String connectionId) throws DBWebException;
|
||||
|
||||
@WebProjectAction(requireProjectPermissions = {RMConstants.PERMISSION_PROJECT_DATASOURCES_EDIT})
|
||||
WebConnectionInfo copyConnectionFromNode(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable @WebObjectId String projectId,
|
||||
@NotNull String nodePath,
|
||||
@NotNull Map<String, Object> connectionConfig
|
||||
) throws DBWebException;
|
||||
@NotNull WebConnectionConfig config) throws DBWebException;
|
||||
|
||||
@WebAction
|
||||
WebConnectionInfo testConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull Map<String, Object> connectionConfig
|
||||
) throws DBWebException;
|
||||
@NotNull WebSession webSession, @Nullable String projectId, @NotNull WebConnectionConfig connectionConfig) throws DBWebException;
|
||||
|
||||
@WebAction
|
||||
WebNetworkEndpointInfo testNetworkHandler(@NotNull WebSession webSession, @NotNull WebNetworkHandlerConfigInput nhConfig) throws DBWebException;
|
||||
|
||||
+10
-8
@@ -17,9 +17,11 @@
|
||||
package io.cloudbeaver.service.core;
|
||||
|
||||
import graphql.TypeResolutionEnvironment;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import graphql.schema.idl.TypeRuntimeWiring;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebServiceUtils;
|
||||
import io.cloudbeaver.model.WebConnectionConfig;
|
||||
import io.cloudbeaver.model.WebNetworkHandlerConfigInput;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.server.WebAppSessionManager;
|
||||
@@ -103,20 +105,16 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
|
||||
.dataFetcher("changeSessionLanguage", env -> getService(env).changeSessionLanguage(getWebSession(env), env.getArgument("locale")))
|
||||
|
||||
.dataFetcher("createConnection", env -> getService(env).createConnection(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("config"))
|
||||
)
|
||||
getWebSession(env), getProjectReference(env), getConnectionConfig(env)))
|
||||
.dataFetcher("updateConnection", env -> getService(env).updateConnection(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("config"))
|
||||
)
|
||||
getWebSession(env), getProjectReference(env), getConnectionConfig(env)))
|
||||
.dataFetcher("deleteConnection", env -> getService(env).deleteConnection(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("id")))
|
||||
.dataFetcher("copyConnectionFromNode", env -> getService(env).copyConnectionFromNode(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("nodePath"),
|
||||
env.getArgument("config")
|
||||
)
|
||||
)
|
||||
new WebConnectionConfig(env.getArgument("config"))))
|
||||
.dataFetcher("initConnection", env -> {
|
||||
List<Map<String, Object>> networkCredentials = env.getArgument("networkCredentials");
|
||||
List<WebNetworkHandlerConfigInput> nhc = null;
|
||||
@@ -136,7 +134,7 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
|
||||
}
|
||||
)
|
||||
.dataFetcher("testConnection", env -> getService(env).testConnection(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("config")
|
||||
getWebSession(env), getProjectReference(env), getConnectionConfig(env)
|
||||
))
|
||||
.dataFetcher("testNetworkHandler", env -> getService(env).testNetworkHandler(
|
||||
getWebSession(env), new WebNetworkHandlerConfigInput(env.getArgument("config"))
|
||||
@@ -179,4 +177,8 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
private WebConnectionConfig getConnectionConfig(DataFetchingEnvironment env) {
|
||||
return new WebConnectionConfig(env.getArgument("config"));
|
||||
}
|
||||
}
|
||||
|
||||
+83
-220
@@ -44,29 +44,23 @@ import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
import org.jkiss.dbeaver.model.app.DBPProject;
|
||||
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
import org.jkiss.dbeaver.model.exec.DBCConnectException;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNDataSource;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNModel;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNNode;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerType;
|
||||
import org.jkiss.dbeaver.model.net.DBWNetworkHandler;
|
||||
import org.jkiss.dbeaver.model.net.DBWTunnel;
|
||||
import org.jkiss.dbeaver.model.net.ssh.SSHSession;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.secret.DBSSecretController;
|
||||
import org.jkiss.dbeaver.model.secret.DBSSecretValue;
|
||||
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
|
||||
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
|
||||
import org.jkiss.dbeaver.registry.DataSourceProviderRegistry;
|
||||
import org.jkiss.dbeaver.registry.network.NetworkHandlerDescriptor;
|
||||
import org.jkiss.dbeaver.registry.network.NetworkHandlerRegistry;
|
||||
import org.jkiss.dbeaver.registry.settings.ProductSettingDescriptor;
|
||||
import org.jkiss.dbeaver.registry.settings.ProductSettingsRegistry;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.dbeaver.runtime.jobs.ConnectionTestJob;
|
||||
import org.jkiss.dbeaver.utils.RuntimeUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.*;
|
||||
@@ -286,7 +280,7 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
@Nullable String projectId,
|
||||
@NotNull String connectionId
|
||||
) throws DBWebException {
|
||||
return WebDataSourceUtils.getWebConnectionInfo(webSession, projectId, connectionId);
|
||||
return WebAppUtils.getWebApplication().getConnectionController().getConnectionState(webSession, projectId, connectionId);
|
||||
}
|
||||
|
||||
|
||||
@@ -301,137 +295,65 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
boolean sharedCredentials,
|
||||
@Nullable String selectedSecretId
|
||||
) throws DBWebException {
|
||||
WebConnectionInfo connectionInfo = WebDataSourceUtils.getWebConnectionInfo(webSession, projectId, connectionId);
|
||||
connectionInfo.validateConnection();
|
||||
connectionInfo.setSavedCredentials(authProperties, networkCredentials);
|
||||
|
||||
var dataSourceContainer = connectionInfo.getDataSourceContainer();
|
||||
if (dataSourceContainer.isConnected()) {
|
||||
throw new DBWebException("Datasource '" + dataSourceContainer.getName() + "' is already connected");
|
||||
}
|
||||
if (dataSourceContainer.isSharedCredentials() && selectedSecretId != null) {
|
||||
List<DBSSecretValue> allSecrets;
|
||||
try {
|
||||
allSecrets = dataSourceContainer.listSharedCredentials();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error loading connection secret", e);
|
||||
}
|
||||
DBSSecretValue selectedSecret =
|
||||
allSecrets.stream()
|
||||
.filter(secret -> selectedSecretId.equals(secret.getUniqueId()))
|
||||
.findFirst().orElse(null);
|
||||
if (selectedSecret == null) {
|
||||
throw new DBWebException("Secret not found:" + selectedSecretId);
|
||||
}
|
||||
dataSourceContainer.setSelectedSharedCredentials(selectedSecret);
|
||||
}
|
||||
|
||||
boolean oldSavePassword = dataSourceContainer.isSavePassword();
|
||||
DBRProgressMonitor monitor = webSession.getProgressMonitor();
|
||||
validateDriverLibrariesPresence(dataSourceContainer);
|
||||
try {
|
||||
boolean connect = dataSourceContainer.connect(monitor, true, false);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof DBCConnectException) {
|
||||
Throwable rootCause = CommonUtils.getRootCause(e);
|
||||
if (rootCause instanceof ClassNotFoundException) {
|
||||
throwDriverNotFoundException(dataSourceContainer);
|
||||
}
|
||||
}
|
||||
throw new DBWebException("Error connecting to database", e);
|
||||
} finally {
|
||||
dataSourceContainer.setSavePassword(oldSavePassword);
|
||||
connectionInfo.clearCache();
|
||||
}
|
||||
// Mark all specified network configs as saved
|
||||
boolean[] saveConfig = new boolean[1];
|
||||
|
||||
if (networkCredentials != null) {
|
||||
networkCredentials.forEach(c -> {
|
||||
if (CommonUtils.toBoolean(c.isSavePassword())) {
|
||||
DBWHandlerConfiguration handlerCfg = dataSourceContainer.getConnectionConfiguration()
|
||||
.getHandler(c.getId());
|
||||
if (handlerCfg != null &&
|
||||
// check username param only for ssh config
|
||||
!(CommonUtils.isEmpty(c.getUserName()) && CommonUtils.equalObjects(
|
||||
handlerCfg.getType(),
|
||||
DBWHandlerType.TUNNEL
|
||||
))
|
||||
) {
|
||||
WebDataSourceUtils.updateHandlerCredentials(handlerCfg, c);
|
||||
handlerCfg.setSavePassword(true);
|
||||
saveConfig[0] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (saveCredentials) {
|
||||
// Save all passed credentials in the datasource container
|
||||
WebDataSourceUtils.saveAuthProperties(
|
||||
dataSourceContainer,
|
||||
dataSourceContainer.getConnectionConfiguration(),
|
||||
authProperties,
|
||||
true,
|
||||
sharedCredentials
|
||||
);
|
||||
|
||||
var project = dataSourceContainer.getProject();
|
||||
if (project.isUseSecretStorage()) {
|
||||
try {
|
||||
dataSourceContainer.persistSecrets(
|
||||
DBSSecretController.getProjectSecretController(dataSourceContainer.getProject())
|
||||
);
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Failed to save credentials", e);
|
||||
}
|
||||
}
|
||||
|
||||
WebDataSourceUtils.saveCredentialsInDataSource(
|
||||
connectionInfo,
|
||||
dataSourceContainer,
|
||||
dataSourceContainer.getConnectionConfiguration()
|
||||
);
|
||||
saveConfig[0] = true;
|
||||
}
|
||||
if (WebServiceUtils.isGlobalProject(dataSourceContainer.getProject())) {
|
||||
// Do not flush config for global project (only admin can do it - CB-2415)
|
||||
if (saveCredentials) {
|
||||
connectionInfo.setCredentialsSavedInSession(true);
|
||||
}
|
||||
saveConfig[0] = false;
|
||||
}
|
||||
if (saveConfig[0]) {
|
||||
dataSourceContainer.persistConfiguration();
|
||||
}
|
||||
|
||||
return connectionInfo;
|
||||
return WebAppUtils.getWebApplication().getConnectionController().initConnection(webSession, projectId,
|
||||
connectionId, authProperties, networkCredentials, saveCredentials, sharedCredentials, selectedSecretId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebConnectionInfo createConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull Map<String, Object> connectionConfig
|
||||
@NotNull WebConnectionConfig connectionConfig
|
||||
) throws DBWebException {
|
||||
return getProjectById(webSession, projectId).createConnection(connectionConfig);
|
||||
DBPDataSourceContainer dataSourceContainer =
|
||||
WebAppUtils.getWebApplication().getConnectionController().createDataSourceContainer(webSession, projectId, connectionConfig);
|
||||
return WebAppUtils.getWebApplication().getConnectionController().createConnection(
|
||||
webSession,
|
||||
projectId,
|
||||
dataSourceContainer.getRegistry(),
|
||||
dataSourceContainer
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebConnectionInfo updateConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull Map<String, Object> connectionConfig
|
||||
@NotNull WebConnectionConfig config
|
||||
) throws DBWebException {
|
||||
return getProjectById(webSession, projectId).updateConnection(connectionConfig);
|
||||
DBPDataSourceContainer dataSourceContainer =
|
||||
WebAppUtils.getWebApplication().getConnectionController().getDatasourceConnection(webSession, projectId, config);
|
||||
return WebAppUtils.getWebApplication().getConnectionController().updateConnection(
|
||||
webSession,
|
||||
projectId,
|
||||
config,
|
||||
dataSourceContainer,
|
||||
dataSourceContainer.getRegistry()
|
||||
);
|
||||
}
|
||||
|
||||
private WSDataSourceProperty getDatasourceEventProperty(
|
||||
DataSourceDescriptor oldDataSource,
|
||||
DBPDataSourceContainer dataSource
|
||||
) {
|
||||
if (!oldDataSource.equalConfiguration((DataSourceDescriptor) dataSource)) {
|
||||
return WSDataSourceProperty.CONFIGURATION;
|
||||
}
|
||||
|
||||
var nameChanged = !CommonUtils.equalObjects(oldDataSource.getName(), dataSource.getName());
|
||||
var descriptionChanged = !CommonUtils.equalObjects(oldDataSource.getDescription(), dataSource.getDescription());
|
||||
if (nameChanged && descriptionChanged) {
|
||||
return WSDataSourceProperty.CONFIGURATION;
|
||||
}
|
||||
|
||||
return nameChanged ? WSDataSourceProperty.NAME : WSDataSourceProperty.CONFIGURATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull String connectionId
|
||||
@NotNull WebSession webSession, @Nullable String projectId, @NotNull String connectionId
|
||||
) throws DBWebException {
|
||||
return getProjectById(webSession, projectId).deleteConnection(connectionId);
|
||||
return WebAppUtils.getWebApplication().getConnectionController().deleteConnection(webSession, projectId, connectionId);
|
||||
|
||||
}
|
||||
|
||||
@@ -440,7 +362,7 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull String nodePath,
|
||||
@NotNull Map<String, Object> connectionConfig
|
||||
@NotNull WebConnectionConfig config
|
||||
) throws DBWebException {
|
||||
try {
|
||||
DBNModel navigatorModel = webSession.getNavigatorModelOrThrow();
|
||||
@@ -451,20 +373,19 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
if (srcNode == null) {
|
||||
throw new DBException("Node '" + nodePath + "' not found");
|
||||
}
|
||||
if (!(srcNode instanceof DBNDataSource dbnDataSource)) {
|
||||
if (!(srcNode instanceof DBNDataSource)) {
|
||||
throw new DBException("Node '" + nodePath + "' is not a datasource node");
|
||||
}
|
||||
DBPDataSourceContainer dataSourceTemplate = dbnDataSource.getDataSourceContainer();
|
||||
DBPDataSourceContainer dataSourceTemplate = ((DBNDataSource) srcNode).getDataSourceContainer();
|
||||
|
||||
DataSourceDescriptor newDataSource = dataSourceRegistry.createDataSource(dataSourceTemplate);
|
||||
DBPDataSourceContainer newDataSource = dataSourceRegistry.createDataSource(dataSourceTemplate);
|
||||
|
||||
ServletApplication app = ServletAppUtils.getServletApplication();
|
||||
if (app instanceof WebApplication webApplication) {
|
||||
newDataSource.setNavigatorSettings(webApplication.getAppConfiguration().getDefaultNavigatorSettings());
|
||||
((DataSourceDescriptor) newDataSource).setNavigatorSettings(
|
||||
webApplication.getAppConfiguration().getDefaultNavigatorSettings());
|
||||
}
|
||||
|
||||
WebConnectionConfig config = project.getConnectionConfigInput(connectionConfig);
|
||||
|
||||
// Copy props from config
|
||||
if (!CommonUtils.isEmpty(config.getName())) {
|
||||
newDataSource.setName(config.getName());
|
||||
@@ -486,84 +407,12 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
public WebConnectionInfo testConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull Map<String, Object> connectionConfig
|
||||
@NotNull WebConnectionConfig connectionConfig
|
||||
) throws DBWebException {
|
||||
WebSessionProjectImpl project = getProjectById(webSession, projectId);
|
||||
WebConnectionConfig configInput = project.getConnectionConfigInput(connectionConfig);
|
||||
|
||||
DataSourceDescriptor dataSource = (DataSourceDescriptor) WebDataSourceUtils.getLocalOrGlobalDataSource(
|
||||
webSession, projectId, configInput.getConnectionId());
|
||||
|
||||
DataSourceDescriptor testDataSource;
|
||||
if (dataSource != null) {
|
||||
try {
|
||||
// Check that creds are saved to trigger secrets resolve
|
||||
dataSource.isCredentialsSaved();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Can't determine whether datasource credentials are saved", e);
|
||||
}
|
||||
|
||||
testDataSource = (DataSourceDescriptor) dataSource.createCopy(dataSource.getRegistry());
|
||||
WebDataSourceUtils.setConnectionConfiguration(
|
||||
testDataSource.getDriver(),
|
||||
testDataSource.getConnectionConfiguration(),
|
||||
configInput
|
||||
);
|
||||
if (configInput.getSelectedSecretId() != null) {
|
||||
try {
|
||||
dataSource.listSharedCredentials()
|
||||
.stream()
|
||||
.filter(secret -> configInput.getSelectedSecretId().equals(secret.getSubjectId()))
|
||||
.findFirst()
|
||||
.ifPresent(testDataSource::setSelectedSharedCredentials);
|
||||
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Failed to load secret value: " + configInput.getSelectedSecretId());
|
||||
}
|
||||
}
|
||||
WebDataSourceUtils.saveAuthProperties(
|
||||
testDataSource,
|
||||
testDataSource.getConnectionConfiguration(),
|
||||
configInput.getCredentials(),
|
||||
true,
|
||||
false,
|
||||
true
|
||||
);
|
||||
} else {
|
||||
testDataSource = project.getDataSourceContainerFromInput(connectionConfig);
|
||||
}
|
||||
validateDriverLibrariesPresence(testDataSource);
|
||||
webSession.provideAuthParameters(
|
||||
webSession.getProgressMonitor(),
|
||||
testDataSource,
|
||||
testDataSource.getConnectionConfiguration()
|
||||
);
|
||||
testDataSource.setSavePassword(true); // We need for test to avoid password callback
|
||||
testDataSource.setAccessCheckRequired(!webSession.hasPermission(DBWConstants.PERMISSION_ADMIN));
|
||||
try {
|
||||
ConnectionTestJob ct = new ConnectionTestJob(
|
||||
testDataSource, param -> {
|
||||
}
|
||||
);
|
||||
ct.run(webSession.getProgressMonitor());
|
||||
if (ct.getConnectError() != null) {
|
||||
if (ct.getConnectError() instanceof DBCConnectException error) {
|
||||
Throwable rootCause = CommonUtils.getRootCause(error);
|
||||
if (rootCause instanceof ClassNotFoundException) {
|
||||
throwDriverNotFoundException(testDataSource);
|
||||
}
|
||||
}
|
||||
throw new DBWebException("Connection failed", ct.getConnectError());
|
||||
}
|
||||
WebConnectionInfo connectionInfo = project.createConnectionInfo(testDataSource);
|
||||
connectionInfo.setConnectError(ct.getConnectError());
|
||||
connectionInfo.setServerVersion(ct.getServerVersion());
|
||||
connectionInfo.setClientVersion(ct.getClientVersion());
|
||||
connectionInfo.setConnectTime(RuntimeUtils.formatExecutionTime(ct.getConnectTime()));
|
||||
return connectionInfo;
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error connecting to database", e);
|
||||
}
|
||||
DataSourceDescriptor dataSourceDescriptor = WebAppUtils.getWebApplication().getConnectionController()
|
||||
.prepareTestConnection(webSession, projectId, connectionConfig);
|
||||
return WebAppUtils.getWebApplication().getConnectionController()
|
||||
.testConnection(webSession, projectId, connectionConfig, dataSourceDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -622,15 +471,42 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
|
||||
@Override
|
||||
public WebConnectionInfo closeConnection(
|
||||
@NotNull WebSession webSession, @Nullable String projectId, @NotNull String connectionId
|
||||
) throws DBWebException {
|
||||
return closeAndDeleteConnection(webSession, projectId, connectionId, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private WebConnectionInfo closeAndDeleteConnection(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull String connectionId
|
||||
@NotNull String projectId,
|
||||
@NotNull String connectionId,
|
||||
boolean forceDelete
|
||||
) throws DBWebException {
|
||||
WebSessionProjectImpl project = getProjectById(webSession, projectId);
|
||||
WebConnectionInfo connectionInfo = project.getWebConnectionInfo(connectionId);
|
||||
|
||||
DBPDataSourceContainer dataSourceContainer = connectionInfo.getDataSourceContainer();
|
||||
boolean disconnected = WebDataSourceUtils.disconnectDataSource(webSession, dataSourceContainer);
|
||||
if (forceDelete) {
|
||||
DBPDataSourceRegistry registry = project.getDataSourceRegistry();
|
||||
registry.removeDataSource(dataSourceContainer);
|
||||
try {
|
||||
registry.checkForErrors();
|
||||
} catch (DBException e) {
|
||||
try {
|
||||
registry.addDataSource(dataSourceContainer);
|
||||
} catch (DBException ex) {
|
||||
log.error("Error re-adding after delete attempt", e);
|
||||
}
|
||||
throw new DBWebException("Failed to delete connection", e);
|
||||
}
|
||||
project.removeConnection(dataSourceContainer);
|
||||
} else {
|
||||
// Just reset saved credentials
|
||||
connectionInfo.clearCache();
|
||||
}
|
||||
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
@@ -735,24 +611,11 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
return new WebGroupPropertiesInfo<>(webSession, ProductSettingsRegistry.getInstance().getSettings());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private WebSessionProjectImpl getProjectById(@NotNull WebSession webSession, @Nullable String projectId) throws DBWebException {
|
||||
private WebSessionProjectImpl getProjectById(WebSession webSession, String projectId) throws DBWebException {
|
||||
WebSessionProjectImpl project = webSession.getProjectById(projectId);
|
||||
if (project == null) {
|
||||
throw new DBWebException("Project '" + projectId + "' not found");
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
private void validateDriverLibrariesPresence(@NotNull DBPDataSourceContainer container) throws DBWebException {
|
||||
if (!DBWorkbench.isDistributed() && container.getDriver().getDriverLoader(container).needsExternalDependencies()) {
|
||||
throwDriverNotFoundException(container);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String throwDriverNotFoundException(@NotNull DBPDataSourceContainer container) throws DBWebException {
|
||||
throw new DBWebException("Driver files for %s are not found. Please ask the administrator to download it."
|
||||
.formatted(container.getDriver().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
-21
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package io.cloudbeaver.service.navigator;
|
||||
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -35,8 +34,6 @@ public class WebStructContainers {
|
||||
private List<WebNavigatorNodeInfo> schemaList = new ArrayList<>();
|
||||
private boolean supportsCatalogChange = false;
|
||||
private boolean supportsSchemaChange = false;
|
||||
private String defaultCatalog = null;
|
||||
private String defaultSchema = null;
|
||||
|
||||
public Boolean getSupportsCatalogChange() {
|
||||
return supportsCatalogChange;
|
||||
@@ -77,22 +74,4 @@ public class WebStructContainers {
|
||||
public void setSupportsSchemaChange(boolean support) {
|
||||
this.supportsSchemaChange = support;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDefaultCatalog() {
|
||||
return defaultCatalog;
|
||||
}
|
||||
|
||||
public void setDefaultCatalog(@Nullable String defaultCatalog) {
|
||||
this.defaultCatalog = defaultCatalog;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDefaultSchema() {
|
||||
return defaultSchema;
|
||||
}
|
||||
|
||||
public void setDefaultSchema(@Nullable String defaultSchema) {
|
||||
this.defaultSchema = defaultSchema;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-11
@@ -323,17 +323,8 @@ public class WebServiceNavigator implements DBWServiceNavigator {
|
||||
|
||||
WebStructContainers structContainers = new WebStructContainers();
|
||||
|
||||
if (contextDefaults != null) {
|
||||
structContainers.setSupportsCatalogChange(contextDefaults.supportsCatalogChange());
|
||||
structContainers.setSupportsSchemaChange(contextDefaults.supportsSchemaChange());
|
||||
if (contextDefaults.getDefaultSchema() != null) {
|
||||
structContainers.setDefaultSchema(contextDefaults.getDefaultSchema().getName());
|
||||
}
|
||||
if (contextDefaults.getDefaultCatalog() != null) {
|
||||
structContainers.setDefaultCatalog(contextDefaults.getDefaultCatalog().getName());
|
||||
}
|
||||
}
|
||||
|
||||
structContainers.setSupportsCatalogChange(contextDefaults != null && contextDefaults.supportsCatalogChange());
|
||||
structContainers.setSupportsSchemaChange(contextDefaults != null && contextDefaults.supportsSchemaChange());
|
||||
|
||||
DBRProgressMonitor monitor = connection.getSession().getProgressMonitor();
|
||||
List<? extends DBSObject> dbsObjects = this.getCatalogs(
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Service - Administration
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.admin;singleton:=true
|
||||
Bundle-Version: 1.0.130.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.129.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: io.cloudbeaver.server.ce,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.admin</artifactId>
|
||||
<version>1.0.130-SNAPSHOT</version>
|
||||
<version>1.0.129-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+1
-2
@@ -35,7 +35,6 @@ import io.cloudbeaver.service.DBWServiceServerConfigurator;
|
||||
import io.cloudbeaver.service.admin.*;
|
||||
import io.cloudbeaver.service.security.SMUtils;
|
||||
import io.cloudbeaver.utils.ServletAppUtils;
|
||||
import io.cloudbeaver.utils.WebDataSourceUtils;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
@@ -702,7 +701,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
// driver is removed from disabled list
|
||||
// we need to enable if it is embedded
|
||||
try {
|
||||
DBPDriver driver = WebDataSourceUtils.getDriverById(driverId);
|
||||
DBPDriver driver = WebServiceUtils.getDriverById(driverId);
|
||||
if (driver.isEmbedded()) {
|
||||
enabledIds.add(driverId);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Service - Authentication
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.auth;singleton:=true
|
||||
Bundle-Version: 1.0.130.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.129.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: io.cloudbeaver.server.ce
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.auth</artifactId>
|
||||
<version>1.0.130-SNAPSHOT</version>
|
||||
<version>1.0.129-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+5
-12
@@ -22,7 +22,7 @@ import io.cloudbeaver.auth.SMSignOutLinkProvider;
|
||||
import io.cloudbeaver.auth.provider.local.LocalAuthProvider;
|
||||
import io.cloudbeaver.model.WebAsyncTaskInfo;
|
||||
import io.cloudbeaver.model.WebPropertyInfo;
|
||||
import io.cloudbeaver.model.app.ServletApplication;
|
||||
import io.cloudbeaver.model.app.ServletAppConfiguration;
|
||||
import io.cloudbeaver.model.session.WebAuthInfo;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.model.session.WebSessionAuthProcessor;
|
||||
@@ -224,12 +224,9 @@ public class WebServiceAuthImpl implements DBWServiceAuth {
|
||||
throw new DBWebException("Not logged in");
|
||||
}
|
||||
try {
|
||||
List<WebAuthInfo> removedInfos = webSession.removeAuthInfo(providerId, false);
|
||||
var cbApp = CBApplication.getInstance();
|
||||
cbApp.getSessionManager().closeSession(webSession.getSessionId(), false);
|
||||
webSession.resetUserState();
|
||||
|
||||
List<WebAuthInfo> removedInfos = webSession.removeAuthInfo(providerId);
|
||||
List<String> logoutUrls = new ArrayList<>();
|
||||
var cbApp = CBApplication.getInstance();
|
||||
String origin = ServletAppUtils.getOriginFromRequest(httpRequest);
|
||||
for (WebAuthInfo removedInfo : removedInfos) {
|
||||
if (removedInfo.getAuthProviderDescriptor()
|
||||
@@ -267,12 +264,8 @@ public class WebServiceAuthImpl implements DBWServiceAuth {
|
||||
@Override
|
||||
public WebUserInfo activeUser(@NotNull WebSession webSession) throws DBWebException {
|
||||
if (webSession.getUser() == null) {
|
||||
ServletApplication application = webSession.getApplication();
|
||||
if (application.getAppConfiguration().isAnonymousAccessEnabled() && webSession.isAuthorizedInSecurityManager()) {
|
||||
SMUser anonymous = new SMUser("anonymous", true, null);
|
||||
return new WebUserInfo(webSession, new WebUser(anonymous));
|
||||
}
|
||||
if (!application.isAnonymousAccessEnabled()) {
|
||||
ServletAppConfiguration appConfiguration = webSession.getApplication().getAppConfiguration();
|
||||
if (!appConfiguration.isAnonymousAccessEnabled()) {
|
||||
return null;
|
||||
}
|
||||
SMUser anonymous = new SMUser("anonymous", true, null);
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public class LocalSessionHandler extends AbstractActionSessionHandler {
|
||||
|
||||
@Override
|
||||
public boolean handleSessionAuth(WebSession webSession) throws DBException, IOException {
|
||||
if (webSession.getUser() == null && !CBApplication.getInstance().isAnonymousAccessEnabled()) {
|
||||
if (webSession.getUser() == null && !CBApplication.getInstance().getAppConfiguration().isAnonymousAccessEnabled()) {
|
||||
return false;
|
||||
}
|
||||
executeAction(webSession);
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Service - Data Transfer
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.data.transfer;singleton:=true
|
||||
Bundle-Version: 1.0.131.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.130.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: io.cloudbeaver.server.ce,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.data.transfer</artifactId>
|
||||
<version>1.0.131-SNAPSHOT</version>
|
||||
<version>1.0.130-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2010-2024 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.
|
||||
@@ -53,7 +53,7 @@ public class WebDataTransferStreamProcessor {
|
||||
|
||||
@Property
|
||||
public String getFileExtension() {
|
||||
return processor.getProcessorFileExtension();
|
||||
return WebDataTransferUtils.getProcessorFileExtension(processor);
|
||||
}
|
||||
|
||||
@Property
|
||||
|
||||
+6
-3
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2010-2024 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.
|
||||
@@ -19,6 +19,7 @@ package io.cloudbeaver.service.data.transfer.impl;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
|
||||
import org.jkiss.dbeaver.tools.transfer.registry.DataTransferProcessorDescriptor;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
@@ -31,7 +32,9 @@ class WebDataTransferUtils {
|
||||
|
||||
|
||||
public static String getProcessorFileExtension(DataTransferProcessorDescriptor processor) {
|
||||
return processor.getProcessorFileExtension();
|
||||
DBPPropertyDescriptor extProperty = processor.getProperty("extension");
|
||||
String ext = extProperty == null ? processor.getAppFileExtension() : CommonUtils.toString(extProperty.getDefaultValue(), null);
|
||||
return CommonUtils.isEmpty(ext) ? "data" : ext;
|
||||
}
|
||||
|
||||
public static String getProcessorFileExtension(DataTransferProcessorDescriptor processor, Map<String, Object> processorProperties) {
|
||||
@@ -39,7 +42,7 @@ class WebDataTransferUtils {
|
||||
return CommonUtils.toString(processorProperties.get(EXTENSION), "data");
|
||||
}
|
||||
|
||||
return processor.getProcessorFileExtension();
|
||||
return getProcessorFileExtension(processor);
|
||||
}
|
||||
|
||||
public static String normalizeFileName(
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Service - File System
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.fs;singleton:=true
|
||||
Bundle-Version: 1.0.48.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.47.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: io.cloudbeaver.server.ce,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.fs</artifactId>
|
||||
<version>1.0.48-SNAPSHOT</version>
|
||||
<version>1.0.47-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Cloudbeaver Web Service - LDAP
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.ldap.auth;singleton:=true
|
||||
Bundle-Version: 1.0.13.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.12.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: org.jkiss.dbeaver.model;visibility:=reexport,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.ldap.auth</artifactId>
|
||||
<version>1.0.13-SNAPSHOT</version>
|
||||
<version>1.0.12-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Service - Metadata
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.metadata;singleton:=true
|
||||
Bundle-Version: 1.0.134.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.133.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: io.cloudbeaver.server
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.metadata</artifactId>
|
||||
<version>1.0.134-SNAPSHOT</version>
|
||||
<version>1.0.133-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Resource manager NIO implementation
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.rm.nio;singleton:=true
|
||||
Bundle-Version: 1.0.48.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.47.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: io.cloudbeaver.model,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.rm.nio</artifactId>
|
||||
<version>1.0.48-SNAPSHOT</version>
|
||||
<version>1.0.47-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Service - Resource manager
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.rm;singleton:=true
|
||||
Bundle-Version: 1.0.83.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.82.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: io.cloudbeaver.server,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.rm</artifactId>
|
||||
<version>1.0.83-SNAPSHOT</version>
|
||||
<version>1.0.82-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -67,8 +67,6 @@ extend type Query {
|
||||
resourcePath: String!
|
||||
): String!
|
||||
|
||||
"Returns project settings that are specified for a current user"
|
||||
rmUserProjectSettings(projectId: ID!): Object @since(version: "25.2.1")
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
@@ -111,13 +109,6 @@ extend type Mutation {
|
||||
description: String
|
||||
): RMProject!
|
||||
|
||||
"Updates project with the specified projectId. If projectName is not specified then does not change it."
|
||||
rmUpdateProject(
|
||||
projectId: ID!,
|
||||
projectName: String,
|
||||
description: String
|
||||
): RMProject!
|
||||
|
||||
"Deletes project by projectId. Returns true if project was deleted, false if project not found"
|
||||
rmDeleteProject(projectId: ID!): Boolean!
|
||||
|
||||
@@ -132,9 +123,4 @@ extend type Mutation {
|
||||
|
||||
"Sets resource property by name. If value is null then removes the property (e.g., sets relation between resource and connection)."
|
||||
rmSetResourceProperty(projectId: String!, resourcePath: String!, name: ID!, value: String): Boolean!
|
||||
|
||||
"Adds project settings (e.g. enables simple view for a project) for a current user"
|
||||
rmAddUserProjectSettings(projectId: ID!, settings: Object!): Boolean! @since(version: "25.2.1")
|
||||
"Deletes project settings that are specified for a current user"
|
||||
rmDeleteUserProjectSettings(projectId: ID!, settingIds: [String!]!): Boolean! @since(version: "25.2.1")
|
||||
}
|
||||
-31
@@ -31,7 +31,6 @@ import org.jkiss.dbeaver.model.rm.RMResource;
|
||||
import org.jkiss.dbeaver.model.security.SMObjectPermissionsGrant;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Web service API
|
||||
@@ -129,14 +128,6 @@ public interface DBWServiceRM extends DBWService {
|
||||
@NotNull String name,
|
||||
@Nullable String description) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = {RMConstants.PERMISSION_RM_ADMIN})
|
||||
RMProject updateProject(
|
||||
@NotNull WebSession session,
|
||||
@NotNull String projectId,
|
||||
@Nullable String name,
|
||||
@Nullable String description
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = {RMConstants.PERMISSION_RM_ADMIN})
|
||||
boolean deleteProject(
|
||||
@NotNull WebSession session,
|
||||
@@ -192,26 +183,4 @@ public interface DBWServiceRM extends DBWService {
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String subjectId
|
||||
) throws DBWebException;
|
||||
|
||||
@NotNull
|
||||
@WebProjectAction(requireProjectPermissions = RMConstants.PERMISSION_PROJECT_RESOURCE_VIEW)
|
||||
Map<String, Object> getProjectSettings(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull @WebObjectId String projectId,
|
||||
@Nullable String settingId
|
||||
) throws DBWebException;
|
||||
|
||||
@WebProjectAction(requireProjectPermissions = RMConstants.PERMISSION_PROJECT_RESOURCE_VIEW)
|
||||
boolean addProjectSettings(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull @WebObjectId String projectId,
|
||||
@NotNull Map<String, Object> settings
|
||||
) throws DBWebException;
|
||||
|
||||
@WebProjectAction(requireProjectPermissions = RMConstants.PERMISSION_PROJECT_RESOURCE_VIEW)
|
||||
boolean deleteProjectSettings(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull @WebObjectId String projectId,
|
||||
@Nullable List<String> settings
|
||||
) throws DBWebException;
|
||||
}
|
||||
|
||||
-30
@@ -64,13 +64,6 @@ public class WebServiceBindingRM extends WebServiceBindingBase<DBWServiceRM> {
|
||||
getWebSession(env),
|
||||
env.getArgument("subjectId")
|
||||
))
|
||||
.dataFetcher(
|
||||
"rmUserProjectSettings", env -> getService(env).getProjectSettings(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("settingId")
|
||||
)
|
||||
)
|
||||
;
|
||||
model.getMutationType()
|
||||
.dataFetcher("rmCreateResource",
|
||||
@@ -98,14 +91,6 @@ public class WebServiceBindingRM extends WebServiceBindingBase<DBWServiceRM> {
|
||||
env.getArgument("projectName"),
|
||||
env.getArgument("description")
|
||||
))
|
||||
.dataFetcher(
|
||||
"rmUpdateProject", env -> getService(env).updateProject(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("projectName"),
|
||||
env.getArgument("description")
|
||||
)
|
||||
)
|
||||
.dataFetcher("rmDeleteProject", env -> getService(env).deleteProject(
|
||||
getWebSession(env),
|
||||
getProjectReference(env)
|
||||
@@ -139,21 +124,6 @@ public class WebServiceBindingRM extends WebServiceBindingBase<DBWServiceRM> {
|
||||
env.getArgument("subjectIds"),
|
||||
env.getArgument("permissions")
|
||||
))
|
||||
.dataFetcher(
|
||||
"rmAddUserProjectSettings", env -> getService(env).addProjectSettings(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("settings")
|
||||
)
|
||||
)
|
||||
.dataFetcher(
|
||||
"rmDeleteUserProjectSettings", env -> getService(env).deleteProjectSettings(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("settingIds")
|
||||
)
|
||||
)
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
-92
@@ -31,7 +31,6 @@ import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.rm.RMController;
|
||||
import org.jkiss.dbeaver.model.rm.RMProject;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectInfo;
|
||||
import org.jkiss.dbeaver.model.rm.RMResource;
|
||||
import org.jkiss.dbeaver.model.secret.DBSSecretController;
|
||||
import org.jkiss.dbeaver.model.security.*;
|
||||
@@ -267,31 +266,6 @@ public class WebServiceRM implements DBWServiceRM {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RMProject updateProject(
|
||||
@NotNull WebSession session,
|
||||
@NotNull String projectId,
|
||||
@Nullable String name,
|
||||
@Nullable String description
|
||||
) throws DBWebException {
|
||||
try {
|
||||
var project = session.getProjectById(projectId);
|
||||
if (project == null) {
|
||||
throw new DBException("Project not found: " + projectId);
|
||||
}
|
||||
RMProjectInfo projectInfo = new RMProjectInfo(name, description);
|
||||
RMProject rmProject = getResourceController(session).updateProject(projectId, projectInfo);
|
||||
project.updateProject(rmProject.getName(), rmProject.getDescription());
|
||||
|
||||
ServletAppUtils.getServletApplication().getEventController().addEvent(
|
||||
WSProjectUpdateEvent.update(session.getSessionId(), session.getUserId(), rmProject.getId(), projectInfo)
|
||||
);
|
||||
return project.getRMProject();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error updating project", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteProject(@NotNull WebSession session, @NotNull String projectId) throws DBWebException {
|
||||
try {
|
||||
@@ -469,72 +443,6 @@ public class WebServiceRM implements DBWServiceRM {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> getProjectSettings(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String projectId,
|
||||
@Nullable String settingId
|
||||
) throws DBWebException {
|
||||
try {
|
||||
var project = webSession.getProjectById(projectId);
|
||||
if (project == null) {
|
||||
throw new DBWebException("Project '" + projectId + "' not found");
|
||||
}
|
||||
return webSession.getSecurityController().getObjectSettings(
|
||||
projectId,
|
||||
SMObjectType.project,
|
||||
settingId
|
||||
);
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error getting project settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addProjectSettings(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String projectId,
|
||||
@NotNull Map<String, Object> settings
|
||||
) throws DBWebException {
|
||||
try {
|
||||
var project = webSession.getProjectById(projectId);
|
||||
if (project == null) {
|
||||
throw new DBWebException("Project '" + projectId + "' not found");
|
||||
}
|
||||
webSession.getSecurityController().setObjectSettings(
|
||||
projectId,
|
||||
SMObjectType.project,
|
||||
settings
|
||||
);
|
||||
return true;
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error adding object settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteProjectSettings(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String projectId,
|
||||
@Nullable List<String> settings
|
||||
) throws DBWebException {
|
||||
try {
|
||||
var project = webSession.getProjectById(projectId);
|
||||
if (project == null) {
|
||||
throw new DBWebException("Project '" + projectId + "' not found");
|
||||
}
|
||||
webSession.getSecurityController().deleteObjectSettings(
|
||||
projectId,
|
||||
SMObjectType.project,
|
||||
settings == null ? null : new HashSet<>(settings)
|
||||
);
|
||||
return true;
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error deleting object settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
private RMController getResourceController(WebSession webSession) {
|
||||
return webSession.getRmController();
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Cloudbeaver Web Service - Security
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-SymbolicName: io.cloudbeaver.service.security;singleton:=true
|
||||
Bundle-Version: 1.0.86.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.85.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: org.jkiss.dbeaver.model;visibility:=reexport,
|
||||
|
||||
@@ -240,19 +240,3 @@ CREATE TABLE {table_prefix}CB_AUTH_ATTEMPT_INFO
|
||||
PRIMARY KEY (AUTH_ID, AUTH_PROVIDER_ID),
|
||||
FOREIGN KEY (AUTH_ID) REFERENCES {table_prefix}CB_AUTH_ATTEMPT (AUTH_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE {table_prefix}CB_OBJECT_SETTINGS
|
||||
(
|
||||
OBJECT_ID VARCHAR(128) NOT NULL,
|
||||
OBJECT_TYPE VARCHAR(128) NOT NULL,
|
||||
SUBJECT_ID VARCHAR(128) NOT NULL,
|
||||
SETTING_ID VARCHAR(32) NOT NULL,
|
||||
SETTING_VALUE VARCHAR(1024),
|
||||
|
||||
UPDATE_TIME TIMESTAMP NOT NULL,
|
||||
UPDATED_BY VARCHAR(128) NOT NULL,
|
||||
|
||||
PRIMARY KEY (SUBJECT_ID, OBJECT_TYPE, OBJECT_ID, SETTING_ID),
|
||||
FOREIGN KEY (SUBJECT_ID) REFERENCES {table_prefix}CB_AUTH_SUBJECT(SUBJECT_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
CREATE TABLE {table_prefix}CB_OBJECT_SETTINGS
|
||||
(
|
||||
OBJECT_ID VARCHAR(128) NOT NULL,
|
||||
OBJECT_TYPE VARCHAR(128) NOT NULL,
|
||||
SUBJECT_ID VARCHAR(128) NOT NULL,
|
||||
SETTING_ID VARCHAR(32) NOT NULL,
|
||||
SETTING_VALUE VARCHAR(1024),
|
||||
|
||||
UPDATE_TIME TIMESTAMP NOT NULL,
|
||||
UPDATED_BY VARCHAR(128) NOT NULL,
|
||||
|
||||
PRIMARY KEY (SUBJECT_ID, OBJECT_TYPE, OBJECT_ID, SETTING_ID),
|
||||
FOREIGN KEY (SUBJECT_ID) REFERENCES {table_prefix}CB_AUTH_SUBJECT(SUBJECT_ID) ON DELETE CASCADE
|
||||
);
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.security</artifactId>
|
||||
<version>1.0.86-SNAPSHOT</version>
|
||||
<version>1.0.85-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+1
-108
@@ -104,107 +104,6 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
this.smConfig = smConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setObjectSettings(
|
||||
@NotNull String objectId,
|
||||
@NotNull SMObjectType objectType,
|
||||
@NotNull Map<String, Object> settings
|
||||
) throws DBException {
|
||||
String userId = getUserIdOrThrow();
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
|
||||
deleteObjectSettings(objectId, objectType, settings.keySet());
|
||||
try (
|
||||
PreparedStatement dbStat = dbCon.prepareStatement(
|
||||
"INSERT INTO {table_prefix}CB_OBJECT_SETTINGS" +
|
||||
"(OBJECT_ID,OBJECT_TYPE,SUBJECT_ID,SETTING_ID,SETTING_VALUE,UPDATED_BY,UPDATE_TIME) " +
|
||||
"VALUES(?,?,?,?,?,?,CURRENT_TIMESTAMP)")
|
||||
) {
|
||||
for (Map.Entry<String, Object> entry : settings.entrySet()) {
|
||||
dbStat.setString(1, objectId);
|
||||
dbStat.setString(2, objectType.name());
|
||||
dbStat.setString(3, userId);
|
||||
dbStat.setString(4, entry.getKey());
|
||||
dbStat.setString(5, CommonUtils.toString(entry.getValue()));
|
||||
dbStat.setString(6, userId);
|
||||
dbStat.addBatch();
|
||||
}
|
||||
dbStat.executeBatch();
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new DBCException("Error while adding object settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> getObjectSettings(
|
||||
@NotNull String objectId,
|
||||
@NotNull SMObjectType objectType,
|
||||
@Nullable String settingId
|
||||
) throws DBException {
|
||||
String userId = getUserIdOrThrow();
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (
|
||||
PreparedStatement dbStat = dbCon.prepareStatement("SELECT SETTING_ID,SETTING_VALUE " +
|
||||
"FROM {table_prefix}CB_OBJECT_SETTINGS " +
|
||||
"WHERE OBJECT_ID=? AND OBJECT_TYPE=? AND SUBJECT_ID=?" +
|
||||
(settingId == null ? "" : " AND SETTING_ID=?"))
|
||||
) {
|
||||
int index = 1;
|
||||
dbStat.setString(index++, objectId);
|
||||
dbStat.setString(index++, objectType.name());
|
||||
dbStat.setString(index++, userId);
|
||||
if (settingId != null) {
|
||||
dbStat.setString(index++, settingId);
|
||||
}
|
||||
try (ResultSet dbResult = dbStat.executeQuery()) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
while (dbResult.next()) {
|
||||
result.put(
|
||||
dbResult.getString(1),
|
||||
dbResult.getString(2)
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new DBCException("Error while getting object settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteObjectSettings(
|
||||
@NotNull String objectId,
|
||||
@NotNull SMObjectType objectType,
|
||||
@Nullable Set<String> settingIds
|
||||
) throws DBException {
|
||||
String userId = getUserIdOrThrow();
|
||||
String sql = "DELETE FROM {table_prefix}CB_OBJECT_SETTINGS WHERE OBJECT_ID=? AND OBJECT_TYPE=? AND SUBJECT_ID=?";
|
||||
if (settingIds != null && !settingIds.isEmpty()) {
|
||||
sql += " AND SETTING_ID IN (" + SQLUtils.generateParamList(settingIds.size()) + ")";
|
||||
}
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (PreparedStatement dbStat = dbCon.prepareStatement(sql)) {
|
||||
int index = 1;
|
||||
dbStat.setString(index++, objectId);
|
||||
dbStat.setString(index++, objectType.name());
|
||||
dbStat.setString(index++, userId);
|
||||
if (settingIds != null) {
|
||||
for (String settingId : settingIds) {
|
||||
dbStat.setString(index++, settingId);
|
||||
}
|
||||
}
|
||||
dbStat.executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new DBCException("Error while deleting object settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isSubjectExists(String subjectId) throws DBCException {
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (PreparedStatement dbStat = dbCon.prepareStatement(
|
||||
@@ -1680,7 +1579,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
|
||||
@Override
|
||||
public SMAuthInfo authenticateAnonymousUser(@NotNull String appSessionId, @NotNull Map<String, Object> sessionParameters, @NotNull SMSessionType sessionType) throws DBException {
|
||||
if (!application.isAnonymousAccessEnabled()) {
|
||||
if (!application.getAppConfiguration().isAnonymousAccessEnabled()) {
|
||||
throw new SMException("Anonymous access restricted");
|
||||
}
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
@@ -3157,12 +3056,6 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
objectType.name(),
|
||||
objectId
|
||||
);
|
||||
JDBCUtils.executeStatement(
|
||||
dbCon,
|
||||
"DELETE FROM {table_prefix}CB_OBJECT_SETTINGS WHERE OBJECT_TYPE=? AND OBJECT_ID=?",
|
||||
objectType.name(),
|
||||
objectId
|
||||
);
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new DBCException("Error deleting object permissions", e);
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ import javax.sql.DataSource;
|
||||
public class CBDatabase extends InternalDB<WebDatabaseConfig> {
|
||||
private static final Log log = Log.getLog(CBDatabase.class);
|
||||
|
||||
private static final int CURRENT_SCHEMA_VERSION = 26;
|
||||
private static final int CURRENT_SCHEMA_VERSION = 25;
|
||||
private static final String SCHEMA_ID = "CB_CE";
|
||||
|
||||
private static final SQLSchemaConfig SCHEMA_CREATE_CONFIG = new SQLSchemaConfig(
|
||||
|
||||
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: CloudBeaver SLF4j Binding
|
||||
Bundle-SymbolicName: io.cloudbeaver.slf4j;singleton:=true
|
||||
Bundle-Version: 1.0.46.qualifier
|
||||
Bundle-Release-Date: 20251006
|
||||
Bundle-Version: 1.0.45.qualifier
|
||||
Bundle-Release-Date: 20250922
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Fragment-Host: slf4j.api
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.slf4j</artifactId>
|
||||
<version>1.0.46-SNAPSHOT</version>
|
||||
<version>1.0.45-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -20,12 +20,6 @@
|
||||
<artifactId>clickhouse-jdbc</artifactId>
|
||||
<version>0.8.5</version>
|
||||
<classifier>http</classifier>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<feature
|
||||
id="io.cloudbeaver.ce.drivers.feature"
|
||||
label="Cloudbeaver CE 3rd Party Drivers"
|
||||
version="1.0.154.qualifier"
|
||||
version="1.0.153.qualifier"
|
||||
provider-name="DBeaver Corp">
|
||||
|
||||
<plugin id="io.cloudbeaver.resources.drivers.base" download-size="0" install-size="0" version="0.0.0"/>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user