diff --git a/README.md b/README.md index a656ab0327..be604f1cdb 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,10 @@ You can see a live demo of CloudBeaver here: https://demo.cloudbeaver.io ## Changelog +### 24.2.5. 2024-11-18 +- Updated user storage mechanism: New user logins are now stored in lowercase to prevent duplicate entries (e.g., "ADMIN" and "admin"). Note: This update does not affect previously created user logins; +- A new setting in Global Preferences was added to restrict data import for non-admin users. + ### 24.2.4. 2024-11-04 - General: - Data export: Added the ability to export JSON values as embedded JSON; diff --git a/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF index 66edf9bbb2..5f998bc37e 100644 --- a/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Web Model Bundle-SymbolicName: io.cloudbeaver.model;singleton:=true -Bundle-Version: 1.0.65.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.66.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.model/pom.xml b/server/bundles/io.cloudbeaver.model/pom.xml index 0832142631..cd0f7854f8 100644 --- a/server/bundles/io.cloudbeaver.model/pom.xml +++ b/server/bundles/io.cloudbeaver.model/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.model - 1.0.65-SNAPSHOT + 1.0.66-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWebException.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWebException.java index f4cc8e50ea..a06626ed51 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWebException.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWebException.java @@ -22,7 +22,6 @@ import graphql.language.SourceLocation; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.model.sql.SQLState; -import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.utils.CommonUtils; import java.io.PrintWriter; @@ -100,7 +99,7 @@ public ErrorClassification getErrorType() { @Override public Map getExtensions() { StringWriter buf = new StringWriter(); - GeneralUtils.getRootCause(this).printStackTrace(new PrintWriter(buf, true)); + CommonUtils.getRootCause(this).printStackTrace(new PrintWriter(buf, true)); Map extensions = new LinkedHashMap<>(); String stString = buf.toString(); 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 16822ec600..78a87c8fcb 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 @@ -55,6 +55,7 @@ public class WebAuthProviderDescriptor extends AbstractDescriptor { private final boolean trusted; private final boolean isPrivate; private final boolean isAuthHidden; + private final boolean isCaseInsensitive; private final String[] requiredFeatures; private final boolean isRequired; private final String[] types; @@ -69,6 +70,7 @@ public WebAuthProviderDescriptor(IConfigurationElement cfg) { this.isPrivate = CommonUtils.toBoolean(cfg.getAttribute("private")); this.isRequired = CommonUtils.toBoolean(cfg.getAttribute("required")); this.isAuthHidden = CommonUtils.toBoolean(cfg.getAttribute("authHidden")); + this.isCaseInsensitive = CommonUtils.toBoolean(cfg.getAttribute("caseInsensitive")); for (IConfigurationElement cfgElement : cfg.getChildren("configuration")) { List properties = WebAuthProviderRegistry.readProperties(cfgElement); @@ -132,6 +134,10 @@ public boolean isAuthHidden() { return isAuthHidden; } + public boolean isCaseInsensitive() { + return isCaseInsensitive; + } + public List getConfigurationParameters() { return new ArrayList<>(configurationParameters.values()); } diff --git a/server/bundles/io.cloudbeaver.product.ce/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.product.ce/META-INF/MANIFEST.MF index eab0fb4e5a..3cc02705d6 100644 --- a/server/bundles/io.cloudbeaver.product.ce/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.product.ce/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Community Product Bundle-SymbolicName: io.cloudbeaver.product.ce;singleton:=true -Bundle-Version: 24.2.5.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 24.3.0.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.product.ce/pom.xml b/server/bundles/io.cloudbeaver.product.ce/pom.xml index 2f72ef816c..19029a80e4 100644 --- a/server/bundles/io.cloudbeaver.product.ce/pom.xml +++ b/server/bundles/io.cloudbeaver.product.ce/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.product.ce - 24.2.5-SNAPSHOT + 24.3.0-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.resources.drivers.base/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.resources.drivers.base/META-INF/MANIFEST.MF index d543d9254a..31f399616b 100644 --- a/server/bundles/io.cloudbeaver.resources.drivers.base/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.resources.drivers.base/META-INF/MANIFEST.MF @@ -2,8 +2,8 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Base JDBC drivers Bundle-SymbolicName: io.cloudbeaver.resources.drivers.base;singleton:=true -Bundle-Version: 1.0.110.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.111.qualifier +Bundle-Release-Date: 20241202 Bundle-Vendor: DBeaver Corp Bundle-ActivationPolicy: lazy Automatic-Module-Name: io.cloudbeaver.resources.drivers.base diff --git a/server/bundles/io.cloudbeaver.resources.drivers.base/pom.xml b/server/bundles/io.cloudbeaver.resources.drivers.base/pom.xml index da070a045f..d327cd569d 100644 --- a/server/bundles/io.cloudbeaver.resources.drivers.base/pom.xml +++ b/server/bundles/io.cloudbeaver.resources.drivers.base/pom.xml @@ -9,6 +9,6 @@ ../ io.cloudbeaver.resources.drivers.base - 1.0.110-SNAPSHOT + 1.0.111-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.server/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.server/META-INF/MANIFEST.MF index 609e4ccc38..76578bc27f 100644 --- a/server/bundles/io.cloudbeaver.server/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.server/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Web Server Bundle-SymbolicName: io.cloudbeaver.server;singleton:=true -Bundle-Version: 24.2.5.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 24.3.0.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-Activator: io.cloudbeaver.server.CBPlatformActivator diff --git a/server/bundles/io.cloudbeaver.server/pom.xml b/server/bundles/io.cloudbeaver.server/pom.xml index c1df15d32f..e674aef409 100644 --- a/server/bundles/io.cloudbeaver.server/pom.xml +++ b/server/bundles/io.cloudbeaver.server/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.server - 24.2.5-SNAPSHOT + 24.3.0-SNAPSHOT eclipse-plugin 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 18fde20361..de0f13c5cc 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 @@ -529,7 +529,7 @@ public synchronized void finishConfiguration( } if (isConfigurationMode()) { - finishSecurityServiceConfiguration(adminName, adminPassword, authInfoList); + finishSecurityServiceConfiguration(adminName.toLowerCase(), adminPassword, authInfoList); } // Save runtime configuration diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBAbstractWebSocket.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBAbstractWebSocket.java index 2dac868a86..7af0f380c4 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBAbstractWebSocket.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBAbstractWebSocket.java @@ -25,7 +25,7 @@ public class CBAbstractWebSocket extends Session.Listener.AbstractAutoDemanding { private static final Log log = Log.getLog(CBAbstractWebSocket.class); - protected static final Gson gson = WSUtils.gson; + protected static final Gson gson = WSUtils.clientGson; public void handleEvent(WSEvent event) { if (!isOpen()) { diff --git a/server/bundles/io.cloudbeaver.service.admin/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.admin/META-INF/MANIFEST.MF index e1bf687cda..f753b33cdc 100644 --- a/server/bundles/io.cloudbeaver.service.admin/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.service.admin/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Web Service - Administration Bundle-SymbolicName: io.cloudbeaver.service.admin;singleton:=true -Bundle-Version: 1.0.109.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.110.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.service.admin/pom.xml b/server/bundles/io.cloudbeaver.service.admin/pom.xml index 7b69a7997d..71acee8ddf 100644 --- a/server/bundles/io.cloudbeaver.service.admin/pom.xml +++ b/server/bundles/io.cloudbeaver.service.admin/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.service.admin - 1.0.109-SNAPSHOT + 1.0.110-SNAPSHOT eclipse-plugin 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 48e78992a3..51c959e209 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 @@ -161,12 +161,13 @@ public AdminUserInfo createUser( if (userName.isEmpty()) { throw new DBWebException("Empty user name"); } - webSession.addInfoMessage("Create new user - " + userName); + String userId = userName.toLowerCase(); + webSession.addInfoMessage("Create new user - " + userId); try { var securityController = webSession.getAdminSecurityController(); - securityController.createUser(userName, Map.of(), enabled, authRole); - var smUser = securityController.getUserById(userName); + securityController.createUser(userId, Map.of(), enabled, authRole); + var smUser = securityController.getUserById(userId); return new AdminUserInfo(webSession, new WebUser(smUser)); } catch (Exception e) { throw new DBWebException("Error creating new user", e); diff --git a/server/bundles/io.cloudbeaver.service.auth/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.auth/META-INF/MANIFEST.MF index 62fff52e87..f54eb321f8 100644 --- a/server/bundles/io.cloudbeaver.service.auth/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.service.auth/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Web Service - Authentication Bundle-SymbolicName: io.cloudbeaver.service.auth;singleton:=true -Bundle-Version: 1.0.109.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.110.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.service.auth/pom.xml b/server/bundles/io.cloudbeaver.service.auth/pom.xml index 943eb24778..972be7be9e 100644 --- a/server/bundles/io.cloudbeaver.service.auth/pom.xml +++ b/server/bundles/io.cloudbeaver.service.auth/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.service.auth - 1.0.109-SNAPSHOT + 1.0.110-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java index 64040e3a6f..767823b4c3 100644 --- a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java +++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java @@ -98,9 +98,13 @@ public void reverseProxyAuthentication(@NotNull HttpServletRequest request, @Not String firstName = request.getHeader(resolveParam(paramConfigMap.get(RPConstants.PARAM_FIRST_NAME), RPAuthProvider.X_FIRST_NAME)); String lastName = request.getHeader(resolveParam(paramConfigMap.get(RPConstants.PARAM_LAST_NAME), RPAuthProvider.X_LAST_NAME)); String fullName = request.getHeader(resolveParam(paramConfigMap.get(RPConstants.PARAM_FULL_NAME), RPAuthProvider.X_FULL_NAME)); - String logoutUrl = Objects.requireNonNull(configuration).getParameter(RPConstants.PARAM_LOGOUT_URL); - String teamDelimiter = resolveParam(JSONUtils.getString(configuration.getParameters(), - RPConstants.PARAM_TEAM_DELIMITER), "\\|"); + String logoutUrl = null; + String teamDelimiter = DEFAULT_TEAM_DELIMITER; + if (configuration != null) { + logoutUrl = configuration.getParameter(RPConstants.PARAM_LOGOUT_URL); + teamDelimiter = resolveParam(JSONUtils.getString(configuration.getParameters(), + RPConstants.PARAM_TEAM_DELIMITER), DEFAULT_TEAM_DELIMITER); + } List userTeams = teams == null ? null : (teams.isEmpty() ? List.of() : List.of(teams.split(teamDelimiter))); if (userName != null) { try { diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.data.transfer/META-INF/MANIFEST.MF index 4a317c4f3f..7c899f7153 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.service.data.transfer/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Web Service - Data Transfer Bundle-SymbolicName: io.cloudbeaver.service.data.transfer;singleton:=true -Bundle-Version: 1.0.110.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.111.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/pom.xml b/server/bundles/io.cloudbeaver.service.data.transfer/pom.xml index ed68b1bc06..716f6f3734 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/pom.xml +++ b/server/bundles/io.cloudbeaver.service.data.transfer/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.service.data.transfer - 1.0.110-SNAPSHOT + 1.0.111-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java index 6367944b53..2d26f85dfd 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java @@ -362,7 +362,7 @@ private void importData( processorInstance, properties); DatabaseMappingContainer databaseMappingContainer = - new DatabaseMappingContainer(databaseConsumerSettings, producer.getDatabaseObject()); + new DatabaseMappingContainer(monitor, databaseConsumerSettings, producer.getDatabaseObject(), consumer.getTargetObject()); databaseMappingContainer.getAttributeMappings(monitor); databaseMappingContainer.setTarget(dataContainer); consumer.setContainerMapping(databaseMappingContainer); diff --git a/server/bundles/io.cloudbeaver.service.fs/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.fs/META-INF/MANIFEST.MF index 12b77ec447..4c9a9b339a 100644 --- a/server/bundles/io.cloudbeaver.service.fs/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.service.fs/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Web Service - File System Bundle-SymbolicName: io.cloudbeaver.service.fs;singleton:=true -Bundle-Version: 1.0.27.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.28.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.service.fs/pom.xml b/server/bundles/io.cloudbeaver.service.fs/pom.xml index 016ae1e163..c1ae61238b 100644 --- a/server/bundles/io.cloudbeaver.service.fs/pom.xml +++ b/server/bundles/io.cloudbeaver.service.fs/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.service.fs - 1.0.27-SNAPSHOT + 1.0.28-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/WebFSServlet.java b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/WebFSServlet.java index fa2514c98f..9a39ba821d 100644 --- a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/WebFSServlet.java +++ b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/WebFSServlet.java @@ -31,7 +31,6 @@ import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.model.data.json.JSONUtils; import org.jkiss.dbeaver.model.navigator.fs.DBNPathBase; -import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.utils.CommonUtils; import org.jkiss.utils.IOUtils; @@ -100,7 +99,7 @@ private void doPost(WebSession session, HttpServletRequest request, HttpServletR } } catch (Exception e) { throw new DBWebException("File Upload Failed: Unable to Save File to the File System", - GeneralUtils.getRootCause(e)); + CommonUtils.getRootCause(e)); } } } diff --git a/server/bundles/io.cloudbeaver.service.metadata/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.metadata/META-INF/MANIFEST.MF index 6ba80756b2..5d88fe8e2d 100644 --- a/server/bundles/io.cloudbeaver.service.metadata/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.service.metadata/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Web Service - Metadata Bundle-SymbolicName: io.cloudbeaver.service.metadata;singleton:=true -Bundle-Version: 1.0.113.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.114.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.service.metadata/pom.xml b/server/bundles/io.cloudbeaver.service.metadata/pom.xml index 0a20df5524..1e1e2f3d33 100644 --- a/server/bundles/io.cloudbeaver.service.metadata/pom.xml +++ b/server/bundles/io.cloudbeaver.service.metadata/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.service.metadata - 1.0.113-SNAPSHOT + 1.0.114-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.rm.nio/META-INF/MANIFEST.MF index dbc5f5abb9..60f77cdf24 100644 --- a/server/bundles/io.cloudbeaver.service.rm.nio/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.service.rm.nio/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Resource manager NIO implementation Bundle-SymbolicName: io.cloudbeaver.service.rm.nio;singleton:=true -Bundle-Version: 1.0.27.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.28.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/pom.xml b/server/bundles/io.cloudbeaver.service.rm.nio/pom.xml index 97b4a6b2da..6457bd6f1e 100644 --- a/server/bundles/io.cloudbeaver.service.rm.nio/pom.xml +++ b/server/bundles/io.cloudbeaver.service.rm.nio/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.service.rm.nio - 1.0.27-SNAPSHOT + 1.0.28-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystem.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystem.java index ed535b60d1..53c60d23b1 100644 --- a/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystem.java +++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystem.java @@ -28,6 +28,7 @@ import java.net.URI; import java.nio.file.Path; +import java.util.List; public class RMVirtualFileSystem extends AbstractVirtualFileSystem { @NotNull @@ -83,7 +84,7 @@ public Path getPathByURI(@NotNull DBRProgressMonitor monitor, @NotNull URI uri) @NotNull @Override - public DBFVirtualFileSystemRoot[] getRootFolders(DBRProgressMonitor monitor) throws DBException { - return new RMVirtualFileSystemRoot[]{new RMVirtualFileSystemRoot(this, rmProject, rmNioFileSystemProvider)}; + public List getRootFolders(DBRProgressMonitor monitor) throws DBException { + return List.of(new RMVirtualFileSystemRoot(this, rmProject, rmNioFileSystemProvider)); } } diff --git a/server/bundles/io.cloudbeaver.service.rm/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.rm/META-INF/MANIFEST.MF index c2c7843837..8fc6de2a28 100644 --- a/server/bundles/io.cloudbeaver.service.rm/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.service.rm/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: Cloudbeaver Web Service - Resource manager Bundle-SymbolicName: io.cloudbeaver.service.rm;singleton:=true -Bundle-Version: 1.0.62.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.63.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.service.rm/pom.xml b/server/bundles/io.cloudbeaver.service.rm/pom.xml index 4ccace9c42..24653a9748 100644 --- a/server/bundles/io.cloudbeaver.service.rm/pom.xml +++ b/server/bundles/io.cloudbeaver.service.rm/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.service.rm - 1.0.62-SNAPSHOT + 1.0.63-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.service.security/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.security/META-INF/MANIFEST.MF index db16db1b1b..374682a3a2 100644 --- a/server/bundles/io.cloudbeaver.service.security/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.service.security/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Name: Cloudbeaver Web Service - Security Bundle-Vendor: DBeaver Corp Bundle-SymbolicName: io.cloudbeaver.service.security;singleton:=true -Bundle-Version: 1.0.65.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.66.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.service.security/plugin.xml b/server/bundles/io.cloudbeaver.service.security/plugin.xml index e9ef310594..e4b77aab29 100644 --- a/server/bundles/io.cloudbeaver.service.security/plugin.xml +++ b/server/bundles/io.cloudbeaver.service.security/plugin.xml @@ -4,6 +4,7 @@ diff --git a/server/bundles/io.cloudbeaver.service.security/pom.xml b/server/bundles/io.cloudbeaver.service.security/pom.xml index 18a205d5e0..b4567ab6b5 100644 --- a/server/bundles/io.cloudbeaver.service.security/pom.xml +++ b/server/bundles/io.cloudbeaver.service.security/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.service.security - 1.0.65-SNAPSHOT + 1.0.66-SNAPSHOT eclipse-plugin diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthProvider.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthProvider.java index fce0269e82..60cf8809cc 100644 --- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthProvider.java +++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthProvider.java @@ -68,7 +68,9 @@ public String validateLocalAuth(@NotNull DBRProgressMonitor monitor, throw new DBException("No user password provided"); } String clientPasswordHash = AuthPropertyEncryption.hash.encrypt(userName, clientPassword); - if (!storedPasswordHash.equals(clientPasswordHash)) { + // we also need to check a hash with lower case (CB-5833) + String clientPasswordHashLowerCase = AuthPropertyEncryption.hash.encrypt(userName.toLowerCase(), clientPassword); + if (!storedPasswordHash.equals(clientPasswordHash) && !clientPasswordHashLowerCase.equals(storedPasswordHash)) { throw new DBException("Invalid user name or password"); } diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java index 3827bfa13a..68ba34ae9f 100644 --- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java +++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java @@ -116,6 +116,9 @@ private boolean isSubjectExists(String subjectId) throws DBCException { /////////////////////////////////////////// // Users + /** + * Creates user. Saves user id in database in lower-case. + */ @Override public void createUser( @NotNull String userId, @@ -126,6 +129,7 @@ public void createUser( if (CommonUtils.isEmpty(userId)) { throw new DBCException("Empty user name is not allowed"); } + userId = userId.toLowerCase(); // creating new users only with lowercase if (isSubjectExists(userId)) { throw new DBCException("User or team '" + userId + "' already exists"); } @@ -140,6 +144,9 @@ public void createUser( } } + /** + * Creates user. Saves user id in database as it is. + */ public void createUser( @NotNull Connection dbCon, @NotNull String userId, @@ -844,8 +851,13 @@ public void setUserCredentials( } List transformedCredentials; WebAuthProviderDescriptor authProvider = getAuthProvider(authProviderId); + if (authProvider.isCaseInsensitive() && !isSubjectExists(userId) && isSubjectExists(userId.toLowerCase())) { + log.warn("User with id '" + userId + "' not found, credentials will be set for the user: " + userId.toLowerCase()); + userId = userId.toLowerCase(); + } try { SMAuthCredentialsProfile credProfile = getCredentialProfileByParameters(authProvider, credentials.keySet()); + String finalUserId = userId; transformedCredentials = credentials.entrySet().stream().map(cred -> { String propertyName = cred.getKey(); AuthPropertyDescriptor property = credProfile.getCredentialParameter(propertyName); @@ -853,7 +865,7 @@ public void setUserCredentials( return null; } String encodedValue = CommonUtils.toString(cred.getValue()); - encodedValue = property.getEncryption().encrypt(userId, encodedValue); + encodedValue = property.getEncryption().encrypt(finalUserId, encodedValue); return new String[]{propertyName, encodedValue}; }).toList(); } catch (Exception e) { @@ -910,20 +922,38 @@ private String findUserByCredentials( @NotNull WebAuthProviderDescriptor authProvider, @NotNull Map authParameters, boolean onlyActive // throws exception if user is inactive + ) throws DBException { + String userId = findUserByCredentials(authProvider, authParameters, onlyActive, false); + if (userId == null && authProvider.isCaseInsensitive()) { + // try to find user id with lower case is auth provider is case-insensitive + return findUserByCredentials(authProvider, authParameters, onlyActive, true); + } + return userId; + } + + @Nullable + private String findUserByCredentials( + @NotNull WebAuthProviderDescriptor authProvider, + @NotNull Map authParameters, + boolean onlyActive, + boolean isCaseInsensitive ) throws DBCException { - Map identCredentials = new LinkedHashMap<>(); + Map identCredentials = new LinkedHashMap<>(); String[] propNames = authParameters.keySet().toArray(new String[0]); for (AuthPropertyDescriptor prop : authProvider.getCredentialParameters(propNames)) { if (prop.isIdentifying()) { String propId = CommonUtils.toString(prop.getId()); - Object paramValue = authParameters.get(propId); - if (paramValue == null) { + if (authParameters.get(propId) == null) { throw new DBCException("Authentication parameter '" + prop.getId() + "' is missing"); } if (prop.getEncryption() == AuthPropertyEncryption.hash) { throw new DBCException("Hash encryption can't be used in identifying credentials"); } - identCredentials.put(propId, paramValue); + String paramValue = CommonUtils.toString(authParameters.get(propId)); + identCredentials.put( + propId, + isCaseInsensitive ? paramValue.toLowerCase() : paramValue + ); } } if (identCredentials.isEmpty()) { @@ -947,9 +977,9 @@ private String findUserByCredentials( try (PreparedStatement dbStat = dbCon.prepareStatement(database.normalizeTableNames(sql.toString()))) { dbStat.setString(1, authProvider.getId()); int param = 2; - for (Map.Entry credEntry : identCredentials.entrySet()) { + for (Map.Entry credEntry : identCredentials.entrySet()) { dbStat.setString(param++, credEntry.getKey()); - dbStat.setString(param++, CommonUtils.toString(credEntry.getValue())); + dbStat.setString(param++, credEntry.getValue()); } try (ResultSet dbResult = dbStat.executeQuery()) { @@ -980,6 +1010,15 @@ private String findUserByCredentials( @Override public Map getUserCredentials(String userId, String authProviderId) throws DBCException { WebAuthProviderDescriptor authProvider = getAuthProvider(authProviderId); + Map creds = getUserCredentials(authProvider, userId); + if (creds.isEmpty() && authProvider.isCaseInsensitive()) { + return getUserCredentials(authProvider, userId.toLowerCase()); + } + return creds; + } + + @NotNull + private Map getUserCredentials(WebAuthProviderDescriptor authProvider, String userId) throws DBCException { try (Connection dbCon = database.openConnection()) { try (PreparedStatement dbStat = dbCon.prepareStatement( database.normalizeTableNames("SELECT CRED_ID,CRED_VALUE FROM {table_prefix}CB_USER_CREDENTIALS\n" + @@ -990,7 +1029,6 @@ public Map getUserCredentials(String userId, String authProvider try (ResultSet dbResult = dbStat.executeQuery()) { Map credentials = new LinkedHashMap<>(); - while (dbResult.next()) { credentials.put(dbResult.getString(1), dbResult.getString(2)); } @@ -1182,6 +1220,7 @@ public void createTeam(String teamId, String name, String description, String gr if (CommonUtils.isEmpty(teamId)) { throw new DBCException("Empty team name is not allowed"); } + teamId = teamId.toLowerCase(); if (isSubjectExists(teamId)) { throw new DBCException("User or team '" + teamId + "' already exists"); } @@ -2427,13 +2466,20 @@ private String findOrCreateExternalUserByCredentials( return null; } - userId = userIdFromCredentials; + userId = authProvider.isCaseInsensitive() ? userIdFromCredentials.toLowerCase() : userIdFromCredentials; if (!isSubjectExists(userId)) { - createUser(userId, - Map.of(), - true, - resolveUserAuthRole(null, authRole) - ); + log.debug("Create user: " + userId); + try (Connection dbCon = database.openConnection()) { + createUser( + dbCon, + userId, + Map.of(), + true, + resolveUserAuthRole(null, authRole) + ); + } catch (SQLException e) { + throw new DBException("Error saving user in database", e); + } } setUserCredentials(userId, authProvider.getId(), userCredentials); } else if (userId == null) { diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabaseInitialData.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabaseInitialData.java index 17c42babb2..7f2879f4f6 100644 --- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabaseInitialData.java +++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabaseInitialData.java @@ -17,6 +17,7 @@ package io.cloudbeaver.service.security.db; import org.jkiss.dbeaver.model.security.user.SMTeam; +import org.jkiss.utils.CommonUtils; import java.util.List; @@ -26,7 +27,7 @@ class CBDatabaseInitialData { private List teams; public String getAdminName() { - return adminName; + return CommonUtils.isEmpty(adminName) ? null : adminName.toLowerCase(); } public String getAdminPassword() { diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/ClearAuthAttemptInfoJob.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/ClearAuthAttemptInfoJob.java index 9c700dcca4..8eb28b5721 100644 --- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/ClearAuthAttemptInfoJob.java +++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/ClearAuthAttemptInfoJob.java @@ -23,7 +23,7 @@ import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.runtime.AbstractJob; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; -import org.jkiss.dbeaver.utils.GeneralUtils; +import org.jkiss.utils.CommonUtils; public class ClearAuthAttemptInfoJob extends AbstractJob { @@ -45,7 +45,7 @@ protected IStatus run(DBRProgressMonitor monitor) { securityController.clearOldAuthAttemptInfo(); schedule(CHECK_PERIOD); } catch (DBException e) { - log.error("Error to clear the auth attempt info: " + GeneralUtils.getRootCause(e).getMessage()); + log.error("Error to clear the auth attempt info: " + CommonUtils.getRootCause(e).getMessage()); // Check failed. Re-schedule after 5 seconds schedule(RETRY_PERIOD); } diff --git a/server/bundles/io.cloudbeaver.slf4j/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.slf4j/META-INF/MANIFEST.MF index 00ad68d5d8..7e877266d2 100644 --- a/server/bundles/io.cloudbeaver.slf4j/META-INF/MANIFEST.MF +++ b/server/bundles/io.cloudbeaver.slf4j/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Bundle-Vendor: DBeaver Corp Bundle-Name: CloudBeaver SLF4j Binding Bundle-SymbolicName: io.cloudbeaver.slf4j;singleton:=true -Bundle-Version: 1.0.25.qualifier -Bundle-Release-Date: 20241118 +Bundle-Version: 1.0.26.qualifier +Bundle-Release-Date: 20241202 Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/server/bundles/io.cloudbeaver.slf4j/pom.xml b/server/bundles/io.cloudbeaver.slf4j/pom.xml index 96b8d8ab41..71d70e2ebd 100644 --- a/server/bundles/io.cloudbeaver.slf4j/pom.xml +++ b/server/bundles/io.cloudbeaver.slf4j/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.slf4j - 1.0.25-SNAPSHOT + 1.0.26-SNAPSHOT eclipse-plugin diff --git a/server/features/io.cloudbeaver.ce.drivers.feature/feature.xml b/server/features/io.cloudbeaver.ce.drivers.feature/feature.xml index ec65c2a21a..16abcc7a31 100644 --- a/server/features/io.cloudbeaver.ce.drivers.feature/feature.xml +++ b/server/features/io.cloudbeaver.ce.drivers.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/server/features/io.cloudbeaver.ce.drivers.feature/pom.xml b/server/features/io.cloudbeaver.ce.drivers.feature/pom.xml index 6f1c5d6ca5..2b38e45be3 100644 --- a/server/features/io.cloudbeaver.ce.drivers.feature/pom.xml +++ b/server/features/io.cloudbeaver.ce.drivers.feature/pom.xml @@ -9,6 +9,6 @@ ../ io.cloudbeaver.ce.drivers.feature - 1.0.133-SNAPSHOT + 1.0.134-SNAPSHOT eclipse-feature diff --git a/server/features/io.cloudbeaver.product.ce.feature/feature.xml b/server/features/io.cloudbeaver.product.ce.feature/feature.xml index 83817d2299..3c40e2869a 100644 --- a/server/features/io.cloudbeaver.product.ce.feature/feature.xml +++ b/server/features/io.cloudbeaver.product.ce.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/server/features/io.cloudbeaver.product.ce.feature/pom.xml b/server/features/io.cloudbeaver.product.ce.feature/pom.xml index 6e938928d4..d1e15f4360 100644 --- a/server/features/io.cloudbeaver.product.ce.feature/pom.xml +++ b/server/features/io.cloudbeaver.product.ce.feature/pom.xml @@ -10,7 +10,7 @@ ../ io.cloudbeaver.product.ce.feature - 24.2.5-SNAPSHOT + 24.3.0-SNAPSHOT eclipse-feature @@ -19,7 +19,6 @@ org.apache.maven.plugins maven-resources-plugin - 2.6 process-product-info diff --git a/server/features/io.cloudbeaver.server.feature/feature.xml b/server/features/io.cloudbeaver.server.feature/feature.xml index 9ed477595f..628631759f 100644 --- a/server/features/io.cloudbeaver.server.feature/feature.xml +++ b/server/features/io.cloudbeaver.server.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/server/features/io.cloudbeaver.server.feature/pom.xml b/server/features/io.cloudbeaver.server.feature/pom.xml index ca4d958756..cf2b93d852 100644 --- a/server/features/io.cloudbeaver.server.feature/pom.xml +++ b/server/features/io.cloudbeaver.server.feature/pom.xml @@ -10,6 +10,6 @@ ../ io.cloudbeaver.server.feature - 24.2.5-SNAPSHOT + 24.3.0-SNAPSHOT eclipse-feature diff --git a/server/features/io.cloudbeaver.ws.feature/feature.xml b/server/features/io.cloudbeaver.ws.feature/feature.xml index 63f31ce8cb..ccbee9242a 100644 --- a/server/features/io.cloudbeaver.ws.feature/feature.xml +++ b/server/features/io.cloudbeaver.ws.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/server/features/io.cloudbeaver.ws.feature/pom.xml b/server/features/io.cloudbeaver.ws.feature/pom.xml index 6ae86adae8..03d179e748 100644 --- a/server/features/io.cloudbeaver.ws.feature/pom.xml +++ b/server/features/io.cloudbeaver.ws.feature/pom.xml @@ -10,6 +10,6 @@ ../ io.cloudbeaver.ws.feature - 1.0.63-SNAPSHOT + 1.0.64-SNAPSHOT eclipse-feature diff --git a/server/pom.xml b/server/pom.xml index 43afd2610e..14cc87de26 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -19,7 +19,7 @@ CloudBeaver CE - 24.2.5 + 24.3.0 diff --git a/server/product/web-server/CloudbeaverServer.product b/server/product/web-server/CloudbeaverServer.product index 03517f8893..abc42cf0ce 100644 --- a/server/product/web-server/CloudbeaverServer.product +++ b/server/product/web-server/CloudbeaverServer.product @@ -2,7 +2,7 @@ diff --git a/server/product/web-server/pom.xml b/server/product/web-server/pom.xml index c508ad67b0..0218d3d2c9 100644 --- a/server/product/web-server/pom.xml +++ b/server/product/web-server/pom.xml @@ -9,7 +9,7 @@ 1.0.0-SNAPSHOT ../../ - 24.2.5-SNAPSHOT + 24.3.0-SNAPSHOT web-server eclipse-repository Cloudbeaver Server Product diff --git a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/AuthenticationTest.java b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/AuthenticationTest.java index d642b44e34..e2bebd4db8 100644 --- a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/AuthenticationTest.java +++ b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/AuthenticationTest.java @@ -16,15 +16,19 @@ */ package io.cloudbeaver.test.platform; +import io.cloudbeaver.auth.provider.local.LocalAuthProvider; import io.cloudbeaver.auth.provider.rp.RPAuthProvider; import io.cloudbeaver.test.WebGQLClient; +import org.jkiss.code.NotNull; import org.jkiss.dbeaver.model.auth.SMAuthStatus; import org.jkiss.dbeaver.model.data.json.JSONUtils; +import org.jkiss.utils.SecurityUtils; import org.junit.Assert; import org.junit.Test; import java.util.List; import java.util.Map; +import java.util.Set; public class AuthenticationTest { private static final String GQL_OPEN_SESSION = """ @@ -39,6 +43,12 @@ mutation openSession($defaultLocale: String) { userId } }"""; + private static final String GQL_AUTH_LOGOUT = """ + query authLogoutExtended($provider: ID, $configuration: ID) { + result: authLogoutExtended(provider: $provider, configuration: $configuration) { + redirectLinks + } + }"""; @Test public void testLoginUser() throws Exception { @@ -47,6 +57,34 @@ public void testLoginUser() throws Exception { Assert.assertEquals(SMAuthStatus.SUCCESS.name(), JSONUtils.getString(authInfo, "authStatus")); } + + @Test + public void testLoginUserWithCamelCase() throws Exception { + WebGQLClient client = CEServerTestSuite.createClient(); + for (String userId : Set.of("Test", "tESt", "tesT", "TEST")) { + Map credsWithCamelCase = getUserCredentials(userId); + // authenticating with user + Map authInfo = CEServerTestSuite.authenticateTestUser(client, credsWithCamelCase); + Assert.assertEquals(SMAuthStatus.SUCCESS.name(), JSONUtils.getString(authInfo, "authStatus")); + Map activeUser = client.sendQuery(GQL_ACTIVE_USER, null); + Assert.assertEquals(userId.toLowerCase(), JSONUtils.getString(activeUser, "userId")); + // making logout + client.sendQuery(GQL_AUTH_LOGOUT, Map.of("provider", "local")); + + activeUser = client.sendQuery(GQL_ACTIVE_USER, null); + Assert.assertNotEquals(userId.toLowerCase(), JSONUtils.getString(activeUser, "userId")); + } + } + + @NotNull + private Map getUserCredentials(@NotNull String userId) throws Exception { + return Map.of( + LocalAuthProvider.CRED_USER, userId, + LocalAuthProvider.CRED_PASSWORD, SecurityUtils.makeDigest("test") + ); + } + + @Test public void testReverseProxyAnonymousModeLogin() throws Exception { WebGQLClient client = CEServerTestSuite.createClient(); diff --git a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java index 3ca615b5ea..b133f1baa5 100644 --- a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java +++ b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java @@ -101,11 +101,18 @@ public static WebGQLClient createClient(@NotNull HttpClient httpClient) { } public static Map authenticateTestUser(@NotNull WebGQLClient client) throws Exception { + return authenticateTestUser(client, TEST_CREDENTIALS); + } + + public static Map authenticateTestUser( + @NotNull WebGQLClient client, + @NotNull Map credentials + ) throws Exception { return client.sendQuery( WebGQLClient.GQL_AUTHENTICATE, Map.of( "provider", LocalAuthProvider.PROVIDER_ID, - "credentials", TEST_CREDENTIALS + "credentials", credentials ) ); } diff --git a/webapp/packages/plugin-administration/src/locales/en.ts b/webapp/packages/plugin-administration/src/locales/en.ts index 610540de9c..d1cefaf553 100644 --- a/webapp/packages/plugin-administration/src/locales/en.ts +++ b/webapp/packages/plugin-administration/src/locales/en.ts @@ -59,7 +59,7 @@ export default [ ['administration_configuration_wizard_configuration_security_admin_credentials', 'Save credentials'], [ 'administration_configuration_wizard_configuration_security_admin_credentials_description', - 'Allow to save credentials for pre-configured database', + 'Allow to save credentials for pre-configured databases', ], ['administration_configuration_wizard_configuration_security_public_credentials', 'Save users credentials'], ['administration_configuration_wizard_configuration_security_public_credentials_description', 'Allow to save credentials for non-admin users'], diff --git a/webapp/packages/plugin-administration/src/locales/ru.ts b/webapp/packages/plugin-administration/src/locales/ru.ts index 08a2829fb7..252de8a04e 100644 --- a/webapp/packages/plugin-administration/src/locales/ru.ts +++ b/webapp/packages/plugin-administration/src/locales/ru.ts @@ -41,11 +41,11 @@ export default [ ['administration_configuration_wizard_configuration_security_public_credentials', 'Позволить сохранять приватные данные для пользователей'], [ 'administration_configuration_wizard_configuration_security_admin_credentials_description', - 'Позволяет сохранять приватные данные, такие как пароли и SSH ключи', + 'Позволяет сохранять приватные данные для настроенных подключений', ], [ 'administration_configuration_wizard_configuration_security_public_credentials_description', - 'Пользователи будут иметь возможность сохранять приватные данные, такие как пароли и SSH ключи', + 'Позволяет сохранять приватные данные (такие как пароли и SSH ключи) для пользователей, не являющихся администраторами', ], ['administration_disabled_drivers_title', 'Отключенные драйверы'], diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.module.css b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.module.css index 293ac777b5..fbccc496b0 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.module.css +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.module.css @@ -17,6 +17,10 @@ overflow: auto !important; } +.placeholder { + margin: 0 !important; +} + .loader { z-index: 2; } diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx index 496c6fbf3b..122bff1dac 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx @@ -55,9 +55,11 @@ export const GrantedUsers: TabContainerPanelComponent = observer if (isDefaultTeam) { return ( - - - {translate('plugin_authentication_administration_team_default_users_tooltip')} + + + + {translate('plugin_authentication_administration_team_default_users_tooltip')} + ); @@ -66,10 +68,12 @@ export const GrantedUsers: TabContainerPanelComponent = observer return ( {() => ( - + {!users.resource.values.length ? ( - - {translate('administration_teams_team_granted_users_empty')} + + + {translate('administration_teams_team_granted_users_empty')} + ) : ( <> diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoCredentials.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoCredentials.tsx index ac13ee727f..c5136b7564 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoCredentials.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoCredentials.tsx @@ -54,7 +54,16 @@ export const UserFormInfoCredentials = observer(function UserFormInfoCred return ( {translate('authentication_user_credentials')} - + {translate('authentication_user_name')} {local && ( diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts index 19b4cb1663..240cd8e90b 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts @@ -104,6 +104,8 @@ export class UserFormInfoPart extends FormPart connectionKey && connection.resource.isConnecting(connectionKey)); + const connecting = getComputed(() => (connectionKey && connection.resource.isConnecting(connectionKey)) || connection.loading); + const isConnectionReady = getComputed(() => !connecting && connection.data?.connected && connection.loaded && !connection.outdated); async function handleConnect() { - if (connecting || !connection.data || !connectionKey) { + if (isConnectionReady || !connection.data || !connectionKey) { return; } @@ -37,11 +38,11 @@ export const ConnectionShield = observer connection.data && !connection.data.connected)) { - if (connecting) { - return ; - } + if (connecting) { + return ; + } + if (!isConnectionReady) { return (