dbeaver/pro#5614 api for expert settings props (#3727)

This commit is contained in:
Ainur
2025-09-16 13:51:38 +00:00
committed by GitHub
parent 5a394e648d
commit e6e92f0bb3
31 changed files with 264 additions and 144 deletions
@@ -10,4 +10,10 @@ meta.io.cloudbeaver.model.app.ServletSystemInformationCollector.deploymentType.n
meta.io.cloudbeaver.model.app.ServletSystemInformationCollector.smDbUrl.name=Security manager database URL
meta.io.cloudbeaver.model.app.ServletSystemInformationCollector.smDbDriverName.name=Security manager database driver name
meta.io.cloudbeaver.model.app.ServletSystemInformationCollector.smDbProductName.name=Security manager database product name
meta.io.cloudbeaver.model.app.ServletSystemInformationCollector.smDbProductVersion.name=Security manager database product version
meta.io.cloudbeaver.model.app.ServletSystemInformationCollector.smDbProductVersion.name=Security manager database product version
meta.io.cloudbeaver.model.WebExpertSettingsProperties.readOnly.name = Read-only connection
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommit.name = Auto-commit
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = Keep-alive interval (seconds)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.defaultSchema.name = Default schema
meta.io.cloudbeaver.model.WebExpertSettingsProperties.defaultCatalog.name = Default catalog
@@ -0,0 +1,2 @@
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = Garder actif (en secondes)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.description = Pas de déconnexion automatique
@@ -0,0 +1,5 @@
meta.io.cloudbeaver.model.WebExpertSettingsProperties.readOnly.name = Только для чтения
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommit.name = Авто-коммит
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = Интервал Keep-alive (в секундах)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.defaultSchema.name = Схема по умолчанию
meta.io.cloudbeaver.model.WebExpertSettingsProperties.defaultCatalog.name = Каталог по умолчанию
@@ -0,0 +1,4 @@
meta.io.cloudbeaver.model.WebExpertSettingsProperties.readOnly.name = Kết nối chỉ đọc
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommit.name = Tự động commit
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = Giữ kết nối (tính bằng giây)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.description = Không tự động ngắt kết nối
@@ -0,0 +1,3 @@
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommit.name = 自动提交
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = 保持连接 (秒)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.description = 无自动断开连接
@@ -56,6 +56,7 @@ public class WebConnectionConfig {
private boolean saveCredentials;
private boolean sharedCredentials;
private Map<String, Object> mainPropertyValues;
private Map<String, Object> expertSettingsValues;
private Map<String, Object> providerProperties;
private Map<String, Object> externalParameters;
private List<WebNetworkHandlerConfigInput> networkHandlersConfig;
@@ -72,7 +73,6 @@ public class WebConnectionConfig {
if (!CommonUtils.isEmpty(params)) {
connectionId = JSONUtils.getString(params, "connectionId");
driverId = JSONUtils.getString(params, "driverId");
readOnly = JSONUtils.getBoolean(params, "readOnly");
host = JSONUtils.getString(params, "host");
port = JSONUtils.getString(params, "port");
@@ -80,9 +80,6 @@ public class WebConnectionConfig {
databaseName = JSONUtils.getString(params, "databaseName");
url = JSONUtils.getString(params, "url");
keepAliveInterval = JSONUtils.getInteger(params, "keepAliveInterval", -1);
defaultAutoCommit = JSONUtils.getBoolean(params, "autocommit", true);
name = JSONUtils.getString(params, "name");
description = JSONUtils.getString(params, "description");
folder = JSONUtils.getString(params, "folder");
@@ -99,8 +96,18 @@ public class WebConnectionConfig {
mainPropertyValues = JSONUtils.getObjectOrNull(params, "mainPropertyValues");
providerProperties = JSONUtils.getObjectOrNull(params, "providerProperties");
defaultCatalogName = JSONUtils.getString(params, "defaultCatalogName");
defaultSchemaName = JSONUtils.getString(params, "defaultSchemaName");
expertSettingsValues = JSONUtils.getObjectOrNull(params, "expertSettingsValues");
keepAliveInterval = JSONUtils.getInteger(
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_KEEP_ALIVE_INTERVAL, -1);
readOnly = JSONUtils.getBoolean(
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_READ_ONLY);
defaultAutoCommit = JSONUtils.getBoolean(
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_AUTO_COMMIT, true);
defaultCatalogName = JSONUtils.getString(
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_DEFAULT_CATALOG);
defaultSchemaName = JSONUtils.getString(
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_DEFAULT_SCHEMA);
String configType = JSONUtils.getString(params, "configurationType");
configurationType = configType == null ? null : DBPDriverConfigurationType.valueOf(configType);
@@ -221,6 +228,11 @@ public class WebConnectionConfig {
return mainPropertyValues;
}
@Property
public Map<String, Object> getExpertSettingsValues() {
return expertSettingsValues;
}
@Property
public Map<String, Object> getProviderProperties() {
return providerProperties;
@@ -417,6 +417,17 @@ public class WebConnectionInfo {
return mainProperties;
}
@Property
public Map<String, Object> getExpertSettingsValues() {
Map<String, Object> expertSettings = new LinkedHashMap<>();
expertSettings.put(WebExpertSettingsProperties.PROP_AUTO_COMMIT, isAutocommit());
expertSettings.put(WebExpertSettingsProperties.PROP_KEEP_ALIVE_INTERVAL, getKeepAliveInterval());
expertSettings.put(WebExpertSettingsProperties.PROP_READ_ONLY, isReadOnly());
expertSettings.put(WebExpertSettingsProperties.PROP_DEFAULT_CATALOG, getDefaultCatalogName());
expertSettings.put(WebExpertSettingsProperties.PROP_DEFAULT_SCHEMA, getDefaultSchemaName());
return expertSettings;
}
@Property
public Map<String, String> getProviderProperties() {
return dataSourceContainer.getConnectionConfiguration().getProviderProperties();
@@ -0,0 +1,87 @@
package io.cloudbeaver.model;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.DBPObject;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.connection.DBPDriverConstants;
import org.jkiss.dbeaver.model.meta.IPropertyValueValidator;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.utils.CommonUtils;
/**
* Web expert settings properties. Class for returning filtered expert settings properties in web interface.
*/
public class WebExpertSettingsProperties implements DBPObject {
public static final String PROP_READ_ONLY = "readOnly";
public static final String PROP_AUTO_COMMIT = "autocommit";
public static final String PROP_KEEP_ALIVE_INTERVAL = "keepAliveInterval";
public static final String PROP_DEFAULT_CATALOG = "defaultCatalogName";
public static final String PROP_DEFAULT_SCHEMA = "defaultSchemaName";
private final DBPDriver driver;
public WebExpertSettingsProperties(@NotNull DBPDriver driver) {
this.driver = driver;
}
@Property(order = 1, id = PROP_KEEP_ALIVE_INTERVAL, visibleIf = KeepAliveIntervalFieldValidator.class)
public int getKeepAliveInterval() {
return 0;
}
@Property(order = 2, id = PROP_AUTO_COMMIT, visibleIf = AutoCommitFieldValidator.class)
public boolean isAutoCommit() {
return true;
}
@Property(order = 3, id = PROP_READ_ONLY, visibleIf = ReadOnlyFieldValidator.class)
public boolean isReadOnly() {
return false;
}
@Property(order = 4, id = PROP_DEFAULT_CATALOG, visibleIf = DefaultCatalogFieldVisibleValidator.class)
public String getDefaultCatalog() {
return null;
}
@Property(order = 5, id = PROP_DEFAULT_SCHEMA, visibleIf = DefaultSchemaFieldVisibleValidator.class)
public String getDefaultSchema() {
return null;
}
public static class KeepAliveIntervalFieldValidator implements IPropertyValueValidator<WebExpertSettingsProperties, Object> {
@Override
public boolean isValidValue(WebExpertSettingsProperties object, 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 {
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 {
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 {
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 {
return CommonUtils.toBoolean(object.driver.getDriverParameter(DBPDriverConstants.PARAM_SUPPORTS_SCHEMA_SELECTION), true);
}
}
}
@@ -1,2 +1,2 @@
log.api.graphql.debug = Log GraphQL requests to console
log.api.graphql.debug.description = Enable detailed logging of GraphQL queries in the server log, including all provided variables
log.api.graphql.debug.description = Enable detailed logging of GraphQL queries in the server log, including all provided variables
@@ -1,2 +1,2 @@
log.api.graphql.debug =Логировать GraphQL-запросы в консоль
log.api.graphql.debug.description = Включите подробное логирование запросов GraphQL в журнале сервера, включая все предоставленные переменные
log.api.graphql.debug.description = Включите подробное логирование запросов GraphQL в журнале сервера, включая все предоставленные переменные
@@ -351,6 +351,9 @@ type DriverInfo {
"""
providerProperties: [ObjectPropertyInfo!]!
"Expert driver settings properties. Returns properties (like keep-alive interval) that are not often used and can be hidden in UI"
expertSettingsProperties: [ObjectPropertyInfo!]! @since(version: "25.2.1")
"False for drivers which do not support authentication."
anonymousAccess: Boolean
"Default auth model that is used for this driver (see authModels)"
@@ -486,6 +489,9 @@ type ConnectionInfo {
"Main connection properties. Contains host, port, database, server name fields"
mainPropertyValues: Object @since(version: "24.1.2")
"Expert connection settings. Contains expert settings properties (like keep-alive interval or auto-commit) that are not often used"
expertSettingsValues: Object @since(version: "25.2.1")
"Connection keep-alive interval in seconds"
keepAliveInterval: Int!
"Defines if the connection is in auto-commit mode"
@@ -672,6 +678,9 @@ input ConnectionConfig {
"Host, port, serverName, databaseName are also stored in mainPropertyValues for custom pages"
mainPropertyValues: Object @since(version: "24.1.2")
"Keep-alive, auto-commit, read-only and other expert settings are stored in expertSettingsValues"
expertSettingsValues: Object @since(version: "25.2.1")
"Sets connection URL jdbc:{driver}://{host}[:{port}]/[{database}]"
url: String
@@ -679,13 +688,13 @@ input ConnectionConfig {
properties: Object
"Set keep-alive interval"
keepAliveInterval: Int
keepAliveInterval: Int @deprecated(reason: "25.2.1 use expertPropertyValues instead")
"Sets auto-commit connection state"
autocommit: Boolean
autocommit: Boolean @deprecated(reason: "25.2.1 use expertPropertyValues instead")
"Sets read-only connection state"
readOnly: Boolean
readOnly: Boolean @deprecated(reason: "25.2.1 use expertPropertyValues instead")
# User credentials
@@ -721,9 +730,9 @@ input ConnectionConfig {
"Configuration type (MANUAL, URL)"
configurationType: DriverConfigurationType
"Sets catalog name for the connection"
defaultCatalogName: String @since(version: "25.0.5")
defaultCatalogName: String @since(version: "25.0.5") @deprecated(reason: "25.2.1 use expertPropertyValues instead")
"Sets schema name for the connection"
defaultSchemaName: String @since(version: "25.0.5")
defaultSchemaName: String @since(version: "25.0.5") @deprecated(reason: "25.2.1 use expertPropertyValues instead")
}
####################################################
@@ -257,6 +257,10 @@ public class WebDatabaseDriverInfo {
.toArray(WebPropertyInfo[]::new);
}
public WebPropertyInfo[] getExpertSettingsProperties() {
return WebServiceUtils.getObjectFilteredProperties(webSession, new WebExpertSettingsProperties(driver), null);
}
@Property
public boolean isEnabled() {
return WebServiceUtils.isDriverEnabled(driver);
@@ -87,6 +87,7 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
const required = property.required && !readonly;
const value = getObjectPropertyValue(property);
const defaultValue = getObjectPropertyDefaultValue(property);
const hint = property.hint === property.displayName ? undefined : property.hint;
if (controlType === 'link') {
return (
@@ -178,7 +179,7 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
title={property.description}
disabled={disabled}
readOnly={readonly}
description={property.hint}
description={hint}
className={className}
>
{property.displayName ?? ''}
@@ -253,7 +254,7 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
state={state}
defaultState={defaultState || { [property.id!]: defaultValue }}
autoHide={autoHide}
description={property.hint}
description={hint}
placeholder={passwordSavedMessage}
readOnly={readonly || disabled}
autoComplete={RESERVED_KEYWORDS.includes(autofillToken) ? autofillToken : `${autofillToken} ${property.id}`}
@@ -275,7 +276,7 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
name={property.id!}
value={value}
defaultValue={defaultValue}
description={property.hint}
description={hint}
placeholder={passwordSavedMessage}
readOnly={readonly || disabled}
autoComplete={RESERVED_KEYWORDS.includes(autofillToken) ? autofillToken : `${autofillToken} ${property.id}`}
@@ -0,0 +1,57 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2025 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { CachedMapResource, isResourceAlias, ResourceKeyUtils, type ResourceKey } from '@cloudbeaver/core-resource';
import { GraphQLService } from '@cloudbeaver/core-sdk';
import { injectable } from '@cloudbeaver/core-di';
import { SessionDataResource } from '@cloudbeaver/core-root';
import { DBDriverResource, type DriverPropertyInfo } from './DBDriverResource.js';
@injectable(() => [GraphQLService, DBDriverResource, SessionDataResource])
export class DBDriverExpertSettingsResource extends CachedMapResource<string, DriverPropertyInfo[]> {
constructor(
private readonly graphQLService: GraphQLService,
private readonly dbDriverResource: DBDriverResource,
private readonly sessionDataResource: SessionDataResource,
) {
super();
this.sessionDataResource.outdateResource(this);
this.sync(this.dbDriverResource);
this.dbDriverResource.onItemDelete.addHandler(this.delete.bind(this));
}
protected async loader(originalKey: ResourceKey<string>): Promise<Map<string, DriverPropertyInfo[]>> {
if (isResourceAlias(originalKey)) {
throw new Error('Aliases not supported by this resource.');
}
const values: DriverPropertyInfo[][] = [];
await ResourceKeyUtils.forEachAsync(originalKey, async key => {
const { drivers } = await this.graphQLService.sdk.getDriverExpertProperties({ driverId: key });
if (drivers.length === 0) {
throw new Error('Driver not found');
}
const driver = drivers[0]!;
values.push(driver.expertSettingsProperties);
});
this.set(ResourceKeyUtils.toList(originalKey), values);
return this.data;
}
protected validateKey(key: string): boolean {
return typeof key === 'string';
}
}
@@ -16,6 +16,7 @@ import {
type DatabaseDriverFragment,
DriverConfigurationType,
type DriverListQueryVariables,
type DriverPropertyInfoFragment,
GraphQLService,
} from '@cloudbeaver/core-sdk';
import { isArraysEqual } from '@cloudbeaver/core-utils';
@@ -27,6 +28,8 @@ export const NEW_DRIVER_SYMBOL = Symbol('new-driver');
export type NewDBDriver = DBDriver & { [NEW_DRIVER_SYMBOL]: boolean; timestamp: number };
export type DBDriverResourceIncludes = Omit<DriverListQueryVariables, 'driverId'>;
export type DriverPropertyInfo = DriverPropertyInfoFragment;
@injectable(() => [ServerConfigResource, GraphQLService, WorkspaceConfigEventHandler, AppAuthService])
export class DBDriverResource extends CachedMapResource<string, DBDriver, DBDriverResourceIncludes> {
get enabledDrivers() {
@@ -41,6 +44,7 @@ export class DBDriverResource extends CachedMapResource<string, DBDriver, DBDriv
) {
super();
appAuthService.requireAuthentication(this);
this.sync(
this.serverConfigResource,
() => {},
@@ -63,5 +63,6 @@ export * from './useConnectionInfo.js';
export * from './useDBDriver.js';
export * from './USER_NAME_PROPERTY_ID.js';
export * from './parseConnectionKey.js';
export * from './DBDriverExpertSettingsResource.js';
export { manifest as coreConnectionsManifest } from './manifest.js';
@@ -27,7 +27,6 @@ export default [
['connections_connection_edit_search', 'Suchen'],
['connections_connection_edit_search_hosts', 'Hostnamen'],
['connections_connection_expert_settings', 'Expert settings'],
['connections_connection_read_only', 'Read-only connection'],
['connections_connection_address', 'Adresse'],
['connections_connection_folder', 'Ordner'],
['connections_connection_name', 'Verbindungsname'],
@@ -45,9 +44,6 @@ export default [
['connections_network_handler_ssh_tunnel_auth_type', 'Authentifizierungsmethode'],
['connections_network_handler_ssh_tunnel_advanced_settings', 'Erweiterte Einstellungen'],
['connections_not_found', 'Es wurden keine Datenbankverbindungen gefunden'],
['connections_connection_autocommit', 'Auto commit'],
['connections_connection_default_catalog', 'Default catalog'],
['connections_connection_default_schema', 'Default schema'],
['core_connections_settings_disable', 'Disable'],
['core_connections_settings_disable_description', 'Disable the ability to create new connections'],
@@ -52,12 +52,6 @@ export default [
['connections_connection_create_fail', 'Fail to create connection'],
['connections_connection_save_fail', 'Fail to save connection'],
['connections_connection_expert_settings', 'Expert settings'],
['connections_connection_keep_alive', 'Keep alive (in seconds)'],
['connections_connection_read_only', 'Read-only connection'],
['connections_connection_autocommit', 'Auto commit'],
['connections_connection_default_catalog', 'Default catalog'],
['connections_connection_default_schema', 'Default schema'],
['connections_connection_keep_alive_tooltip', 'No auto disconnect'],
['connections_network_handler_test', 'Test Tunnel'],
['connections_network_handler_test_fail', 'Tunnel test failed'],
['connections_network_handler_test_success', 'Tunnel test success'],
@@ -49,7 +49,6 @@ export default [
['connections_connection_configuration', 'Configuration'],
['connections_connection_host', 'Hôte'],
['connections_connection_port', 'Port'],
['connections_connection_read_only', 'Read-only connection'],
['core_connections_connection_create_success', 'Connection was created'],
['core_connections_connection_update_success', 'Connection was updated'],
['connections_connection_test', 'Tester'],
@@ -58,11 +57,6 @@ export default [
['connections_connection_create_fail', 'Échec de la création de la connexion'],
['connections_connection_save_fail', 'Échec de la sauvegarde de la connexion'],
['connections_connection_expert_settings', 'Expert settings'],
['connections_connection_keep_alive', 'Garder actif (en secondes)'],
['connections_connection_autocommit', 'Auto commit'],
['connections_connection_default_catalog', 'Default catalog'],
['connections_connection_default_schema', 'Default schema'],
['connections_connection_keep_alive_tooltip', 'Pas de déconnexion automatique'],
['connections_network_handler_test', 'Tester le tunnel'],
['connections_network_handler_test_fail', 'Échec du test du tunnel'],
['connections_network_handler_test_success', 'Test du tunnel réussi'],
@@ -50,12 +50,6 @@ export default [
['connections_connection_create_fail', 'Errore di creazione connessione'],
['connections_connection_save_fail', 'Errore di salvataggio connessione'],
['connections_connection_expert_settings', 'Expert settings'],
['connections_connection_keep_alive', 'Keep alive (in seconds)'],
['connections_connection_autocommit', 'Auto commit'],
['connections_connection_default_catalog', 'Default catalog'],
['connections_connection_default_schema', 'Default schema'],
['connections_connection_keep_alive_tooltip', 'No auto disconnect'],
['connections_connection_read_only', 'Read-only connection'],
['connections_network_handler_test', 'Prova il Tunnel'],
['connections_network_handler_test_fail', 'Prova del Tunnel fallita'],
['connections_network_handler_test_success', 'Prova del Tunnel terminata con successo'],
@@ -61,12 +61,6 @@ export default [
['connections_connection_create_fail', 'Не удалось создать подключение'],
['connections_connection_save_fail', 'Не удалось сохранить подключение'],
['connections_connection_expert_settings', 'Продвинутые настройки'],
['connections_connection_keep_alive', 'Поддерживать соединение (в секундах)'],
['connections_connection_autocommit', 'Авто коммит'],
['connections_connection_default_catalog', 'Каталог по умолчанию'],
['connections_connection_default_schema', 'Схема по умолчанию'],
['connections_connection_keep_alive_tooltip', 'Не отключать соединение'],
['connections_connection_read_only', 'Разрешить только чтение'],
['connections_network_handler_test', 'Проверить подключение'],
['connections_network_handler_test_fail', 'Не удалось установить соединение'],
['connections_network_handler_test_success', 'Соединение установлено'],
@@ -66,10 +66,6 @@ export default [
['connections_connection_create_fail', 'Tạo kết nối thất bại'],
['connections_connection_save_fail', 'Lưu kết nối thất bại'],
['connections_connection_expert_settings', 'Cài đặt nâng cao'],
['connections_connection_keep_alive', 'Giữ kết nối (tính bằng giây)'],
['connections_connection_read_only', 'Kết nối chỉ đọc'],
['connections_connection_autocommit', 'Tự động commit'],
['connections_connection_keep_alive_tooltip', 'Không tự động ngắt kết nối'],
['connections_network_handler_test', 'Kiểm tra Tunnel'],
['connections_network_handler_test_fail', 'Kiểm tra tunnel thất bại'],
['connections_network_handler_test_success', 'Kiểm tra tunnel thành công'],
@@ -44,12 +44,6 @@ export default [
['connections_connection_create_fail', '无法创建连接'],
['connections_connection_save_fail', '无法保存连接'],
['connections_connection_expert_settings', '专业设置'],
['connections_connection_keep_alive', '保持连接 (秒)'],
['connections_connection_autocommit', '自动提交'],
['connections_connection_default_catalog', 'Default catalog'],
['connections_connection_default_schema', 'Default schema'],
['connections_connection_keep_alive_tooltip', '无自动断开连接'],
['connections_connection_read_only', 'Read-only connection'],
['connections_network_handler_test', '测试隧道'],
['connections_network_handler_test_fail', '隧道测试失败'],
['connections_network_handler_test_success', '隧道测试成功'],
@@ -32,6 +32,7 @@ import { ConnectionExecutionContextService } from './ConnectionExecutionContext/
import { ConnectionFolderEventHandler } from './ConnectionFolderEventHandler.js';
import { ConnectionExecutionContextResource } from './ConnectionExecutionContext/ConnectionExecutionContextResource.js';
import { ConnectionDialectResource } from './ConnectionDialectResource.js';
import { DBDriverExpertSettingsResource } from './DBDriverExpertSettingsResource.js';
ModuleRegistry.add({
name: '@cloudbeaver/core-connections',
@@ -57,10 +58,12 @@ ModuleRegistry.add({
.addSingleton(Dependency, proxy(ConnectionInfoCustomOptionsResource))
.addSingleton(Dependency, proxy(ConnectionFolderResource))
.addSingleton(Dependency, proxy(ConnectionExecutionContextResource))
.addSingleton(Dependency, proxy(DBDriverExpertSettingsResource))
.addSingleton(ConnectionDialectResource)
.addSingleton(NetworkHandlerResource)
.addSingleton(NavNodeExtensionsService)
.addSingleton(DBDriverResource)
.addSingleton(DBDriverExpertSettingsResource)
.addSingleton(DatabaseAuthModelsResource)
.addSingleton(ContainerResource)
.addSingleton(ConnectionToolsResource)
@@ -16,7 +16,7 @@ export function getObjectPropertyValueType(property: ObjectPropertyInfo): Object
return 'password';
}
if (dataType === 'integer') {
if (dataType === 'integer' || dataType === 'int') {
return 'number';
}
@@ -0,0 +1,7 @@
query getDriverExpertProperties($driverId: ID) {
drivers: driverList(id: $driverId) {
expertSettingsProperties {
...DriverPropertyInfo
}
}
}
@@ -12,10 +12,6 @@ fragment DatabaseConnectionCustomOptions on ConnectionInfo {
description
folder
driverId
keepAliveInterval
autocommit
defaultCatalogName
defaultSchemaName
readOnly
mainPropertyValues
expertSettingsValues
}
@@ -7,17 +7,9 @@
*/
import { observer } from 'mobx-react-lite';
import { Container, Expandable, FieldCheckbox, Flex, Group, InputField, useTranslate } from '@cloudbeaver/core-blocks';
import { Container, Expandable, Group, ObjectPropertyInfoForm, useResource, useTranslate } from '@cloudbeaver/core-blocks';
import type { ConnectionConfig } from '@cloudbeaver/core-sdk';
const MAX_KEEP_ALIVE_INTERVAL = 32767;
const DEFAULT_CONFIG: ConnectionConfig = {
keepAliveInterval: 0,
autocommit: true,
defaultCatalogName: '',
defaultSchemaName: '',
readOnly: false,
};
import { DBDriverExpertSettingsResource } from '@cloudbeaver/core-connections';
interface Props {
config: ConnectionConfig;
@@ -27,70 +19,17 @@ interface Props {
export const AdvancedPropertiesForm = observer<Props>(function AdvancedPropertiesForm({ config, disabled, readonly }) {
const translate = useTranslate();
const properties = useResource(AdvancedPropertiesForm, DBDriverExpertSettingsResource, config.driverId ?? null);
if (!properties.data?.length) {
return null;
}
return (
<Group form gap>
<Expandable label={translate('connections_connection_expert_settings')}>
<Container wrap gap>
<InputField
type="number"
minLength={1}
min={0}
max={MAX_KEEP_ALIVE_INTERVAL}
name="keepAliveInterval"
readOnly={readonly || disabled}
title={translate('connections_connection_keep_alive_tooltip')}
state={config}
defaultState={DEFAULT_CONFIG}
>
{translate('connections_connection_keep_alive')}
</InputField>
<FieldCheckbox
name="autocommit"
state={config}
defaultChecked={DEFAULT_CONFIG.autocommit}
title={translate('connections_connection_autocommit')}
disabled={disabled}
readOnly={readonly}
>
{translate('connections_connection_autocommit')}
</FieldCheckbox>
<FieldCheckbox
name="readOnly"
state={config}
defaultChecked={DEFAULT_CONFIG.readOnly}
title={translate('connections_connection_read_only')}
disabled={disabled}
readOnly={readonly}
>
{translate('connections_connection_read_only')}
</FieldCheckbox>
<Flex gap="xs">
<InputField
name="defaultCatalogName"
readOnly={readonly || disabled}
title={translate('connections_connection_default_catalog')}
state={config}
defaultState={DEFAULT_CONFIG}
fill
>
{translate('connections_connection_default_catalog')}
</InputField>
<InputField
name="defaultSchemaName"
readOnly={readonly || disabled}
title={translate('connections_connection_default_schema')}
state={config}
defaultState={DEFAULT_CONFIG}
fill
>
{translate('connections_connection_default_schema')}
</InputField>
</Flex>
<ObjectPropertyInfoForm state={config.expertSettingsValues} properties={properties.data} disabled={disabled} readOnly={readonly} />
</Container>
</Expandable>
</Group>
@@ -16,6 +16,7 @@ import {
ConnectionInfoResource,
createConnectionParam,
DatabaseAuthModelsResource,
DBDriverExpertSettingsResource,
DBDriverResource,
type ConnectionInfoAuthProperties,
type DBDriver,
@@ -45,9 +46,9 @@ const defaultStateGetter = (connectionId?: string, credentials?: Record<string,
({
connectionId,
configurationType: DriverConfigurationType.Manual,
keepAliveInterval: 0,
credentials: credentials ?? {},
mainPropertyValues: {},
expertSettingsValues: {},
networkHandlersConfig: [],
providerProperties: {},
}) as IConnectionFormOptionsState;
@@ -69,6 +70,7 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
private readonly localizationService: LocalizationService,
private readonly commonDialogService: CommonDialogService,
private readonly notificationService: NotificationService,
private readonly dbDriverExpertSettingsResource: DBDriverExpertSettingsResource,
) {
super(formState, defaultStateGetter(formState.state.connectionId));
@@ -218,12 +220,6 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
config.saveCredentials = authPropertiesInfo.credentialsSaved;
config.sharedCredentials = authPropertiesInfo.sharedCredentials;
config.keepAliveInterval = customOptionsInfo.keepAliveInterval;
config.autocommit = customOptionsInfo.autocommit;
config.defaultCatalogName = customOptionsInfo.defaultCatalogName;
config.defaultSchemaName = customOptionsInfo.defaultSchemaName;
config.readOnly = customOptionsInfo.readOnly;
if (authPropertiesInfo.authProperties) {
for (const property of authPropertiesInfo.authProperties) {
if (!property.features.includes('password')) {
@@ -240,6 +236,10 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
config.mainPropertyValues = { ...toJS(customOptionsInfo.mainPropertyValues) };
}
if (customOptionsInfo.expertSettingsValues) {
config.expertSettingsValues = toJS(customOptionsInfo.expertSettingsValues);
}
this.formState.state.availableDrivers = [customOptionsInfo.driverId];
this.setInitialState(config);
@@ -311,6 +311,8 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
if (driver?.id !== prevDriver?.id) {
this.state.credentials = {};
this.state.providerProperties = {};
this.state.expertSettingsValues = {};
await this.setAuthModelId(driver?.defaultAuthModel);
await this.onDriverIdChange.execute(this.state.driverId);
}
@@ -335,11 +337,13 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
return;
}
const driver = await this.dbDriverResource.load(this.state.driverId, ['includeProviderProperties', 'includeMainProperties']);
const [driver, expertSettings] = await Promise.all([
this.dbDriverResource.load(this.state.driverId, ['includeProviderProperties', 'includeMainProperties']),
this.dbDriverExpertSettingsResource.load(this.state.driverId),
]);
this.formState.state.requiredNetworkHandlersIds = observable([]);
this.state.networkHandlersConfig = observable([]);
this.state.keepAliveInterval = this.state.keepAliveInterval ? Number(this.state.keepAliveInterval) : undefined;
this.state.name = this.state.name?.trim();
this.state.description = this.state.description?.trim();
@@ -400,6 +404,10 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
if (driver.useCustomPage && driver.mainProperties.length > 0) {
this.state.mainPropertyValues = prepareDynamicProperties(driver.mainProperties, this.state.mainPropertyValues!, this.state.configurationType);
}
if (expertSettings.length > 0) {
this.state.expertSettingsValues = prepareDynamicProperties(expertSettings, this.state.expertSettingsValues!);
}
}
private async getConnectionAuthModelProperties(authModelId: string, connectionInfo?: ConnectionInfoAuthProperties): Promise<ObjectPropertyInfo[]> {
@@ -13,7 +13,6 @@ export const CONNECTION_PROPERTIES_SCHEMA = schema.record(schema.string(), schem
export const CONNECTION_CONFIG_SCHEMA = schema.object({
authModelId: schema.string().optional(),
autocommit: schema.boolean().optional(),
configurationType: schema.enum([DriverConfigurationType.Manual, DriverConfigurationType.Url]).optional(),
connectionId: schema.string().optional(),
credentials: schema.record(schema.string(), schema.any()).optional(),
@@ -23,16 +22,13 @@ export const CONNECTION_CONFIG_SCHEMA = schema.object({
driverId: schema.string().optional(),
folder: schema.string().optional(),
host: schema.string().optional(),
keepAliveInterval: schema.number().optional(),
defaultCatalogName: schema.string().optional(),
defaultSchemaName: schema.string().optional(),
mainPropertyValues: schema.record(schema.string(), schema.any()).optional(),
expertSettingsValues: schema.record(schema.string(), schema.any()).optional(),
name: schema.string().optional(),
networkHandlersConfig: schema.array(CONNECTION_NETWORK_HANDLER_SCHEMA).optional(),
port: schema.string().optional(),
properties: CONNECTION_PROPERTIES_SCHEMA.optional(),
providerProperties: schema.record(schema.string(), schema.any()).optional(),
readOnly: schema.boolean().optional(),
saveCredentials: schema.boolean().optional(),
selectedSecretId: schema.string().optional(),
serverName: schema.string().optional(),
@@ -14,6 +14,7 @@ import {
ConnectionInfoProviderPropertiesResource,
ConnectionInfoResource,
DatabaseAuthModelsResource,
DBDriverExpertSettingsResource,
DBDriverResource,
} from '@cloudbeaver/core-connections';
import { ProjectInfoResource } from '@cloudbeaver/core-projects';
@@ -37,6 +38,7 @@ export function getConnectionFormOptionsPart(formState: IFormState<IConnectionFo
const connectionInfoAuthPropertiesResource = di.getService(ConnectionInfoAuthPropertiesResource);
const connectionInfoCustomOptionsResource = di.getService(ConnectionInfoCustomOptionsResource);
const connectionInfoProviderPropertiesResource = di.getService(ConnectionInfoProviderPropertiesResource);
const dbDriverExpertSettingsResource = di.getService(DBDriverExpertSettingsResource);
return new ConnectionFormOptionsPart(
formState,
@@ -50,6 +52,7 @@ export function getConnectionFormOptionsPart(formState: IFormState<IConnectionFo
localizationService,
commonDialogService,
notificationService,
dbDriverExpertSettingsResource,
);
});
}