From 969fcd90884e39fa17caa7bc9e5ca6de48c654b2 Mon Sep 17 00:00:00 2001 From: Serge Rider Date: Mon, 18 Oct 2021 17:14:48 +0300 Subject: [PATCH] CB-1235 Web features API --- .../schema/service.core.graphqls | 1 + .../src/io/cloudbeaver/DBWFeatureSet.java | 39 +++++++++++ .../registry/WebFeatureDescriptor.java | 69 +++++++++++++++++++ .../registry/WebFeatureRegistry.java | 63 +++++++++++++++++ .../io/cloudbeaver/server/CBAppConfig.java | 16 +++++ .../io/cloudbeaver/server/CBApplication.java | 3 + .../schema/service.admin.graphqls | 14 ++++ .../service/admin/AdminServerConfig.java | 12 ++++ .../service/admin/DBWServiceAdmin.java | 6 ++ .../service/admin/WebServiceBindingAdmin.java | 3 + .../service/admin/impl/WebServiceAdmin.java | 16 +++-- 11 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/DBWFeatureSet.java create mode 100644 server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/registry/WebFeatureDescriptor.java create mode 100644 server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/registry/WebFeatureRegistry.java diff --git a/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls b/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls index 40367e96cb..6fed3a11e1 100644 --- a/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls +++ b/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls @@ -129,6 +129,7 @@ type ServerConfig { configurationMode: Boolean developmentMode: Boolean + enabledFeatures: [ID!]! enabledAuthProviders: [ID!]! supportedLanguages: [ ServerLanguage! ]! services: [ WebServiceConfig ] diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/DBWFeatureSet.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/DBWFeatureSet.java new file mode 100644 index 0000000000..aeadd70455 --- /dev/null +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/DBWFeatureSet.java @@ -0,0 +1,39 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2021 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.cloudbeaver; + +import org.jkiss.code.NotNull; +import org.jkiss.dbeaver.model.DBPImage; + +/** + * Web feature + */ +public interface DBWFeatureSet { + + @NotNull + String getId(); + + @NotNull + String getLabel(); + + String getDescription(); + + DBPImage getIcon(); + + boolean isEnabled(); + +} diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/registry/WebFeatureDescriptor.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/registry/WebFeatureDescriptor.java new file mode 100644 index 0000000000..5b695f9c51 --- /dev/null +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/registry/WebFeatureDescriptor.java @@ -0,0 +1,69 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2021 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.registry; + +import io.cloudbeaver.DBWFeatureSet; +import io.cloudbeaver.server.CBApplication; +import org.eclipse.core.runtime.IConfigurationElement; +import org.jkiss.dbeaver.model.DBPImage; +import org.jkiss.dbeaver.model.impl.AbstractContextDescriptor; + +/** + * WebFeatureDescriptor + */ +public class WebFeatureDescriptor extends AbstractContextDescriptor implements DBWFeatureSet { + + public static final String EXTENSION_ID = "io.cloudbeaver.feature"; //$NON-NLS-1$ + + private final String id; + private final String label; + private final String description; + private final DBPImage icon; + + public WebFeatureDescriptor(IConfigurationElement config) + { + super(config); + this.id = config.getAttribute("id"); + this.label = config.getAttribute("label"); + this.description = config.getAttribute("description"); + this.icon = iconToImage(config.getAttribute("icon")); + } + + public String getId() { + return id; + } + + public String getLabel() { + return label; + } + + public String getDescription() { + return description; + } + + @Override + public DBPImage getIcon() { + return icon; + } + + @Override + public boolean isEnabled() { + return CBApplication.getInstance().getAppConfiguration().isFeatureEnabled(this.id); + } + +} diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/registry/WebFeatureRegistry.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/registry/WebFeatureRegistry.java new file mode 100644 index 0000000000..d25a4d9aa4 --- /dev/null +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/registry/WebFeatureRegistry.java @@ -0,0 +1,63 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2021 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.registry; + +import io.cloudbeaver.DBWFeatureSet; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; +import org.jkiss.dbeaver.Log; + +import java.util.ArrayList; +import java.util.List; + +public class WebFeatureRegistry { + + private static final Log log = Log.getLog(WebFeatureRegistry.class); + + private static final String TAG_FEATURE = "feature"; //$NON-NLS-1$ + + private static WebFeatureRegistry instance = null; + + public synchronized static WebFeatureRegistry getInstance() { + if (instance == null) { + instance = new WebFeatureRegistry(); + instance.loadExtensions(Platform.getExtensionRegistry()); + } + return instance; + } + + private final List webFeatures = new ArrayList<>(); + + private WebFeatureRegistry() { + } + + private void loadExtensions(IExtensionRegistry registry) { + IConfigurationElement[] extConfigs = registry.getConfigurationElementsFor(WebFeatureDescriptor.EXTENSION_ID); + for (IConfigurationElement ext : extConfigs) { + if (TAG_FEATURE.equals(ext.getName())) { + this.webFeatures.add( + new WebFeatureDescriptor(ext)); + } + } + } + + public List getWebFeatures() { + return webFeatures; + } + +} diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java index ff5d50cd34..49311b8160 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java @@ -24,6 +24,7 @@ import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings; import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings; +import org.jkiss.utils.ArrayUtils; import java.util.Collections; import java.util.LinkedHashMap; @@ -46,6 +47,7 @@ public class CBAppConfig { private String[] enabledDrivers; private String[] disabledDrivers; private String defaultAuthProvider; + private String[] enabledFeatures; private String[] enabledAuthProviders; private DataSourceNavigatorSettings defaultNavigatorSettings; private final Map plugins; @@ -63,6 +65,7 @@ public class CBAppConfig { this.enabledDrivers = new String[0]; this.disabledDrivers = new String[0]; this.defaultAuthProvider = LocalAuthProvider.PROVIDER_ID; + this.enabledFeatures = null; this.enabledAuthProviders = null; this.defaultNavigatorSettings = DEFAULT_VIEW_SETTINGS; this.plugins = new LinkedHashMap<>(); @@ -81,6 +84,7 @@ public class CBAppConfig { this.enabledDrivers = src.enabledDrivers; this.disabledDrivers = src.disabledDrivers; this.defaultAuthProvider = src.defaultAuthProvider; + this.enabledFeatures = src.enabledFeatures; this.enabledAuthProviders = src.enabledAuthProviders; this.defaultNavigatorSettings = src.defaultNavigatorSettings; this.plugins = new LinkedHashMap<>(src.plugins); @@ -143,6 +147,18 @@ public class CBAppConfig { return disabledDrivers; } + public boolean isFeatureEnabled(String id) { + return ArrayUtils.contains(enabledFeatures, id); + } + + public String[] getEnabledFeatures() { + return enabledAuthProviders; + } + + public void setEnabledFeatures(String[] enabledFeatures) { + this.enabledFeatures = enabledFeatures; + } + public String getDefaultAuthProvider() { return defaultAuthProvider; } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java index e92596603b..06839e7148 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java @@ -718,6 +718,9 @@ public class CBApplication extends BaseApplicationImpl { json.endObject(); } + if (appConfig.getEnabledFeatures() != null) { + JSONUtils.serializeStringList(json, "enabledFeatures", Arrays.asList(appConfig.getEnabledFeatures()), true); + } if (appConfig.getEnabledAuthProviders() != null) { JSONUtils.serializeStringList(json, "enabledAuthProviders", Arrays.asList(appConfig.getEnabledAuthProviders()), true); } diff --git a/server/bundles/io.cloudbeaver.service.admin/schema/service.admin.graphqls b/server/bundles/io.cloudbeaver.service.admin/schema/service.admin.graphqls index 2984e13a9c..6a2afebf8a 100644 --- a/server/bundles/io.cloudbeaver.service.admin/schema/service.admin.graphqls +++ b/server/bundles/io.cloudbeaver.service.admin/schema/service.admin.graphqls @@ -67,6 +67,15 @@ type AdminAuthProviderConfiguration { metadataLink: String } +type WebFeatureSet { + id: String! + label: String! + description: String + icon: String + + enabled: Boolean! +} + input ServerConfigInput { serverName: String serverURL: String @@ -80,6 +89,7 @@ input ServerConfigInput { publicCredentialsSaveEnabled: Boolean adminCredentialsSaveEnabled: Boolean + enabledFeatures: [ID!] enabledAuthProviders: [ID!] sessionExpireTime: Int @@ -127,6 +137,10 @@ extend type Query { getSubjectConnectionAccess(subjectId: ID): [AdminConnectionGrantInfo!]! setSubjectConnectionAccess(subjectId: ID!, connections: [ID!]!): Boolean + #### Feature sets + + listFeatureSets: [WebFeatureSet!]! + #### Auth providers and configurations listAuthProviderConfigurationParameters(providerId: ID!): [ObjectPropertyInfo!]! diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminServerConfig.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminServerConfig.java index b9f23beee5..9e8a947fc7 100644 --- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminServerConfig.java +++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminServerConfig.java @@ -39,6 +39,7 @@ public class AdminServerConfig { private final boolean customConnectionsEnabled; private final boolean publicCredentialsSaveEnabled; private final boolean adminCredentialsSaveEnabled; + private final List enabledFeatures; private final List enabledAuthProviders; private long sessionExpireTime; @@ -54,6 +55,13 @@ public class AdminServerConfig { this.customConnectionsEnabled = JSONUtils.getBoolean(params, "customConnectionsEnabled", appConfig.isSupportsCustomConnections()); this.publicCredentialsSaveEnabled = JSONUtils.getBoolean(params, "publicCredentialsSaveEnabled", appConfig.isPublicCredentialsSaveEnabled()); this.adminCredentialsSaveEnabled = JSONUtils.getBoolean(params, "adminCredentialsSaveEnabled", appConfig.isAdminCredentialsSaveEnabled()); + + if (params.containsKey("enabledFeatures")) { + this.enabledFeatures = JSONUtils.getStringList(params, "enabledFeatures"); + } else { + this.enabledFeatures = Arrays.asList(appConfig.getEnabledFeatures()); + } + if (params.containsKey("enabledAuthProviders")) { this.enabledAuthProviders = JSONUtils.getStringList(params, "enabledAuthProviders"); } else { @@ -119,6 +127,10 @@ public class AdminServerConfig { this.sessionExpireTime = sessionExpireTime; } + public List getEnabledFeatures() { + return enabledFeatures; + } + public List getEnabledAuthProviders() { return enabledAuthProviders; } diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/DBWServiceAdmin.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/DBWServiceAdmin.java index f408c7b950..58aeebb2f5 100644 --- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/DBWServiceAdmin.java +++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/DBWServiceAdmin.java @@ -93,6 +93,12 @@ public interface DBWServiceAdmin extends DBWService { @WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN) boolean deleteConnectionConfiguration(@NotNull WebSession webSession, @NotNull String id) throws DBWebException; + //////////////////////////////////////////////////////////////////// + // Features + + @WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN) + List listFeatureSets(@NotNull WebSession webSession) throws DBWebException; + //////////////////////////////////////////////////////////////////// // Auth providers diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/WebServiceBindingAdmin.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/WebServiceBindingAdmin.java index d2c34541e3..a873c4e7bb 100644 --- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/WebServiceBindingAdmin.java +++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/WebServiceBindingAdmin.java @@ -99,6 +99,9 @@ public class WebServiceBindingAdmin extends WebServiceBindingBase getService(env).setSubjectConnectionAccess(getWebSession(env), env.getArgument("subjectId"), env.getArgument("connections"))) + .dataFetcher("listFeatureSets", + env -> getService(env).listFeatureSets(getWebSession(env))) + .dataFetcher("listAuthProviderConfigurationParameters", env -> getService(env).listAuthProviderConfigurationParameters(getWebSession(env), env.getArgument("providerId"))) .dataFetcher("listAuthProviderConfigurations", diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java index 6d19dc905a..75b7b161e1 100644 --- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java +++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java @@ -17,6 +17,7 @@ package io.cloudbeaver.service.admin.impl; import io.cloudbeaver.DBWConnectionGrant; +import io.cloudbeaver.DBWFeatureSet; import io.cloudbeaver.DBWebException; import io.cloudbeaver.WebServiceUtils; import io.cloudbeaver.auth.provider.AuthProviderConfig; @@ -29,10 +30,7 @@ import io.cloudbeaver.model.session.WebSession; import io.cloudbeaver.model.user.WebAuthProviderConfiguration; import io.cloudbeaver.model.user.WebRole; import io.cloudbeaver.model.user.WebUser; -import io.cloudbeaver.registry.WebAuthProviderDescriptor; -import io.cloudbeaver.registry.WebPermissionDescriptor; -import io.cloudbeaver.registry.WebServiceDescriptor; -import io.cloudbeaver.registry.WebServiceRegistry; +import io.cloudbeaver.registry.*; import io.cloudbeaver.server.CBAppConfig; import io.cloudbeaver.server.CBApplication; import io.cloudbeaver.server.CBConstants; @@ -378,6 +376,14 @@ public class WebServiceAdmin implements DBWServiceAdmin { return true; } + //////////////////////////////////////////////////////////////////// + // Features + + @Override + public List listFeatureSets(@NotNull WebSession webSession) throws DBWebException { + return WebFeatureRegistry.getInstance().getWebFeatures(); + } + //////////////////////////////////////////////////////////////////// // Auth providers @@ -453,6 +459,8 @@ public class WebServiceAdmin implements DBWServiceAdmin { appConfig.setSupportsCustomConnections(config.isCustomConnectionsEnabled()); appConfig.setPublicCredentialsSaveEnabled(config.isPublicCredentialsSaveEnabled()); appConfig.setAdminCredentialsSaveEnabled(config.isAdminCredentialsSaveEnabled()); + appConfig.setEnabledFeatures(config.getEnabledFeatures().toArray(new String[0])); + if (CommonUtils.isEmpty(config.getEnabledAuthProviders())) { // All of them appConfig.setEnabledAuthProviders(new String[0]);