mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-16 14:50:15 +08:00
Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c814017566 | ||
|
|
4ab47583ad | ||
|
|
37cfecbf91 | ||
|
|
046659672c | ||
|
|
2a3a94608c | ||
|
|
bf52e23793 | ||
|
|
4a2ce73a9c | ||
|
|
b73b707b7f | ||
|
|
57461bd8be | ||
|
|
71bebb32dd | ||
|
|
d810edf89d | ||
|
|
28cade86aa | ||
|
|
e64d5ff92c | ||
|
|
92186dd332 | ||
|
|
36be366c64 | ||
|
|
860a9f55f2 | ||
|
|
754c8d562d | ||
|
|
ed0e92cdd6 | ||
|
|
9267e65300 | ||
|
|
4e3ec7cbf4 | ||
|
|
6978ae5355 | ||
|
|
3986debe8f | ||
|
|
38cfb0a690 | ||
|
|
682a387564 | ||
|
|
de0dee29ed | ||
|
|
3a1ae15ecb | ||
|
|
8cf064e845 | ||
|
|
ec1b455f4d | ||
|
|
683d85c8d6 | ||
|
|
8066904d4d | ||
|
|
7ea46ea2c5 | ||
|
|
8aee24cf1c | ||
|
|
5d83098d38 | ||
|
|
3e855c3afd | ||
|
|
9c50589586 | ||
|
|
f99c2e3ebd | ||
|
|
e141575785 | ||
|
|
b93b85f622 | ||
|
|
267a753d87 | ||
|
|
6cea8cd64f | ||
|
|
b630cb6791 |
@@ -25,9 +25,19 @@ You can see a live demo of CloudBeaver here: https://demo.cloudbeaver.io
|
||||
|
||||
## Changelog
|
||||
|
||||
### 25.2.3 2025-10-20
|
||||
- Added visualization for column reordering in the Data Editor;
|
||||
- Fixed the critical issue with duplicating the execution of queries executed by a shortcut in the SQL Editor;
|
||||
- Fixed the critical vulnerability (CVE-2025-61927) in the Happy DOM library. The library was updated to version 20.0.2.
|
||||
|
||||
### 25.2.2 2025-10-06
|
||||
- Replaced true/false text with intuitive checkboxes for boolean values in the metadata editor, making editing easier and faster;
|
||||
- Keyboard navigation was improved across the application. Additional shortcuts are available in the main info panel (top-right corner). To help you discover them faster, relevant keyboard shortcuts are also shown directly in the tooltips of Data Editor buttons;
|
||||
- Fixed an issue in the Data Editor where resizing one column in a wide table would cause previously resized columns to revert to their original width. Users can resize multiple columns as intended.
|
||||
|
||||
### 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.
|
||||
- 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
|
||||
|
||||
@@ -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.88.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.88-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -32,6 +32,8 @@ public interface DBWConstants {
|
||||
String PERMISSION_SQL_RESULT_UPDATE = "sql-result-update";
|
||||
String PERMISSION_SQL_EXECUTE_QUERY = "sql-execute-query";
|
||||
|
||||
String PERMISSION_FS_RESOURCE_EDIT = "fs-resource-edit";
|
||||
|
||||
String GLOBAL_PERMISSION_SCRIPT_EXECUTE = "permission.sql.script.execution";
|
||||
String GLOBAL_PERMISSION_DATA_EDITOR_IMPORT = "permission.data-editor.import";
|
||||
String GLOBAL_PERMISSION_DATA_EDITOR_EDITING = "permission.data-editor.editing";
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public class WebDataSourceConnectEventListener implements DBPEventListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleDataSourceEvent(DBPEvent event) {
|
||||
public void handleDataSourceEvent(@NotNull DBPEvent event) {
|
||||
if (!(event.getObject() instanceof DBPDataSourceContainer container)) {
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
public abstract class BaseDatasourceAccessCheckHandler implements DBPDataSourceHandler {
|
||||
@Override
|
||||
public void beforeConnect(
|
||||
DBRProgressMonitor monitor,
|
||||
@NotNull DBRProgressMonitor monitor,
|
||||
@NotNull DBPDataSourceContainer dataSourceContainer
|
||||
) throws DBException {
|
||||
if (isDriverDisabled(dataSourceContainer.getDriver())) {
|
||||
@@ -20,7 +20,7 @@ public abstract class BaseDatasourceAccessCheckHandler implements DBPDataSourceH
|
||||
|
||||
@Override
|
||||
public void beforeDisconnect(
|
||||
DBRProgressMonitor monitor,
|
||||
@NotNull DBRProgressMonitor monitor,
|
||||
@NotNull DBPDataSourceContainer dataSourceContainer
|
||||
) throws DBException {
|
||||
|
||||
|
||||
+18
-3
@@ -252,6 +252,7 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public String[] getFeatures() {
|
||||
List<String> features = new ArrayList<>();
|
||||
|
||||
@@ -281,11 +282,13 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public DBNBrowseSettings getNavigatorSettings() {
|
||||
return dataSourceContainer.getNavigatorSettings();
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public List<WebDataFormat> getSupportedDataFormats() {
|
||||
List<WebDataFormat> formats = new ArrayList<>();
|
||||
formats.add(WebDataFormat.resultset);
|
||||
@@ -300,11 +303,13 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public WebConnectionOriginInfo getOrigin() {
|
||||
return new WebConnectionOriginInfo(session, dataSourceContainer, dataSourceContainer.getOrigin());
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public DBPDriverConfigurationType getConfigurationType() {
|
||||
DBPDriverConfigurationType configurationType = dataSourceContainer.getConnectionConfiguration().getConfigurationType();
|
||||
if (configurationType == null) {
|
||||
@@ -330,6 +335,7 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public String getAuthModel() {
|
||||
String authModelId = dataSourceContainer.getConnectionConfiguration().getAuthModelId();
|
||||
if (CommonUtils.isEmpty(authModelId)) {
|
||||
@@ -339,6 +345,7 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public WebPropertyInfo[] getAuthProperties() {
|
||||
String authModelId = getAuthModel();
|
||||
DBPAuthModelDescriptor authModel = DBWorkbench.getPlatform().getDataSourceProviderRegistry().getAuthModel(authModelId);
|
||||
@@ -361,6 +368,7 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public List<WebNetworkHandlerConfig> getNetworkHandlersConfig() {
|
||||
var registry = NetworkHandlerRegistry.getInstance();
|
||||
return dataSourceContainer.getConnectionConfiguration()
|
||||
@@ -375,20 +383,23 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@Nullable
|
||||
public Map<String, Object> getCredentials() {
|
||||
//dataSourceContainer.getConnectionConfiguration().getCredentialsProvider().getCredentials();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, Object> getSavedAuthProperties() {
|
||||
return savedAuthProperties;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<WebNetworkHandlerConfigInput> getSavedNetworkCredentials() {
|
||||
return savedNetworkCredentials;
|
||||
}
|
||||
|
||||
public void setSavedCredentials(Map<String, Object> authProperties, List<WebNetworkHandlerConfigInput> networkCredentials) {
|
||||
public void setSavedCredentials(@Nullable Map<String, Object> authProperties, @Nullable List<WebNetworkHandlerConfigInput> networkCredentials) {
|
||||
this.savedAuthProperties = authProperties;
|
||||
this.savedNetworkCredentials = networkCredentials;
|
||||
}
|
||||
@@ -413,6 +424,7 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public Map<String, String> getMainPropertyValues() {
|
||||
Map<String, String> mainProperties = new LinkedHashMap<>();
|
||||
mainProperties.put(DBConstants.PROP_HOST, getHost());
|
||||
@@ -468,7 +480,7 @@ public class WebConnectionInfo {
|
||||
return dataSourceContainer.getRequiredExternalAuth();
|
||||
}
|
||||
|
||||
private boolean hasProjectPermission(RMProjectPermission projectPermission) {
|
||||
private boolean hasProjectPermission(@NotNull RMProjectPermission projectPermission) {
|
||||
DBPProject project = dataSourceContainer.getProject();
|
||||
if (!(project instanceof WebProjectImpl webProject)) {
|
||||
return false;
|
||||
@@ -508,18 +520,21 @@ public class WebConnectionInfo {
|
||||
}
|
||||
|
||||
@Property
|
||||
@Nullable
|
||||
public String getDefaultCatalogName() {
|
||||
DBPConnectionConfiguration connectionConfiguration = dataSourceContainer.getConnectionConfiguration();
|
||||
return connectionConfiguration.getBootstrap().getDefaultCatalogName();
|
||||
}
|
||||
|
||||
@Property
|
||||
@Nullable
|
||||
public String getDefaultSchemaName() {
|
||||
DBPConnectionConfiguration connectionConfiguration = dataSourceContainer.getConnectionConfiguration();
|
||||
return connectionConfiguration.getBootstrap().getDefaultSchemaName();
|
||||
}
|
||||
|
||||
@Property
|
||||
@NotNull
|
||||
public List<WebSecretInfo> getSharedSecrets() throws DBException {
|
||||
return dataSourceContainer.listSharedCredentials()
|
||||
.stream()
|
||||
@@ -527,8 +542,8 @@ public class WebConnectionInfo {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Property
|
||||
@NotNull
|
||||
public List<String> getTools() {
|
||||
if (!session.hasPermission(RMConstants.PERMISSION_DATABASE_DEVELOPER)) {
|
||||
return List.of();
|
||||
|
||||
+6
-5
@@ -1,6 +1,7 @@
|
||||
package io.cloudbeaver.model;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.DBPObject;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriverConstants;
|
||||
@@ -52,35 +53,35 @@ public class WebExpertSettingsProperties implements DBPObject {
|
||||
|
||||
public static class KeepAliveIntervalFieldValidator implements IPropertyValueValidator<WebExpertSettingsProperties, Object> {
|
||||
@Override
|
||||
public boolean isValidValue(WebExpertSettingsProperties object, Object value) throws IllegalArgumentException {
|
||||
public boolean isValidValue(@NotNull WebExpertSettingsProperties object, @Nullable Object value) throws IllegalArgumentException {
|
||||
return CommonUtils.toBoolean(!object.driver.isEmbedded(), true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AutoCommitFieldValidator implements IPropertyValueValidator<WebExpertSettingsProperties, Object> {
|
||||
@Override
|
||||
public boolean isValidValue(WebExpertSettingsProperties object, Object value) throws IllegalArgumentException {
|
||||
public boolean isValidValue(@NotNull WebExpertSettingsProperties object, @Nullable Object value) throws IllegalArgumentException {
|
||||
return CommonUtils.toBoolean(object.driver.getDriverParameter(DBPDriverConstants.PARAM_SUPPORTS_TRANSACTIONS), true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReadOnlyFieldValidator implements IPropertyValueValidator<WebExpertSettingsProperties, Object> {
|
||||
@Override
|
||||
public boolean isValidValue(WebExpertSettingsProperties object, Object value) throws IllegalArgumentException {
|
||||
public boolean isValidValue(@NotNull WebExpertSettingsProperties object, @Nullable Object value) throws IllegalArgumentException {
|
||||
return CommonUtils.toBoolean(object.driver.getDriverParameter(DBPDriverConstants.PARAM_SUPPORTS_READ_ONLY_MODE), true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DefaultCatalogFieldVisibleValidator implements IPropertyValueValidator<WebExpertSettingsProperties, Object> {
|
||||
@Override
|
||||
public boolean isValidValue(WebExpertSettingsProperties object, Object value) throws IllegalArgumentException {
|
||||
public boolean isValidValue(@NotNull WebExpertSettingsProperties object, @Nullable Object value) throws IllegalArgumentException {
|
||||
return CommonUtils.toBoolean(object.driver.getDriverParameter(DBPDriverConstants.PARAM_SUPPORTS_CATALOG_SELECTION), true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DefaultSchemaFieldVisibleValidator implements IPropertyValueValidator<WebExpertSettingsProperties, Object> {
|
||||
@Override
|
||||
public boolean isValidValue(WebExpertSettingsProperties object, Object value) throws IllegalArgumentException {
|
||||
public boolean isValidValue(@NotNull WebExpertSettingsProperties object, @Nullable Object value) throws IllegalArgumentException {
|
||||
return CommonUtils.toBoolean(object.driver.getDriverParameter(DBPDriverConstants.PARAM_SUPPORTS_SCHEMA_SELECTION), true);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -41,6 +41,7 @@ import org.jkiss.dbeaver.utils.GeneralUtils;
|
||||
import org.jkiss.dbeaver.utils.RuntimeUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
@@ -204,7 +205,7 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
|
||||
initializeApplicationServices();
|
||||
try {
|
||||
try {
|
||||
this.instanceServer = new CloudBeaverInstanceServer();
|
||||
this.instanceServer = createInstanceServer();
|
||||
} catch (Exception e) {
|
||||
log.error("Error initializing instance server", e);
|
||||
}
|
||||
@@ -216,6 +217,10 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
|
||||
return EXIT_OK;
|
||||
}
|
||||
|
||||
protected CloudBeaverInstanceServer createInstanceServer() throws IOException {
|
||||
return new CloudBeaverInstanceServer();
|
||||
}
|
||||
|
||||
protected abstract void startServer() throws DBException;
|
||||
|
||||
@Override
|
||||
|
||||
+10
-1
@@ -62,6 +62,7 @@ public class ServletSystemInformationCollector<T extends ServletApplication> imp
|
||||
private DBPConnectionInformation smDatabaseInfo;
|
||||
private String workspacePath;
|
||||
private final DeploymentType deploymentType;
|
||||
private boolean internalDatabaseInfoCollected = false;
|
||||
|
||||
public ServletSystemInformationCollector(@NotNull T application) {
|
||||
this.application = application;
|
||||
@@ -158,7 +159,15 @@ public class ServletSystemInformationCollector<T extends ServletApplication> imp
|
||||
/**
|
||||
* Collects info about internal databases.
|
||||
*/
|
||||
public void collectInternalDatabaseUseInformation() throws DBException {
|
||||
public synchronized void collectInternalDatabaseUseInformation() throws DBException {
|
||||
if (internalDatabaseInfoCollected) {
|
||||
return;
|
||||
}
|
||||
collectInternalDatabaseInfo();
|
||||
this.internalDatabaseInfoCollected = true;
|
||||
}
|
||||
|
||||
protected void collectInternalDatabaseInfo() throws DBException {
|
||||
this.smDatabaseInfo = application.getAdminSecurityController(new NoAuthCredentialsProvider())
|
||||
.getInternalDatabaseInformation();
|
||||
}
|
||||
|
||||
+29
-8
@@ -16,20 +16,41 @@
|
||||
*/
|
||||
package io.cloudbeaver.model.cli;
|
||||
|
||||
import org.jkiss.dbeaver.model.cli.ApplicationCommandLine;
|
||||
import org.jkiss.dbeaver.model.cli.ApplicationInstanceController;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.cli.*;
|
||||
import org.jkiss.dbeaver.model.cli.model.CommandLineAuthenticator;
|
||||
import picocli.CommandLine;
|
||||
|
||||
public class CloudBeaverCommandLine extends ApplicationCommandLine<ApplicationInstanceController> {
|
||||
private static CloudBeaverCommandLine INSTANCE = null;
|
||||
|
||||
private CloudBeaverCommandLine() {
|
||||
@Nullable
|
||||
private final CommandLineAuthenticator authenticator;
|
||||
|
||||
public CloudBeaverCommandLine(@Nullable CommandLineAuthenticator authenticator) {
|
||||
super();
|
||||
this.authenticator = authenticator;
|
||||
}
|
||||
|
||||
public synchronized static CloudBeaverCommandLine getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new CloudBeaverCommandLine();
|
||||
@Override
|
||||
protected CloudBeaverTopLevelCommand createTopLevelCommand(
|
||||
@Nullable ApplicationInstanceController applicationInstanceController,
|
||||
@NotNull CommandLineContext context,
|
||||
@NotNull CLIRunMeta runMeta
|
||||
) {
|
||||
if (authenticator != null) {
|
||||
context.setContextParameter(CLIConstants.CONTEXT_PARAM_AUTHENTICATOR, authenticator);
|
||||
}
|
||||
return INSTANCE;
|
||||
return new CloudBeaverTopLevelCommand(applicationInstanceController, context, runMeta);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected CommandLine initCommandLine(
|
||||
@Nullable ApplicationInstanceController applicationInstanceController,
|
||||
@NotNull CommandLineContext context,
|
||||
@NotNull CLIRunMeta runMeta
|
||||
) {
|
||||
return super.initCommandLine(applicationInstanceController, context, runMeta);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-5
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
package io.cloudbeaver.model.cli;
|
||||
|
||||
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;
|
||||
@@ -25,20 +25,27 @@ import org.jkiss.dbeaver.model.cli.CLIProcessResult;
|
||||
import java.io.IOException;
|
||||
|
||||
public class CloudBeaverInstanceServer extends ApplicationInstanceServer<ApplicationInstanceController> {
|
||||
private final CloudBeaverCommandLine commandLine;
|
||||
|
||||
public CloudBeaverInstanceServer() throws IOException {
|
||||
super(ApplicationInstanceController.class);
|
||||
this.commandLine = new CloudBeaverCommandLine(null);
|
||||
}
|
||||
|
||||
protected CloudBeaverInstanceServer(@NotNull CloudBeaverCommandLine commandLine) throws IOException {
|
||||
super(ApplicationInstanceController.class);
|
||||
this.commandLine = commandLine;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CLIProcessResult handleCommandLine(@NotNull String[] args) {
|
||||
CommandLine cmd = CloudBeaverCommandLine.getInstance().getCommandLine(args);
|
||||
try {
|
||||
return CloudBeaverCommandLine.getInstance().executeCommandLineCommands(
|
||||
cmd,
|
||||
return commandLine.executeCommandLineCommands(
|
||||
this,
|
||||
false,
|
||||
false
|
||||
false,
|
||||
args
|
||||
);
|
||||
} catch (Exception e) {
|
||||
return new CLIProcessResult(CLIProcessResult.PostAction.ERROR, "Error executing command: " + e.getMessage());
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.cli.ApplicationInstanceController;
|
||||
import org.jkiss.dbeaver.model.cli.CLIRunMeta;
|
||||
import org.jkiss.dbeaver.model.cli.CommandLineContext;
|
||||
import org.jkiss.dbeaver.model.cli.command.AbstractTopLevelCommand;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "cbvr", description = "CloudBeaver commands", mixinStandardHelpOptions = true)
|
||||
public class CloudBeaverTopLevelCommand extends AbstractTopLevelCommand {
|
||||
protected CloudBeaverTopLevelCommand(
|
||||
@Nullable ApplicationInstanceController controller,
|
||||
@NotNull CommandLineContext context,
|
||||
@NotNull CLIRunMeta meta
|
||||
|
||||
) {
|
||||
super(controller, context, meta);
|
||||
}
|
||||
}
|
||||
+11
-2
@@ -60,26 +60,31 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
|
||||
return project.getId();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNodeType() {
|
||||
return "rm.project";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNodeDisplayName() {
|
||||
return project.getDisplayName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getLocalizedName(String locale) {
|
||||
public String getLocalizedName(@NotNull String locale) {
|
||||
return getNodeDisplayName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getNodeDescription() {
|
||||
return project.getDescription();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBPImage getNodeIcon() {
|
||||
return DBIcon.PROJECT;
|
||||
@@ -90,6 +95,7 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBNResourceManagerResource[] getChildren(@NotNull DBRProgressMonitor monitor) throws DBException {
|
||||
if (children == null && !monitor.isForceCacheUsage()) {
|
||||
@@ -109,14 +115,16 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
|
||||
return ((DBNResourceManagerRoot) getParentNode()).getResourceController();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getNodeItemPath() {
|
||||
return getParentNode().getNodeItemPath() + "/" + getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBNNode refreshNode(DBRProgressMonitor monitor, Object source) throws DBException {
|
||||
public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException {
|
||||
children = null;
|
||||
return this;
|
||||
}
|
||||
@@ -141,6 +149,7 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
|
||||
return project;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNodeDisplayName();
|
||||
|
||||
+10
-2
@@ -49,21 +49,25 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNodeType() {
|
||||
return "rm.resource";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNodeDisplayName() {
|
||||
return resource.getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getNodeDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBPImage getNodeIcon() {
|
||||
if (resource.isFolder()) {
|
||||
@@ -109,6 +113,7 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
return resource.isFolder();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBNNode[] getChildren(@NotNull DBRProgressMonitor monitor) throws DBException {
|
||||
if (children == null && !monitor.isForceCacheUsage()) {
|
||||
@@ -154,14 +159,16 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
throw new DBException("Can't detect resource root node");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getNodeItemPath() {
|
||||
return getParentNode().getNodeItemPath() + "/" + getNodeDisplayName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBNNode refreshNode(DBRProgressMonitor monitor, Object source) throws DBException {
|
||||
public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException {
|
||||
this.children = null;
|
||||
return super.refreshNode(monitor, source);
|
||||
}
|
||||
@@ -171,7 +178,7 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rename(DBRProgressMonitor monitor, String newName) throws DBException {
|
||||
public void rename(@NotNull DBRProgressMonitor monitor, @NotNull String newName) throws DBException {
|
||||
String resourceName = resource.getName();
|
||||
try {
|
||||
if (newName.indexOf('.') == -1) {
|
||||
@@ -192,6 +199,7 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNodeDisplayName();
|
||||
|
||||
+9
-1
@@ -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;
|
||||
@@ -49,6 +50,7 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
return resourceController;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNodeType() {
|
||||
return "rm";
|
||||
@@ -60,16 +62,19 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
return "rm";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNodeDisplayName() {
|
||||
return "resources";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getNodeDescription() {
|
||||
return "Resources";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBPImage getNodeIcon() {
|
||||
return null;
|
||||
@@ -80,6 +85,7 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBNResourceManagerProject[] getChildren(@NotNull DBRProgressMonitor monitor) throws DBException {
|
||||
if (projects == null && !monitor.isForceCacheUsage()) {
|
||||
@@ -109,6 +115,7 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
return projects;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getNodeItemPath() {
|
||||
@@ -116,8 +123,9 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
return NodePathType.ext.getPrefix() + getNodeDisplayName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DBNNode refreshNode(DBRProgressMonitor monitor, Object source) throws DBException {
|
||||
public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException {
|
||||
projects = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
+6
-4
@@ -54,12 +54,12 @@ import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
import org.jkiss.utils.Pair;
|
||||
import org.jkiss.utils.StandardConstants;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.text.MessageFormat;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -1262,8 +1262,10 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
project.setProjectPermissions(allProjectPermissions);
|
||||
if (Files.exists(path)) {
|
||||
try {
|
||||
project.setCreateTime(
|
||||
OffsetDateTime.ofInstant(Files.getLastModifiedTime(path).toInstant(), ZoneId.of("UTC")).toInstant().toEpochMilli());
|
||||
project.setCreateTime(OffsetDateTime.ofInstant(
|
||||
Files.getLastModifiedTime(path).toInstant(),
|
||||
StandardConstants.ZONE_ID_UTC
|
||||
).toInstant().toEpochMilli());
|
||||
} catch (IOException e) {
|
||||
log.error(e);
|
||||
}
|
||||
@@ -1271,7 +1273,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
// Resource types
|
||||
project.setResourceTypes(ResourceTypeRegistry.getInstance().getResourceTypes()
|
||||
.stream()
|
||||
.filter(ResourceTypeDescriptor::isManagable)
|
||||
.filter(ResourceTypeDescriptor::isManageable)
|
||||
.map(RMResourceType::new)
|
||||
.toArray(RMResourceType[]::new));
|
||||
|
||||
|
||||
+3
-92
@@ -18,22 +18,15 @@ 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 org.jkiss.dbeaver.registry.project.LocalProjectImpl;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
public class RMLocalProject extends BaseProjectImpl {
|
||||
@NotNull
|
||||
private final Path projectPath;
|
||||
public class RMLocalProject extends LocalProjectImpl {
|
||||
@NotNull
|
||||
private final RMProjectType projectType;
|
||||
|
||||
@@ -43,12 +36,10 @@ public class RMLocalProject extends BaseProjectImpl {
|
||||
@NotNull Path projectPath,
|
||||
@NotNull RMProjectType type
|
||||
) {
|
||||
super(workspace, sessionContext);
|
||||
this.projectPath = projectPath;
|
||||
super(workspace, sessionContext, projectPath);
|
||||
this.projectType = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return true;
|
||||
@@ -60,88 +51,8 @@ public class RMLocalProject extends BaseProjectImpl {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -29,8 +29,8 @@ import org.jkiss.dbeaver.model.auth.SMAuthSpace;
|
||||
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.security.user.SMTeam;
|
||||
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;
|
||||
@@ -254,8 +254,12 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
|
||||
@Property
|
||||
public long getRemainingTime() {
|
||||
if (application instanceof ServletAuthApplication authApplication) {
|
||||
return authApplication.getMaxSessionIdleTime() + lastAccessTime - System.currentTimeMillis();
|
||||
return getMaxSessionIdleTime(authApplication) + lastAccessTime - System.currentTimeMillis();
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
protected long getMaxSessionIdleTime(@NotNull ServletAuthApplication authApplication) {
|
||||
return authApplication.getMaxSessionIdleTime();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-6
@@ -793,7 +793,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 +806,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);
|
||||
}
|
||||
|
||||
+4
@@ -190,6 +190,10 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
return isAuthorizedInSecurityManager() && getUser() != null;
|
||||
}
|
||||
|
||||
public synchronized boolean isAnonymousUserAuthorizedInSM() {
|
||||
return isAuthorizedInSecurityManager() && getUser() == null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized WebUser getUser() {
|
||||
return user;
|
||||
|
||||
@@ -56,6 +56,7 @@ public abstract class BaseServletPlatform extends BasePlatformImpl {
|
||||
return folder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract ServletApplication getApplication();
|
||||
|
||||
private void initTempFolder(@NotNull DBRProgressMonitor monitor) {
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
package io.cloudbeaver.utils;
|
||||
|
||||
import org.jkiss.dbeaver.model.DBConstants;
|
||||
import org.jkiss.utils.StandardConstants;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class CBModelConstants {
|
||||
public static final DateTimeFormatter ISO_DATE_FORMAT = DateTimeFormatter.ofPattern(DBConstants.DEFAULT_ISO_TIMESTAMP_FORMAT)
|
||||
.withZone(ZoneId.of("UTC"));
|
||||
.withZone(StandardConstants.ZONE_ID_UTC);
|
||||
}
|
||||
|
||||
@@ -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.4.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.4-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.133.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.133-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.4.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.4-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+3
-5
@@ -314,11 +314,6 @@ public abstract class CBApplication<T extends CBServerConfig>
|
||||
}
|
||||
grantPermissionsToConnections();
|
||||
}
|
||||
try {
|
||||
this.systemInformationCollector.collectInternalDatabaseUseInformation();
|
||||
} catch (DBException e) {
|
||||
log.error("Error collecting system information", e);
|
||||
}
|
||||
|
||||
eventController.scheduleCheckJob();
|
||||
|
||||
@@ -400,6 +395,9 @@ public abstract class CBApplication<T extends CBServerConfig>
|
||||
getAppConfiguration(),
|
||||
null
|
||||
);
|
||||
if (!isMultiNode()) {
|
||||
grantPermissionsToConnections();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error loading server auto configuration", e);
|
||||
}
|
||||
|
||||
+6
-1
@@ -219,8 +219,13 @@ public class CBStaticServlet extends DefaultServlet {
|
||||
if (pathInContext.startsWith("/")) {
|
||||
pathInContext = pathInContext.substring(1);
|
||||
}
|
||||
Path filePath = contentRoot.resolve(pathInContext).normalize();
|
||||
if (!filePath.startsWith(contentRoot)) {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
Path filePath = contentRoot.resolve(pathInContext);
|
||||
try (InputStream fis = Files.newInputStream(filePath)) {
|
||||
IOUtils.copyStream(fis, baos);
|
||||
}
|
||||
|
||||
+1
-4
@@ -304,14 +304,11 @@ public class CBSessionManager implements WebAppSessionManager {
|
||||
}
|
||||
|
||||
public void expireIdleSessions() {
|
||||
long maxSessionIdleTime = application.getMaxSessionIdleTime();
|
||||
|
||||
List<BaseWebSession> expiredList = new ArrayList<>();
|
||||
synchronized (sessionMap) {
|
||||
for (Iterator<BaseWebSession> iterator = sessionMap.values().iterator(); iterator.hasNext(); ) {
|
||||
var session = iterator.next();
|
||||
long idleMillis = System.currentTimeMillis() - session.getLastAccessTimeMillis();
|
||||
if (idleMillis >= maxSessionIdleTime) {
|
||||
if (!session.isValid()) {
|
||||
iterator.remove();
|
||||
expiredList.add(session);
|
||||
}
|
||||
|
||||
@@ -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.4.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.4-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+27
-14
@@ -114,12 +114,11 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
|
||||
|
||||
@Nullable
|
||||
protected static WebSession getSessionFromContext(DataFetchingEnvironment env) {
|
||||
WebSession webSession = env.getGraphQlContext().get(WebSession.class.getName());
|
||||
return webSession;
|
||||
return env.getGraphQlContext().get(WebSession.class.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static WebSession getSessionFromContextOrThrow(DataFetchingEnvironment env) throws DBWebException {
|
||||
protected static WebSession getSessionFromContextOrThrow(@NotNull DataFetchingEnvironment env) throws DBWebException {
|
||||
WebSession webSession = env.getGraphQlContext().get(WebSession.class.getName());
|
||||
if (webSession == null) {
|
||||
throw new DBWebException("Web session not found in GraphQL context");
|
||||
@@ -127,7 +126,7 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
|
||||
return webSession;
|
||||
}
|
||||
|
||||
protected static WebSession getWebSession(DataFetchingEnvironment env, boolean errorOnNotFound) throws DBWebException {
|
||||
protected static WebSession getWebSession(@NotNull DataFetchingEnvironment env, boolean errorOnNotFound) throws DBWebException {
|
||||
if (env.getGraphQlContext().getBoolean(CloudbeaverCliConstants.CLI_MODE)) {
|
||||
return getSessionFromContextOrThrow(env);
|
||||
}
|
||||
@@ -135,20 +134,20 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env), getServletResponse(env), errorOnNotFound);
|
||||
}
|
||||
|
||||
protected static String getProjectReference(DataFetchingEnvironment env) {
|
||||
protected static String getProjectReference(@NotNull DataFetchingEnvironment env) {
|
||||
return env.getArgument("projectId");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static WebConnectionInfo getWebConnection(DataFetchingEnvironment env) throws DBWebException {
|
||||
return getWebConnection(getWebSession(env), getProjectReference(env), env.getArgument("connectionId"));
|
||||
protected static WebConnectionInfo getWebConnection(@NotNull DataFetchingEnvironment env) throws DBWebException {
|
||||
return getWebConnection(getWebSession(env), getProjectReference(env), getArgumentVal(env, "connectionId"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns WebSession from cache or null
|
||||
*/
|
||||
@Nullable
|
||||
public static WebSession findWebSession(DataFetchingEnvironment env) {
|
||||
public static WebSession findWebSession(@NotNull DataFetchingEnvironment env) {
|
||||
if (env.getGraphQlContext().getBoolean(CloudbeaverCliConstants.CLI_MODE)) {
|
||||
return getSessionFromContext(env);
|
||||
}
|
||||
@@ -156,16 +155,30 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env));
|
||||
}
|
||||
|
||||
public static WebSession findWebSession(DataFetchingEnvironment env, boolean errorOnNotFound) throws DBWebException {
|
||||
public static WebSession findWebSession(@NotNull DataFetchingEnvironment env, boolean errorOnNotFound) throws DBWebException {
|
||||
return WebAppUtils.getWebApplication().getSessionManager().findWebSession(
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env), errorOnNotFound);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static WebConnectionInfo getWebConnection(WebSession session, String projectId, String connectionId) throws DBWebException {
|
||||
public static WebConnectionInfo getWebConnection(@NotNull WebSession session, @NotNull String projectId, @NotNull String connectionId) throws DBWebException {
|
||||
return WebDataSourceUtils.getWebConnectionInfo(session, projectId, connectionId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static <T> T getArgument(@NotNull DataFetchingEnvironment env, @NotNull String name) {
|
||||
return env.getArgument(name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static <T> T getArgumentVal(@NotNull DataFetchingEnvironment env, @NotNull String name) throws DBWebException {
|
||||
T value = env.getArgument(name);
|
||||
if (value == null) {
|
||||
throw new DBWebException("Argument '" + name + "' is null");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private class ServiceInvocationHandler implements InvocationHandler {
|
||||
private final API_TYPE impl;
|
||||
private final DataFetchingEnvironment env;
|
||||
@@ -181,7 +194,7 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
|
||||
try {
|
||||
WebActionSet actionSet = method.getDeclaringClass().getAnnotation(WebActionSet.class);
|
||||
if (actionSet != null) {
|
||||
checkServicePermissions(method, actionSet);
|
||||
checkServicePermissions(actionSet);
|
||||
}
|
||||
WebAction webAction = method.getAnnotation(WebAction.class);
|
||||
if (webAction != null) {
|
||||
@@ -266,7 +279,7 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
|
||||
}
|
||||
}
|
||||
|
||||
private void checkServicePermissions(Method method, WebActionSet actionSet) throws DBWebException {
|
||||
private void checkServicePermissions(WebActionSet actionSet) throws DBWebException {
|
||||
String[] features = actionSet.requireFeatures();
|
||||
ServletApplication servletApplication = ServletAppUtils.getServletApplication();
|
||||
for (String feature : features) {
|
||||
@@ -339,9 +352,9 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
|
||||
Log.setContext(null);
|
||||
}
|
||||
|
||||
protected void setLogContext(Method method, Object[] args) {
|
||||
protected void setLogContext(Method method, @Nullable Object[] args) {
|
||||
WebSession activeSession = null;
|
||||
if (args != null && args.length > 0) {
|
||||
if (args != null) {
|
||||
for (Object arg : args) {
|
||||
if (arg instanceof WebSession) {
|
||||
activeSession = (WebSession) arg;
|
||||
|
||||
+2
-2
@@ -119,7 +119,7 @@ public interface DBWServiceCore extends DBWService {
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull String connectionId,
|
||||
@NotNull Map<String, Object> authProperties,
|
||||
@Nullable Map<String, Object> authProperties,
|
||||
@Nullable List<WebNetworkHandlerConfigInput> networkCredentials,
|
||||
boolean saveCredentials,
|
||||
boolean sharedCredentials,
|
||||
@@ -181,7 +181,7 @@ public interface DBWServiceCore extends DBWService {
|
||||
WebConnectionFolderInfo createConnectionFolder(
|
||||
@NotNull WebSession session,
|
||||
@Nullable @WebObjectId String projectId,
|
||||
@NotNull String parentNodePath,
|
||||
@Nullable String parentNodePath,
|
||||
@NotNull String newName) throws DBWebException;
|
||||
|
||||
@WebProjectAction(requireProjectPermissions = {RMConstants.PERMISSION_PROJECT_DATASOURCES_EDIT})
|
||||
|
||||
+35
-32
@@ -54,20 +54,20 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
|
||||
.dataFetcher("systemInfo", env -> getService(env).getSystemInformationProperties(getWebSession(env)))
|
||||
.dataFetcher("productSettings", env -> getService(env).getProductSettings(getWebSession(env)))
|
||||
|
||||
.dataFetcher("driverList", env -> getService(env).getDriverList(getWebSession(env), env.getArgument("id")))
|
||||
.dataFetcher("driverList", env -> getService(env).getDriverList(getWebSession(env), getArgument(env, "id")))
|
||||
.dataFetcher("authModels", env -> getService(env).getAuthModels(getWebSession(env)))
|
||||
.dataFetcher("networkHandlers", env -> getService(env).getNetworkHandlers(getWebSession(env)))
|
||||
.dataFetcher("userConnections", env -> getService(env).getUserConnections(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("id"), env.getArgument("projectIds")))
|
||||
getWebSession(env), getProjectReference(env), getArgument(env, "id"), getArgument(env, "projectIds")))
|
||||
|
||||
.dataFetcher("connectionFolders", env -> getService(env).getConnectionFolders(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("path")))
|
||||
getWebSession(env), getProjectReference(env), getArgument(env, "path")))
|
||||
|
||||
.dataFetcher("sessionPermissions", env -> getService(env).getSessionPermissions(getWebSession(env)))
|
||||
.dataFetcher("sessionState", env -> getService(env).getSessionState(findWebSession(env, true)))
|
||||
|
||||
.dataFetcher("connectionInfo", env -> getService(env).getConnectionState(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("id")))
|
||||
getWebSession(env), getProjectReference(env), getArgument(env, "id")))
|
||||
|
||||
.dataFetcher("listProjects", env -> getService(env).getProjects(getWebSession(env)))
|
||||
.dataFetcher("readSessionLog", env -> {
|
||||
@@ -78,8 +78,8 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
|
||||
}
|
||||
return getService(env).readSessionLog(
|
||||
session,
|
||||
env.getArgument("maxEntries"),
|
||||
env.getArgument("clearEntries"));
|
||||
getArgument(env, "maxEntries"),
|
||||
getArgument(env, "clearEntries"));
|
||||
})
|
||||
;
|
||||
|
||||
@@ -89,7 +89,7 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
|
||||
HttpServletResponse servletResponse = GraphQLEndpoint.getServletResponse(env);
|
||||
return getService(env).openSession(
|
||||
sessionManager.getWebSession(servletRequest, servletResponse, false),
|
||||
env.getArgument("defaultLocale"),
|
||||
getArgument(env, "defaultLocale"),
|
||||
servletRequest,
|
||||
servletResponse);
|
||||
})
|
||||
@@ -100,25 +100,25 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env), GraphQLEndpoint.getServletResponse(env)))
|
||||
.dataFetcher("refreshSessionConnections", env -> getService(env).refreshSessionConnections(
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env), GraphQLEndpoint.getServletResponse(env)))
|
||||
.dataFetcher("changeSessionLanguage", env -> getService(env).changeSessionLanguage(getWebSession(env), env.getArgument("locale")))
|
||||
.dataFetcher("changeSessionLanguage", env -> getService(env).changeSessionLanguage(getWebSession(env), getArgument(env, "locale")))
|
||||
|
||||
.dataFetcher("createConnection", env -> getService(env).createConnection(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("config"))
|
||||
getWebSession(env), getProjectReference(env), getArgumentVal(env, "config"))
|
||||
)
|
||||
.dataFetcher("updateConnection", env -> getService(env).updateConnection(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("config"))
|
||||
getWebSession(env), getProjectReference(env), getArgumentVal(env, "config"))
|
||||
)
|
||||
.dataFetcher("deleteConnection", env -> getService(env).deleteConnection(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("id")))
|
||||
getWebSession(env), getProjectReference(env), getArgumentVal(env, "id")))
|
||||
.dataFetcher("copyConnectionFromNode", env -> getService(env).copyConnectionFromNode(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("nodePath"),
|
||||
env.getArgument("config")
|
||||
getArgumentVal(env, "nodePath"),
|
||||
getArgumentVal(env, "config")
|
||||
)
|
||||
)
|
||||
.dataFetcher("initConnection", env -> {
|
||||
List<Map<String, Object>> networkCredentials = env.getArgument("networkCredentials");
|
||||
List<Map<String, Object>> networkCredentials = getArgument(env, "networkCredentials");
|
||||
List<WebNetworkHandlerConfigInput> nhc = null;
|
||||
if (networkCredentials != null) {
|
||||
nhc = networkCredentials.stream().map(WebNetworkHandlerConfigInput::new).collect(Collectors.toList());
|
||||
@@ -126,52 +126,55 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
|
||||
return getService(env).initConnection(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("id"),
|
||||
env.getArgument("credentials"),
|
||||
getArgumentVal(env, "id"),
|
||||
getArgument(env, "credentials"),
|
||||
nhc,
|
||||
CommonUtils.toBoolean(env.getArgument("saveCredentials")),
|
||||
CommonUtils.toBoolean(env.getArgument("sharedCredentials")),
|
||||
env.getArgument("selectedSecretId")
|
||||
CommonUtils.toBoolean(getArgument(env, "saveCredentials")),
|
||||
CommonUtils.toBoolean(getArgument(env, "sharedCredentials")),
|
||||
getArgument(env, "selectedSecretId")
|
||||
);
|
||||
}
|
||||
)
|
||||
.dataFetcher("testConnection", env -> getService(env).testConnection(
|
||||
getWebSession(env), getProjectReference(env), env.getArgument("config")
|
||||
getWebSession(env), getProjectReference(env), getArgumentVal(env, "config")
|
||||
))
|
||||
.dataFetcher("testNetworkHandler", env -> getService(env).testNetworkHandler(
|
||||
getWebSession(env), new WebNetworkHandlerConfigInput(env.getArgument("config"))
|
||||
getWebSession(env), new WebNetworkHandlerConfigInput(getArgument(env, "config"))
|
||||
))
|
||||
.dataFetcher("closeConnection", env -> getService(env).closeConnection(getWebSession(env), getProjectReference(env), env.getArgument("id")))
|
||||
.dataFetcher("closeConnection", env -> getService(env).closeConnection(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
getArgumentVal(env, "id")))
|
||||
|
||||
.dataFetcher("setConnectionNavigatorSettings", env -> getService(env).setConnectionNavigatorSettings(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("id"),
|
||||
WebServiceUtils.parseNavigatorSettings(env.getArgument("settings"))
|
||||
getArgument(env, "id"),
|
||||
WebServiceUtils.parseNavigatorSettings(getArgument(env, "settings"))
|
||||
))
|
||||
|
||||
.dataFetcher("asyncTaskInfo", env -> getService(env).getAsyncTaskInfo(
|
||||
getWebSession(env),
|
||||
env.getArgument("id"),
|
||||
env.getArgument("removeOnFinish")))
|
||||
.dataFetcher("asyncTaskCancel", env -> getService(env).cancelAsyncTask(getWebSession(env), env.getArgument("id")))
|
||||
getArgument(env, "id"),
|
||||
getArgument(env, "removeOnFinish")))
|
||||
.dataFetcher("asyncTaskCancel", env -> getService(env).cancelAsyncTask(getWebSession(env), getArgument(env, "id")))
|
||||
|
||||
.dataFetcher("createConnectionFolder", env -> getService(env).createConnectionFolder(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("parentFolderPath"),
|
||||
env.getArgument("folderName")
|
||||
getArgument(env, "parentFolderPath"),
|
||||
getArgumentVal(env, "folderName")
|
||||
))
|
||||
.dataFetcher("renameConnectionFolder", env -> getService(env).renameConnectionFolder(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("folderPath"),
|
||||
env.getArgument("newName")
|
||||
getArgumentVal(env, "folderPath"),
|
||||
getArgumentVal(env, "newName")
|
||||
))
|
||||
.dataFetcher("deleteConnectionFolder", env -> getService(env).deleteConnectionFolder(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("folderPath")
|
||||
getArgumentVal(env, "folderPath")
|
||||
))
|
||||
;
|
||||
|
||||
|
||||
+9
-5
@@ -20,6 +20,7 @@ package io.cloudbeaver.service.core.impl;
|
||||
import io.cloudbeaver.*;
|
||||
import io.cloudbeaver.model.*;
|
||||
import io.cloudbeaver.model.app.ServletApplication;
|
||||
import io.cloudbeaver.model.app.ServletSystemInformationCollector;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.registry.WebHandlerRegistry;
|
||||
import io.cloudbeaver.registry.WebSessionHandlerDescriptor;
|
||||
@@ -89,10 +90,13 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
|
||||
@Override
|
||||
public WebPropertyInfo[] getSystemInformationProperties(@NotNull WebSession webSession) {
|
||||
return WebCommonUtils.getObjectProperties(
|
||||
webSession,
|
||||
WebAppUtils.getWebApplication().getSystemInformationCollector()
|
||||
);
|
||||
ServletSystemInformationCollector<?> collector = WebAppUtils.getWebApplication().getSystemInformationCollector();
|
||||
try {
|
||||
collector.collectInternalDatabaseUseInformation();
|
||||
} catch (DBException e) {
|
||||
log.error("Error collecting system information", e);
|
||||
}
|
||||
return WebCommonUtils.getObjectProperties(webSession, collector);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -295,7 +299,7 @@ public class WebServiceCore implements DBWServiceCore {
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
@NotNull String connectionId,
|
||||
@NotNull Map<String, Object> authProperties,
|
||||
@Nullable Map<String, Object> authProperties,
|
||||
@Nullable List<WebNetworkHandlerConfigInput> networkCredentials,
|
||||
boolean saveCredentials,
|
||||
boolean sharedCredentials,
|
||||
|
||||
+5
-5
@@ -34,15 +34,15 @@ public interface DBWServiceNavigator extends DBWService {
|
||||
@WebAction
|
||||
List<WebNavigatorNodeInfo> getNavigatorNodeChildren(
|
||||
@NotNull WebSession session,
|
||||
String parentPath,
|
||||
Integer offset,
|
||||
Integer limit,
|
||||
Boolean onlyFolders) throws DBWebException;
|
||||
@NotNull String parentPath,
|
||||
@Nullable Integer offset,
|
||||
@Nullable Integer limit,
|
||||
@Nullable Boolean onlyFolders) throws DBWebException;
|
||||
|
||||
@WebAction
|
||||
List<WebNavigatorNodeInfo> getNavigatorNodeParents(
|
||||
@NotNull WebSession session,
|
||||
String nodePath) throws DBWebException;
|
||||
@NotNull String nodePath) throws DBWebException;
|
||||
|
||||
@WebAction
|
||||
WebNavigatorNodeInfo getNavigatorNodeInfo(
|
||||
|
||||
+19
-19
@@ -38,61 +38,61 @@ public class WebServiceBindingNavigator extends WebServiceBindingBase<DBWService
|
||||
model.getQueryType()
|
||||
.dataFetcher("navNodeChildren", env -> getService(env).getNavigatorNodeChildren(
|
||||
getWebSession(env),
|
||||
env.getArgument("parentPath"),
|
||||
env.getArgument("offset"),
|
||||
env.getArgument("limit"),
|
||||
env.getArgument("onlyFolders")
|
||||
getArgumentVal(env, "parentPath"),
|
||||
getArgument(env, "offset"),
|
||||
getArgument(env, "limit"),
|
||||
getArgument(env, "onlyFolders")
|
||||
))
|
||||
.dataFetcher("navNodeParents", env -> getService(env).getNavigatorNodeParents(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath")
|
||||
getArgumentVal(env, "nodePath")
|
||||
))
|
||||
.dataFetcher("navNodeInfo", env -> getService(env).getNavigatorNodeInfo(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath")
|
||||
getArgumentVal(env, "nodePath")
|
||||
))
|
||||
.dataFetcher("navRefreshNode", env -> getService(env).refreshNavigatorNode(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath"),
|
||||
getArgumentVal(env, "nodePath"),
|
||||
false
|
||||
) != null)
|
||||
.dataFetcher("navGetStructContainers", env -> getService(env).getStructContainers(
|
||||
getProjectReference(env),
|
||||
getWebConnection(env),
|
||||
env.getArgument("contextId"),
|
||||
env.getArgument("catalog")
|
||||
getArgument(env, "contextId"),
|
||||
getArgument(env, "catalog")
|
||||
|
||||
));
|
||||
model.getMutationType()
|
||||
.dataFetcher("navReloadNode", env -> getService(env).refreshNavigatorNode(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath"),
|
||||
getArgumentVal(env, "nodePath"),
|
||||
true
|
||||
))
|
||||
.dataFetcher("navSetFolderFilter", env -> getService(env).setNavigatorNodeFilter(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath"),
|
||||
env.getArgument("include"),
|
||||
env.getArgument("exclude")
|
||||
getArgumentVal(env, "nodePath"),
|
||||
getArgument(env, "include"),
|
||||
getArgument(env, "exclude")
|
||||
))
|
||||
.dataFetcher("navRenameNode", env -> getService(env).renameNode(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath"),
|
||||
env.getArgument("newName")
|
||||
getArgumentVal(env, "nodePath"),
|
||||
getArgumentVal(env, "newName")
|
||||
))
|
||||
.dataFetcher("navDeleteNodes", env -> getService(env).deleteNodes(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePaths")
|
||||
getArgumentVal(env, "nodePaths")
|
||||
))
|
||||
.dataFetcher("navMoveNodesToFolder", env -> getService(env).moveNodesToFolder(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePaths"),
|
||||
env.getArgument("folderPath")
|
||||
getArgumentVal(env, "nodePaths"),
|
||||
getArgumentVal(env, "folderPath")
|
||||
));
|
||||
|
||||
model.getRuntimeWiring().type(TypeRuntimeWiring.newTypeWiring("DatabaseObjectInfo")
|
||||
.dataFetcher("properties", env -> {
|
||||
Map<String, Object> filterProps = env.getArgument("filter");
|
||||
Map<String, Object> filterProps = getArgument(env, "filter");
|
||||
WebPropertyFilter filter = filterProps == null ? null : new WebPropertyFilter(filterProps);
|
||||
return ((WebDatabaseObjectInfo)env.getSource()).filterProperties(filter);
|
||||
})
|
||||
|
||||
+13
-7
@@ -18,6 +18,7 @@ package io.cloudbeaver.service.navigator.impl;
|
||||
|
||||
|
||||
import io.cloudbeaver.BaseWebProjectImpl;
|
||||
import io.cloudbeaver.DBWConstants;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebServiceUtils;
|
||||
import io.cloudbeaver.model.WebCommandContext;
|
||||
@@ -44,6 +45,7 @@ import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
|
||||
import org.jkiss.dbeaver.model.exec.DBCExecutionContextDefaults;
|
||||
import org.jkiss.dbeaver.model.exec.DBExecUtils;
|
||||
import org.jkiss.dbeaver.model.navigator.*;
|
||||
import org.jkiss.dbeaver.model.navigator.fs.DBNPathBase;
|
||||
import org.jkiss.dbeaver.model.navigator.meta.DBXTreeItem;
|
||||
import org.jkiss.dbeaver.model.rm.RMControllerProvider;
|
||||
import org.jkiss.dbeaver.model.rm.RMProject;
|
||||
@@ -157,7 +159,7 @@ public class WebServiceNavigator implements DBWServiceNavigator {
|
||||
@Override
|
||||
public List<WebNavigatorNodeInfo> getNavigatorNodeParents(
|
||||
@NotNull WebSession session,
|
||||
String nodePath
|
||||
@NotNull String nodePath
|
||||
) throws DBWebException {
|
||||
try {
|
||||
DBRProgressMonitor monitor = session.getProgressMonitor();
|
||||
@@ -462,12 +464,14 @@ public class WebServiceNavigator implements DBWServiceNavigator {
|
||||
@NotNull
|
||||
private String renameConnectionFolder(@NotNull WebSession session, DBNNode node, @NotNull String newName) throws DBException {
|
||||
WebConnectionFolderUtils.validateConnectionFolder(newName);
|
||||
List<String> siblings = Arrays.stream(
|
||||
((DBNLocalFolder) node).getLogicalParent().getChildren(session.getProgressMonitor()))
|
||||
.filter(n -> n instanceof DBNLocalFolder)
|
||||
.map(DBNNode::getName).toList();
|
||||
if (siblings.contains(newName)) {
|
||||
throw new DBWebException("Name " + newName + " is unavailable or invalid");
|
||||
DBNNode[] children = ((DBNLocalFolder) node).getLogicalParent().getChildren(session.getProgressMonitor());
|
||||
if (children != null) {
|
||||
List<String> siblings = Arrays.stream(children)
|
||||
.filter(n -> n instanceof DBNLocalFolder)
|
||||
.map(DBNNode::getName).toList();
|
||||
if (siblings.contains(newName)) {
|
||||
throw new DBWebException("Name " + newName + " is unavailable or invalid");
|
||||
}
|
||||
}
|
||||
node.rename(session.getProgressMonitor(), newName);
|
||||
return node.getName();
|
||||
@@ -596,6 +600,8 @@ public class WebServiceNavigator implements DBWServiceNavigator {
|
||||
return SMUtils.hasProjectPermission(session, rmProject, RMProjectPermission.DATA_SOURCES_EDIT);
|
||||
} else if (node instanceof DBNAbstractResourceManagerNode) {
|
||||
return SMUtils.hasProjectPermission(session, rmProject, RMProjectPermission.RESOURCE_EDIT);
|
||||
} else if (node instanceof DBNPathBase) {
|
||||
return !DBWorkbench.isDistributed() || session.hasPermission(DBWConstants.PERMISSION_FS_RESOURCE_EDIT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+2
-2
@@ -48,10 +48,10 @@ import org.jkiss.dbeaver.model.struct.rdb.DBSSchema;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSTransactionalCountEvent;
|
||||
import org.jkiss.dbeaver.utils.RuntimeUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.StandardConstants;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -74,7 +74,7 @@ public class WebSQLContextInfo implements WebSessionProvider {
|
||||
private final AtomicInteger resultId = new AtomicInteger();
|
||||
|
||||
public static final DateTimeFormatter ISO_DATE_FORMAT = DateTimeFormatter.ofPattern(DBConstants.DEFAULT_ISO_TIMESTAMP_FORMAT)
|
||||
.withZone(ZoneId.of("UTC"));
|
||||
.withZone(StandardConstants.ZONE_ID_UTC);
|
||||
|
||||
public WebSQLContextInfo(
|
||||
WebSQLProcessor processor, String id, String catalogName, String schemaName, String projectId
|
||||
|
||||
+6
@@ -19,6 +19,7 @@ package io.cloudbeaver.service.sql;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.cloudbeaver.DBWConstants;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.model.app.ServletApplication;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
@@ -33,6 +34,7 @@ import org.eclipse.jetty.ee10.servlet.ServletContextRequest;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -73,6 +75,10 @@ public class WebSQLFileLoaderServlet extends WebServiceServletBase {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Update for users only");
|
||||
return;
|
||||
}
|
||||
if (DBWorkbench.isDistributed() && !session.hasPermission(DBWConstants.PERMISSION_SQL_RESULT_UPDATE)) {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Permission denied");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!"POST".equalsIgnoreCase(request.getMethod())) {
|
||||
return;
|
||||
|
||||
+2
-1
@@ -81,12 +81,13 @@ public class WebSQLQueryDataContainer implements DBSDataContainer, DBPContextPro
|
||||
return queryDataContainer.getDescription();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public DBPDataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String[] getSupportedFeatures() {
|
||||
return queryDataContainer.getSupportedFeatures();
|
||||
|
||||
+33
-39
@@ -22,12 +22,10 @@ import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.server.CBConstants;
|
||||
import io.cloudbeaver.service.WebServiceServletBase;
|
||||
import jakarta.servlet.MultipartConfigElement;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.annotation.MultipartConfig;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.Part;
|
||||
import org.eclipse.jetty.ee10.servlet.ServletContextRequest;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
@@ -37,7 +35,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@MultipartConfig
|
||||
@@ -57,44 +54,41 @@ public class WebSQLResultServlet extends WebServiceServletBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
request.setAttribute(ServletContextRequest.MULTIPART_CONFIG_ELEMENT, MULTI_PART_CONFIG);
|
||||
String fileName = UUID.randomUUID().toString();
|
||||
for (Part part : request.getParts()) {
|
||||
part.write(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER + "/" + fileName);
|
||||
protected void processServiceRequest(
|
||||
WebSession session,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response
|
||||
) throws DBException, IOException {
|
||||
if (!request.getMethod().equals("GET")) {
|
||||
return;
|
||||
}
|
||||
response.addHeader("fileName", fileName);
|
||||
Path dataFile = getDataFile(request);
|
||||
session.addInfoMessage("Download LOB file ...");
|
||||
response.setHeader("Content-Type", "application/octet-stream");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + dataFile.getFileName().toString() + "\"");
|
||||
response.setHeader("Content-Length", String.valueOf(Files.size(dataFile)));
|
||||
response.setDateHeader("Expires", System.currentTimeMillis() + CBConstants.STATIC_CACHE_SECONDS * 1000);
|
||||
response.setHeader("Cache-Control", "public, max-age=" + CBConstants.STATIC_CACHE_SECONDS);
|
||||
|
||||
try (InputStream is = Files.newInputStream(dataFile)) {
|
||||
IOUtils.copyStream(is, response.getOutputStream());
|
||||
}
|
||||
Files.deleteIfExists(dataFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processServiceRequest(WebSession session, HttpServletRequest request, HttpServletResponse response) throws DBException, IOException {
|
||||
if (request.getMethod().equals("POST")) {
|
||||
try {
|
||||
doPost(request, response);
|
||||
} catch (Exception e) {
|
||||
throw new DBWebException("Servlet exception ", e);
|
||||
}
|
||||
} else {
|
||||
String valuePath = request.getPathInfo();
|
||||
if (CommonUtils.isEmpty(valuePath)) {
|
||||
throw new DBWebException("Result value ID not specified");
|
||||
}
|
||||
while (valuePath.startsWith("/")) {
|
||||
valuePath = valuePath.substring(1);
|
||||
}
|
||||
|
||||
Path dataFile = WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.resolve(valuePath);
|
||||
session.addInfoMessage("Download LOB file ...");
|
||||
response.setHeader("Content-Type", "application/octet-stream");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + dataFile.getFileName().toString() + "\"");
|
||||
response.setHeader("Content-Length", String.valueOf(Files.size(dataFile)));
|
||||
response.setDateHeader("Expires", System.currentTimeMillis() + CBConstants.STATIC_CACHE_SECONDS * 1000);
|
||||
response.setHeader("Cache-Control", "public, max-age=" + CBConstants.STATIC_CACHE_SECONDS);
|
||||
|
||||
try (InputStream is = Files.newInputStream(dataFile)) {
|
||||
IOUtils.copyStream(is, response.getOutputStream());
|
||||
}
|
||||
Files.deleteIfExists(dataFile);
|
||||
@NotNull
|
||||
private Path getDataFile(HttpServletRequest request) throws DBWebException {
|
||||
String valuePath = request.getPathInfo();
|
||||
if (CommonUtils.isEmpty(valuePath)) {
|
||||
throw new DBWebException("Result value ID not specified");
|
||||
}
|
||||
while (valuePath.startsWith("/")) {
|
||||
valuePath = valuePath.substring(1);
|
||||
}
|
||||
Path dataFile = WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.resolve(valuePath).normalize();
|
||||
if (!dataFile.startsWith(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER)) {
|
||||
throw new DBWebException("Bad result value ID");
|
||||
}
|
||||
return dataFile;
|
||||
}
|
||||
}
|
||||
+53
-53
@@ -55,55 +55,55 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
.dataFetcher("sqlListContexts", env ->
|
||||
getService(env).listContexts(getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("connectionId"),
|
||||
env.getArgument("contextId"))
|
||||
getArgument(env, "connectionId"),
|
||||
getArgument(env, "contextId"))
|
||||
)
|
||||
.dataFetcher("sqlCompletionProposals", env ->
|
||||
getService(env).getCompletionProposals(
|
||||
getSQLContext(env),
|
||||
env.getArgument("query"),
|
||||
env.getArgument("position"),
|
||||
env.getArgument("maxResults"),
|
||||
env.getArgument("simpleMode")
|
||||
getArgumentVal(env, "query"),
|
||||
getArgument(env, "position"),
|
||||
getArgument(env, "maxResults"),
|
||||
getArgument(env, "simpleMode")
|
||||
)
|
||||
)
|
||||
.dataFetcher("sqlFormatQuery", env ->
|
||||
getService(env).formatQuery(
|
||||
getSQLContext(env),
|
||||
env.getArgument("query")
|
||||
getArgumentVal(env, "query")
|
||||
)
|
||||
)
|
||||
.dataFetcher("sqlSupportedOperations", env ->
|
||||
getService(env).getSupportedOperations(
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
env.getArgument("attributeIndex"))
|
||||
getArgumentVal(env, "resultsId"),
|
||||
getArgumentVal(env, "attributeIndex"))
|
||||
)
|
||||
.dataFetcher("sqlEntityQueryGenerators", env ->
|
||||
getService(env).getEntityQueryGenerators(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePathList"))
|
||||
getArgumentVal(env, "nodePathList"))
|
||||
)
|
||||
.dataFetcher("sqlGenerateEntityQuery", env ->
|
||||
getService(env).generateEntityQuery(
|
||||
getWebSession(env),
|
||||
env.getArgument("generatorId"),
|
||||
env.getArgument("options"),
|
||||
env.getArgument("nodePathList"))
|
||||
getArgumentVal(env, "generatorId"),
|
||||
getArgumentVal(env, "options"),
|
||||
getArgumentVal(env, "nodePathList"))
|
||||
).dataFetcher("sqlParseScript", env ->
|
||||
getService(env).parseSqlScript(getWebConnection(env), env.getArgument("script"))
|
||||
getService(env).parseSqlScript(getWebConnection(env), getArgumentVal(env, "script"))
|
||||
).dataFetcher("sqlParseQuery", env ->
|
||||
getService(env).parseSqlQuery(
|
||||
getWebConnection(env),
|
||||
env.getArgument("script"),
|
||||
env.getArgument("position"))
|
||||
getArgumentVal(env, "script"),
|
||||
getArgumentVal(env, "position"))
|
||||
).dataFetcher("sqlGenerateGroupingQuery", env ->
|
||||
getService(env).generateGroupByQuery(
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
env.getArgument("columnNames"),
|
||||
env.getArgument("functions"),
|
||||
env.getArgument("showDuplicatesOnly"))
|
||||
getArgumentVal(env, "resultsId"),
|
||||
getArgumentVal(env, "columnNames"),
|
||||
getArgument(env, "functions"),
|
||||
getArgument(env, "showDuplicatesOnly"))
|
||||
)
|
||||
;
|
||||
|
||||
@@ -111,14 +111,14 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
.dataFetcher("sqlContextCreate", env -> getService(env).createContext(
|
||||
getSQLProcessor(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("defaultCatalog"),
|
||||
env.getArgument("defaultSchema")))
|
||||
getArgument(env, "defaultCatalog"),
|
||||
getArgument(env, "defaultSchema")))
|
||||
.dataFetcher("sqlContextDestroy", env -> { getService(env).destroyContext(getSQLContext(env)); return true; } )
|
||||
.dataFetcher("sqlContextSetDefaults", env -> {
|
||||
getService(env).setContextDefaults(
|
||||
getSQLContext(env),
|
||||
env.getArgument("defaultCatalog"),
|
||||
env.getArgument("defaultSchema"));
|
||||
getArgument(env, "defaultCatalog"),
|
||||
getArgument(env, "defaultSchema"));
|
||||
return true;
|
||||
})
|
||||
|
||||
@@ -130,36 +130,36 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
}
|
||||
return getService(env).closeResult(
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultId"));
|
||||
getArgumentVal(env, "resultId"));
|
||||
})
|
||||
.dataFetcher("readLobValue", env -> // deprecated
|
||||
getService(env).readLobValue(
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
env.getArgument("lobColumnIndex"),
|
||||
getArgumentVal(env, "resultsId"),
|
||||
getArgumentVal(env, "lobColumnIndex"),
|
||||
getResultsRow(env, "row").get(0)))
|
||||
.dataFetcher("sqlReadLobValue", env ->
|
||||
getService(env).readLobValue(
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
env.getArgument("lobColumnIndex"),
|
||||
new WebSQLResultsRow(env.getArgument("row"))))
|
||||
getArgumentVal(env, "resultsId"),
|
||||
getArgumentVal(env, "lobColumnIndex"),
|
||||
new WebSQLResultsRow(getArgument(env, "row"))))
|
||||
.dataFetcher("sqlReadStringValue", env ->
|
||||
getService(env).getCellValue(
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
env.getArgument("columnIndex"),
|
||||
new WebSQLResultsRow(env.getArgument("row"))))
|
||||
getArgumentVal(env, "resultsId"),
|
||||
getArgumentVal(env, "columnIndex"),
|
||||
new WebSQLResultsRow(getArgument(env, "row"))))
|
||||
.dataFetcher("sqlGetDynamicTrace", env ->
|
||||
getService(env).readDynamicTrace(
|
||||
getWebSession(env),
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId")
|
||||
getArgumentVal(env, "resultsId")
|
||||
))
|
||||
.dataFetcher("updateResultsDataBatch", env ->
|
||||
getService(env).updateResultsDataBatch(
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
getArgumentVal(env, "resultsId"),
|
||||
getResultsRow(env, "updatedRows"),
|
||||
getResultsRow(env, "deletedRows"),
|
||||
getResultsRow(env, "addedRows"),
|
||||
@@ -168,7 +168,7 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
getService(env).asyncUpdateResultsDataBatch(
|
||||
getWebSession(env),
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
getArgumentVal(env, "resultsId"),
|
||||
getResultsRow(env, "updatedRows"),
|
||||
getResultsRow(env, "deletedRows"),
|
||||
getResultsRow(env, "addedRows"),
|
||||
@@ -176,7 +176,7 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
.dataFetcher("updateResultsDataBatchScript", env ->
|
||||
getService(env).updateResultsDataBatchScript(
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
getArgumentVal(env, "resultsId"),
|
||||
getResultsRow(env, "updatedRows"),
|
||||
getResultsRow(env, "deletedRows"),
|
||||
getResultsRow(env, "addedRows"),
|
||||
@@ -187,51 +187,51 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
getSQLContext(env),
|
||||
env.getArgument("sql"),
|
||||
env.getArgument("resultId"),
|
||||
getArgumentVal(env, "sql"),
|
||||
getArgument(env, "resultId"),
|
||||
getDataFilter(env),
|
||||
getDataFormat(env),
|
||||
CommonUtils.toBoolean(env.getArgument("readLogs"))
|
||||
CommonUtils.toBoolean(getArgument(env, "readLogs"))
|
||||
)
|
||||
)
|
||||
.dataFetcher("asyncReadDataFromContainer", env ->
|
||||
getService(env).asyncReadDataFromContainer(
|
||||
getSQLContext(env),
|
||||
env.getArgument("containerNodePath"),
|
||||
env.getArgument("resultId"),
|
||||
getArgumentVal(env, "containerNodePath"),
|
||||
getArgument(env, "resultId"),
|
||||
getDataFilter(env),
|
||||
getDataFormat(env)
|
||||
))
|
||||
.dataFetcher("asyncSqlExecuteResults", env ->
|
||||
getService(env).asyncGetQueryResults(
|
||||
getWebSession(env), env.getArgument("taskId")
|
||||
getWebSession(env), getArgumentVal(env, "taskId")
|
||||
))
|
||||
.dataFetcher("asyncSqlExplainExecutionPlan", env ->
|
||||
getService(env).asyncSqlExplainExecutionPlan(
|
||||
getSQLContext(env),
|
||||
env.getArgument("query"),
|
||||
env.getArgument("configuration")
|
||||
getArgumentVal(env, "query"),
|
||||
getArgumentVal(env, "configuration")
|
||||
))
|
||||
.dataFetcher("asyncSqlExplainExecutionPlanResult", env ->
|
||||
getService(env).asyncSqlExplainExecutionPlanResult(
|
||||
getWebSession(env), env.getArgument("taskId")
|
||||
getWebSession(env), getArgumentVal(env, "taskId")
|
||||
))
|
||||
.dataFetcher("asyncSqlRowDataCount", env ->
|
||||
getService(env).getRowDataCount(
|
||||
getWebSession(env),
|
||||
getSQLContext(env),
|
||||
env.getArgument("resultsId")
|
||||
getArgumentVal(env, "resultsId")
|
||||
))
|
||||
.dataFetcher("asyncSqlRowDataCountResult", env ->
|
||||
getService(env).getRowDataCountResult(
|
||||
getWebSession(env),
|
||||
env.getArgument("taskId")
|
||||
getArgumentVal(env, "taskId")
|
||||
))
|
||||
.dataFetcher("asyncSqlSetAutoCommit", env ->
|
||||
getService(env).asyncSqlSetAutoCommit(
|
||||
getWebSession(env),
|
||||
getSQLContext(env),
|
||||
env.getArgument("autoCommit")
|
||||
getArgumentVal(env, "autoCommit")
|
||||
))
|
||||
.dataFetcher("asyncSqlCommitTransaction", env ->
|
||||
getService(env).asyncSqlCommitTransaction(
|
||||
@@ -252,7 +252,7 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
|
||||
@NotNull
|
||||
public static WebDataFormat getDataFormat(DataFetchingEnvironment env) {
|
||||
String dataFormat = env.getArgument("dataFormat");
|
||||
String dataFormat = getArgument(env, "dataFormat");
|
||||
return CommonUtils.valueOf(WebDataFormat.class, dataFormat, WebDataFormat.resultset);
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
if (processor == null) {
|
||||
return null;
|
||||
}
|
||||
String contextId = env.getArgument("contextId");
|
||||
String contextId = getArgument(env, "contextId");
|
||||
return getSQLContext(processor, contextId);
|
||||
}
|
||||
|
||||
@@ -374,12 +374,12 @@ public class WebServiceBindingSQL extends WebServiceBindingBase<DBWServiceSQL>
|
||||
///////////////////////////////////////
|
||||
// Helpers
|
||||
public static WebSQLDataFilter getDataFilter(DataFetchingEnvironment env) {
|
||||
Map<String, Object> filterProps = env.getArgument("filter");
|
||||
Map<String, Object> filterProps = getArgument(env, "filter");
|
||||
return filterProps == null ? null : new WebSQLDataFilter(filterProps);
|
||||
}
|
||||
|
||||
private static List<WebSQLResultsRow> getResultsRow(DataFetchingEnvironment env, String param) {
|
||||
List<Map<String, Object>> mapList = env.getArgument(param);
|
||||
List<Map<String, Object>> mapList = getArgument(env, param);
|
||||
if (CommonUtils.isEmpty(mapList)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -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.132.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.132-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+74
-25
@@ -74,39 +74,63 @@ public interface DBWServiceAdmin extends DBWService {
|
||||
List<String> listTeamRoles();
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean deleteUser(@NotNull WebSession webSession, String userName) throws DBWebException;
|
||||
boolean deleteUser(@NotNull WebSession webSession, @NotNull String userName) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
@NotNull
|
||||
AdminTeamInfo createTeam(@NotNull WebSession webSession, String teamId, String teamName, String description) throws DBWebException;
|
||||
AdminTeamInfo createTeam(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String teamId,
|
||||
@NotNull String teamName,
|
||||
@Nullable String description
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
@NotNull
|
||||
AdminTeamInfo updateTeam(@NotNull WebSession webSession, String teamId, String teamName, String description) throws DBWebException;
|
||||
AdminTeamInfo updateTeam(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String teamId,
|
||||
@NotNull String teamName,
|
||||
@Nullable String description
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean deleteTeam(@NotNull WebSession webSession, String teamId, boolean force) throws DBWebException;
|
||||
boolean deleteTeam(@NotNull WebSession webSession, @NotNull String teamId, boolean force) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean grantUserTeam(@NotNull WebSession webSession, String user, String team) throws DBWebException;
|
||||
boolean grantUserTeam(@NotNull WebSession webSession, @NotNull String user, @NotNull String team) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean revokeUserTeam(@NotNull WebSession webSession, String user, String team) throws DBWebException;
|
||||
boolean revokeUserTeam(@NotNull WebSession webSession, @NotNull String user, @NotNull String team) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
List<AdminPermissionInfo> setSubjectPermissions(@NotNull WebSession webSession, String subjectID, List<String> permissions) throws DBWebException;
|
||||
@NotNull
|
||||
List<AdminPermissionInfo> setSubjectPermissions(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String subjectID,
|
||||
@NotNull List<String> permissions
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean setUserCredentials(@NotNull WebSession webSession, @NotNull String userID, @NotNull String providerId, @NotNull Map<String, Object> credentials) throws DBWebException;
|
||||
boolean setUserCredentials(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String userID,
|
||||
@NotNull String providerId,
|
||||
@NotNull Map<String, Object> credentials
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean deleteUserCredentials(@NotNull WebSession webSession, @NotNull String userId, @NotNull String providerId) throws DBWebException;
|
||||
boolean deleteUserCredentials(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String userId,
|
||||
@NotNull String providerId
|
||||
) throws DBWebException;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Connection management
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
List<AdminConnectionSearchInfo> searchConnections(WebSession webSession, List<String> hostNames) throws DBWebException;
|
||||
List<AdminConnectionSearchInfo> searchConnections(WebSession webSession, @NotNull List<String> hostNames) throws DBWebException;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Features
|
||||
@@ -129,7 +153,8 @@ public interface DBWServiceAdmin extends DBWService {
|
||||
@NotNull String providerId,
|
||||
@NotNull String id,
|
||||
@NotNull String displayName,
|
||||
boolean disabled, @Nullable String iconURL,
|
||||
boolean disabled,
|
||||
@Nullable String iconURL,
|
||||
@Nullable String description,
|
||||
@Nullable Map<String, Object> parameters) throws DBWebException;
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
@@ -139,12 +164,12 @@ public interface DBWServiceAdmin extends DBWService {
|
||||
// Server configuration
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean configureServer(WebSession webSession, Map<String, Object> params) throws DBWebException;
|
||||
boolean configureServer(@NotNull WebSession webSession, @NotNull Map<String, Object> params) throws DBWebException;
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean setDefaultNavigatorSettings(WebSession webSession, DBNBrowseSettings settings) throws DBWebException;
|
||||
boolean setDefaultNavigatorSettings(@NotNull WebSession webSession, @NotNull DBNBrowseSettings settings) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
boolean updateProductConfiguration(WebSession webSession, Map<String, Object> productConfiguration) throws DBWebException;
|
||||
boolean updateProductConfiguration(@NotNull WebSession webSession, @NotNull Map<String, Object> productConfiguration) throws DBWebException;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Permissions
|
||||
@@ -153,7 +178,7 @@ public interface DBWServiceAdmin extends DBWService {
|
||||
SMDataSourceGrant[] getConnectionSubjectAccess(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
String connectionId) throws DBWebException;
|
||||
@NotNull String connectionId) throws DBWebException;
|
||||
|
||||
@Deprecated
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
@@ -191,26 +216,50 @@ public interface DBWServiceAdmin extends DBWService {
|
||||
// User meta parameters
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
WebPropertyInfo saveUserMetaParameter(WebSession webSession, String id, String displayName, String description, Boolean required) throws
|
||||
DBWebException;
|
||||
WebPropertyInfo saveUserMetaParameter(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String id,
|
||||
@NotNull String displayName,
|
||||
@Nullable String description,
|
||||
@Nullable Boolean required
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
Boolean deleteUserMetaParameter(WebSession webSession, String id) throws DBWebException;
|
||||
Boolean deleteUserMetaParameter(@NotNull WebSession webSession, @NotNull String id) throws DBWebException;
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
Boolean setUserMetaParameterValues(WebSession webSession, String userId, Map<String, String> parameters) throws DBWebException;
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
Boolean setTeamMetaParameterValues(WebSession webSession, String teamId, Map<String, String> parameters) throws DBWebException;
|
||||
Boolean setUserMetaParameterValues(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String userId,
|
||||
@NotNull Map<String, String> parameters
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
Boolean enableUser(WebSession webSession, String userId, Boolean enabled) throws DBWebException;
|
||||
Boolean setTeamMetaParameterValues(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String teamId,
|
||||
@NotNull Map<String, String> parameters
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
Boolean setUserAuthRole(WebSession webSession, String userId, String authRole) throws DBWebException;
|
||||
Boolean enableUser(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String userId,
|
||||
@NotNull Boolean enabled
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
Boolean setUserAuthRole(
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String userId,
|
||||
@NotNull String authRole
|
||||
) throws DBWebException;
|
||||
|
||||
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
|
||||
Boolean setUserTeamRole(
|
||||
@NotNull WebSession webSession, @NotNull String userId,
|
||||
@NotNull String teamId, @Nullable String teamRole
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String userId,
|
||||
@NotNull String teamId,
|
||||
@Nullable String teamRole
|
||||
) throws DBWebException;
|
||||
|
||||
}
|
||||
|
||||
+60
-61
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package io.cloudbeaver.service.admin;
|
||||
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebServiceUtils;
|
||||
import io.cloudbeaver.server.CBApplication;
|
||||
import io.cloudbeaver.server.graphql.GraphQLEndpoint;
|
||||
@@ -33,7 +32,7 @@ import org.jkiss.utils.CommonUtils;
|
||||
* Web service implementation
|
||||
*/
|
||||
public class WebServiceBindingAdmin extends WebServiceBindingBase<DBWServiceAdmin>
|
||||
implements DBWServiceBindingServlet<CBApplication> {
|
||||
implements DBWServiceBindingServlet<CBApplication<?>> {
|
||||
|
||||
private static final String SCHEMA_FILE_NAME = "schema/service.admin.graphqls";
|
||||
|
||||
@@ -42,21 +41,21 @@ public class WebServiceBindingAdmin extends WebServiceBindingBase<DBWServiceAdmi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindWiring(DBWBindingContext model) throws DBWebException {
|
||||
public void bindWiring(DBWBindingContext model) {
|
||||
model.getQueryType()
|
||||
.dataFetcher(
|
||||
"adminUserInfo",
|
||||
env -> getService(env).getUserById(getWebSession(env), env.getArgument("userId"))
|
||||
env -> getService(env).getUserById(getWebSession(env), getArgumentVal(env, "userId"))
|
||||
)
|
||||
.dataFetcher(
|
||||
"listUsers",
|
||||
env -> getService(env).listUsers(
|
||||
getWebSession(env),
|
||||
new AdminUserInfoFilter(env.getArgument("filter"), env.getArgument("page"))
|
||||
new AdminUserInfoFilter(getArgumentVal(env, "filter"), getArgumentVal(env, "page"))
|
||||
)
|
||||
)
|
||||
.dataFetcher("listTeams",
|
||||
env -> getService(env).listTeams(getWebSession(env), env.getArgument("teamId")))
|
||||
env -> getService(env).listTeams(getWebSession(env), getArgument(env, "teamId")))
|
||||
.dataFetcher("listPermissions",
|
||||
env -> getService(env).listPermissions(getWebSession(env)))
|
||||
.dataFetcher("listAuthRoles",
|
||||
@@ -68,141 +67,141 @@ public class WebServiceBindingAdmin extends WebServiceBindingBase<DBWServiceAdmi
|
||||
.dataFetcher("createUser",
|
||||
env -> getService(env).createUser(
|
||||
getWebSession(env),
|
||||
env.getArgument("userId"),
|
||||
env.getArgument("enabled"),
|
||||
env.getArgument("authRole")
|
||||
getArgument(env, "userId"),
|
||||
getArgumentVal(env, "enabled"),
|
||||
getArgument(env, "authRole")
|
||||
))
|
||||
.dataFetcher("deleteUser",
|
||||
env -> getService(env).deleteUser(getWebSession(env), env.getArgument("userId")))
|
||||
env -> getService(env).deleteUser(getWebSession(env), getArgumentVal(env, "userId")))
|
||||
.dataFetcher("createTeam",
|
||||
env -> getService(env).createTeam(
|
||||
getWebSession(env),
|
||||
env.getArgument("teamId"),
|
||||
env.getArgument("teamName"),
|
||||
env.getArgument("description")))
|
||||
getArgumentVal(env, "teamId"),
|
||||
getArgumentVal(env, "teamName"),
|
||||
getArgument(env, "description")))
|
||||
.dataFetcher("updateTeam",
|
||||
env -> getService(env).updateTeam(
|
||||
getWebSession(env),
|
||||
env.getArgument("teamId"),
|
||||
env.getArgument("teamName"),
|
||||
env.getArgument("description")))
|
||||
getArgumentVal(env, "teamId"),
|
||||
getArgumentVal(env, "teamName"),
|
||||
getArgument(env, "description")))
|
||||
.dataFetcher("deleteTeam",
|
||||
env -> getService(env).deleteTeam(
|
||||
getWebSession(env),
|
||||
env.getArgument("teamId"),
|
||||
CommonUtils.toBoolean(env.getArgument("force"))))
|
||||
getArgumentVal(env, "teamId"),
|
||||
CommonUtils.toBoolean(getArgument(env, "force"))))
|
||||
|
||||
.dataFetcher("grantUserTeam",
|
||||
env -> getService(env).grantUserTeam(getWebSession(env), env.getArgument("userId"), env.getArgument("teamId")))
|
||||
env -> getService(env).grantUserTeam(getWebSession(env), getArgumentVal(env, "userId"), getArgumentVal(env, "teamId")))
|
||||
.dataFetcher("revokeUserTeam",
|
||||
env -> getService(env).revokeUserTeam(getWebSession(env), env.getArgument("userId"), env.getArgument("teamId")))
|
||||
env -> getService(env).revokeUserTeam(getWebSession(env), getArgumentVal(env, "userId"), getArgumentVal(env, "teamId")))
|
||||
.dataFetcher("setSubjectPermissions",
|
||||
env -> getService(env).setSubjectPermissions(getWebSession(env), env.getArgument("subjectId"), env.getArgument("permissions")))
|
||||
env -> getService(env).setSubjectPermissions(getWebSession(env), getArgumentVal(env, "subjectId"), getArgumentVal(env, "permissions")))
|
||||
.dataFetcher("setUserCredentials",
|
||||
env -> getService(env).setUserCredentials(getWebSession(env),
|
||||
env.getArgument("userId"),
|
||||
env.getArgument("providerId"),
|
||||
env.getArgument("credentials")))
|
||||
getArgumentVal(env, "userId"),
|
||||
getArgumentVal(env, "providerId"),
|
||||
getArgumentVal(env, "credentials")))
|
||||
.dataFetcher("deleteUserCredentials",
|
||||
env -> getService(env).deleteUserCredentials(getWebSession(env), env.getArgument("userId"), env.getArgument("providerId")))
|
||||
env -> getService(env).deleteUserCredentials(getWebSession(env), getArgumentVal(env, "userId"), getArgumentVal(env, "providerId")))
|
||||
.dataFetcher("enableUser",
|
||||
env -> getService(env).enableUser(getWebSession(env), env.getArgument("userId"), env.getArgument("enabled")))
|
||||
env -> getService(env).enableUser(getWebSession(env), getArgumentVal(env, "userId"), getArgumentVal(env, "enabled")))
|
||||
.dataFetcher("setUserAuthRole",
|
||||
env -> getService(env).setUserAuthRole(getWebSession(env), env.getArgument("userId"), env.getArgument("authRole")))
|
||||
env -> getService(env).setUserAuthRole(getWebSession(env), getArgumentVal(env, "userId"), getArgumentVal(env, "authRole")))
|
||||
.dataFetcher("setUserTeamRole",
|
||||
env -> getService(env).setUserTeamRole(
|
||||
getWebSession(env),
|
||||
env.getArgument("userId"),
|
||||
env.getArgument("teamId"),
|
||||
env.getArgument("teamRole")
|
||||
getArgumentVal(env, "userId"),
|
||||
getArgumentVal(env, "teamId"),
|
||||
getArgument(env, "teamRole")
|
||||
)
|
||||
)
|
||||
.dataFetcher("searchConnections", env -> getService(env).searchConnections(getWebSession(env), env.getArgument("hostNames")))
|
||||
.dataFetcher("searchConnections", env -> getService(env).searchConnections(getWebSession(env), getArgumentVal(env, "hostNames")))
|
||||
.dataFetcher("getConnectionSubjectAccess",
|
||||
env -> getService(env).getConnectionSubjectAccess(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("connectionId")))
|
||||
getArgumentVal(env, "connectionId")))
|
||||
.dataFetcher("setConnectionSubjectAccess",
|
||||
env -> getService(env).setConnectionSubjectAccess(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("connectionId"),
|
||||
env.getArgument("subjects")))
|
||||
getArgumentVal(env, "connectionId"),
|
||||
getArgumentVal(env, "subjects")))
|
||||
.dataFetcher("addConnectionsAccess",
|
||||
env -> getService(env).addConnectionsAccess(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("connectionIds"),
|
||||
env.getArgument("subjects")))
|
||||
getArgumentVal(env, "connectionIds"),
|
||||
getArgumentVal(env, "subjects")))
|
||||
.dataFetcher("deleteConnectionsAccess",
|
||||
env -> getService(env).deleteConnectionsAccess(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("connectionIds"),
|
||||
env.getArgument("subjects")))
|
||||
getArgumentVal(env, "connectionIds"),
|
||||
getArgumentVal(env, "subjects")))
|
||||
|
||||
.dataFetcher("getSubjectConnectionAccess",
|
||||
env -> getService(env).getSubjectConnectionAccess(getWebSession(env), env.getArgument("subjectId")))
|
||||
env -> getService(env).getSubjectConnectionAccess(getWebSession(env), getArgumentVal(env, "subjectId")))
|
||||
.dataFetcher("setSubjectConnectionAccess",
|
||||
env -> getService(env).setSubjectConnectionAccess(getWebSession(env), env.getArgument("subjectId"), env.getArgument("connections")))
|
||||
env -> getService(env).setSubjectConnectionAccess(getWebSession(env), getArgumentVal(env, "subjectId"), getArgumentVal(env, "connections")))
|
||||
|
||||
.dataFetcher("listFeatureSets",
|
||||
env -> getService(env).listFeatureSets(getWebSession(env)))
|
||||
|
||||
.dataFetcher("listAuthProviderConfigurationParameters",
|
||||
env -> getService(env).listAuthProviderConfigurationParameters(getWebSession(env), env.getArgument("providerId")))
|
||||
env -> getService(env).listAuthProviderConfigurationParameters(getWebSession(env), getArgumentVal(env, "providerId")))
|
||||
.dataFetcher("listAuthProviderConfigurations",
|
||||
env -> getService(env).listAuthProviderConfigurations(
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env),
|
||||
getWebSession(env), env.getArgument("providerId"))
|
||||
getWebSession(env), getArgument(env, "providerId"))
|
||||
)
|
||||
.dataFetcher("saveAuthProviderConfiguration",
|
||||
env -> getService(env).saveAuthProviderConfiguration(
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env),
|
||||
getWebSession(env),
|
||||
env.getArgument("providerId"),
|
||||
env.getArgument("id"),
|
||||
env.getArgument("displayName"),
|
||||
CommonUtils.toBoolean((Boolean)env.getArgument("disabled")),
|
||||
env.getArgument("iconURL"),
|
||||
env.getArgument("description"), env.getArgument("parameters")
|
||||
getArgumentVal(env, "providerId"),
|
||||
getArgumentVal(env, "id"),
|
||||
getArgumentVal(env, "displayName"),
|
||||
CommonUtils.toBoolean(getArgument(env, "disabled")),
|
||||
getArgument(env, "iconURL"),
|
||||
getArgument(env, "description"), getArgument(env, "parameters")
|
||||
))
|
||||
.dataFetcher("deleteAuthProviderConfiguration",
|
||||
env -> getService(env).deleteAuthProviderConfiguration(getWebSession(env), env.getArgument("id")))
|
||||
env -> getService(env).deleteAuthProviderConfiguration(getWebSession(env), getArgumentVal(env, "id")))
|
||||
|
||||
.dataFetcher("saveUserMetaParameter",
|
||||
env -> getService(env).saveUserMetaParameter(
|
||||
getWebSession(env),
|
||||
env.getArgument("id"),
|
||||
env.getArgument("displayName"),
|
||||
env.getArgument("description"),
|
||||
env.getArgument("required")))
|
||||
getArgumentVal(env, "id"),
|
||||
getArgumentVal(env, "displayName"),
|
||||
getArgument(env, "description"),
|
||||
getArgument(env, "required")))
|
||||
|
||||
.dataFetcher("deleteUserMetaParameter",
|
||||
env -> getService(env).deleteUserMetaParameter(
|
||||
getWebSession(env),
|
||||
env.getArgument("id")))
|
||||
getArgumentVal(env, "id")))
|
||||
|
||||
.dataFetcher("setUserMetaParameterValues",
|
||||
env -> getService(env).setUserMetaParameterValues(
|
||||
getWebSession(env),
|
||||
env.getArgument("userId"),
|
||||
env.getArgument("parameters")))
|
||||
getArgumentVal(env, "userId"),
|
||||
getArgumentVal(env, "parameters")))
|
||||
.dataFetcher("setTeamMetaParameterValues",
|
||||
env -> getService(env).setTeamMetaParameterValues(
|
||||
getWebSession(env),
|
||||
env.getArgument("teamId"),
|
||||
env.getArgument("parameters")))
|
||||
getArgumentVal(env, "teamId"),
|
||||
getArgumentVal(env, "parameters")))
|
||||
|
||||
.dataFetcher("configureServer",
|
||||
env -> getService(env).configureServer(getWebSession(env), env.getArgument("configuration")))
|
||||
env -> getService(env).configureServer(getWebSession(env), getArgumentVal(env, "configuration")))
|
||||
.dataFetcher("setDefaultNavigatorSettings",
|
||||
env -> getService(env).setDefaultNavigatorSettings(getWebSession(env), WebServiceUtils.parseNavigatorSettings(env.getArgument("settings"))))
|
||||
env -> getService(env).setDefaultNavigatorSettings(getWebSession(env), WebServiceUtils.parseNavigatorSettings(getArgument(env, "settings"))))
|
||||
;
|
||||
model.getMutationType()
|
||||
.dataFetcher("adminUpdateProductConfiguration",
|
||||
env -> getService(env).updateProductConfiguration(getWebSession(env), env.getArgument("configuration")));
|
||||
env -> getService(env).updateProductConfiguration(getWebSession(env), getArgumentVal(env, "configuration")));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+16
-15
@@ -193,7 +193,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteUser(@NotNull WebSession webSession, String userName) throws DBWebException {
|
||||
public boolean deleteUser(@NotNull WebSession webSession, @NotNull String userName) throws DBWebException {
|
||||
if (CommonUtils.equalObjects(userName, webSession.getUser().getUserId())) {
|
||||
throw new DBWebException("You cannot delete yourself");
|
||||
}
|
||||
@@ -253,7 +253,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AdminTeamInfo updateTeam(@NotNull WebSession webSession, String teamId, String teamName, String description) throws DBWebException {
|
||||
public AdminTeamInfo updateTeam(@NotNull WebSession webSession, @NotNull String teamId, @NotNull String teamName, @Nullable String description) throws DBWebException {
|
||||
if (teamId.isEmpty()) {
|
||||
throw new DBWebException("Empty team ID");
|
||||
}
|
||||
@@ -270,7 +270,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTeam(@NotNull WebSession webSession, String teamId, boolean force) throws DBWebException {
|
||||
public boolean deleteTeam(@NotNull WebSession webSession, @NotNull String teamId, boolean force) throws DBWebException {
|
||||
try {
|
||||
webSession.addInfoMessage("Delete team - " + teamId);
|
||||
|
||||
@@ -291,7 +291,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean grantUserTeam(@NotNull WebSession webSession, String user, String team) throws DBWebException {
|
||||
public boolean grantUserTeam(@NotNull WebSession webSession, @NotNull String user, @NotNull String team) throws DBWebException {
|
||||
WebUser grantor = webSession.getUser();
|
||||
if (grantor == null) {
|
||||
throw new DBWebException("Cannot grant team in anonymous mode");
|
||||
@@ -312,7 +312,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeUserTeam(@NotNull WebSession webSession, String user, String team) throws DBWebException {
|
||||
public boolean revokeUserTeam(@NotNull WebSession webSession, @NotNull String user, @NotNull String team) throws DBWebException {
|
||||
WebUser grantor = webSession.getUser();
|
||||
if (grantor == null) {
|
||||
throw new DBWebException("Cannot revoke team in anonymous mode");
|
||||
@@ -337,8 +337,9 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<AdminPermissionInfo> setSubjectPermissions(@NotNull WebSession webSession, String subjectID, List<String> permissions) throws DBWebException {
|
||||
public List<AdminPermissionInfo> setSubjectPermissions(@NotNull WebSession webSession, @NotNull String subjectID, @NotNull List<String> permissions) throws DBWebException {
|
||||
validatePermissions(SMConstants.SUBJECT_PERMISSION_SCOPE, permissions);
|
||||
WebUser grantor = webSession.getUser();
|
||||
if (grantor == null) {
|
||||
@@ -415,7 +416,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean setUserAuthRole(WebSession webSession, String userId, String authRole) throws DBWebException {
|
||||
public Boolean setUserAuthRole(@NotNull WebSession webSession, @NotNull String userId, @NotNull String authRole) throws DBWebException {
|
||||
try {
|
||||
log.info(String.format("User set auth role: [grantorUserId=%s]", webSession.getUserId()));
|
||||
webSession.getAdminSecurityController().setUserAuthRole(userId, authRole);
|
||||
@@ -569,7 +570,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean configureServer(WebSession webSession, Map<String, Object> params) throws DBWebException {
|
||||
public boolean configureServer(@NotNull WebSession webSession, @NotNull Map<String, Object> params) throws DBWebException {
|
||||
try {
|
||||
CBAppConfig appConfig = new CBAppConfig(CBApplication.getInstance().getAppConfiguration());
|
||||
CBServerConfig serverConfig = new CBServerConfig();
|
||||
@@ -715,7 +716,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setDefaultNavigatorSettings(WebSession webSession, DBNBrowseSettings settings) throws DBWebException {
|
||||
public boolean setDefaultNavigatorSettings(@NotNull WebSession webSession, @NotNull DBNBrowseSettings settings) throws DBWebException {
|
||||
CBApplication.getInstance().getAppConfiguration().setDefaultNavigatorSettings(settings);
|
||||
if (CBApplication.getInstance().isConfigurationMode()) {
|
||||
return true;
|
||||
@@ -730,7 +731,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean updateProductConfiguration(WebSession webSession, Map<String, Object> productConfiguration) throws DBWebException {
|
||||
public boolean updateProductConfiguration(@NotNull WebSession webSession, @NotNull Map<String, Object> productConfiguration) throws DBWebException {
|
||||
try {
|
||||
CBApplication.getInstance().saveProductConfiguration(webSession, productConfiguration);
|
||||
return true;
|
||||
@@ -746,7 +747,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
public SMDataSourceGrant[] getConnectionSubjectAccess(
|
||||
@NotNull WebSession webSession,
|
||||
@Nullable String projectId,
|
||||
String connectionId
|
||||
@NotNull String connectionId
|
||||
) throws DBWebException {
|
||||
DBPProject globalProject = webSession.getProjectById(projectId);
|
||||
if (!WebServiceUtils.isGlobalProject(globalProject)) {
|
||||
@@ -903,17 +904,17 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebPropertyInfo saveUserMetaParameter(WebSession webSession, String id, String displayName, String description, Boolean required) throws DBWebException {
|
||||
public WebPropertyInfo saveUserMetaParameter(@NotNull WebSession webSession, @NotNull String id, @NotNull String displayName, String description, Boolean required) throws DBWebException {
|
||||
throw new DBWebException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteUserMetaParameter(WebSession webSession, String id) throws DBWebException {
|
||||
public Boolean deleteUserMetaParameter(@NotNull WebSession webSession, @NotNull String id) throws DBWebException {
|
||||
throw new DBWebException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean setUserMetaParameterValues(WebSession webSession, String userId, Map<String, String> parameters) throws DBWebException {
|
||||
public Boolean setUserMetaParameterValues(@NotNull WebSession webSession, @NotNull String userId, @NotNull Map<String, String> parameters) throws DBWebException {
|
||||
try {
|
||||
webSession.getAdminSecurityController().setSubjectMetas(userId, parameters);
|
||||
return true;
|
||||
@@ -923,7 +924,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean setTeamMetaParameterValues(WebSession webSession, String teamId, Map<String, String> parameters) throws DBWebException {
|
||||
public Boolean setTeamMetaParameterValues(@NotNull WebSession webSession, @NotNull String teamId, @NotNull Map<String, String> parameters) throws DBWebException {
|
||||
try {
|
||||
webSession.getAdminSecurityController().setSubjectMetas(teamId, parameters);
|
||||
return true;
|
||||
|
||||
@@ -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.132.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.132-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+22
-23
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package io.cloudbeaver.service.auth;
|
||||
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.server.graphql.GraphQLEndpoint;
|
||||
import io.cloudbeaver.service.DBWBindingContext;
|
||||
import io.cloudbeaver.service.WebServiceBindingBase;
|
||||
@@ -35,45 +34,45 @@ public class WebServiceBindingAuth extends WebServiceBindingBase<DBWServiceAuth>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindWiring(DBWBindingContext model) throws DBWebException {
|
||||
public void bindWiring(DBWBindingContext model) {
|
||||
model.getQueryType()
|
||||
.dataFetcher("authLogin", env -> getService(env).authLogin(
|
||||
getWebSession(env, false),
|
||||
env.getArgument("provider"),
|
||||
env.getArgument("configuration"),
|
||||
env.getArgument("credentials"),
|
||||
CommonUtils.toBoolean(env.getArgument("linkUser")),
|
||||
CommonUtils.toBoolean(env.getArgument("forceSessionsLogout"))
|
||||
getArgumentVal(env, "provider"),
|
||||
getArgument(env, "configuration"),
|
||||
getArgument(env, "credentials"),
|
||||
CommonUtils.toBoolean(getArgument(env, "linkUser")),
|
||||
CommonUtils.toBoolean(getArgument(env, "forceSessionsLogout"))
|
||||
))
|
||||
.dataFetcher("federatedAuthTaskResult", env -> getService(env).federatedAuthTaskResult(
|
||||
getWebSession(env, false),
|
||||
env.getArgument("taskId")
|
||||
getArgumentVal(env, "taskId")
|
||||
))
|
||||
.dataFetcher("authLogoutExtended", env -> getService(env).authLogout(
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env),
|
||||
getWebSession(env, false),
|
||||
env.getArgument("provider"),
|
||||
env.getArgument("configuration")
|
||||
getArgument(env, "provider"),
|
||||
getArgument(env, "configuration")
|
||||
))
|
||||
.dataFetcher("authLogout", env -> {
|
||||
getService(env).authLogout(
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env),
|
||||
getWebSession(env, false),
|
||||
env.getArgument("provider"),
|
||||
env.getArgument("configuration"));
|
||||
getArgument(env, "provider"),
|
||||
getArgument(env, "configuration"));
|
||||
return true;
|
||||
})
|
||||
.dataFetcher("authUpdateStatus", env -> getService(env).authUpdateStatus(
|
||||
getWebSession(env, false),
|
||||
env.getArgument("authId"),
|
||||
CommonUtils.toBoolean(env.getArgument("linkUser"))
|
||||
getArgumentVal(env, "authId"),
|
||||
CommonUtils.toBoolean(getArgument(env, "linkUser"))
|
||||
))
|
||||
.dataFetcher("activeUser", env -> getService(env).activeUser(getWebSession(env, false)))
|
||||
.dataFetcher("authProviders", env -> getService(env).getAuthProviders(GraphQLEndpoint.getServletRequestOrThrow(env)))
|
||||
.dataFetcher("authChangeLocalPassword", env -> getService(env).changeLocalPassword(
|
||||
getWebSession(env),
|
||||
env.getArgument("oldPassword"),
|
||||
env.getArgument("newPassword")
|
||||
getArgumentVal(env, "oldPassword"),
|
||||
getArgumentVal(env, "newPassword")
|
||||
))
|
||||
.dataFetcher("listUserProfileProperties",
|
||||
env -> getService(env).listUserProfileProperties(getWebSession(env)))
|
||||
@@ -81,18 +80,18 @@ public class WebServiceBindingAuth extends WebServiceBindingBase<DBWServiceAuth>
|
||||
model.getMutationType()
|
||||
.dataFetcher("setUserConfigurationParameter",
|
||||
env -> getService(env).setUserConfigurationParameter(getWebSession(env),
|
||||
env.getArgument("name"),
|
||||
env.getArgument("value")))
|
||||
getArgumentVal(env, "name"),
|
||||
getArgument(env, "value")))
|
||||
.dataFetcher("setUserPreferences",
|
||||
env -> getService(env).setUserConfigurationParameters(getWebSession(env),
|
||||
env.getArgument("preferences")))
|
||||
getArgumentVal(env, "preferences")))
|
||||
.dataFetcher("federatedLogin", env -> getService(env).federatedLogin(
|
||||
GraphQLEndpoint.getServletRequestOrThrow(env),
|
||||
getWebSession(env, false),
|
||||
env.getArgument("provider"),
|
||||
env.getArgument("configuration"),
|
||||
CommonUtils.toBoolean(env.getArgument("linkUser")),
|
||||
CommonUtils.toBoolean(env.getArgument("forceSessionsLogout"))
|
||||
getArgumentVal(env, "provider"),
|
||||
getArgument(env, "configuration"),
|
||||
CommonUtils.toBoolean(getArgument(env, "linkUser")),
|
||||
CommonUtils.toBoolean(getArgument(env, "forceSessionsLogout"))
|
||||
))
|
||||
;
|
||||
}
|
||||
|
||||
+2
-8
@@ -224,10 +224,8 @@ public class WebServiceAuthImpl implements DBWServiceAuth {
|
||||
throw new DBWebException("Not logged in");
|
||||
}
|
||||
try {
|
||||
List<WebAuthInfo> removedInfos = webSession.removeAuthInfo(providerId, false);
|
||||
List<WebAuthInfo> removedInfos = webSession.removeAuthInfo(providerId);
|
||||
var cbApp = CBApplication.getInstance();
|
||||
cbApp.getSessionManager().closeSession(webSession.getSessionId(), false);
|
||||
webSession.resetUserState();
|
||||
|
||||
List<String> logoutUrls = new ArrayList<>();
|
||||
String origin = ServletAppUtils.getOriginFromRequest(httpRequest);
|
||||
@@ -268,11 +266,7 @@ public class WebServiceAuthImpl implements DBWServiceAuth {
|
||||
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()) {
|
||||
if (!application.getAppConfiguration().isAnonymousAccessEnabled() || !webSession.isAuthorizedInSecurityManager()) {
|
||||
return null;
|
||||
}
|
||||
SMUser anonymous = new SMUser("anonymous", true, null);
|
||||
|
||||
@@ -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.133.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.133-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+5
-5
@@ -47,17 +47,17 @@ public class WebServiceBindingDataTransfer extends WebServiceBindingBase<DBWServ
|
||||
env -> getService(env).getAvailableImportStreamProcessors(getWebSession(env)))
|
||||
.dataFetcher("dataTransferExportDataFromContainer", env -> getService(env).dataTransferExportDataFromContainer(
|
||||
WebServiceBindingSQL.getSQLProcessor(env),
|
||||
env.getArgument("containerNodePath"),
|
||||
new WebDataTransferParameters(env.getArgument("parameters"))
|
||||
getArgument(env, "containerNodePath"),
|
||||
new WebDataTransferParameters(getArgument(env, "parameters"))
|
||||
))
|
||||
.dataFetcher("dataTransferExportDataFromResults", env -> getService(env).dataTransferExportDataFromResults(
|
||||
WebServiceBindingSQL.getSQLContext(env),
|
||||
env.getArgument("resultsId"),
|
||||
new WebDataTransferParameters(env.getArgument("parameters"))
|
||||
getArgument(env, "resultsId"),
|
||||
new WebDataTransferParameters(getArgument(env, "parameters"))
|
||||
))
|
||||
.dataFetcher("dataTransferRemoveDataFile", env -> getService(env).dataTransferRemoveDataFile(
|
||||
getWebSession(env),
|
||||
env.getArgument("dataFileId")
|
||||
getArgument(env, "dataFileId")
|
||||
))
|
||||
.dataFetcher("dataTransferDefaultExportSettings", env -> getService(env).defaultExportSettings())
|
||||
;
|
||||
|
||||
+5
@@ -39,6 +39,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -72,6 +73,10 @@ public class WebDataTransferImportServlet extends WebServiceServletBase {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Import for users only");
|
||||
return;
|
||||
}
|
||||
if (DBWorkbench.isDistributed() && !session.hasPermission(DBWConstants.PERMISSION_SQL_RESULT_UPDATE)) {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Permission denied");
|
||||
return;
|
||||
}
|
||||
if (!session.hasPermission(DBWConstants.GLOBAL_PERMISSION_DATA_EDITOR_IMPORT)) {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Import is not allowed for this user");
|
||||
return;
|
||||
|
||||
@@ -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.50.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.50-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+22
-22
@@ -30,7 +30,7 @@ import org.jkiss.utils.CommonUtils;
|
||||
/**
|
||||
* Web service implementation
|
||||
*/
|
||||
public class WebServiceBindingFS extends WebServiceBindingBase<DBWServiceFS> implements DBWServiceBindingServlet<CBApplication> {
|
||||
public class WebServiceBindingFS extends WebServiceBindingBase<DBWServiceFS> implements DBWServiceBindingServlet<CBApplication<?>> {
|
||||
|
||||
private static final String SCHEMA_FILE_NAME = "schema/service.fs.graphqls";
|
||||
|
||||
@@ -42,82 +42,82 @@ public class WebServiceBindingFS extends WebServiceBindingBase<DBWServiceFS> imp
|
||||
public void bindWiring(DBWBindingContext model) throws DBWebException {
|
||||
model.getQueryType()
|
||||
.dataFetcher("fsListFileSystems",
|
||||
env -> getService(env).getAvailableFileSystems(getWebSession(env), env.getArgument("projectId")))
|
||||
env -> getService(env).getAvailableFileSystems(getWebSession(env), getArgumentVal(env, "projectId")))
|
||||
.dataFetcher("fsFileSystem",
|
||||
env -> getService(env).getFileSystem(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("nodePath")
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgumentVal(env, "nodePath")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsFile",
|
||||
env -> getService(env).getFile(getWebSession(env),
|
||||
env.getArgument("nodePath")
|
||||
getArgumentVal(env, "nodePath")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsListFiles",
|
||||
env -> getService(env).getFiles(getWebSession(env),
|
||||
env.getArgument("folderPath")
|
||||
getArgumentVal(env, "folderPath")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsReadFileContentAsString",
|
||||
env -> getService(env).readFileContent(getWebSession(env),
|
||||
env.getArgument("nodePath")
|
||||
getArgumentVal(env, "nodePath")
|
||||
)
|
||||
)
|
||||
;
|
||||
model.getMutationType()
|
||||
.dataFetcher("fsCreateFile",
|
||||
env -> getService(env).createFile(getWebSession(env),
|
||||
env.getArgument("parentPath"),
|
||||
env.getArgument("fileName")
|
||||
getArgumentVal(env, "parentPath"),
|
||||
getArgumentVal(env, "fileName")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsCreateFolder",
|
||||
env -> getService(env).createFolder(getWebSession(env),
|
||||
env.getArgument("parentPath"),
|
||||
env.getArgument("folderName")
|
||||
getArgumentVal(env, "parentPath"),
|
||||
getArgumentVal(env, "folderName")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsDelete",
|
||||
env -> getService(env).deleteFile(getWebSession(env),
|
||||
env.getArgument("nodePath")
|
||||
getArgumentVal(env, "nodePath")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsMove",
|
||||
env -> getService(env).moveFile(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath"),
|
||||
env.getArgument("toParentNodePath")
|
||||
getArgumentVal(env, "nodePath"),
|
||||
getArgumentVal(env, "toParentNodePath")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsRename",
|
||||
env -> getService(env).renameFile(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath"),
|
||||
env.getArgument("newName")
|
||||
getArgumentVal(env, "nodePath"),
|
||||
getArgumentVal(env, "newName")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsCopy",
|
||||
env -> getService(env).copyFile(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath"),
|
||||
env.getArgument("toParentNodePath")
|
||||
getArgumentVal(env, "nodePath"),
|
||||
getArgumentVal(env, "toParentNodePath")
|
||||
)
|
||||
)
|
||||
.dataFetcher("fsWriteFileStringContent",
|
||||
env -> getService(env).writeFileContent(
|
||||
getWebSession(env),
|
||||
env.getArgument("nodePath"),
|
||||
env.getArgument("data"),
|
||||
CommonUtils.toBoolean(env.getArgument("forceOverwrite"))
|
||||
getArgumentVal(env, "nodePath"),
|
||||
getArgumentVal(env, "data"),
|
||||
CommonUtils.toBoolean(getArgument(env, "forceOverwrite"))
|
||||
)
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addServlets(CBApplication application, DBWServletContext servletContext) throws DBException {
|
||||
public void addServlets(CBApplication<?> application, DBWServletContext servletContext) throws DBException {
|
||||
if (!application.isMultiuser()) {
|
||||
return;
|
||||
}
|
||||
|
||||
+24
-2
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package io.cloudbeaver.service.fs.impl;
|
||||
|
||||
import io.cloudbeaver.DBWConstants;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.model.fs.FSUtils;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
@@ -30,6 +31,7 @@ import org.jkiss.dbeaver.model.navigator.fs.DBNFileSystem;
|
||||
import org.jkiss.dbeaver.model.navigator.fs.DBNFileSystems;
|
||||
import org.jkiss.dbeaver.model.navigator.fs.DBNPathBase;
|
||||
import org.jkiss.dbeaver.registry.fs.FileSystemProviderRegistry;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@@ -61,10 +63,14 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
}
|
||||
DBNFileSystems dbnFileSystems = projectNode.getExtraNode(DBNFileSystems.class);
|
||||
var fsRegistry = FileSystemProviderRegistry.getInstance();
|
||||
return Arrays.stream(dbnFileSystems.getChildren(webSession.getProgressMonitor()))
|
||||
DBNFileSystem[] children = dbnFileSystems.getChildren(webSession.getProgressMonitor());
|
||||
if (children == null) {
|
||||
return new FSFileSystem[0];
|
||||
}
|
||||
return Arrays.stream(children)
|
||||
.map(fs -> new FSFileSystem(
|
||||
FSUtils.makeUniqueFsId(fs.getFileSystem()),
|
||||
fs.getNodeUri(),
|
||||
fs.getNodeUri(),
|
||||
fsRegistry.getProvider(fs.getFileSystem().getProviderId()).getRequiredAuth()
|
||||
)
|
||||
)
|
||||
@@ -116,6 +122,9 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
try {
|
||||
DBNPathBase folderPath = FSUtils.getNodeByPath(webSession, parentPath);
|
||||
var children = folderPath.getChildren(webSession.getProgressMonitor());
|
||||
if (children == null) {
|
||||
return new FSFile[0];
|
||||
}
|
||||
return Arrays.stream(children)
|
||||
.filter(c -> c instanceof DBNPathBase)
|
||||
.map(c -> (DBNPathBase) c)
|
||||
@@ -147,6 +156,7 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
boolean forceOverwrite
|
||||
)
|
||||
throws DBWebException {
|
||||
validateEditPermissions(webSession);
|
||||
try {
|
||||
DBNPathBase node = FSUtils.getNodeByPath(webSession, nodePath);
|
||||
Path filePath = node.getPath();
|
||||
@@ -167,6 +177,7 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
@NotNull String parentPath,
|
||||
@NotNull String fileName
|
||||
) throws DBWebException {
|
||||
validateEditPermissions(webSession);
|
||||
try {
|
||||
DBNPathBase parentNode = FSUtils.getNodeByPath(webSession, parentPath);
|
||||
if (!Files.isDirectory(parentNode.getPath())) {
|
||||
@@ -187,6 +198,7 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
@NotNull String oldNodePath,
|
||||
@NotNull String parentNodePath
|
||||
) throws DBWebException {
|
||||
validateEditPermissions(webSession);
|
||||
try {
|
||||
DBNPathBase oldNode = FSUtils.getNodeByPath(webSession, oldNodePath);
|
||||
DBNPathBase oldParentNode = (DBNPathBase) oldNode.getParentNode();
|
||||
@@ -212,6 +224,7 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
@NotNull String nodePath,
|
||||
@NotNull String newName
|
||||
) throws DBWebException {
|
||||
validateEditPermissions(webSession);
|
||||
validateFilename(newName);
|
||||
try {
|
||||
DBNPathBase node = FSUtils.getNodeByPath(webSession, nodePath);
|
||||
@@ -228,6 +241,7 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
@NotNull String oldNodePath,
|
||||
@NotNull String parentNodePath
|
||||
) throws DBWebException {
|
||||
validateEditPermissions(webSession);
|
||||
try {
|
||||
DBNPathBase oldNode = FSUtils.getNodeByPath(webSession, oldNodePath);
|
||||
String fileName = oldNode.getName();
|
||||
@@ -251,6 +265,7 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
@NotNull String parentPath,
|
||||
@NotNull String folderName
|
||||
) throws DBWebException {
|
||||
validateEditPermissions(webSession);
|
||||
try {
|
||||
DBNPathBase parentNode = FSUtils.getNodeByPath(webSession, parentPath);
|
||||
if (!Files.isDirectory(parentNode.getPath())) {
|
||||
@@ -270,6 +285,7 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
@NotNull WebSession webSession,
|
||||
@NotNull String nodePath
|
||||
) throws DBWebException {
|
||||
validateEditPermissions(webSession);
|
||||
try {
|
||||
DBNPathBase node = FSUtils.getNodeByPath(webSession, nodePath);
|
||||
Path path = node.getPath();
|
||||
@@ -289,4 +305,10 @@ public class WebServiceFS implements DBWServiceFS {
|
||||
throw new DBWebException(String.format("File %s contains forbidden symbols", filename));
|
||||
}
|
||||
}
|
||||
|
||||
private void validateEditPermissions(@NotNull WebSession webSession) throws DBWebException {
|
||||
if (DBWorkbench.isDistributed() && !webSession.hasPermission(DBWConstants.PERMISSION_FS_RESOURCE_EDIT)) {
|
||||
throw new DBWebException("Permission denied");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-8
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package io.cloudbeaver.service.fs.model;
|
||||
|
||||
import io.cloudbeaver.DBWConstants;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.model.fs.FSUtils;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
@@ -32,6 +33,7 @@ import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.model.navigator.fs.DBNPathBase;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
|
||||
@@ -48,7 +50,7 @@ public class WebFSServlet extends WebServiceServletBase {
|
||||
private static final String PARAM_PROJECT_ID = "projectId";
|
||||
private final DBWServiceFS fs;
|
||||
|
||||
public WebFSServlet(CBApplication application, DBWServiceFS fs) {
|
||||
public WebFSServlet(CBApplication<?> application, DBWServiceFS fs) {
|
||||
super(application);
|
||||
this.fs = fs;
|
||||
}
|
||||
@@ -60,6 +62,10 @@ public class WebFSServlet extends WebServiceServletBase {
|
||||
return;
|
||||
}
|
||||
if (request.getMethod().equals("POST")) {
|
||||
if (DBWorkbench.isDistributed() && !session.hasPermission(DBWConstants.PERMISSION_SQL_RESULT_UPDATE)) {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Permission denied.");
|
||||
return;
|
||||
}
|
||||
doPost(session, request, response);
|
||||
} else {
|
||||
doGet(session, request, response);
|
||||
@@ -109,15 +115,17 @@ public class WebFSServlet extends WebServiceServletBase {
|
||||
@Override
|
||||
protected Map<String, Object> getVariables(HttpServletRequest request) {
|
||||
Map<String, Object> variables = super.getVariables(request);
|
||||
try {
|
||||
for (Part part : request.getParts()) {
|
||||
if (part.getSubmittedFileName()!= null && !part.getSubmittedFileName().isEmpty()) {
|
||||
variables.put("fileName", part.getSubmittedFileName());
|
||||
break;
|
||||
if (request.getMethod().equals("POST")) {
|
||||
try {
|
||||
for (Part part : request.getParts()) {
|
||||
if (part.getSubmittedFileName() != null && !part.getSubmittedFileName().isEmpty()) {
|
||||
variables.put("fileName", part.getSubmittedFileName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to get fileName from request for logging", e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to get fileName from request for logging", e);
|
||||
}
|
||||
return variables;
|
||||
}
|
||||
|
||||
@@ -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.15.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: org.jkiss.dbeaver.model;visibility:=reexport,
|
||||
|
||||
@@ -22,4 +22,5 @@ prop.auth.model.ldap.ldap-enable-ssl = Enable SSL
|
||||
prop.auth.model.ldap.ldap-enable-ssl.description = Use a secure SSL connection to the LDAP server
|
||||
prop.auth.model.ldap.ldap-ssl-cert = Certificate (PEM format)
|
||||
prop.auth.model.ldap.ldap-ssl-cert.description = PEM-encoded certificate used to validate the LDAP server when SSL is enabled
|
||||
|
||||
prop.auth.model.ldap.ldap-referral = Referral handling
|
||||
prop.auth.model.ldap.ldap-referral.description = Specify how LDAP referrals are handled. Default is 'ignore'
|
||||
|
||||
@@ -21,4 +21,6 @@ prop.auth.model.ldap.ldap-login.description = Атрибут LDAP, которы
|
||||
prop.auth.model.ldap.ldap-enable-ssl = Включить SSL
|
||||
prop.auth.model.ldap.ldap-enable-ssl.description = Использовать защищённое SSL-соединение с сервером LDAP
|
||||
prop.auth.model.ldap.ldap-ssl-cert = Сертификат (в формате PEM)
|
||||
prop.auth.model.ldap.ldap-ssl-cert.description = PEM-сертификат, используемый для проверки подлинности LDAP-сервера при включённом SSL
|
||||
prop.auth.model.ldap.ldap-ssl-cert.description = PEM-сертификат, используемый для проверки подлинности LDAP-сервера при включённом SSL
|
||||
prop.auth.model.ldap.ldap-referral = Обработка перенаправлений
|
||||
prop.auth.model.ldap.ldap-referral.description = Укажите, как обрабатываются перенаправления LDAP. По умолчанию 'ignore'
|
||||
@@ -31,6 +31,7 @@
|
||||
description="%ldap-login.description"/>
|
||||
<property id="ldap-enable-ssl" label="%ldap-enable-ssl" description="%ldap-enable-ssl.description" type="boolean" defaultValue="false"/>
|
||||
<property id="ldap-ssl-cert" label="%ldap-ssl-cert" description="%ldap-ssl-cert.description" type="file" features="file"/>
|
||||
<property id="ldap-referral" label="%ldap-referral" description="%ldap-referral.description" type="string" defaultValue="ignore"/>
|
||||
|
||||
</propertyGroup>
|
||||
</configuration>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.service.ldap.auth</artifactId>
|
||||
<version>1.0.13-SNAPSHOT</version>
|
||||
<version>1.0.15-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+12
-1
@@ -540,6 +540,12 @@ public class LdapAuthProvider implements SMAuthProviderExternal<SMSession>, SMBr
|
||||
//it's a hack. Otherwise password will be written to database
|
||||
authParameters.remove(LdapConstants.CRED_PASSWORD);
|
||||
|
||||
String referralHandlingMode = ldapSettings.getReferralHandlingMode();
|
||||
environment.put(Context.REFERRAL, referralHandlingMode);
|
||||
if ("follow".equalsIgnoreCase(referralHandlingMode)) {
|
||||
environment.put("java.naming.ldap.referral.limit", "5");
|
||||
}
|
||||
|
||||
context = initConnection(environment);
|
||||
|
||||
String searchFilter = "(member=" + fullDN + ")";
|
||||
@@ -548,7 +554,12 @@ public class LdapAuthProvider implements SMAuthProviderExternal<SMSession>, SMBr
|
||||
|
||||
searchResults = context.search(ldapSettings.getBaseDN(), searchFilter, searchControls);
|
||||
while (searchResults.hasMore()) {
|
||||
result.add(searchResults.next().getName());
|
||||
try {
|
||||
SearchResult next = searchResults.next();
|
||||
result.add(next.getName());
|
||||
} catch (Exception e) {
|
||||
log.error("Failed fetch user group. Skipping...", e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Group not found", e);
|
||||
|
||||
+1
@@ -27,6 +27,7 @@ public interface LdapConstants {
|
||||
String PARAM_LOGIN = "ldap-login";
|
||||
String PARAM_SSL_ENABLE = "ldap-enable-ssl";
|
||||
String PARAM_SSL_CERT = "ldap-ssl-cert";
|
||||
String PARAM_REFERRAL_HANDLING = "ldap-referral";
|
||||
|
||||
String CRED_USERNAME = "user";
|
||||
String CRED_DISPLAY_NAME = "displayName";
|
||||
|
||||
+6
@@ -36,6 +36,7 @@ public class LdapSettings {
|
||||
private final String filter;
|
||||
private final String loginAttribute;
|
||||
private final LdapSslSetting ldapSslSetting;
|
||||
private final String referralHandlingMode;
|
||||
|
||||
|
||||
public LdapSettings(
|
||||
@@ -56,6 +57,7 @@ public class LdapSettings {
|
||||
providerConfiguration.getParameter(LdapConstants.PARAM_SSL_ENABLE),
|
||||
providerConfiguration.getParameter(LdapConstants.PARAM_SSL_CERT)
|
||||
);
|
||||
this.referralHandlingMode = providerConfiguration.getParameterOrDefault(LdapConstants.PARAM_REFERRAL_HANDLING, "ignore");
|
||||
}
|
||||
|
||||
|
||||
@@ -109,4 +111,8 @@ public class LdapSettings {
|
||||
public SMAuthProviderCustomConfiguration getProviderConfiguration() {
|
||||
return providerConfiguration;
|
||||
}
|
||||
|
||||
public String getReferralHandlingMode() {
|
||||
return referralHandlingMode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.136.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.136-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+3
-4
@@ -17,7 +17,6 @@
|
||||
package io.cloudbeaver.service.metadata;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.service.DBWBindingContext;
|
||||
import io.cloudbeaver.service.WebServiceBindingBase;
|
||||
@@ -37,12 +36,12 @@ public class WebServiceBindingMetadata extends WebServiceBindingBase<DBWServiceM
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindWiring(DBWBindingContext model) throws DBWebException {
|
||||
public void bindWiring(DBWBindingContext model) {
|
||||
model.getQueryType()
|
||||
.dataFetcher("metadataGetNodeDDL", env -> getService(env).getNodeDDL(
|
||||
getWebSession(env),
|
||||
getNodeFromPath(env),
|
||||
env.getArgument("options"))
|
||||
getArgument(env, "options"))
|
||||
).dataFetcher("metadataGetNodeExtendedDDL", env -> getService(env).getNodeExtendedDDL(
|
||||
getWebSession(env),
|
||||
getNodeFromPath(env)
|
||||
@@ -51,7 +50,7 @@ public class WebServiceBindingMetadata extends WebServiceBindingBase<DBWServiceM
|
||||
|
||||
private DBNNode getNodeFromPath(DataFetchingEnvironment env) throws DBException {
|
||||
WebSession webSession = getWebSession(env);
|
||||
String nodePath = env.getArgument("nodeId");
|
||||
String nodePath = getArgument(env, "nodeId");
|
||||
if (nodePath == null) {
|
||||
throw new DBException("Node path is null");
|
||||
}
|
||||
|
||||
@@ -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.50.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.50-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.85.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.85-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+47
-48
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package io.cloudbeaver.service.rm;
|
||||
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.service.DBWBindingContext;
|
||||
import io.cloudbeaver.service.WebServiceBindingBase;
|
||||
import io.cloudbeaver.service.rm.impl.WebServiceRM;
|
||||
@@ -36,74 +35,74 @@ public class WebServiceBindingRM extends WebServiceBindingBase<DBWServiceRM> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindWiring(DBWBindingContext model) throws DBWebException {
|
||||
public void bindWiring(DBWBindingContext model) {
|
||||
model.getQueryType()
|
||||
.dataFetcher("rmListProjects",
|
||||
env -> getService(env).listProjects(getWebSession(env)))
|
||||
.dataFetcher("rmListSharedProjects",
|
||||
env -> getService(env).listSharedProjects(getWebSession(env)))
|
||||
.dataFetcher("rmProject",
|
||||
env -> getService(env).getProject(getWebSession(env), env.getArgument("projectId")))
|
||||
env -> getService(env).getProject(getWebSession(env), getArgumentVal(env, "projectId")))
|
||||
.dataFetcher("rmListResources",
|
||||
env -> getService(env).listResources(getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("folder"),
|
||||
env.getArgument("nameMask"),
|
||||
CommonUtils.toBoolean(env.getArgument("readProperties")),
|
||||
CommonUtils.toBoolean(env.getArgument("readHistory"))))
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgument(env, "folder"),
|
||||
getArgument(env, "nameMask"),
|
||||
CommonUtils.toBoolean(getArgument(env, "readProperties")),
|
||||
CommonUtils.toBoolean(getArgument(env, "readHistory"))))
|
||||
.dataFetcher("rmReadResourceAsString",
|
||||
env -> getService(env).readResourceAsString(getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("resourcePath")))
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgumentVal(env, "resourcePath")))
|
||||
.dataFetcher("rmListProjectPermissions", env -> getService(env).listProjectPermissions())
|
||||
.dataFetcher("rmListProjectGrantedPermissions", env -> getService(env).listProjectGrantedPermissions(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId")
|
||||
getArgumentVal(env, "projectId")
|
||||
))
|
||||
.dataFetcher("rmListSubjectProjectsPermissionGrants", env -> getService(env).listSubjectProjectsPermissionGrants(
|
||||
getWebSession(env),
|
||||
env.getArgument("subjectId")
|
||||
getArgumentVal(env, "subjectId")
|
||||
))
|
||||
.dataFetcher(
|
||||
"rmUserProjectSettings", env -> getService(env).getProjectSettings(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("settingId")
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgument(env, "settingId")
|
||||
)
|
||||
)
|
||||
;
|
||||
model.getMutationType()
|
||||
.dataFetcher("rmCreateResource",
|
||||
env -> getService(env).createResource(getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("resourcePath"),
|
||||
CommonUtils.toBoolean(env.getArgument("isFolder"))))
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgumentVal(env, "resourcePath"),
|
||||
CommonUtils.toBoolean(getArgument(env, "isFolder"))))
|
||||
.dataFetcher("rmMoveResource",
|
||||
env -> getService(env).moveResource(getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("oldResourcePath"),
|
||||
env.getArgument("newResourcePath")))
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgumentVal(env, "oldResourcePath"),
|
||||
getArgumentVal(env, "newResourcePath")))
|
||||
.dataFetcher("rmDeleteResource",
|
||||
env -> getService(env).deleteResource(getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("resourcePath")))
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgumentVal(env, "resourcePath")))
|
||||
.dataFetcher("rmWriteResourceStringContent",
|
||||
env -> getService(env).writeResourceStringContent(getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("resourcePath"),
|
||||
env.getArgument("data"),
|
||||
env.getArgument("forceOverwrite")))
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgumentVal(env, "resourcePath"),
|
||||
getArgumentVal(env, "data"),
|
||||
getArgumentVal(env, "forceOverwrite")))
|
||||
.dataFetcher("rmCreateProject", env -> getService(env).createProject(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectName"),
|
||||
env.getArgument("description")
|
||||
getArgumentVal(env, "projectName"),
|
||||
getArgument(env, "description")
|
||||
))
|
||||
.dataFetcher(
|
||||
"rmUpdateProject", env -> getService(env).updateProject(
|
||||
getWebSession(env),
|
||||
getProjectReference(env),
|
||||
env.getArgument("projectName"),
|
||||
env.getArgument("description")
|
||||
getArgument(env, "projectName"),
|
||||
getArgument(env, "description")
|
||||
)
|
||||
)
|
||||
.dataFetcher("rmDeleteProject", env -> getService(env).deleteProject(
|
||||
@@ -112,45 +111,45 @@ public class WebServiceBindingRM extends WebServiceBindingBase<DBWServiceRM> {
|
||||
))
|
||||
.dataFetcher("rmSetProjectPermissions", env -> getService(env).setProjectPermissions(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
new RMSubjectProjectPermissions(env.getArgument("permissions"))
|
||||
getArgumentVal(env, "projectId"),
|
||||
new RMSubjectProjectPermissions(getArgumentVal(env, "permissions"))
|
||||
))
|
||||
.dataFetcher("rmSetResourceProperty", env -> getService(env).setResourceProperty(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("resourcePath"),
|
||||
env.getArgument("name"),
|
||||
env.getArgument("value")
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgumentVal(env, "resourcePath"),
|
||||
getArgumentVal(env, "name"),
|
||||
getArgument(env, "value")
|
||||
))
|
||||
.dataFetcher("rmSetSubjectProjectPermissions", env -> getService(env).setSubjectProjectPermissions(
|
||||
getWebSession(env),
|
||||
env.getArgument("subjectId"),
|
||||
new RMProjectPermissions(env.getArgument("permissions"))
|
||||
getArgumentVal(env, "subjectId"),
|
||||
new RMProjectPermissions(getArgumentVal(env, "permissions"))
|
||||
))
|
||||
.dataFetcher("rmAddProjectsPermissions", env -> getService(env).addProjectsPermissions(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectIds"),
|
||||
env.getArgument("subjectIds"),
|
||||
env.getArgument("permissions")
|
||||
getArgumentVal(env, "projectIds"),
|
||||
getArgumentVal(env, "subjectIds"),
|
||||
getArgumentVal(env, "permissions")
|
||||
))
|
||||
.dataFetcher("rmDeleteProjectsPermissions", env -> getService(env).deleteProjectsPermissions(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectIds"),
|
||||
env.getArgument("subjectIds"),
|
||||
env.getArgument("permissions")
|
||||
getArgumentVal(env, "projectIds"),
|
||||
getArgumentVal(env, "subjectIds"),
|
||||
getArgumentVal(env, "permissions")
|
||||
))
|
||||
.dataFetcher(
|
||||
"rmAddUserProjectSettings", env -> getService(env).addProjectSettings(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("settings")
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgumentVal(env, "settings")
|
||||
)
|
||||
)
|
||||
.dataFetcher(
|
||||
"rmDeleteUserProjectSettings", env -> getService(env).deleteProjectSettings(
|
||||
getWebSession(env),
|
||||
env.getArgument("projectId"),
|
||||
env.getArgument("settingIds")
|
||||
getArgumentVal(env, "projectId"),
|
||||
getArgument(env, "settingIds")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -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.88.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-21
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: org.jkiss.dbeaver.model;visibility:=reexport,
|
||||
|
||||
@@ -256,3 +256,46 @@ CREATE TABLE {table_prefix}CB_OBJECT_SETTINGS
|
||||
FOREIGN KEY (SUBJECT_ID) REFERENCES {table_prefix}CB_AUTH_SUBJECT(SUBJECT_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
|
||||
-- Secrets
|
||||
CREATE TABLE {table_prefix}CB_ACCESS_TOKEN
|
||||
(
|
||||
TOKEN_ID VARCHAR(128) NOT NULL,
|
||||
USER_ID VARCHAR(128) NOT NULL,
|
||||
TOKEN_NAME VARCHAR(128) NOT NULL,
|
||||
CREATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
EXPIRATION_TIME TIMESTAMP NULL,
|
||||
|
||||
PRIMARY KEY (USER_ID, TOKEN_ID),
|
||||
UNIQUE (USER_ID, TOKEN_NAME),
|
||||
FOREIGN KEY (USER_ID) REFERENCES {table_prefix}CB_USER(USER_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Tasks
|
||||
CREATE TABLE {table_prefix}CB_TASKS
|
||||
(
|
||||
TASK_ID VARCHAR(128) NOT NULL,
|
||||
CREATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
TIMEOUT INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (TASK_ID)
|
||||
);
|
||||
|
||||
CREATE TABLE {table_prefix}CB_SUBJECT_SECRETS
|
||||
(
|
||||
SUBJECT_ID VARCHAR(128) NOT NULL,
|
||||
SECRET_ID VARCHAR(255) NOT NULL,
|
||||
|
||||
PROJECT_ID VARCHAR(128),
|
||||
OBJECT_TYPE VARCHAR(32),
|
||||
OBJECT_ID VARCHAR(128),
|
||||
|
||||
SECRET_VALUE TEXT NOT NULL,
|
||||
|
||||
ENCODING_TYPE VARCHAR(32) DEFAULT 'PLAINTEXT' NOT NULL,
|
||||
CREATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
UPDATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
|
||||
PRIMARY KEY (SUBJECT_ID, SECRET_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.88-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
+15
-4
@@ -314,9 +314,13 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
}
|
||||
for (String possibleUserId : List.of(userId, userId.toLowerCase())) {
|
||||
if (isSubjectExists(possibleUserId)) {
|
||||
log.info("User already exist : " + possibleUserId);
|
||||
setUserAuthRole(connection, possibleUserId, authRole);
|
||||
enableUser(connection, possibleUserId, true, null, null);
|
||||
if (getSubjectType(possibleUserId) == SMSubjectType.team) {
|
||||
log.error("Cannot import user '%s': a team with this name already exists.".formatted(possibleUserId));
|
||||
} else {
|
||||
log.info("User already exist : " + possibleUserId);
|
||||
setUserAuthRole(connection, possibleUserId, authRole);
|
||||
enableUser(connection, possibleUserId, true, null, null);
|
||||
}
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
@@ -812,6 +816,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> getCurrentUserParameters() throws DBCException {
|
||||
String userId = getUserIdOrThrow();
|
||||
@@ -1212,6 +1217,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
return getUserCredentials(getUserIdOrThrow(), authProviderId);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String[] getCurrentUserLinkedProviders() throws DBException {
|
||||
return getUserLinkedProviders(getUserIdOrThrow());
|
||||
@@ -1631,7 +1637,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
// Sessions
|
||||
|
||||
@Override
|
||||
public boolean isSessionPersisted(String id) throws DBException {
|
||||
public boolean isSessionPersisted(@NotNull String id) throws DBException {
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT 1 FROM {table_prefix}CB_SESSION WHERE SESSION_ID=?")) {
|
||||
dbStat.setString(1, id);
|
||||
@@ -1647,6 +1653,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String createSmSession(
|
||||
@NotNull String appSessionId,
|
||||
@Nullable String userId,
|
||||
@@ -1678,6 +1685,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SMAuthInfo authenticateAnonymousUser(@NotNull String appSessionId, @NotNull Map<String, Object> sessionParameters, @NotNull SMSessionType sessionType) throws DBException {
|
||||
if (!application.isAnonymousAccessEnabled()) {
|
||||
@@ -1709,6 +1717,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
return getSubjectPermissions(anonymousUserTeam);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SMAuthInfo authenticate(
|
||||
@NotNull String appSessionId,
|
||||
@@ -2057,6 +2066,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SMAuthInfo getAuthStatus(@NotNull String authId) throws DBException {
|
||||
var smAuthInfo = getAuthStatus(authId, false);
|
||||
@@ -2903,6 +2913,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
|
||||
return new SMAuthPermissions(userId, sessionId, permissions);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SMAuthProviderDescriptor[] getAvailableAuthProviders() throws DBException {
|
||||
ServletAuthConfiguration appConfiguration = application.getAuthConfiguration();
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public class CBDatabase extends InternalDB<WebDatabaseConfig> {
|
||||
|
||||
private static final SQLSchemaConfig SCHEMA_CREATE_CONFIG = new SQLSchemaConfig(
|
||||
SCHEMA_ID,
|
||||
"db/cb_schema_create.sql",
|
||||
"db/cb_schema_create",
|
||||
"db/cb_schema_update_",
|
||||
CURRENT_SCHEMA_VERSION,
|
||||
0,
|
||||
|
||||
@@ -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.48.qualifier
|
||||
Bundle-Release-Date: 20251103
|
||||
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.48-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -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.156.qualifier"
|
||||
provider-name="DBeaver Corp">
|
||||
|
||||
<plugin id="io.cloudbeaver.resources.drivers.base" download-size="0" install-size="0" version="0.0.0"/>
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.ce.drivers.feature</artifactId>
|
||||
<version>1.0.154-SNAPSHOT</version>
|
||||
<version>1.0.156-SNAPSHOT</version>
|
||||
<packaging>eclipse-feature</packaging>
|
||||
</project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<feature
|
||||
id="io.cloudbeaver.product.ce.feature"
|
||||
label="%featureName"
|
||||
version="25.2.2.qualifier"
|
||||
version="25.2.4.qualifier"
|
||||
provider-name="%providerName"
|
||||
plugin="io.cloudbeaver.product.ce">
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.product.ce.feature</artifactId>
|
||||
<version>25.2.2-SNAPSHOT</version>
|
||||
<version>25.2.4-SNAPSHOT</version>
|
||||
<packaging>eclipse-feature</packaging>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<feature
|
||||
id="io.cloudbeaver.server.feature"
|
||||
label="%featureName"
|
||||
version="25.2.2.qualifier"
|
||||
version="25.2.4.qualifier"
|
||||
provider-name="%providerName"
|
||||
plugin="io.cloudbeaver.server">
|
||||
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.server.feature</artifactId>
|
||||
<version>25.2.2-SNAPSHOT</version>
|
||||
<version>25.2.4-SNAPSHOT</version>
|
||||
<packaging>eclipse-feature</packaging>
|
||||
</project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<feature
|
||||
id="io.cloudbeaver.ws.feature"
|
||||
label="%featureName"
|
||||
version="1.0.84.qualifier"
|
||||
version="1.0.86.qualifier"
|
||||
provider-name="%providerName"
|
||||
plugin="io.cloudbeaver.model">
|
||||
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.ws.feature</artifactId>
|
||||
<version>1.0.84-SNAPSHOT</version>
|
||||
<version>1.0.86-SNAPSHOT</version>
|
||||
<packaging>eclipse-feature</packaging>
|
||||
</project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?pde version="3.5"?>
|
||||
|
||||
<product name="CloudBeaver ce Server" uid="io.cloudbeaver.product" id="io.cloudbeaver.product.ce.product"
|
||||
application="io.cloudbeaver.product.ce.application" version="25.2.2.qualifier" useFeatures="true"
|
||||
application="io.cloudbeaver.product.ce.application" version="25.2.4.qualifier" useFeatures="true"
|
||||
includeLaunchers="false">
|
||||
|
||||
<configIni use="default">
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
<version>25.2.2-SNAPSHOT</version>
|
||||
<version>25.2.4-SNAPSHOT</version>
|
||||
<artifactId>web-server</artifactId>
|
||||
<packaging>eclipse-repository</packaging>
|
||||
<name>Cloudbeaver Server Product</name>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
ComboboxPopover as AriaComboboxPopover,
|
||||
ComboboxItem as AriaComboboxItem,
|
||||
ComboboxDisclosure,
|
||||
ComboboxCancel,
|
||||
ComboboxValue,
|
||||
type ComboboxValueProps,
|
||||
type ComboboxProviderProps,
|
||||
@@ -29,7 +30,7 @@ export interface ComboboxProps extends Omit<AriaComboboxProps, 'size'> {
|
||||
size?: 'small' | 'medium' | 'large' | 'xlarge';
|
||||
}
|
||||
|
||||
export function ComboboxInput({ size, ...props }: ComboboxProps) {
|
||||
export function ComboboxInput({ size, ...props }: ComboboxProps): React.JSX.Element {
|
||||
return <Combobox {...props} className={clsx('dbv-kit-combobox', `dbv-kit-combobox--${size ?? 'medium'}`, props.className)} autoSelect />;
|
||||
}
|
||||
|
||||
@@ -40,7 +41,7 @@ export interface ComboboxPopoverProps extends AriaComboboxPopoverProps {
|
||||
/**
|
||||
* ComboboxPopover - Wrapper around AriaKit's popover with default styles
|
||||
*/
|
||||
export function ComboboxPopover({ children, className, ...props }: ComboboxPopoverProps) {
|
||||
export function ComboboxPopover({ children, className, ...props }: ComboboxPopoverProps): React.JSX.Element {
|
||||
return (
|
||||
<AriaComboboxPopover gutter={8} className={clsx('dbv-kit-combobox__popover', className)} portal sameWidth unmountOnHide {...props}>
|
||||
{children}
|
||||
@@ -48,7 +49,7 @@ export function ComboboxPopover({ children, className, ...props }: ComboboxPopov
|
||||
);
|
||||
}
|
||||
|
||||
export function ComboboxItem(props: ComboboxItemProps) {
|
||||
export function ComboboxItem(props: ComboboxItemProps): React.JSX.Element {
|
||||
return <AriaComboboxItem {...props} className={clsx('dbv-kit-combobox__item', props.className)} />;
|
||||
}
|
||||
|
||||
@@ -57,6 +58,7 @@ export {
|
||||
useComboboxStore,
|
||||
useStoreState,
|
||||
ComboboxDisclosure,
|
||||
ComboboxCancel,
|
||||
ComboboxValue,
|
||||
ComboboxProvider,
|
||||
type ComboboxProviderProps,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"@dbeaver/prettier-config": "workspace:^",
|
||||
"@dbeaver/react-tests": "workspace:^",
|
||||
"@wroud/ts-template": "^0",
|
||||
"happy-dom": "^18",
|
||||
"happy-dom": "^20",
|
||||
"prettier": "^3.6.2",
|
||||
"rimraf": "^6",
|
||||
"vitest": "^3"
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@
|
||||
"@types/react-dom": "^19",
|
||||
"concurrently": "^9",
|
||||
"eslint": "^9.30.1",
|
||||
"happy-dom": "^18",
|
||||
"happy-dom": "^20",
|
||||
"mobx": "^6",
|
||||
"mobx-react-lite": "^4",
|
||||
"msw": "^2",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user