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 1014afbe0f..0650ecd72b 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 @@ -116,16 +116,11 @@ public WebSession( @NotNull WebAuthApplication application, @NotNull Map sessionHandlers ) throws DBException { - super(requestInfo.getId(), application); - this.lastAccessTime = this.createTime; - setLocale(CommonUtils.toString(requestInfo.getLocale(), this.locale)); - this.sessionHandlers = sessionHandlers; - //force authorization of anonymous session to avoid access error, - //because before authorization could be called by any request, - //but now 'updateInfo' is called only in special requests, - //and the order of requests is not guaranteed. - //look at CB-4747 - refreshSessionAuth(); + this(requestInfo.getId(), + CommonUtils.toString(requestInfo.getLocale()), + application, + sessionHandlers + ); updateSessionParameters(requestInfo); } @@ -138,7 +133,7 @@ protected WebSession( super(id, application); this.lastAccessTime = this.createTime; this.sessionHandlers = sessionHandlers; - setLocale(locale); + setLocale(CommonUtils.toString(locale, this.locale)); //force authorization of anonymous session to avoid access error, //because before authorization could be called by any request, //but now 'updateInfo' is called only in special requests, diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/WebGlobalWorkspace.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/WebGlobalWorkspace.java index 02a3b4e53d..3e975239a6 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/WebGlobalWorkspace.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/WebGlobalWorkspace.java @@ -17,8 +17,8 @@ package io.cloudbeaver.server; import io.cloudbeaver.WebProjectImpl; +import io.cloudbeaver.model.app.WebApplication; import io.cloudbeaver.utils.WebAppUtils; -import org.eclipse.core.runtime.Platform; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.Log; @@ -28,8 +28,6 @@ import org.jkiss.dbeaver.model.impl.app.BaseWorkspaceImpl; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; @@ -48,17 +46,7 @@ public class WebGlobalWorkspace extends BaseWorkspaceImpl { private WebGlobalProject globalProject; public WebGlobalWorkspace(DBPPlatform platform) { - super(platform, Path.of(getWorkspaceURI())); - } - - @NotNull - private static URI getWorkspaceURI() { - String workspacePath = Platform.getInstanceLocation().getURL().toString(); - try { - return new URI(workspacePath); - } catch (URISyntaxException e) { - throw new IllegalStateException("Workspace path is invalid: " + workspacePath, e); - } + super(platform, ((WebApplication) platform.getApplication()).getWorkspaceDirectory()); } @Override diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatasourceAccessCheckHandler.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatasourceAccessCheckHandler.java index 2e3ca7aea1..ddd680fb03 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatasourceAccessCheckHandler.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebDatasourceAccessCheckHandler.java @@ -20,11 +20,16 @@ import io.cloudbeaver.model.config.CBAppConfig; import io.cloudbeaver.model.utils.ConfigurationUtils; import io.cloudbeaver.server.CBApplication; +import io.cloudbeaver.utils.WebAppUtils; import org.jkiss.dbeaver.model.connection.DBPDriver; +//TODO move to a separate CBApplication plugin public class WebDatasourceAccessCheckHandler extends BaseDatasourceAccessCheckHandler { @Override protected boolean isDriverDisabled(DBPDriver driver) { + if (!WebAppUtils.getWebApplication().isMultiuser()) { + return false; + } CBAppConfig config = CBApplication.getInstance().getAppConfiguration(); return !ConfigurationUtils.isDriverEnabled( driver, 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 2027832a9d..0bf84aae33 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 @@ -229,7 +229,7 @@ protected void startServer() { Location instanceLoc = Platform.getInstanceLocation(); try { - if (!instanceLoc.isSet()) { + if (!instanceLoc.isSet()) { // always false? URL wsLocationURL = new URL( "file", //$NON-NLS-1$ null, diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatformActivator.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatformActivator.java index 8bfd80106d..cee656629f 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatformActivator.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatformActivator.java @@ -28,7 +28,7 @@ public class CBPlatformActivator extends WebPlatformActivator { protected void shutdownPlatform() { try { // Dispose core - if (DBWorkbench.getPlatform() instanceof CBPlatform cbPlatform) { + if (DBWorkbench.isPlatformStarted() && DBWorkbench.getPlatform() instanceof CBPlatform cbPlatform) { cbPlatform.dispose(); } } catch (Throwable e) { diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java index b004e7e80d..15506f79dd 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java @@ -31,8 +31,6 @@ import io.cloudbeaver.WebServiceUtils; import io.cloudbeaver.model.session.WebSession; import io.cloudbeaver.registry.WebServiceRegistry; -import io.cloudbeaver.server.CBApplication; -import io.cloudbeaver.server.CBPlatform; import io.cloudbeaver.server.HttpConstants; import io.cloudbeaver.service.DBWBindingContext; import io.cloudbeaver.service.DBWServiceBindingGraphQL; @@ -63,6 +61,8 @@ public class GraphQLEndpoint extends HttpServlet { private static final Log log = Log.getLog(GraphQLEndpoint.class); + private static final boolean DEBUG = true; + private static final String HEADER_ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; private static final String HEADER_ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; private static final String HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; @@ -255,6 +255,8 @@ private void executeQuery(HttpServletRequest request, HttpServletResponse respon // } if (apiCall != null) { log.debug("API > " + apiCall); + } else if (DEBUG) { + log.debug("API > " + query); } } ExecutionInput executionInput = contextBuilder.build(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebDatabaseObjectInfo.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebDatabaseObjectInfo.java index 7d251b5755..fd9569ec59 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebDatabaseObjectInfo.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebDatabaseObjectInfo.java @@ -16,15 +16,17 @@ */ package io.cloudbeaver.service.navigator; +import io.cloudbeaver.WebProjectImpl; import io.cloudbeaver.WebServiceUtils; import io.cloudbeaver.model.WebPropertyInfo; import io.cloudbeaver.model.session.WebSession; +import io.cloudbeaver.service.security.SMUtils; +import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.*; import org.jkiss.dbeaver.model.meta.Property; -import org.jkiss.dbeaver.model.navigator.DBNDataSource; -import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor; +import org.jkiss.dbeaver.model.rm.RMProjectPermission; import org.jkiss.dbeaver.model.struct.*; import org.jkiss.dbeaver.model.struct.rdb.DBSCatalog; import org.jkiss.dbeaver.model.struct.rdb.DBSSchema; @@ -91,9 +93,22 @@ public WebPropertyInfo[] getProperties() { @Property public WebPropertyInfo[] filterProperties(@Nullable WebPropertyFilter filter) { + if (object instanceof DBPDataSourceContainer container && !isDataSourceEditable(container)) { + // If user cannot edit a connection, then return only name + filter = new WebPropertyFilter(); + filter.setFeatures(List.of(DBConstants.PROP_FEATURE_NAME)); + } return WebServiceUtils.getObjectFilteredProperties(session, object, filter); } + private boolean isDataSourceEditable(@NotNull DBPDataSourceContainer container) { + WebProjectImpl project = session.getProjectById(container.getProject().getId()); + if (project == null) { + return false; + } + return SMUtils.hasProjectPermission(session, project.getRMProject(), RMProjectPermission.DATA_SOURCES_EDIT); + } + /////////////////////////////////// // Advanced diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryDataReceiver.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryDataReceiver.java index 6a5800cb20..89bdc1e5f1 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryDataReceiver.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryDataReceiver.java @@ -17,7 +17,7 @@ package io.cloudbeaver.service.sql; import io.cloudbeaver.model.session.WebSession; -import io.cloudbeaver.server.CBApplication; +import io.cloudbeaver.utils.WebAppUtils; import org.jkiss.code.NotNull; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; @@ -58,7 +58,9 @@ class WebSQLQueryDataReceiver implements DBDDataReceiver { this.contextInfo = contextInfo; this.dataContainer = dataContainer; this.dataFormat = dataFormat; - rowLimit = CBApplication.getInstance().getAppConfiguration().getResourceQuota(WebSQLConstants.QUOTA_PROP_ROW_LIMIT); + rowLimit = WebAppUtils.getWebApplication() + .getAppConfiguration() + .getResourceQuota(WebSQLConstants.QUOTA_PROP_ROW_LIMIT); } public WebSQLQueryResultSet getResultSet() { 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 2e55d43b34..9bf207fa4c 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 @@ -16,11 +16,11 @@ */ package io.cloudbeaver.service.sql; -import io.cloudbeaver.model.config.CBAppConfig; +import io.cloudbeaver.model.app.WebAppConfiguration; import io.cloudbeaver.model.session.WebSession; import io.cloudbeaver.registry.WebServiceRegistry; -import io.cloudbeaver.server.CBApplication; import io.cloudbeaver.utils.CBModelConstants; +import io.cloudbeaver.utils.WebAppUtils; import org.jkiss.code.NotNull; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.data.*; @@ -151,9 +151,11 @@ private static Object serializeContentValue(WebSession session, DBDContent value if (ContentUtils.isTextContent(value)) { String stringValue = ContentUtils.getContentStringValue(session.getProgressMonitor(), value); int textPreviewMaxLength = CommonUtils.toInt( - CBApplication.getInstance().getAppConfiguration().getResourceQuota( - WebSQLConstants.QUOTA_PROP_TEXT_PREVIEW_MAX_LENGTH, - WebSQLConstants.TEXT_PREVIEW_MAX_LENGTH)); + WebAppUtils.getWebApplication() + .getAppConfiguration() + .getResourceQuota(WebSQLConstants.QUOTA_PROP_TEXT_PREVIEW_MAX_LENGTH), + WebSQLConstants.TEXT_PREVIEW_MAX_LENGTH + ); if (stringValue != null && stringValue.length() > textPreviewMaxLength) { stringValue = stringValue.substring(0, textPreviewMaxLength); } @@ -164,12 +166,11 @@ private static Object serializeContentValue(WebSession session, DBDContent value if (binaryValue != null) { byte[] previewValue = binaryValue; // gets parameters from the configuration file - CBAppConfig config = CBApplication.getInstance().getAppConfiguration(); + WebAppConfiguration config = WebAppUtils.getWebApplication().getAppConfiguration(); // the max length of the text preview int textPreviewMaxLength = CommonUtils.toInt( config.getResourceQuota( - WebSQLConstants.QUOTA_PROP_TEXT_PREVIEW_MAX_LENGTH, - WebSQLConstants.TEXT_PREVIEW_MAX_LENGTH)); + WebSQLConstants.QUOTA_PROP_TEXT_PREVIEW_MAX_LENGTH), WebSQLConstants.TEXT_PREVIEW_MAX_LENGTH); if (previewValue.length > textPreviewMaxLength) { previewValue = Arrays.copyOf(previewValue, textPreviewMaxLength); } @@ -177,8 +178,8 @@ private static Object serializeContentValue(WebSession session, DBDContent value // the max length of the binary preview int binaryPreviewMaxLength = CommonUtils.toInt( config.getResourceQuota( - WebSQLConstants.QUOTA_PROP_BINARY_PREVIEW_MAX_LENGTH, - WebSQLConstants.BINARY_PREVIEW_MAX_LENGTH)); + WebSQLConstants.QUOTA_PROP_BINARY_PREVIEW_MAX_LENGTH), + WebSQLConstants.BINARY_PREVIEW_MAX_LENGTH); byte[] inlineValue = binaryValue; if (inlineValue.length > binaryPreviewMaxLength) { inlineValue = Arrays.copyOf(inlineValue, textPreviewMaxLength); @@ -214,9 +215,11 @@ private static Object serializeGeometryValue(DBGeometry value) { */ public static Object serializeStringValue(Object value) { int textPreviewMaxLength = CommonUtils.toInt( - CBApplication.getInstance().getAppConfiguration().getResourceQuota( - WebSQLConstants.QUOTA_PROP_TEXT_PREVIEW_MAX_LENGTH, - WebSQLConstants.TEXT_PREVIEW_MAX_LENGTH)); + WebAppUtils.getWebApplication() + .getAppConfiguration() + .getResourceQuota(WebSQLConstants.QUOTA_PROP_TEXT_PREVIEW_MAX_LENGTH), + WebSQLConstants.TEXT_PREVIEW_MAX_LENGTH + ); String stringValue = value.toString(); if (stringValue.length() < textPreviewMaxLength) { return value.toString(); diff --git a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/ReverseProxyConfigurator.java b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/ReverseProxyConfigurator.java index 5bda8362a2..8420f4e8ba 100644 --- a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/ReverseProxyConfigurator.java +++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/ReverseProxyConfigurator.java @@ -71,7 +71,7 @@ private void migrateConfiguration( smReverseProxyProviderConfiguration.setProvider(RPAuthProvider.AUTH_PROVIDER); smReverseProxyProviderConfiguration.setDisplayName("Reverse Proxy"); smReverseProxyProviderConfiguration.setDescription( - "Automatically created provider after changing Reverse Proxy configuration way in 23.3.4 version" + "This provider was created automatically" ); smReverseProxyProviderConfiguration .setIconURL(""); Map parameters = new HashMap<>(); diff --git a/webapp/packages/core-authentication/src/AuthProvidersResource.ts b/webapp/packages/core-authentication/src/AuthProvidersResource.ts index 4056802585..a17f5c53c3 100644 --- a/webapp/packages/core-authentication/src/AuthProvidersResource.ts +++ b/webapp/packages/core-authentication/src/AuthProvidersResource.ts @@ -18,9 +18,9 @@ import { } from '@cloudbeaver/core-resource'; import { ServerConfigResource } from '@cloudbeaver/core-root'; import { type AuthProviderConfigurationInfoFragment, type AuthProviderInfoFragment, GraphQLService } from '@cloudbeaver/core-sdk'; +import { isNotNullDefined } from '@cloudbeaver/core-utils'; import { AuthConfigurationsResource } from './AuthConfigurationsResource.js'; -import { AuthSettingsService } from './AuthSettingsService.js'; export type AuthProvider = NonNullable; export type AuthProviderConfiguration = NonNullable; @@ -31,8 +31,13 @@ export class AuthProvidersResource extends CachedMapResource provider.configurable); } + get enabledConfigurableAuthProviders(): AuthProvider[] { + const enabledProviders = new Set(this.serverConfigResource.data?.enabledAuthProviders); + + return this.configurable.filter(provider => enabledProviders.has(provider.id)); + } + constructor( - private readonly authSettingsService: AuthSettingsService, private readonly graphQLService: GraphQLService, private readonly serverConfigResource: ServerConfigResource, private readonly authConfigurationsResource: AuthConfigurationsResource, @@ -64,7 +69,7 @@ export class AuthProvidersResource extends CachedMapResource = observer(function IconButto const Button = tag ?? ReakitButton; return ( -