From 88eb789763e32c297e737d301649a84ee369cfca Mon Sep 17 00:00:00 2001 From: Aleksandr Skoblikov Date: Tue, 16 Jan 2024 13:51:23 +0400 Subject: [PATCH 1/2] CB-4257 validate required features for providers --- .../registry/WebAuthProviderDescriptor.java | 6 ++-- .../registry/WebAuthProviderProperty.java | 36 +++++++++++++++++++ .../service/admin/impl/WebServiceAdmin.java | 15 ++++++-- 3 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderProperty.java diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java index 5992027a3f..6fa301fb76 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java @@ -49,7 +49,7 @@ public class WebAuthProviderDescriptor extends AbstractDescriptor { private final Map> metaParameters = new HashMap<>(); private SMAuthProvider instance; private final DBPImage icon; - private final Map configurationParameters = new LinkedHashMap<>(); + private final Map configurationParameters = new LinkedHashMap<>(); private final List credentialProfiles = new ArrayList<>(); private final boolean configurable; private final boolean trusted; @@ -72,7 +72,7 @@ public WebAuthProviderDescriptor(IConfigurationElement cfg) { String category = propGroup.getAttribute(PropertyDescriptor.ATTR_LABEL); IConfigurationElement[] propElements = propGroup.getChildren(PropertyDescriptor.TAG_PROPERTY); for (IConfigurationElement prop : propElements) { - PropertyDescriptor propertyDescriptor = new PropertyDescriptor(category, prop); + WebAuthProviderProperty propertyDescriptor = new WebAuthProviderProperty(category, prop); configurationParameters.put(CommonUtils.toString(propertyDescriptor.getId()), propertyDescriptor); } } @@ -130,7 +130,7 @@ public boolean isRequired() { return isRequired; } - public List getConfigurationParameters() { + public List getConfigurationParameters() { return new ArrayList<>(configurationParameters.values()); } diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderProperty.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderProperty.java new file mode 100644 index 0000000000..e755acae3d --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderProperty.java @@ -0,0 +1,36 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.cloudbeaver.registry; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.jkiss.code.NotNull; +import org.jkiss.dbeaver.model.impl.PropertyDescriptor; + +public class WebAuthProviderProperty extends PropertyDescriptor { + private final String[] requiredFeatures; + + public WebAuthProviderProperty(String category, IConfigurationElement config) { + super(category, config); + String featuresAttr = config.getAttribute("requiredFeatures"); + this.requiredFeatures = featuresAttr == null ? new String[0] : featuresAttr.split(","); + } + + @NotNull + public String[] getRequiredFeatures() { + return requiredFeatures; + } +} 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 3097e4020b..9be0a2321b 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 @@ -404,11 +404,20 @@ public List listAuthProviderConfigurationParameters(@NotNull We if (authProvider == null) { throw new DBWebException("Invalid provider ID " + providerId); } + var application = CBApplication.getInstance(); return authProvider.getConfigurationParameters().stream().filter(p -> { - if (p.hasFeature("distributed")) { - return CBApplication.getInstance().isDistributed(); + boolean allFeaturesEnabled = true; + for (String feature : p.getRequiredFeatures()) { + if (feature.equals("distributed")) { + allFeaturesEnabled = CBApplication.getInstance().isDistributed(); + } else { + allFeaturesEnabled = application.getAppConfiguration().isFeatureEnabled(feature); + } + if (!allFeaturesEnabled) { + break; + } } - return true; + return allFeaturesEnabled; }).map(p -> new WebPropertyInfo(webSession, p)).collect(Collectors.toList()); } From 315fadf7661c324ef87eb689e6fbf8b811075af5 Mon Sep 17 00:00:00 2001 From: Aleksandr Skoblikov Date: Mon, 22 Jan 2024 20:28:30 +0400 Subject: [PATCH 2/2] CB-4257 rename types - categories --- .../registry/WebAuthProviderDescriptor.java | 23 +++--- .../registry/WebAuthProviderProperty.java | 9 +++ .../registry/WebAuthProviderRegistry.java | 24 ++++++ ...bCommonAuthProviderPropertyDescriptor.java | 74 +++++++++++++++++++ .../service/admin/impl/WebServiceAdmin.java | 36 +++++---- 5 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebCommonAuthProviderPropertyDescriptor.java diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java index 6fa301fb76..1ae1b6efea 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java @@ -56,6 +56,7 @@ public class WebAuthProviderDescriptor extends AbstractDescriptor { private final boolean isPrivate; private final String[] requiredFeatures; private final boolean isRequired; + private final String[] types; public WebAuthProviderDescriptor(IConfigurationElement cfg) { super(cfg); @@ -68,13 +69,9 @@ public WebAuthProviderDescriptor(IConfigurationElement cfg) { this.isRequired = CommonUtils.toBoolean(cfg.getAttribute("required")); for (IConfigurationElement cfgElement : cfg.getChildren("configuration")) { - for (IConfigurationElement propGroup : ArrayUtils.safeArray(cfgElement.getChildren(PropertyDescriptor.TAG_PROPERTY_GROUP))) { - String category = propGroup.getAttribute(PropertyDescriptor.ATTR_LABEL); - IConfigurationElement[] propElements = propGroup.getChildren(PropertyDescriptor.TAG_PROPERTY); - for (IConfigurationElement prop : propElements) { - WebAuthProviderProperty propertyDescriptor = new WebAuthProviderProperty(category, prop); - configurationParameters.put(CommonUtils.toString(propertyDescriptor.getId()), propertyDescriptor); - } + List properties = WebAuthProviderRegistry.readProperties(cfgElement); + for (WebAuthProviderProperty property : properties) { + configurationParameters.put(CommonUtils.toString(property.getId()), property); } } for (IConfigurationElement credElement : cfg.getChildren("credentials")) { @@ -90,11 +87,10 @@ public WebAuthProviderDescriptor(IConfigurationElement cfg) { } String rfList = cfg.getAttribute("requiredFeatures"); - if (!CommonUtils.isEmpty(rfList)) { - requiredFeatures = rfList.split(","); - } else { - requiredFeatures = null; - } + requiredFeatures = CommonUtils.isEmpty(rfList) ? null : rfList.split(","); + + String typesAttr = cfg.getAttribute("categories"); + this.types = CommonUtils.isEmpty(typesAttr) ? new String[0] : typesAttr.split(","); } @NotNull @@ -198,4 +194,7 @@ public List getMetaParameters(SMSubjectType subjectType) return metaParameters.get(subjectType); } + public String[] getTypes() { + return types; + } } diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderProperty.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderProperty.java index e755acae3d..cf30e97988 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderProperty.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderProperty.java @@ -18,19 +18,28 @@ import org.eclipse.core.runtime.IConfigurationElement; import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; import org.jkiss.dbeaver.model.impl.PropertyDescriptor; public class WebAuthProviderProperty extends PropertyDescriptor { private final String[] requiredFeatures; + @Nullable + private final String type; public WebAuthProviderProperty(String category, IConfigurationElement config) { super(category, config); String featuresAttr = config.getAttribute("requiredFeatures"); this.requiredFeatures = featuresAttr == null ? new String[0] : featuresAttr.split(","); + this.type = config.getAttribute("type"); } @NotNull public String[] getRequiredFeatures() { return requiredFeatures; } + + @Nullable + public String getType() { + return type; + } } diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderRegistry.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderRegistry.java index 5f2a8cb86a..e2a842ffdb 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderRegistry.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderRegistry.java @@ -20,7 +20,9 @@ import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.jkiss.dbeaver.Log; +import org.jkiss.dbeaver.model.impl.PropertyDescriptor; import org.jkiss.dbeaver.registry.RegistryConstants; +import org.jkiss.utils.ArrayUtils; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -33,6 +35,7 @@ public class WebAuthProviderRegistry { private static final String TAG_AUTH_PROVIDER = "authProvider"; //$NON-NLS-1$ private static final String TAG_AUTH_PROVIDER_DISABLE = "authProviderDisable"; //$NON-NLS-1$ + private static final String TAG_COMMON_PROVIDER_PROPERTIES = "commonProviderProperties"; //$NON-NLS-1$ private static WebAuthProviderRegistry instance = null; @@ -45,6 +48,7 @@ public synchronized static WebAuthProviderRegistry getInstance() { } private final Map authProviders = new LinkedHashMap<>(); + private final List commonProperties = new ArrayList<>(); private WebAuthProviderRegistry() { } @@ -57,6 +61,9 @@ private void loadExtensions(IExtensionRegistry registry) { if (TAG_AUTH_PROVIDER.equals(ext.getName())) { WebAuthProviderDescriptor providerDescriptor = new WebAuthProviderDescriptor(ext); this.authProviders.put(providerDescriptor.getId(), providerDescriptor); + } else if (TAG_COMMON_PROVIDER_PROPERTIES.equals(ext.getName())) { + var commonProperties = new WebCommonAuthProviderPropertyDescriptor(ext); + this.commonProperties.add(commonProperties); } } @@ -74,6 +81,23 @@ private void loadExtensions(IExtensionRegistry registry) { } } + static List readProperties(IConfigurationElement root) { + List properties = new ArrayList<>(); + for (IConfigurationElement propGroup : ArrayUtils.safeArray(root.getChildren(PropertyDescriptor.TAG_PROPERTY_GROUP))) { + String category = propGroup.getAttribute(PropertyDescriptor.ATTR_LABEL); + IConfigurationElement[] propElements = propGroup.getChildren(PropertyDescriptor.TAG_PROPERTY); + for (IConfigurationElement prop : propElements) { + WebAuthProviderProperty propertyDescriptor = new WebAuthProviderProperty(category, prop); + properties.add(propertyDescriptor); + } + } + return properties; + } + + public List getCommonProperties() { + return commonProperties; + } + public List getAuthProviders() { return new ArrayList<>(authProviders.values()); } diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebCommonAuthProviderPropertyDescriptor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebCommonAuthProviderPropertyDescriptor.java new file mode 100644 index 0000000000..818f2a55a4 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebCommonAuthProviderPropertyDescriptor.java @@ -0,0 +1,74 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.cloudbeaver.registry; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.jkiss.code.NotNull; +import org.jkiss.dbeaver.model.impl.AbstractDescriptor; +import org.jkiss.utils.CommonUtils; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class WebCommonAuthProviderPropertyDescriptor extends AbstractDescriptor { + private final Set supportedProviderCategories = new HashSet<>(); + private final Set exclude = new HashSet<>(); + @NotNull + private final List configurationParameters; + + public WebCommonAuthProviderPropertyDescriptor(IConfigurationElement cfg) { + super(cfg); + configurationParameters = WebAuthProviderRegistry.readProperties(cfg); + String supportedCategoriesAttr = cfg.getAttribute("supportedProviderCategories"); + if (CommonUtils.isNotEmpty(supportedCategoriesAttr)) { + supportedProviderCategories.addAll(Arrays.stream(supportedCategoriesAttr.split(",")).toList()); + } + + String excludeAttr = cfg.getAttribute("exclude"); + if (CommonUtils.isNotEmpty(excludeAttr)) { + exclude.addAll(Arrays.stream(excludeAttr.split(",")).toList()); + } + } + + + @NotNull + public List getConfigurationParameters() { + return configurationParameters; + } + + private boolean supportAllProviders() { + return supportedProviderCategories.isEmpty() && exclude.isEmpty(); + } + + public boolean isApplicableFor(@NotNull WebAuthProviderDescriptor providerDescriptor) { + if (supportAllProviders()) { + return true; + } + boolean supported = false; + for (String type : providerDescriptor.getTypes()) { + if (exclude.contains(type)) { + return false; + } + if (supportedProviderCategories.contains(type)) { + supported = true; + } + } + return supported; + } +} 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 9be0a2321b..64c1209826 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 @@ -53,6 +53,7 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Web service implementation @@ -405,20 +406,29 @@ public List listAuthProviderConfigurationParameters(@NotNull We throw new DBWebException("Invalid provider ID " + providerId); } var application = CBApplication.getInstance(); - return authProvider.getConfigurationParameters().stream().filter(p -> { - boolean allFeaturesEnabled = true; - for (String feature : p.getRequiredFeatures()) { - if (feature.equals("distributed")) { - allFeaturesEnabled = CBApplication.getInstance().isDistributed(); - } else { - allFeaturesEnabled = application.getAppConfiguration().isFeatureEnabled(feature); - } - if (!allFeaturesEnabled) { - break; + + + Stream commonPropertiesStream = WebAuthProviderRegistry.getInstance() + .getCommonProperties() + .stream() + .filter(commonProperties -> commonProperties.isApplicableFor(authProvider)) + .flatMap(commonProperties -> commonProperties.getConfigurationParameters().stream()); + + return Stream.concat(authProvider.getConfigurationParameters().stream(), commonPropertiesStream) + .filter(p -> { + boolean allFeaturesEnabled = true; + for (String feature : p.getRequiredFeatures()) { + if (feature.equals("distributed")) { + allFeaturesEnabled = CBApplication.getInstance().isDistributed(); + } else { + allFeaturesEnabled = application.getAppConfiguration().isFeatureEnabled(feature); + } + if (!allFeaturesEnabled) { + break; + } } - } - return allFeaturesEnabled; - }).map(p -> new WebPropertyInfo(webSession, p)).collect(Collectors.toList()); + return allFeaturesEnabled; + }).map(p -> new WebPropertyInfo(webSession, p)).collect(Collectors.toList()); } @Override