diff --git a/README.md b/README.md index f4f8107f95..b73090cf7e 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ Cloud Database Manager - Community Edition. -CloudBeaver is a web server which provides rich web interface. Server itself is a Java application, web part is written on TypeScript and React. +CloudBeaver is a web server that provides a rich web interface. The server itself is a Java application, and the web part is written in TypeScript and React. It is free to use and open-source (licensed under [Apache 2](https://github.com/dbeaver/cloudbeaver/blob/devel/LICENSE) license). -See out [WIKI](https://github.com/dbeaver/cloudbeaver/wiki) for more details. +See our [WIKI](https://github.com/dbeaver/cloudbeaver/wiki) for more details. ![](https://github.com/dbeaver/cloudbeaver/wiki/images/demo_screenshot_1.png) @@ -16,7 +16,7 @@ See out [WIKI](https://github.com/dbeaver/cloudbeaver/wiki) for more details. ## Demo server -You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io +You can see a live demo of CloudBeaver here: https://demo.cloudbeaver.io [Database access instructions](https://github.com/dbeaver/cloudbeaver/wiki/Demo-Server) @@ -25,7 +25,7 @@ You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io ### 24.2.0. 2024-09-02 ### Changes since 24.1.0: - General: - - French language support was added (thanks to @matthieukhl) + - French language support was added (thanks to [matthieukhl](https://github.com/matthieukhl)) - Added the ability to close editor tabs with the middle mouse button - Added right-click support to open the context menu in the Metadata Editor - The list of forbidden characters for naming and renaming resource manager files has been updated, and now it includes the following characters: / : " \ ' <> | ? * @@ -45,9 +45,15 @@ You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io - Administration: - Redesigned administration navigation panel - now it is more compact and clear - Added the ability to change the default commit mode for each connection separately - - Added the ability to configure the server property rootURI parameter (thanks to @arioko) + - Added the ability to configure the server property rootURI parameter (thanks to [arioko](https://github.com/arioko)) - Databases: - Added the "Keep alive" setting for Db2 LUW and IMB i, Apache Kyuubi, Clickhouse, Firebird, and Trino - Updated Firebird driver to version 5.0.4 - - DDL generation for Oracle Tablespaces was added (thanks to @pandya09) + - DDL generation for Oracle Tablespaces was added (thanks to [pandya09](https://github.com/pandya09)) +## Contribution +As a community-driven open-source project, we warmly welcome contributions through GitHub pull requests. + +[We are happy to reward](https://dbeaver.com/help-beaver/) our most active contributors every major sprint. +The most significant contribution to our code for the major release 24.2.0 was made by: +1. [matthieukhl](https://github.com/matthieukhl) diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java index bd2bab25e2..6fd0ead93f 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java @@ -46,6 +46,9 @@ default String getUserSignOutLink( @Nullable String getAcsLink(String id, @NotNull Map providerConfig) throws DBException; + @Nullable + String getEntityIdLink(String id, @NotNull Map providerConfig) throws DBException; + @Nullable default String getRedirectLink(String id, @NotNull Map providerConfig) throws DBException { return null; diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java index 864d765b41..32f7752fd7 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java @@ -109,6 +109,14 @@ public String getAcsLink() throws DBException { return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getAcsLink(getId(), config.getParameters()) : null; } + @Property + public String getEntityIdLink() throws DBException { + SMAuthProvider instance = providerDescriptor.getInstance(); + return instance instanceof SMAuthProviderFederated + ? ((SMAuthProviderFederated) instance).getEntityIdLink(getId(), config.getParameters()) + : null; + } + @Override public String toString() { return getDisplayName(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBJettyServer.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBJettyServer.java index 93e715ccb6..f30a4a1e46 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBJettyServer.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBJettyServer.java @@ -29,7 +29,6 @@ import org.eclipse.jetty.server.session.DefaultSessionCache; import org.eclipse.jetty.server.session.DefaultSessionIdManager; import org.eclipse.jetty.server.session.NullSessionDataStore; -import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.servlet.ErrorPageErrorHandler; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -184,7 +183,7 @@ private void initSessionManager( @NotNull ServletContextHandler servletContextHandler ) { // Init sessions persistence - SessionHandler sessionHandler = new SessionHandler(); + CBSessionHandler sessionHandler = new CBSessionHandler(application); var maxIdleTime = application.getMaxSessionIdleTime(); int intMaxIdleSeconds; if (maxIdleTime > Integer.MAX_VALUE) { diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBServerContextListener.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBServerContextListener.java index 999c79fe90..af6215b0ff 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBServerContextListener.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBServerContextListener.java @@ -39,7 +39,7 @@ public void contextInitialized(ServletContextEvent sce) { //scf.setDomain(domain); //scf.setMaxAge(CB_SESSION_LIFE_TIME); cookieConfig.setPath(CBApplication.getInstance().getRootURI()); - cookieConfig.setSecure(application.getServerURL().startsWith("https")); +// cookieConfig.setSecure(application.getServerURL().startsWith("https")); cookieConfig.setHttpOnly(true); cookieConfig.setName(CBConstants.CB_SESSION_COOKIE_NAME); } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBSessionHandler.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBSessionHandler.java new file mode 100644 index 0000000000..6a091573c2 --- /dev/null +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/jetty/CBSessionHandler.java @@ -0,0 +1,145 @@ +/* + * 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.server.jetty; + +import io.cloudbeaver.server.CBApplication; +import jakarta.servlet.SessionCookieConfig; +import org.eclipse.jetty.http.Syntax; +import org.eclipse.jetty.server.session.SessionHandler; + +public class CBSessionHandler extends SessionHandler { + private final CBCookieConfig cbCookieConfig; + private final CBApplication application; + + public CBSessionHandler(CBApplication application) { + this.cbCookieConfig = new CBCookieConfig(); + this.application = application; + } + + + @Override + public SessionCookieConfig getSessionCookieConfig() { + return this.cbCookieConfig; + } + + + //mostly copy of org.eclipse.jetty.server.session.CookieConfig but allows to use dynamic setSecure flag + public final class CBCookieConfig implements SessionCookieConfig { + public CBCookieConfig() { + } + + public String getComment() { + return CBSessionHandler.this._sessionComment; + } + + public String getDomain() { + return CBSessionHandler.this._sessionDomain; + } + + public int getMaxAge() { + return CBSessionHandler.this._maxCookieAge; + } + + public String getName() { + return CBSessionHandler.this._sessionCookie; + } + + public String getPath() { + return CBSessionHandler.this._sessionPath; + } + + public boolean isHttpOnly() { + return CBSessionHandler.this._httpOnly; + } + + public boolean isSecure() { + var serverUrl = CBSessionHandler.this.application.getServerURL(); + return serverUrl != null && serverUrl.startsWith("https://"); + } + + public void setComment(String comment) { + if (CBSessionHandler.this._context != null && CBSessionHandler.this._context.getContextHandler() + .isAvailable()) { + throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); + } else { + CBSessionHandler.this._sessionComment = comment; + } + } + + public void setDomain(String domain) { + if (CBSessionHandler.this._context != null && CBSessionHandler.this._context.getContextHandler() + .isAvailable()) { + throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); + } else { + CBSessionHandler.this._sessionDomain = domain; + } + } + + public void setHttpOnly(boolean httpOnly) { + if (CBSessionHandler.this._context != null && CBSessionHandler.this._context.getContextHandler() + .isAvailable()) { + throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); + } else { + CBSessionHandler.this._httpOnly = httpOnly; + } + } + + public void setMaxAge(int maxAge) { + if (CBSessionHandler.this._context != null && CBSessionHandler.this._context.getContextHandler() + .isAvailable()) { + throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); + } else { + CBSessionHandler.this._maxCookieAge = maxAge; + } + } + + public void setName(String name) { + if (CBSessionHandler.this._context != null && CBSessionHandler.this._context.getContextHandler() + .isAvailable()) { + throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); + } else if ("".equals(name)) { + throw new IllegalArgumentException("Blank cookie name"); + } else { + if (name != null) { + Syntax.requireValidRFC2616Token(name, "Bad Session cookie name"); + } + + CBSessionHandler.this._sessionCookie = name; + } + } + + public void setPath(String path) { + if (CBSessionHandler.this._context != null && CBSessionHandler.this._context.getContextHandler() + .isAvailable()) { + throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); + } else { + CBSessionHandler.this._sessionPath = path; + } + } + + public void setSecure(boolean secure) { + if (CBSessionHandler.this._context != null && CBSessionHandler.this._context.getContextHandler() + .isAvailable()) { + throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); + } else { + CBSessionHandler.this._secureCookies = secure; + } + } + } + + +} 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 559b9b90e4..20f53605dd 100644 --- a/server/bundles/io.cloudbeaver.service.admin/schema/service.admin.graphqls +++ b/server/bundles/io.cloudbeaver.service.admin/schema/service.admin.graphqls @@ -89,6 +89,7 @@ type AdminAuthProviderConfiguration { redirectLink: String metadataLink: String acsLink: String + entityIdLink: String @since(version: "24.2.1") } type WebFeatureSet { diff --git a/server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls b/server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls index eb5b4b4d43..362f5a3549 100644 --- a/server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls +++ b/server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls @@ -42,6 +42,7 @@ type AuthProviderConfiguration { signOutLink: String metadataLink: String acsLink: String + entityIdLink: String @since(version: "24.2.1") } type AuthProviderCredentialsProfile { diff --git a/webapp/packages/core-sdk/src/queries/authentication/getAuthProviderConfigurations.gql b/webapp/packages/core-sdk/src/queries/authentication/getAuthProviderConfigurations.gql index 7c801a911d..92b4659070 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/getAuthProviderConfigurations.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/getAuthProviderConfigurations.gql @@ -12,5 +12,6 @@ query getAuthProviderConfigurations($providerId: ID) { redirectLink metadataLink acsLink + entityIdLink } } diff --git a/webapp/packages/core-sdk/src/queries/authentication/saveAuthProviderConfiguration.gql b/webapp/packages/core-sdk/src/queries/authentication/saveAuthProviderConfiguration.gql index 4909ec68f9..fefbd1560b 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/saveAuthProviderConfiguration.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/saveAuthProviderConfiguration.gql @@ -28,5 +28,6 @@ query saveAuthProviderConfiguration( redirectLink metadataLink acsLink + entityIdLink } } diff --git a/webapp/packages/core-sdk/src/queries/fragments/AuthProviderConfigurationInfo.gql b/webapp/packages/core-sdk/src/queries/fragments/AuthProviderConfigurationInfo.gql index 99c0e023f4..40494db8b5 100644 --- a/webapp/packages/core-sdk/src/queries/fragments/AuthProviderConfigurationInfo.gql +++ b/webapp/packages/core-sdk/src/queries/fragments/AuthProviderConfigurationInfo.gql @@ -8,4 +8,5 @@ fragment AuthProviderConfigurationInfo on AuthProviderConfiguration { signOutLink metadataLink acsLink + entityIdLink }