From 21f57461e0d0f10e8dcf885afea04c27d95bce2c Mon Sep 17 00:00:00 2001 From: Aleksandr Skoblikov Date: Fri, 16 Sep 2022 14:26:35 +0300 Subject: [PATCH 1/2] CB-2515 add type for context credential providers --- .../local/LocalAuthProviderConstants.java | 17 ++++++ .../cloudbeaver/model/WebConnectionInfo.java | 5 +- .../cloudbeaver/model/session/WebSession.java | 52 +++++++++++++------ .../io/cloudbeaver/utils/WebCommonUtils.java | 17 ++++-- .../model/WebDatabaseAuthModel.java | 3 +- 5 files changed, 71 insertions(+), 23 deletions(-) diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/local/LocalAuthProviderConstants.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/local/LocalAuthProviderConstants.java index d71123f544..9069883185 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/local/LocalAuthProviderConstants.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/local/LocalAuthProviderConstants.java @@ -1,3 +1,20 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 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.auth.provider.local; //TODO remove after CBDatabase refactoring diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java index 82e5ca35c2..b9f5bfa35c 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java @@ -19,8 +19,8 @@ package io.cloudbeaver.model; import io.cloudbeaver.VirtualProjectImpl; import io.cloudbeaver.model.session.WebSession; import io.cloudbeaver.service.sql.WebDataFormat; -import io.cloudbeaver.utils.WebCommonUtils; import io.cloudbeaver.utils.CBModelConstants; +import io.cloudbeaver.utils.WebCommonUtils; import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.DBPDataSourceContainer; import org.jkiss.dbeaver.model.DBPDataSourceFolder; @@ -288,14 +288,13 @@ public class WebConnectionInfo { } // Fill session and user provided credentials - boolean hasContextCredentials = session.hasContextCredentials(); DBPConnectionConfiguration configWithAuth = new DBPConnectionConfiguration(dataSourceContainer.getConnectionConfiguration()); session.provideAuthParameters(session.getProgressMonitor(), dataSourceContainer, configWithAuth); DBPPropertySource credentialsSource = authModel.createCredentialsSource(dataSourceContainer, configWithAuth); return Arrays.stream(credentialsSource.getProperties()) - .filter(p -> WebCommonUtils.isAuthPropertyApplicable(p, hasContextCredentials)) + .filter(p -> WebCommonUtils.isAuthPropertyApplicable(p, session.getContextCredentialsProviders())) .map(p -> new WebPropertyInfo(session, p, credentialsSource)).toArray(WebPropertyInfo[]::new); } diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java index f1239c2260..69e5673d23 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java @@ -16,7 +16,10 @@ */ package io.cloudbeaver.model.session; -import io.cloudbeaver.*; +import io.cloudbeaver.DBWConstants; +import io.cloudbeaver.DBWebException; +import io.cloudbeaver.DataSourceFilter; +import io.cloudbeaver.VirtualProjectImpl; import io.cloudbeaver.model.WebAsyncTaskInfo; import io.cloudbeaver.model.WebConnectionInfo; import io.cloudbeaver.model.WebServerMessage; @@ -83,8 +86,7 @@ public class WebSession extends AbstractSessionPersistent implements SMSession, private static final Log log = Log.getLog(WebSession.class); public static final SMSessionType CB_SESSION_TYPE = new SMSessionType("CloudBeaver"); - public static final SMObjectType CB_DATASOURCE_OBJECT = new SMObjectType("datasource"); - + private static final String WEB_SESSION_AUTH_CONTEXT_TYPE = "web-session"; private static final String ATTR_LOCALE = "locale"; private static final AtomicInteger TASK_ID = new AtomicInteger(); @@ -874,8 +876,8 @@ public class WebSession extends AbstractSessionPersistent implements SMSession, } } - public boolean hasContextCredentials() { - return getAdapter(DBACredentialsProvider.class) != null; + public List getContextCredentialsProviders() { + return getAdapters(DBACredentialsProvider.class); } // Auth credentials provider @@ -884,13 +886,10 @@ public class WebSession extends AbstractSessionPersistent implements SMSession, public boolean provideAuthParameters(@NotNull DBRProgressMonitor monitor, @NotNull DBPDataSourceContainer dataSourceContainer, @NotNull DBPConnectionConfiguration configuration) { try { // Properties from nested auth sessions - // FIXME: we need to support multiple credential providers (e.g. multiple clouds). - DBACredentialsProvider nestedProvider = getAdapter(DBACredentialsProvider.class); - if (nestedProvider != null) { - if (!nestedProvider.provideAuthParameters(monitor, dataSourceContainer, configuration)) { - return false; - } + for (DBACredentialsProvider contextCredentialsProvider : getContextCredentialsProviders()) { + contextCredentialsProvider.provideAuthParameters(monitor, dataSourceContainer, configuration); } + WebConnectionInfo webConnectionInfo = findWebConnectionInfo(dataSourceContainer.getId()); if (webConnectionInfo != null) { WebDataSourceUtils.saveCredentialsInDataSource(webConnectionInfo, dataSourceContainer, configuration); @@ -928,21 +927,44 @@ public class WebSession extends AbstractSessionPersistent implements SMSession, return true; } + @NotNull + @Override + public String getAuthContextType() { + return WEB_SESSION_AUTH_CONTEXT_TYPE; + } + // May be called to extract auth information from session @Override public T getAdapter(Class adapter) { synchronized (authTokens) { for (WebAuthInfo authInfo : authTokens) { - if (authInfo != null && authInfo.getAuthSession() != null) { - if (adapter.isInstance(authInfo.getAuthSession())) { - return adapter.cast(authInfo.getAuthSession()); - } + if (isAuthInfoInstanceOf(authInfo, adapter)) { + return adapter.cast(authInfo.getAuthSession()); } } } return null; } + @NotNull + public List getAdapters(Class adapter) { + synchronized (authTokens) { + return authTokens.stream() + .filter(token -> isAuthInfoInstanceOf(token, adapter)) + .map(token -> adapter.cast(token.getAuthSession())) + .collect(Collectors.toList()); + } + } + + private boolean isAuthInfoInstanceOf(WebAuthInfo authInfo, Class adapter) { + if (authInfo != null && authInfo.getAuthSession() != null) { + if (adapter.isInstance(authInfo.getAuthSession())) { + return true; + } + } + return false; + } + /////////////////////////////////////////////////////// // Utils diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/utils/WebCommonUtils.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/utils/WebCommonUtils.java index ee13fac1d9..cd92350713 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/utils/WebCommonUtils.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/utils/WebCommonUtils.java @@ -22,12 +22,15 @@ import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.model.DBPImage; import org.jkiss.dbeaver.model.DBPObject; +import org.jkiss.dbeaver.model.access.DBACredentialsProvider; import org.jkiss.dbeaver.model.auth.AuthProperty; import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor; import org.jkiss.dbeaver.runtime.properties.ObjectPropertyDescriptor; import org.jkiss.dbeaver.runtime.properties.PropertyCollector; +import org.jkiss.utils.CommonUtils; import java.util.Arrays; +import java.util.Collection; public class WebCommonUtils { @@ -44,13 +47,21 @@ public class WebCommonUtils { .map(p -> new WebPropertyInfo(session, p, propertyCollector)).toArray(WebPropertyInfo[]::new); } - public static boolean isAuthPropertyApplicable(DBPPropertyDescriptor prop, boolean hasContextCredentials) { - if (hasContextCredentials && prop instanceof ObjectPropertyDescriptor) { + public static boolean isAuthPropertyApplicable( + DBPPropertyDescriptor prop, + @NotNull Collection credentialsProviders + ) { + if (!CommonUtils.isEmpty(credentialsProviders) && prop instanceof ObjectPropertyDescriptor) { if (((ObjectPropertyDescriptor) prop).isHidden()) { return false; } AuthProperty authProperty = ((ObjectPropertyDescriptor) prop).getAnnotation(AuthProperty.class); - if (authProperty != null) return !authProperty.contextProvided(); + if (authProperty != null) { + var requiredContext = authProperty.authContextType(); + return CommonUtils.isEmpty(requiredContext) + || credentialsProviders.stream() + .noneMatch(provider -> provider.getAuthContextType().equals(requiredContext)); + } } return true; } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatabaseAuthModel.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatabaseAuthModel.java index 4121799805..01e34f4751 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatabaseAuthModel.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatabaseAuthModel.java @@ -65,11 +65,10 @@ public class WebDatabaseAuthModel { @Property public WebPropertyInfo[] getProperties() throws DBWebException { - boolean hasContextCredentials = webSession.hasContextCredentials(); DBPPropertySource credentialsSource = model.createCredentialsSource(null, null); return Arrays.stream(credentialsSource.getProperties()) - .filter(p -> WebServiceUtils.isAuthPropertyApplicable(p, hasContextCredentials)) + .filter(p -> WebServiceUtils.isAuthPropertyApplicable(p, webSession.getContextCredentialsProviders())) .map(p -> new WebPropertyInfo(webSession, p, credentialsSource)).toArray(WebPropertyInfo[]::new); } From 6faa6a697174dd90a3395445419ac674ee2b5774 Mon Sep 17 00:00:00 2001 From: Ainur <59531286+yagudin10@users.noreply.github.com> Date: Wed, 21 Sep 2022 22:15:47 +0300 Subject: [PATCH 2/2] CB-2355 exception for binary files editing (#1170) --- .../cloudbeaver/service/sql/WebSQLUtils.java | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLUtils.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLUtils.java index a464549408..e02645ac16 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLUtils.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLUtils.java @@ -210,24 +210,9 @@ public class WebSQLUtils { switch ((String)typeAttr) { case WebSQLConstants.VALUE_TYPE_CONTENT: { if (map.get(WebSQLConstants.ATTR_BINARY) != null) { - DBDContentStorage storage; - Path openFile = WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.resolve((String) map.get("fileName")); - Object tempValue = ((DBDAttributeBinding) attribute).getValueHandler().getValueFromObject( - session, - attribute, - null, false, true); - storage = new ExternalContentStorage(DBWorkbench.getPlatform(), openFile); - if (tempValue instanceof DBDContent) { - try { - ((DBDContent) tempValue).updateContents(session.getProgressMonitor(), storage); - } catch (Exception e) { - throw new DBCException("Error with inserting file into DB"); - } - } - value = tempValue; - } else { - value = map.get(WebSQLConstants.ATTR_TEXT); + throw new DBCException("Binary content edit is not supported yet"); } + value = map.get(WebSQLConstants.ATTR_TEXT); break; } default: {