Compare commits

..
2 Commits
698 changed files with 8654 additions and 13148 deletions
-8
View File
@@ -107,14 +107,6 @@
"options": {
"cwd": "${workspaceFolder}/webapp"
}
},
{
"label": "Add Custom Plugin",
"type": "shell",
"command": "yarn run add-plugin",
"options": {
"cwd": "${workspaceFolder}/webapp/packages"
}
}
],
"inputs": [
+54 -46
View File
@@ -25,59 +25,67 @@ You can see a live demo of CloudBeaver here: https://demo.cloudbeaver.io
## Changelog
### 24.3.3. 2025-01-20
- Administration:
- Added an ability to match users from LDAP configuration with CloudBeaver users;
- New environment variables were introduced for theme styling, SQL editor, and log viewer settings. You can use them for quick setup during the initial Docker configuration stage.
### 24.2.4. 2024-11-04
- General:
- An ability to show metadata object comments was added in the Navigator tree. You can enable it in the database navigator settings panel;
- Added transaction log viewing for connections with manual commit mode. This allows users to see all modifying statements before committing;
- Added an ability to import data in tables without unique keys;
- Added an ability to insert data in tables without unique keys;
- Added Ctrl + Shift + S (Cmd + Shift + S on Mac) shortcut for "Save As Script" action.
### 24.3.2. 2025-01-06
- Added an ability to specify a user login as an attribute parameter for LDAP providers;
- The collapse of the grouping panel doesn't lead to the full panel cleaning anymore.
### 24.3.1. 2024-12-23
- Added an ability to reconnect for all editors if a connection has been lost;
- Added an option to replace line break characters on any custom value when exporting to CSV;
- Added an ability to create connections in the Navigation tree not only on the initial level but in folders and sub-folders directly;
- Updated list of available shortcuts for MacOS.
### 24.3.0. 2024-12-02
### Changes since 24.2.0:
- General:
- The connections Templates feature is declared obsolete and will be removed in future releases;
- Data export: Added the ability to export JSON values as embedded JSON;
- Fixed a proxy issue that excluded the Content-Type header in responses;
- Data editor enhancements: Rows with focused cells are specially marked to make it easier to locate a position in large tables;
- Keyboard navigation has been enhanced. You can now use the arrow keys to move through navigator tree elements and the tab key to switch between editors' tabs;
- Sample SQLite database was removed;
- Chinese localization has been improved (thanks to @cashlifei);
- Brazilian Portuguese localization was enhanced (thanks to @brlarini).
- Brazilian Portuguese localization was enhanced (thanks to [brlarini](https://github.com/brlarini));
- Fixed a proxy issue that excluded the Content-Type header in responses.
- Administration:
- 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;
- Added an ability to change a user password even if the user is disabled in a system;
- Refreshed design for the User and Teams tab in the Administration panel;
- A new setting in Global Preferences was added to restrict data import for non-admin users;
- A search option was added for preferences in the Administration part;
- Added detailed logging of GraphQL queries in the server logs, including all provided variables, for improved debugging and monitoring;
- Environment variables configuration has been improved - now you can configure more variables on the initial stage of the Docker setup.
- Added an ability to change a user password even if the user is disabled in a system.
### 24.2.3. 2024-10-21
- Important update:
- Connections Templates feature is declared as obsolete and will be removed in future releases.
- General:
- Data editor enhancements: Rows with focused cells are specially marked to make it easier to locate a position in large tables;
- DB2i driver has been updated to version 20.0.7;
- The URL mode for PostgreSQL now supports connecting to multiple databases;
- The issue with displaying BLOB data types in DuckDB has been resolved.
### 24.2.2. 2024-10-07
- Schemas were added to the SQL autocompletion for PostgreSQL, H2, and SQL Server;
- CloudBeaver can now correctly display negative dates for MySQL database;
- A search option was added for preferences in the Administration part;
- Keyboard navigation has been enhanced. You can now use the arrow keys to move through navigator tree elements and the tab key to switch between editors tabs;
- Sample SQLite database was removed.
### 24.2.1. 2024-09-23
- Chinese localization has been improved (thanks to [cashlifei](https://github.com/cashlifei));
- Environment variables configuration has been improved - now you can configure more variables on the initial stage of the Docker setup;
- SQL Server driver has been updated to version 12.8.0.
### 24.2.0. 2024-09-02
### Changes since 24.1.0:
- General:
- 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: / : " \ ' <> | ? *
- Application cookies security was improved
- Authentication:
- Improved LDAP authentication: added the ability to filter users via service account parameters and ability to specify custom unique user identifiers
- Data Editor:
- Added additional notifications about the restricted operations
- Enhanced IPv6 and DateTime32 data representation for Clickhouse
- Data editing was fixed for DuckDB
- SQL Editor:
- SQL Editor auto-completion was enhanced to get column, table, and function names faster
- Fixed the dollar-quoted string parsing in the SQL Editor for PostgreSQL
- Improved display of the long error messages in the SQL Editor and Log viewer
- Changed the save script icon to a floppy disk for better recognition
- Improved application behavior when closing a connection - open editors won't be closed on disconnect
- 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](https://github.com/arioko))
- Databases:
- PostgreSQL, Greenplum, CockroachDB: The URL mode now supports connecting to multiple databases;
- PostgreSQL, H2, and SQL Server: Schemas were added to the SQL autocompletion;
- MySQL: CloudBeaver can now correctly display negative dates;
- DuckDB: The issue with displaying BLOB data types has been resolved.
- Drivers:
- A new LibSQL/Turso driver was added;
- SQL Server driver has been updated to version 12.8.0;
- DB2i driver has been updated to version 20.0.7.
- 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](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-dbeaver/) our most active contributors every major sprint.
The most significant contribution to our code for the major release 24.3.0 was made by:
1. [cashlifei](https://github.com/cashlifei)
The most significant contribution to our code for the major release 24.2.0 was made by:
1. [matthieukhl](https://github.com/matthieukhl)
+9 -9
View File
@@ -13,16 +13,16 @@
productSettings: {
# Global properties
core.theming.theme: "${CLOUDBEAVER_CORE_THEMING_THEME:light}",
core.localization.localization: "${CLOUDBEAVER_CORE_LOCALIZATION:en}",
plugin.sql-editor.autoSave: "${CLOUDBEAVER_SQL_EDITOR_AUTOSAVE:true}",
plugin.sql-editor.disabled: "${CLOUDBEAVER_SQL_EDITOR_DISABLED:false}",
core.theming.theme: 'light',
core.localization.localization: 'en',
plugin.sql-editor.autoSave: true,
plugin.sql-editor.disabled: false,
# max size of the file that can be uploaded to the editor (in kilobytes)
plugin.sql-editor.maxFileSize: "${CLOUDBEAVER_SQL_EDITOR_MAX_FILE_SIZE:10240}",
plugin.log-viewer.disabled: "${CLOUDBEAVER_LOG_VIEWER_DISABLED:false}",
plugin.log-viewer.logBatchSize: "${CLOUDBEAVER_LOG_VIEWER_LOG_BATCH_SIZE:1000}",
plugin.log-viewer.maxLogRecords: "${CLOUDBEAVER_LOG_VIEWER_MAX_LOG_RECORDS:2000}",
sql.proposals.insert.table.alias: "${CLOUDBEAVER_SQL_PROPOSALS_INSERT_TABLE_ALIAS:PLAIN}"
plugin.sql-editor.maxFileSize: 10240,
plugin.log-viewer.disabled: false,
plugin.log-viewer.logBatchSize: 1000,
plugin.log-viewer.maxLogRecords: 2000,
sql.proposals.insert.table.alias: PLAIN
},
expireSessionAfterPeriod: "${CLOUDBEAVER_EXPIRE_SESSION_AFTER_PERIOD:1800000}",
+3 -2
View File
@@ -23,7 +23,8 @@ RUN set -eux; \
tzdata \
# locales ensures proper character encoding and locale-specific behaviors using en_US.UTF-8
locales \
nano && \
nano \
; \
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; \
locale-gen en_US.UTF-8; \
rm -rf /var/lib/apt/lists/*
@@ -31,7 +32,7 @@ RUN set -eux; \
ENV LANG=en_US.UTF-8
ENV JAVA_HOME=/opt/java/openjdk
COPY --from=eclipse-temurin:21 $JAVA_HOME $JAVA_HOME
COPY --from=eclipse-temurin:17 $JAVA_HOME $JAVA_HOME
ENV PATH="${JAVA_HOME}/bin:${PATH}"
RUN set -eux; \
+4 -14
View File
@@ -2,22 +2,12 @@ FROM dbeaver/base-java
MAINTAINER DBeaver Corp, devops@dbeaver.com
ENV DBEAVER_GID=8978
ENV DBEAVER_UID=8978
RUN apt-get update && \
apt-get upgrade -y
RUN groupadd -g $DBEAVER_GID dbeaver && \
useradd -g $DBEAVER_GID -m -u $DBEAVER_UID -s /bin/bash dbeaver
RUN apt-get update; \
apt-get upgrade -y;
COPY cloudbeaver /opt/cloudbeaver
COPY scripts/launch-product.sh /opt/cloudbeaver/launch-product.sh
EXPOSE 8978
RUN find /opt/cloudbeaver -type d -exec chmod 775 {} \;
WORKDIR /opt/cloudbeaver/
RUN chmod +x "run-server.sh" "/opt/cloudbeaver/launch-product.sh"
ENTRYPOINT ["./launch-product.sh"]
ENTRYPOINT ["./run-server.sh"]
-19
View File
@@ -1,19 +0,0 @@
#!/bin/bash
# This script is needed to change ownership and run the application as user dbeaver during the upgrade from version 24.2.0
# Change ownership of the WORKDIR to the dbeaver user and group
# Variables DBEAVER_<UID|GID> are defined in the Dockerfile and exported to the runtime environment
# PWD equals WORKDIR value from product Dockerfile
if [ "$(id -u)" -eq 0 ]; then
TARGET_USER=${TARGET_USER:-dbeaver}
TARGET_UID=${TARGET_UID:-$DBEAVER_UID}
TARGET_GID=${TARGET_GID:-$DBEAVER_GID}
chown -R $DBEAVER_UID:$DBEAVER_GID $PWD
# Execute run-server.sh as the dbeaver user with the JAVA_HOME and PATH environment variables
exec su "$TARGET_USER" -c "JAVA_HOME=$JAVA_HOME PATH=$PATH ./run-server.sh"
else
exec ./run-server.sh
fi
+6 -8
View File
@@ -5,16 +5,12 @@ featuresPaths=\
bundlesPaths=\
dbeaver-common/modules;\
dbeaver/plugins;\
cloudbeaver/server/bundles;\
dbeaver-jdbc-libsql;\
cloudbeaver/server/test
cloudbeaver/server/bundles;
testLibraries=\
org.junit;\
org.mockito.mockito-core;\
junit-jupiter-api;\
org.opentest4j;\
org.hamcrest.core;\
org.hamcrest
org.opentest4j
repositories=\
https://p2.dev.dbeaver.com/eclipse-repo/;\
https://download.eclipse.org/releases/${eclipse-version}/;
@@ -25,10 +21,12 @@ testBundles=\
org.opentest4j
productsPaths=\
dbeaver/product/community/DBeaver.product;\
cloudbeaver/server/product/web-server/CloudbeaverServer.product:../../opt/cloudbeaver;\
cloudbeaver/server/product/web-server-test/CloudbeaverServerTest.product:../../opt/cloudbeaver;
cloudbeaver/server/product/web-server/CloudbeaverServer.product:../../opt/cloudbeaver;
ideaConfigurationFilesPaths=\
dbeaver/.ide/.idea;
testBundlePaths=\
dbeaver/test;\
cloudbeaver/server/test;
additionalModuleRoots=\
opt;
optionalFeatureRepositories=\
@@ -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.70.qualifier
Bundle-Release-Date: 20250203
Bundle-Version: 1.0.65.qualifier
Bundle-Release-Date: 20241118
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
@@ -4,7 +4,6 @@
<plugin>
<extension-point id="io.cloudbeaver.service" name="Web services" schema="schema/io.cloudbeaver.service.exsd"/>
<extension-point id="io.cloudbeaver.feature" name="Web features" schema="schema/io.cloudbeaver.feature.exsd"/>
<extension-point id="io.cloudbeaver.server.feature" name="Web server features" schema="schema/io.cloudbeaver.server.feature.exsd"/>
<extension-point id="io.cloudbeaver.valueSerializer" name="Web value serializers" schema="schema/io.cloudbeaver.valueSerializer.exsd"/>
<extension-point id="org.jkiss.dbeaver.auth.provider" name="%extension-point.org.jkiss.dbeaver.authProvider.name" schema="schema/org.jkiss.dbeaver.authProvider.exsd"/>
<extension-point id="io.cloudbeaver.metaParameters" name="Meta parameters" schema="schema/io.cloudbeaver.metaParameters.exsd"/>
+1 -1
View File
@@ -10,7 +10,7 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.model</artifactId>
<version>1.0.70-SNAPSHOT</version>
<version>1.0.65-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -1,34 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<schema targetNamespace="org.jkiss.dbeaver.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="io.cloudbeaver.model" id="io.cloudbeaver.server.feature" name="Web features"/>
</appInfo>
<documentation>
Web feature
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence>
<element ref="feature"/>
</sequence>
</complexType>
</element>
<element name="feature">
<annotation>
<documentation>
Web service description
</documentation>
</annotation>
</element>
</schema>
@@ -22,6 +22,7 @@ import graphql.GraphQLError;
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;
@@ -99,7 +100,7 @@ public class DBWebException extends DBException implements GraphQLError {
@Override
public Map<String, Object> getExtensions() {
StringWriter buf = new StringWriter();
CommonUtils.getRootCause(this).printStackTrace(new PrintWriter(buf, true));
GeneralUtils.getRootCause(this).printStackTrace(new PrintWriter(buf, true));
Map<String, Object> extensions = new LinkedHashMap<>();
String stString = buf.toString();
@@ -44,12 +44,10 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
public class WebDataSourceRegistryProxy implements DBPDataSourceRegistry, DataSourcePersistentRegistry, DBPDataSourceRegistryCache {
@NotNull
private final DataSourceFilter dataSourceFilter;
@NotNull
private final DataSourceRegistry<?> dataSourceRegistry;
private final DataSourceRegistry dataSourceRegistry;
public WebDataSourceRegistryProxy(@NotNull DataSourceRegistry<?> dataSourceRegistry, @NotNull DataSourceFilter filter) {
public WebDataSourceRegistryProxy(DataSourceRegistry dataSourceRegistry, DataSourceFilter filter) {
this.dataSourceRegistry = dataSourceRegistry;
this.dataSourceFilter = filter;
}
@@ -64,7 +62,7 @@ public class WebDataSourceRegistryProxy implements DBPDataSourceRegistry, DataSo
@Override
public DBPDataSourceContainer getDataSource(@NotNull String id) {
DBPDataSourceContainer dataSource = dataSourceRegistry.getDataSource(id);
if (dataSource == null || !dataSourceFilter.filter(dataSource)) {
if (dataSource == null || dataSourceFilter != null && !dataSourceFilter.filter(dataSource)) {
return null;
}
return dataSource;
@@ -73,7 +71,7 @@ public class WebDataSourceRegistryProxy implements DBPDataSourceRegistry, DataSo
@Nullable
@Override
public DBPDataSourceContainer getDataSource(@NotNull DBPDataSource dataSource) {
if (!dataSourceFilter.filter(dataSource.getContainer())) {
if (dataSourceFilter != null && !dataSourceFilter.filter(dataSource.getContainer())) {
return null;
}
return dataSourceRegistry.getDataSource(dataSource);
@@ -83,8 +81,10 @@ public class WebDataSourceRegistryProxy implements DBPDataSourceRegistry, DataSo
@Override
public DBPDataSourceContainer findDataSourceByName(String name) {
var dataSource = dataSourceRegistry.findDataSourceByName(name);
if (dataSource != null && dataSourceFilter.filter(dataSource)) {
return dataSource;
if (dataSource != null) {
if (dataSourceFilter == null || dataSourceFilter.filter(dataSource)) {
return dataSource;
}
}
return null;
}
@@ -113,26 +113,6 @@ public class WebDataSourceRegistryProxy implements DBPDataSourceRegistry, DataSo
return dataSourceRegistry.createDataSource(driver, connConfig);
}
@Override
public DBPDataSourceContainer createDataSource(
@NotNull String id,
@NotNull DBPDriver driver,
@NotNull DBPConnectionConfiguration connConfig
) {
return dataSourceRegistry.createDataSource(id, driver, connConfig);
}
@Override
public DBPDataSourceContainer createDataSource(
@NotNull DBPDataSourceConfigurationStorage dataSourceStorage,
@NotNull DBPDataSourceOrigin origin,
@NotNull String id,
@NotNull DBPDriver driver,
@NotNull DBPConnectionConfiguration configuration
) {
return dataSourceRegistry.createDataSource(dataSourceStorage, origin, id, driver, configuration);
}
@NotNull
@Override
public DBPDataSourceContainer createDataSource(@NotNull DBPDataSourceContainer source) {
@@ -186,7 +166,7 @@ public class WebDataSourceRegistryProxy implements DBPDataSourceRegistry, DataSo
return dataSourceRegistry.getRootFolders();
}
@NotNull
@Nullable
@Override
public DBPDataSourceFolder getFolder(@NotNull String path) {
return dataSourceRegistry.getFolder(path);
@@ -27,7 +27,6 @@ import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.rm.RMController;
import org.jkiss.dbeaver.model.rm.RMProject;
import org.jkiss.dbeaver.model.task.DBTTaskManager;
import org.jkiss.dbeaver.registry.DataSourceRegistry;
import org.jkiss.dbeaver.registry.rm.DataSourceRegistryRM;
import org.jkiss.dbeaver.runtime.DBWorkbench;
@@ -84,12 +83,15 @@ public abstract class WebProjectImpl extends BaseWebProjectImpl {
@NotNull
@Override
protected DBPDataSourceRegistry createDataSourceRegistry() {
return createRMRegistry();
return new WebDataSourceRegistryProxy(
new DataSourceRegistryRM(this, getResourceController(), preferenceStore),
getDataSourceFilter()
);
}
@NotNull
protected DataSourceRegistry<?> createRMRegistry() {
return new DataSourceRegistryRM<>(this, getResourceController(), preferenceStore);
public DataSourceFilter getDataSourceFilter() {
return (ds) -> true;
}
}
@@ -22,13 +22,13 @@ import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBPEvent;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.rm.RMProject;
import org.jkiss.dbeaver.model.security.SMObjectType;
import org.jkiss.dbeaver.model.security.user.SMObjectPermissions;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
/**
* Global project.
@@ -36,39 +36,31 @@ import java.util.concurrent.CopyOnWriteArraySet;
*/
public class WebSessionGlobalProjectImpl extends WebSessionProjectImpl {
private static final Log log = Log.getLog(WebSessionGlobalProjectImpl.class);
private final Set<String> accessibleConnectionIds = new CopyOnWriteArraySet<>();
private Set<String> accessibleConnectionIds = Collections.emptySet();
public WebSessionGlobalProjectImpl(@NotNull WebSession webSession, @NotNull RMProject project) {
super(webSession, project);
}
/**
* Creates data source registry that can filter data sources that are not accessible for user.
*/
@NotNull
@Override
protected DBPDataSourceRegistry createDataSourceRegistry() {
return new WebDataSourceRegistryProxy(
createRegistryWithCredentialsProvider(),
this::isDataSourceAccessible
);
}
/**
* Update info about accessible connections from a database.
*/
public void refreshAccessibleConnectionIds() {
this.accessibleConnectionIds.clear();
public synchronized void refreshAccessibleConnectionIds() {
this.accessibleConnectionIds = readAccessibleConnectionIds();
}
@NotNull
private Set<String> readAccessibleConnectionIds() {
try {
for (SMObjectPermissions smObjectPermissions : webSession.getSecurityController()
.getAllAvailableObjectsPermissions(SMObjectType.datasource)) {
String objectId = smObjectPermissions.getObjectId();
this.accessibleConnectionIds.add(objectId);
}
return webSession.getSecurityController()
.getAllAvailableObjectsPermissions(SMObjectType.datasource)
.stream()
.map(SMObjectPermissions::getObjectId)
.collect(Collectors.toSet());
} catch (DBException e) {
webSession.addSessionError(e);
log.error("Error reading connection grants", e);
return Collections.emptySet();
}
}
@@ -118,4 +110,9 @@ public class WebSessionGlobalProjectImpl extends WebSessionProjectImpl {
dataSource.dispose();
}
}
@NotNull
public DataSourceFilter getDataSourceFilter() {
return this::isDataSourceAccessible;
}
}
@@ -28,14 +28,12 @@ import org.jkiss.dbeaver.model.app.DBPDataSourceRegistryCache;
import org.jkiss.dbeaver.model.navigator.DBNModel;
import org.jkiss.dbeaver.model.rm.RMProject;
import org.jkiss.dbeaver.model.rm.RMUtils;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceEvent;
import org.jkiss.dbeaver.model.websocket.event.WSEventType;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
import org.jkiss.dbeaver.registry.DataSourceRegistry;
import org.jkiss.dbeaver.runtime.jobs.DisconnectJob;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class WebSessionProjectImpl extends WebProjectImpl {
@@ -84,12 +82,7 @@ public class WebSessionProjectImpl extends WebProjectImpl {
@NotNull
@Override
protected DBPDataSourceRegistry createDataSourceRegistry() {
return createRegistryWithCredentialsProvider();
}
@NotNull
protected DataSourceRegistry<?> createRegistryWithCredentialsProvider() {
DataSourceRegistry<?> dataSourceRegistry = createRMRegistry();
DBPDataSourceRegistry dataSourceRegistry = super.createDataSourceRegistry();
dataSourceRegistry.setAuthCredentialsProvider(webSession);
return dataSourceRegistry;
}
@@ -195,9 +188,9 @@ public class WebSessionProjectImpl extends WebProjectImpl {
* updates data sources based on event in web session
*
* @param dataSourceIds list of updated connections
* @param eventId id of event
* @param type type of event
*/
public synchronized boolean updateProjectDataSources(@NotNull List<String> dataSourceIds, @NotNull String eventId) {
public synchronized boolean updateProjectDataSources(@NotNull List<String> dataSourceIds, @NotNull WSEventType type) {
var sendDataSourceUpdatedEvent = false;
DBPDataSourceRegistry registry = getDataSourceRegistry();
// save old connections
@@ -206,9 +199,9 @@ public class WebSessionProjectImpl extends WebProjectImpl {
.filter(Objects::nonNull)
.collect(Collectors.toMap(
DBPDataSourceContainer::getId,
Function.identity())
);
if (WSDataSourceEvent.CREATED.equals(eventId) || WSDataSourceEvent.UPDATED.equals(eventId)) {
ds -> new DataSourceDescriptor((DataSourceDescriptor) ds, ds.getRegistry())
));
if (type == WSEventType.DATASOURCE_CREATED || type == WSEventType.DATASOURCE_UPDATED) {
registry.refreshConfig(dataSourceIds);
}
for (String dsId : dataSourceIds) {
@@ -216,14 +209,14 @@ public class WebSessionProjectImpl extends WebProjectImpl {
if (ds == null) {
continue;
}
switch (eventId) {
case WSDataSourceEvent.CREATED -> {
switch (type) {
case DATASOURCE_CREATED -> {
addConnection(ds);
sendDataSourceUpdatedEvent = true;
}
case WSDataSourceEvent.UPDATED -> // if settings were changed we need to send event
case DATASOURCE_UPDATED -> // if settings were changed we need to send event
sendDataSourceUpdatedEvent |= !ds.equalSettings(oldDataSources.get(dsId));
case WSDataSourceEvent.DELETED -> {
case DATASOURCE_DELETED -> {
WebDataSourceUtils.disconnectDataSource(webSession, ds);
if (registry instanceof DBPDataSourceRegistryCache dsrc) {
dsrc.removeDataSourceFromList(ds);
@@ -30,7 +30,7 @@ import java.util.Map;
public interface SMAuthProviderFederated extends SMSignOutLinkProvider {
@NotNull
String getSignInLink(String id) throws DBException;
String getSignInLink(String id, @NotNull Map<String, Object> providerConfig) throws DBException;
@Override
default String getUserSignOutLink(
@@ -21,6 +21,5 @@ package io.cloudbeaver.auth.provider.local;
public class LocalAuthProviderConstants {
public static final String PROVIDER_ID = "local";
public static final String CRED_USER = "user";
public static final String CRED_DISPLAY_NAME = "displayName";
public static final String CRED_PASSWORD = "password";
}
@@ -16,19 +16,16 @@
*/
package io.cloudbeaver.model;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
/**
* Web async task info
* Web connection info
*/
public class WebAsyncTaskInfo {
@NotNull
private final String id;
@NotNull
private final String name;
private boolean running = false;
private String id;
private String name;
private boolean running;
private Object result;
private Object extendedResult;
private String status;
@@ -36,21 +33,27 @@ public class WebAsyncTaskInfo {
private AbstractJob job;
public WebAsyncTaskInfo(@NotNull String id, @NotNull String name) {
public WebAsyncTaskInfo(String id, String name) {
this.id = id;
this.name = name;
}
@NotNull
public String getId() {
return id;
}
@NotNull
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isRunning() {
return running;
}
@@ -22,10 +22,9 @@ import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.service.security.SMUtils;
import io.cloudbeaver.service.sql.WebDataFormat;
import io.cloudbeaver.utils.CBModelConstants;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebAppUtils;
import io.cloudbeaver.utils.WebCommonUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.*;
@@ -77,8 +76,6 @@ public class WebConnectionInfo {
private String connectTime;
private String serverVersion;
private String clientVersion;
@Nullable
private Boolean credentialsSavedInSession;
private transient Map<String, Object> savedAuthProperties;
private transient List<WebNetworkHandlerConfigInput> savedNetworkCredentials;
@@ -198,8 +195,7 @@ public class WebConnectionInfo {
@Property
public boolean isCredentialsSaved() throws DBException {
// isCredentialsSaved can be true if credentials were saved during connection init for global project
return dataSourceContainer.isCredentialsSaved() && !(credentialsSavedInSession != null && credentialsSavedInSession);
return dataSourceContainer.isCredentialsSaved();
}
@Property
@@ -469,8 +465,7 @@ public class WebConnectionInfo {
if (isCanEdit()) {
return true;
}
BaseWebAppConfiguration appConfig = (BaseWebAppConfiguration) ServletAppUtils.getServletApplication()
.getAppConfiguration();
BaseWebAppConfiguration appConfig = (BaseWebAppConfiguration) WebAppUtils.getWebApplication().getAppConfiguration();
return appConfig.isShowReadOnlyConnectionInfo();
}
@@ -518,10 +513,4 @@ public class WebConnectionInfo {
return tools;
}
/**
* Updates param that checks whether credentials were saved only in session.
*/
public void setCredentialsSavedInSession(@Nullable Boolean credentialsSavedInSession) {
this.credentialsSavedInSession = credentialsSavedInSession;
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* 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.
@@ -44,12 +44,6 @@ public class WebPropertyInfo {
private DBPPropertySource propertySource;
private boolean showProtected;
private Object[] validValues;
private String[] supportedConfigurationTypes = new String[0];
private Object defaultValue;
public WebPropertyInfo(WebSession session, DBPPropertyDescriptor property, DBPPropertySource propertySource) {
this.session = session;
this.property = property;
@@ -129,7 +123,7 @@ public class WebPropertyInfo {
@Property
public Object getDefaultValue() throws DBException {
var defaultValue = property.getDefaultValue() == null ? this.defaultValue : property.getDefaultValue();
var defaultValue = property.getDefaultValue();
return defaultValue == null ? getValue() : defaultValue;
}
@@ -160,9 +154,9 @@ public class WebPropertyInfo {
}
return validValues;
}
return validValues;
return null;
}
return validValues;
return null;
}
@Property
@@ -178,7 +172,7 @@ public class WebPropertyInfo {
.map(DBPDriverConfigurationType::toString)
.toArray(String[]::new);
}
return supportedConfigurationTypes;
return new String[0];
}
@Property
@@ -258,20 +252,4 @@ public class WebPropertyInfo {
}
return null;
}
//TODO: delete after refactoring on front-end
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
//TODO: delete after refactoring on front-end
public void setValidValues(Object[] validValues) {
this.validValues = validValues;
}
//TODO: delete after refactoring on front-end
public void setSupportedConfigurationTypes(String[] supportedConfigurationTypes) {
this.supportedConfigurationTypes = supportedConfigurationTypes;
}
}
@@ -32,8 +32,8 @@ import java.nio.file.Path;
/**
* Abstract class that contains methods for loading configuration with gson.
*/
public abstract class BaseServerConfigurationController<T extends ServletServerConfiguration>
implements ServletServerConfigurationController<T> {
public abstract class BaseServerConfigurationController<T extends WebServerConfiguration>
implements WebServerConfigurationController<T> {
private static final Log log = Log.getLog(BaseServerConfigurationController.class);
@NotNull
private final Path homeDirectory;
@@ -25,13 +25,12 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
public abstract class BaseWebAppConfiguration implements ServletAppConfiguration {
public abstract class BaseWebAppConfiguration implements WebAppConfiguration {
public static final String DEFAULT_APP_ANONYMOUS_TEAM_NAME = "user";
protected final Map<String, Object> plugins;
protected String defaultUserTeam = DEFAULT_APP_ANONYMOUS_TEAM_NAME;
protected boolean resourceManagerEnabled;
protected boolean secretManagerEnabled;
protected boolean showReadOnlyConnectionInfo;
protected String[] enabledFeatures;
protected String[] disabledBetaFeatures;
@@ -43,7 +42,6 @@ public abstract class BaseWebAppConfiguration implements ServletAppConfiguration
this.enabledFeatures = null;
this.disabledBetaFeatures = new String[0];
this.showReadOnlyConnectionInfo = false;
this.secretManagerEnabled = false;
}
public BaseWebAppConfiguration(BaseWebAppConfiguration src) {
@@ -53,7 +51,6 @@ public abstract class BaseWebAppConfiguration implements ServletAppConfiguration
this.enabledFeatures = src.enabledFeatures;
this.disabledBetaFeatures = src.disabledBetaFeatures;
this.showReadOnlyConnectionInfo = src.showReadOnlyConnectionInfo;
this.secretManagerEnabled = src.secretManagerEnabled;
}
@Override
@@ -87,11 +84,6 @@ public abstract class BaseWebAppConfiguration implements ServletAppConfiguration
return resourceManagerEnabled;
}
@Override
public boolean isSecretManagerEnabled() {
return secretManagerEnabled;
}
@Override
public boolean isFeatureEnabled(String id) {
return ArrayUtils.contains(getEnabledFeatures(), id);
@@ -45,16 +45,16 @@ import java.util.List;
import java.util.Map;
/**
* Servlet application
* Web application
*/
public abstract class BaseServletApplication extends BaseApplicationImpl implements ServletApplication {
public abstract class BaseWebApplication extends BaseApplicationImpl implements WebApplication {
public static final String DEFAULT_CONFIG_FILE_PATH = "/etc/cloudbeaver.conf";
public static final String CUSTOM_CONFIG_FOLDER = "custom";
public static final String CLI_PARAM_WEB_CONFIG = "-web-config";
public static final String LOGBACK_FILE_NAME = "logback.xml";
private static final Log log = Log.getLog(BaseServletApplication.class);
private static final Log log = Log.getLog(BaseWebApplication.class);
private String instanceId;
@@ -252,7 +252,7 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
return null;
}
public abstract ServletServerConfigurationController getServerConfigurationController();
public abstract WebServerConfigurationController getServerConfigurationController();
@Override
public boolean isEnvironmentVariablesAccessible() {
@@ -1,57 +0,0 @@
/*
* 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.model.app;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import java.util.Map;
/**
* Application configuration
*/
public interface ServletAppConfiguration {
String getAnonymousUserTeam();
boolean isAnonymousAccessEnabled();
@Nullable
<T> T getResourceQuota(String quotaId);
String getDefaultUserTeam();
<T> T getPluginOption(@NotNull String pluginId, @NotNull String option);
Map<String, Object> getPluginConfig(@NotNull String pluginId, boolean create);
boolean isResourceManagerEnabled();
boolean isSecretManagerEnabled();
boolean isFeaturesEnabled(String[] requiredFeatures);
boolean isFeatureEnabled(String id);
@NotNull
default String[] getEnabledFeatures() {
return new String[0];
}
default boolean isSupportsCustomConnections() {
return true;
}
}
@@ -17,38 +17,39 @@
package io.cloudbeaver.model.app;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
import org.jkiss.code.Nullable;
import java.util.Map;
/**
* Application configuration
*/
public interface WebAppConfiguration extends ServletAppConfiguration {
DataSourceNavigatorSettings.Preset PRESET_WEB = new DataSourceNavigatorSettings.Preset("web",
"Web",
"Default view");
public interface WebAppConfiguration {
String getAnonymousUserTeam();
DBNBrowseSettings getDefaultNavigatorSettings();
boolean isAnonymousAccessEnabled();
boolean isPublicCredentialsSaveEnabled();
@Nullable
<T> T getResourceQuota(String quotaId);
boolean isAdminCredentialsSaveEnabled();
String getDefaultUserTeam();
default String[] getDisabledBetaFeatures() {
<T> T getPluginOption(@NotNull String pluginId, @NotNull String option);
Map<String, Object> getPluginConfig(@NotNull String pluginId, boolean create);
boolean isResourceManagerEnabled();
boolean isFeaturesEnabled(String[] requiredFeatures);
boolean isFeatureEnabled(String id);
@NotNull
default String[] getEnabledFeatures() {
return new String[0];
}
default String[] getEnabledAuthProviders() {
return new String[0];
default boolean isSupportsCustomConnections() {
return true;
}
@NotNull
String[] getEnabledDrivers();
@NotNull
String[] getDisabledDrivers();
Map<String, Object> getResourceQuotas();
}
@@ -35,16 +35,16 @@ import java.util.Map;
/**
* Base interface for web application
*/
public interface ServletApplication extends DBPApplication {
public interface WebApplication extends DBPApplication {
boolean isConfigurationMode();
default boolean isInitializationMode() {
return false;
}
default boolean isInitializationMode() {
return false;
}
ServletAppConfiguration getAppConfiguration();
WebAppConfiguration getAppConfiguration();
ServletServerConfiguration getServerConfiguration();
WebServerConfiguration getServerConfiguration();
Path getDataDirectory(boolean create);
@@ -20,8 +20,10 @@ package io.cloudbeaver.model.app;
import io.cloudbeaver.auth.CBAuthConstants;
import org.jkiss.dbeaver.DBException;
public interface ServletAuthApplication extends ServletApplication {
ServletAuthConfiguration getAuthConfiguration();
import java.util.List;
public interface WebAuthApplication extends WebApplication {
WebAuthConfiguration getAuthConfiguration();
String getAuthServiceURL();
@@ -25,7 +25,7 @@ import java.util.Set;
/**
* Application authentication configuration
*/
public interface ServletAuthConfiguration {
public interface WebAuthConfiguration {
String getDefaultAuthProvider();
@@ -25,7 +25,7 @@ import java.util.Map;
* Web server configuration.
* Contains only server configuration properties.
*/
public interface ServletServerConfiguration {
public interface WebServerConfiguration {
boolean isDevelMode();
default String getRootURI() {
@@ -39,4 +39,5 @@ public interface ServletServerConfiguration {
default Map<String, Object> getProductSettings() {
return Map.of();
}
}
@@ -27,7 +27,7 @@ import java.util.Map;
* Server configuration controller.
* Works with app server configuration (loads, updates)
*/
public interface ServletServerConfigurationController<T extends ServletServerConfiguration> {
public interface WebServerConfigurationController<T extends WebServerConfiguration> {
/**
* Loads server configuration.
@@ -19,8 +19,7 @@ package io.cloudbeaver.model.config;
import com.google.gson.annotations.Expose;
import io.cloudbeaver.auth.provider.local.LocalAuthProviderConstants;
import io.cloudbeaver.model.app.BaseWebAppConfiguration;
import io.cloudbeaver.model.app.WebAppConfiguration;
import io.cloudbeaver.model.app.ServletAuthConfiguration;
import io.cloudbeaver.model.app.WebAuthConfiguration;
import io.cloudbeaver.registry.WebAuthProviderDescriptor;
import io.cloudbeaver.registry.WebAuthProviderRegistry;
import org.jkiss.code.NotNull;
@@ -37,8 +36,9 @@ import java.util.*;
/**
* Application configuration
*/
public class CBAppConfig extends BaseWebAppConfiguration implements ServletAuthConfiguration, WebAppConfiguration {
public class CBAppConfig extends BaseWebAppConfiguration implements WebAuthConfiguration {
private static final Log log = Log.getLog(CBAppConfig.class);
public static final DataSourceNavigatorSettings.Preset PRESET_WEB = new DataSourceNavigatorSettings.Preset("web", "Web", "Default view");
public static final DataSourceNavigatorSettings DEFAULT_VIEW_SETTINGS = PRESET_WEB.getSettings();
private final Set<SMAuthProviderCustomConfiguration> authConfigurations;
@@ -47,6 +47,8 @@ public class CBAppConfig extends BaseWebAppConfiguration implements ServletAuthC
private final Map<String, SMAuthProviderCustomConfiguration> authConfiguration;
private boolean supportsCustomConnections;
private boolean supportsConnectionBrowser;
private boolean supportsUserWorkspaces;
private boolean enableReverseProxyAuth;
private boolean forwardProxy;
private boolean publicCredentialsSaveEnabled;
@@ -78,6 +80,8 @@ public class CBAppConfig extends BaseWebAppConfiguration implements ServletAuthC
this.anonymousUserRole = DEFAULT_APP_ANONYMOUS_TEAM_NAME;
this.anonymousUserTeam = DEFAULT_APP_ANONYMOUS_TEAM_NAME;
this.supportsCustomConnections = true;
this.supportsConnectionBrowser = false;
this.supportsUserWorkspaces = false;
this.publicCredentialsSaveEnabled = true;
this.adminCredentialsSaveEnabled = true;
this.redirectOnFederatedAuth = false;
@@ -102,6 +106,8 @@ public class CBAppConfig extends BaseWebAppConfiguration implements ServletAuthC
this.anonymousUserRole = src.anonymousUserRole;
this.anonymousUserTeam = src.anonymousUserTeam;
this.supportsCustomConnections = src.supportsCustomConnections;
this.supportsConnectionBrowser = src.supportsConnectionBrowser;
this.supportsUserWorkspaces = src.supportsUserWorkspaces;
this.publicCredentialsSaveEnabled = src.publicCredentialsSaveEnabled;
this.adminCredentialsSaveEnabled = src.adminCredentialsSaveEnabled;
this.redirectOnFederatedAuth = src.redirectOnFederatedAuth;
@@ -134,10 +140,6 @@ public class CBAppConfig extends BaseWebAppConfiguration implements ServletAuthC
this.resourceManagerEnabled = resourceManagerEnabled;
}
public void setSecretManagerEnabled(boolean secretManagerEnabled) {
this.secretManagerEnabled = secretManagerEnabled;
}
public boolean isSupportsCustomConnections() {
return supportsCustomConnections;
}
@@ -146,6 +148,14 @@ public class CBAppConfig extends BaseWebAppConfiguration implements ServletAuthC
this.supportsCustomConnections = supportsCustomConnections;
}
public boolean isSupportsConnectionBrowser() {
return supportsConnectionBrowser;
}
public boolean isSupportsUserWorkspaces() {
return supportsUserWorkspaces;
}
public boolean isPublicCredentialsSaveEnabled() {
return publicCredentialsSaveEnabled;
}
@@ -166,7 +176,6 @@ public class CBAppConfig extends BaseWebAppConfiguration implements ServletAuthC
return redirectOnFederatedAuth;
}
@NotNull
public String[] getEnabledDrivers() {
return enabledDrivers;
}
@@ -175,7 +184,6 @@ public class CBAppConfig extends BaseWebAppConfiguration implements ServletAuthC
this.enabledDrivers = enabledDrivers;
}
@NotNull
public String[] getDisabledDrivers() {
return disabledDrivers;
}
@@ -0,0 +1,51 @@
/*
* 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.model.rm;
import io.cloudbeaver.model.app.WebApplication;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.rm.RMController;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class RMControllerInvocationHandler implements InvocationHandler {
private final WebApplication webApplication;
private final RMController rmController;
public RMControllerInvocationHandler(RMController rmController, WebApplication webApplication) {
this.webApplication = webApplication;
this.rmController = rmController;
}
private void checkIsRmEnabled() throws DBException {
if (!webApplication.getAppConfiguration().isResourceManagerEnabled()) {
throw new DBException("Resource Manager disabled");
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
checkIsRmEnabled();
return method.invoke(rmController, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* 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.
@@ -18,11 +18,11 @@ package io.cloudbeaver.model.rm.local;
import io.cloudbeaver.BaseWebProjectImpl;
import io.cloudbeaver.DBWConstants;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.model.rm.lock.RMFileLockController;
import io.cloudbeaver.service.security.SMUtils;
import io.cloudbeaver.service.sql.WebSQLConstants;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebAppUtils;
import io.cloudbeaver.utils.file.UniversalFileVisitor;
import org.eclipse.core.runtime.IPath;
import org.jkiss.code.NotNull;
@@ -39,6 +39,7 @@ import org.jkiss.dbeaver.model.security.SMController;
import org.jkiss.dbeaver.model.security.SMObjectType;
import org.jkiss.dbeaver.model.sql.DBQuotaException;
import org.jkiss.dbeaver.model.websocket.event.MessageType;
import org.jkiss.dbeaver.model.websocket.event.WSEventType;
import org.jkiss.dbeaver.model.websocket.event.WSSessionLogUpdatedEvent;
import org.jkiss.dbeaver.registry.ResourceTypeDescriptor;
import org.jkiss.dbeaver.registry.ResourceTypeRegistry;
@@ -83,7 +84,7 @@ public class LocalResourceController extends BaseLocalResourceController {
Path sharedProjectsPath,
Supplier<SMController> smControllerSupplier
) throws DBException {
super(workspace, new RMFileLockController(ServletAppUtils.getServletApplication()));
super(workspace, new RMFileLockController(WebAppUtils.getWebApplication()));
this.credentialsProvider = credentialsProvider;
this.rootPath = rootPath;
this.userProjectsPath = userProjectsPath;
@@ -114,22 +115,13 @@ public class LocalResourceController extends BaseLocalResourceController {
if (project == null || refresh) {
SessionContextImpl sessionContext = new SessionContextImpl(null);
RMProject rmProject = makeProjectFromId(projectId, false);
project = createWebProjectImpl(projectId, sessionContext, rmProject);
project = new InternalWebProjectImpl(sessionContext, rmProject, getProjectPath(projectId));
projectRegistries.put(projectId, project);
}
return project;
}
}
@NotNull
protected InternalWebProjectImpl createWebProjectImpl(
String projectId,
SessionContextImpl sessionContext,
RMProject rmProject
) throws DBException {
return new InternalWebProjectImpl(sessionContext, rmProject, getProjectPath(projectId));
}
@NotNull
@Override
public RMProject[] listAccessibleProjects() throws DBException {
@@ -153,7 +145,7 @@ public class LocalResourceController extends BaseLocalResourceController {
}
// Checking if private projects are enabled in the configuration and if the user has permission to them
var webApp = ServletAppUtils.getServletApplication();
var webApp = WebAppUtils.getWebApplication();
var userHasPrivateProjectPermission = userHasAccessToPrivateProject(webApp, activeUserCreds);
if (webApp.getAppConfiguration().isSupportsCustomConnections() && userHasPrivateProjectPermission) {
var userProjectPermission = getProjectPermissions(null, RMProjectType.USER);
@@ -162,7 +154,7 @@ public class LocalResourceController extends BaseLocalResourceController {
projects.add(0, userProject);
}
}
if (ServletAppUtils.getServletApplication().isMultiNode()) {
if (WebAppUtils.getWebApplication().isMultiNode()) {
for (RMProject rmProject : projects) {
handleProjectOpened(rmProject.getId());
}
@@ -208,7 +200,7 @@ public class LocalResourceController extends BaseLocalResourceController {
}
return getRmProjectPermissions(projectId, activeUserCreds);
case USER:
var webApp = ServletAppUtils.getServletApplication();
var webApp = WebAppUtils.getWebApplication();
if (userHasAccessToPrivateProject(webApp, activeUserCreds)) {
return Set.of(RMProjectPermission.RESOURCE_EDIT, RMProjectPermission.DATA_SOURCES_EDIT);
}
@@ -217,7 +209,7 @@ public class LocalResourceController extends BaseLocalResourceController {
}
}
private boolean userHasAccessToPrivateProject(ServletApplication webApp, @Nullable SMCredentials activeUserCreds) {
private boolean userHasAccessToPrivateProject(WebApplication webApp, @Nullable SMCredentials activeUserCreds) {
return !webApp.isMultiNode() ||
(activeUserCreds != null && activeUserCreds.hasPermission(DBWConstants.PERMISSION_PRIVATE_PROJECT_ACCESS));
}
@@ -285,7 +277,7 @@ public class LocalResourceController extends BaseLocalResourceController {
try {
log.debug("Creating project '" + project.getId() + "'");
Files.createDirectories(projectPath);
if (ServletAppUtils.getServletApplication().isMultiNode()) {
if (WebAppUtils.getWebApplication().isMultiNode()) {
createResourceTypeFolders(projectPath);
}
fireRmProjectAddEvent(project);
@@ -445,9 +437,6 @@ public class LocalResourceController extends BaseLocalResourceController {
if (Files.exists(newTargetPath)) {
throw new DBException("Resource with name %s already exists".formatted(newTargetPath.getFileName()));
}
if (!Files.exists(newTargetPath.getParent())) {
throw new DBException("Resource %s doesn't exists".formatted(newTargetPath.getParent().getFileName()));
}
try {
Files.move(oldTargetPath, newTargetPath);
} catch (IOException e) {
@@ -519,7 +508,7 @@ public class LocalResourceController extends BaseLocalResourceController {
log.warn("Failed to remove resources properties", e);
}
try {
if (Files.isDirectory(targetPath)) {
if (targetPath.toFile().isDirectory()) {
IOUtils.deleteDirectory(targetPath);
} else {
Files.delete(targetPath);
@@ -589,7 +578,7 @@ public class LocalResourceController extends BaseLocalResourceController {
) throws DBException {
try (var ignoredLock = lockController.lockProject(projectId, "setResourceContents")) {
validateResourcePath(resourcePath);
Number fileSizeLimit = ServletAppUtils.getServletApplication()
Number fileSizeLimit = WebAppUtils.getWebApplication()
.getAppConfiguration()
.getResourceQuota(WebSQLConstants.QUOTA_PROP_RM_FILE_SIZE_LIMIT);
if (fileSizeLimit != null && data.length > fileSizeLimit.longValue()) {
@@ -783,8 +772,9 @@ public class LocalResourceController extends BaseLocalResourceController {
fileHandler.projectOpened(projectId);
} catch (Exception e) {
if (credentialsProvider.getActiveUserCredentials() != null) {
ServletAppUtils.getServletApplication().getEventController().addEvent(
WebAppUtils.getWebApplication().getEventController().addEvent(
new WSSessionLogUpdatedEvent(
WSEventType.SESSION_LOG_UPDATED,
credentialsProvider.getActiveUserCredentials().getSmSessionId(),
credentialsProvider.getActiveUserCredentials().getUserId(),
MessageType.ERROR,
@@ -801,8 +791,9 @@ public class LocalResourceController extends BaseLocalResourceController {
fileHandler.beforeFileRead(projectId, file);
} catch (Exception e) {
if (credentialsProvider.getActiveUserCredentials() != null) {
ServletAppUtils.getServletApplication().getEventController().addEvent(
WebAppUtils.getWebApplication().getEventController().addEvent(
new WSSessionLogUpdatedEvent(
WSEventType.SESSION_LOG_UPDATED,
credentialsProvider.getActiveUserCredentials().getSmSessionId(),
credentialsProvider.getActiveUserCredentials().getUserId(),
MessageType.ERROR,
@@ -955,19 +946,16 @@ public class LocalResourceController extends BaseLocalResourceController {
return "pong (RM)";
}
public static class Builder {
protected final SMCredentialsProvider credentialsProvider;
protected final Supplier<SMController> smController;
protected final DBPWorkspace workspace;
public static final class Builder {
private final SMCredentialsProvider credentialsProvider;
private final Supplier<SMController> smController;
private final DBPWorkspace workspace;
protected Path rootPath;
protected Path userProjectsPath;
protected Path sharedProjectsPath;
private Path rootPath;
private Path userProjectsPath;
private Path sharedProjectsPath;
protected Builder(
DBPWorkspace workspace, SMCredentialsProvider credentialsProvider,
Supplier<SMController> smControllerSupplier
) {
private Builder(DBPWorkspace workspace, SMCredentialsProvider credentialsProvider, Supplier<SMController> smControllerSupplier) {
this.workspace = workspace;
this.credentialsProvider = credentialsProvider;
this.smController = smControllerSupplier;
@@ -17,7 +17,7 @@
package io.cloudbeaver.model.rm.lock;
import com.google.gson.Gson;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.WebApplication;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
@@ -50,12 +50,12 @@ public class RMFileLockController {
private final int maxLockTime;
public RMFileLockController(ServletApplication application) throws DBException {
public RMFileLockController(WebApplication application) throws DBException {
this(application, DEFAULT_MAX_LOCK_TIME);
}
// for tests
public RMFileLockController(ServletApplication application, int maxLockTime) throws DBException {
public RMFileLockController(WebApplication application, int maxLockTime) throws DBException {
this.lockFolderPath = application.getWorkspaceDirectory()
.resolve(DBPWorkspace.METADATA_FOLDER)
.resolve(LOCK_META_FOLDER);
@@ -17,8 +17,8 @@
package io.cloudbeaver.model.session;
import io.cloudbeaver.model.WebServerMessage;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.ServletAuthApplication;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.model.app.WebAuthApplication;
import io.cloudbeaver.websocket.CBWebSessionEventHandler;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -51,14 +51,14 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
@NotNull
protected final WebUserContext userContext;
@NotNull
protected final ServletApplication application;
protected final WebApplication application;
protected volatile long lastAccessTime;
private final List<CBWebSessionEventHandler> sessionEventHandlers = new CopyOnWriteArrayList<>();
private WebSessionEventsFilter eventsFilter = new WebSessionEventsFilter();
private final WebSessionWorkspace workspace;
public BaseWebSession(@NotNull String id, @NotNull ServletApplication application) throws DBException {
public BaseWebSession(@NotNull String id, @NotNull WebApplication application) throws DBException {
this.id = id;
this.application = application;
this.createTime = System.currentTimeMillis();
@@ -153,7 +153,7 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
}
@NotNull
public ServletApplication getApplication() {
public WebApplication getApplication() {
return application;
}
@@ -238,7 +238,7 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
@Property
public long getRemainingTime() {
if (application instanceof ServletAuthApplication authApplication) {
if (application instanceof WebAuthApplication authApplication) {
return authApplication.getMaxSessionIdleTime() + lastAccessTime - System.currentTimeMillis();
}
return Integer.MAX_VALUE;
@@ -17,7 +17,7 @@
package io.cloudbeaver.model.session;
import io.cloudbeaver.model.WebServerMessage;
import io.cloudbeaver.model.app.ServletAuthApplication;
import io.cloudbeaver.model.app.WebAuthApplication;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
@@ -29,7 +29,7 @@ import org.jkiss.dbeaver.model.auth.SMSessionPrincipal;
public class WebHeadlessSession extends BaseWebSession {
public WebHeadlessSession(
@NotNull String id,
@NotNull ServletAuthApplication application
@NotNull WebAuthApplication application
) throws DBException {
super(id, application);
}
@@ -17,33 +17,22 @@
package io.cloudbeaver.model.session;
import jakarta.servlet.http.HttpServletRequest;
import org.jkiss.code.Nullable;
public class WebHttpRequestInfo {
public static final String USER_AGENT = "User-Agent";
@Nullable
private final String id;
@Nullable
private final Object locale;
@Nullable
private final String lastRemoteAddress;
@Nullable
private final String lastRemoteUserAgent;
public WebHttpRequestInfo(HttpServletRequest request) {
this.id = request.getSession() == null ? null : request.getSession().getId();
this.id = request.getSession().getId();
this.locale = request.getAttribute("locale");
this.lastRemoteAddress = request.getRemoteAddr();
this.lastRemoteUserAgent = request.getHeader(USER_AGENT);
this.lastRemoteUserAgent = request.getHeader("User-Agent");
}
public WebHttpRequestInfo(
@Nullable String id,
@Nullable Object locale,
@Nullable String lastRemoteAddress,
@Nullable String lastRemoteUserAgent
) {
public WebHttpRequestInfo(String id, Object locale, String lastRemoteAddress, String lastRemoteUserAgent) {
this.id = id;
this.locale = locale;
this.lastRemoteAddress = lastRemoteAddress;
@@ -54,17 +43,14 @@ public class WebHttpRequestInfo {
return id;
}
@Nullable
public Object getLocale() {
return locale;
}
@Nullable
public String getLastRemoteAddress() {
return lastRemoteAddress;
}
@Nullable
public String getLastRemoteUserAgent() {
return lastRemoteUserAgent;
}
@@ -24,15 +24,13 @@ import io.cloudbeaver.*;
import io.cloudbeaver.model.WebAsyncTaskInfo;
import io.cloudbeaver.model.WebConnectionInfo;
import io.cloudbeaver.model.WebServerMessage;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.ServletAuthApplication;
import io.cloudbeaver.model.session.monitor.TaskProgressMonitor;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.model.app.WebAuthApplication;
import io.cloudbeaver.model.user.WebUser;
import io.cloudbeaver.service.DBWSessionHandler;
import io.cloudbeaver.service.sql.WebSQLConstants;
import io.cloudbeaver.utils.CBModelConstants;
import io.cloudbeaver.utils.WebDataSourceUtils;
import io.cloudbeaver.utils.WebEventUtils;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@@ -59,11 +57,13 @@ import org.jkiss.dbeaver.model.rm.RMUtils;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
import org.jkiss.dbeaver.model.runtime.BaseProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.ProxyProgressMonitor;
import org.jkiss.dbeaver.model.security.SMAdminController;
import org.jkiss.dbeaver.model.security.SMConstants;
import org.jkiss.dbeaver.model.security.SMController;
import org.jkiss.dbeaver.model.sql.DBQuotaException;
import org.jkiss.dbeaver.model.websocket.event.MessageType;
import org.jkiss.dbeaver.model.websocket.event.WSEventType;
import org.jkiss.dbeaver.model.websocket.event.WSSessionLogUpdatedEvent;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.utils.CommonUtils;
@@ -114,7 +114,7 @@ public class WebSession extends BaseWebSession
public WebSession(
@NotNull WebHttpRequestInfo requestInfo,
@NotNull ServletAuthApplication application,
@NotNull WebAuthApplication application,
@NotNull Map<String, DBWSessionHandler> sessionHandlers
) throws DBException {
this(requestInfo.getId(),
@@ -128,7 +128,7 @@ public class WebSession extends BaseWebSession
protected WebSession(
@NotNull String id,
@Nullable String locale,
@NotNull ServletApplication application,
@NotNull WebApplication application,
@NotNull Map<String, DBWSessionHandler> sessionHandlers
) throws DBException {
super(id, application);
@@ -316,7 +316,7 @@ public class WebSession extends BaseWebSession
if (project.isGlobal()) {
sessionProject = createGlobalProject(project);
} else {
sessionProject = createSessionProject(project);
sessionProject = new WebSessionProjectImpl(this, project, getProjectPath(project));
}
// do not load data sources for anonymous project
if (project.getType() == RMProjectType.USER && userContext.getUser() == null) {
@@ -329,10 +329,6 @@ public class WebSession extends BaseWebSession
return sessionProject;
}
protected WebSessionProjectImpl createSessionProject(@NotNull RMProject project) throws DBException {
return new WebSessionProjectImpl(this, project, getProjectPath(project));
}
@NotNull
protected Path getProjectPath(@NotNull RMProject project) throws DBException {
return RMUtils.getProjectPath(project);
@@ -511,7 +507,7 @@ public class WebSession extends BaseWebSession
///////////////////////////////////////////////////////
// Async model
public WebAsyncTaskInfo getAsyncTask(@NotNull String taskId, @NotNull String taskName, boolean create) {
public WebAsyncTaskInfo getAsyncTask(String taskId, String taskName, boolean create) {
synchronized (asyncTasks) {
WebAsyncTaskInfo taskInfo = asyncTasks.get(taskId);
if (taskInfo == null && create) {
@@ -528,6 +524,7 @@ public class WebSession extends BaseWebSession
if (taskInfo == null) {
throw new DBWebException("Task '" + taskId + "' not found");
}
taskInfo.setRunning(taskInfo.getJob() != null && !taskInfo.getJob().isFinished());
if (removeOnFinish && !taskInfo.isRunning()) {
asyncTasks.remove(taskId);
}
@@ -550,7 +547,7 @@ public class WebSession extends BaseWebSession
return true;
}
public WebAsyncTaskInfo createAndRunAsyncTask(@NotNull String taskName, @NotNull WebAsyncTaskProcessor<?> runnable) {
public WebAsyncTaskInfo createAndRunAsyncTask(String taskName, WebAsyncTaskProcessor<?> runnable) {
int taskId = TASK_ID.incrementAndGet();
WebAsyncTaskInfo asyncTask = getAsyncTask(String.valueOf(taskId), taskName, true);
@@ -559,8 +556,7 @@ public class WebSession extends BaseWebSession
protected IStatus run(DBRProgressMonitor monitor) {
int curTaskCount = taskCount.incrementAndGet();
DBRProgressMonitor taskMonitor = new TaskProgressMonitor(monitor, WebSession.this, asyncTask);
TaskProgressMonitor taskMonitor = new TaskProgressMonitor(monitor, asyncTask);
try {
Number queryLimit = application.getAppConfiguration().getResourceQuota(WebSQLConstants.QUOTA_PROP_QUERY_LIMIT);
if (queryLimit != null && curTaskCount > queryLimit.intValue()) {
@@ -572,6 +568,7 @@ public class WebSession extends BaseWebSession
asyncTask.setResult(runnable.getResult());
asyncTask.setExtendedResult(runnable.getExtendedResults());
asyncTask.setStatus("Finished");
asyncTask.setRunning(false);
} catch (InvocationTargetException e) {
addSessionError(e.getTargetException());
asyncTask.setJobError(e.getTargetException());
@@ -579,8 +576,6 @@ public class WebSession extends BaseWebSession
asyncTask.setJobError(e);
} finally {
taskCount.decrementAndGet();
asyncTask.setRunning(false);
WebEventUtils.sendAsyncTaskEvent(WebSession.this, asyncTask);
}
return Status.OK_STATUS;
}
@@ -601,6 +596,7 @@ public class WebSession extends BaseWebSession
sessionMessages.add(message);
}
addSessionEvent(new WSSessionLogUpdatedEvent(
WSEventType.SESSION_LOG_UPDATED,
this.userContext.getSmSessionId(),
this.userContext.getUserId(),
MessageType.ERROR,
@@ -989,6 +985,27 @@ public class WebSession extends BaseWebSession
}
}
private static class TaskProgressMonitor extends ProxyProgressMonitor {
private final WebAsyncTaskInfo asyncTask;
public TaskProgressMonitor(DBRProgressMonitor original, WebAsyncTaskInfo asyncTask) {
super(original);
this.asyncTask = asyncTask;
}
@Override
public void beginTask(String name, int totalWork) {
super.beginTask(name, totalWork);
asyncTask.setStatus(name);
}
@Override
public void subTask(String name) {
super.subTask(name);
asyncTask.setStatus(name);
}
}
private record PersistentAttribute(Object value) {
}
@@ -20,11 +20,11 @@ package io.cloudbeaver.model.session;
import io.cloudbeaver.DBWUserIdentity;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.auth.SMAuthProviderExternal;
import io.cloudbeaver.model.app.ServletAuthConfiguration;
import io.cloudbeaver.model.app.WebAuthConfiguration;
import io.cloudbeaver.model.user.WebUser;
import io.cloudbeaver.registry.WebAuthProviderDescriptor;
import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
@@ -82,7 +82,7 @@ public class WebSessionAuthProcessor {
@SuppressWarnings("unchecked")
private List<WebAuthInfo> finishWebSessionAuthorization(SMAuthInfo authInfo) throws DBException {
boolean configMode = ServletAppUtils.getServletApplication().isConfigurationMode();
boolean configMode = WebAppUtils.getWebApplication().isConfigurationMode();
boolean alreadyLoggedIn = webSession.getUser() != null;
boolean resetUserStateOnError = !alreadyLoggedIn;
@@ -127,7 +127,7 @@ public class WebSessionAuthProcessor {
DBWUserIdentity userIdentity = null;
var providerConfigId = authConfiguration.getAuthProviderConfigurationId();
var providerConfig = ServletAppUtils.getAuthApplication()
var providerConfig = WebAppUtils.getWebAuthApplication()
.getAuthConfiguration()
.getAuthProviderConfiguration(providerConfigId);
if (authProviderExternal != null) {
@@ -194,8 +194,7 @@ public class WebSessionAuthProcessor {
}
private boolean isProviderEnabled(@NotNull String providerId) {
ServletAuthConfiguration appConfiguration = (ServletAuthConfiguration) ServletAppUtils.getServletApplication()
.getAppConfiguration();
WebAuthConfiguration appConfiguration = (WebAuthConfiguration) WebAppUtils.getWebApplication().getAppConfiguration();
return appConfiguration.isAuthProviderEnabled(providerId);
}
}
@@ -17,7 +17,7 @@
package io.cloudbeaver.model.session;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.model.user.WebUser;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -50,7 +50,7 @@ import java.util.stream.Collectors;
public class WebUserContext implements SMCredentialsProvider {
private static final Log log = Log.getLog(WebUserContext.class);
private final ServletApplication application;
private final WebApplication application;
private final DBPWorkspace workspace;
private WebUser user;
@@ -67,7 +67,7 @@ public class WebUserContext implements SMCredentialsProvider {
private Set<String> accessibleProjectIds = new HashSet<>();
private final WebSessionPreferenceStore preferenceStore;
public WebUserContext(ServletApplication application, DBPWorkspace workspace) throws DBException {
public WebUserContext(WebApplication application, DBPWorkspace workspace) throws DBException {
this.application = application;
this.workspace = workspace;
this.securityController = application.createSecurityController(this);
@@ -1,55 +0,0 @@
/*
* 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.model.session.monitor;
import io.cloudbeaver.model.WebAsyncTaskInfo;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.utils.WebEventUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.ProxyProgressMonitor;
/**
* Task progress monitor.
* Used by async GQL requests.
*/
public class TaskProgressMonitor extends ProxyProgressMonitor {
@NotNull
private final WebAsyncTaskInfo asyncTask;
private final WebSession webSession;
public TaskProgressMonitor(DBRProgressMonitor original, @NotNull WebSession webSession, @NotNull WebAsyncTaskInfo asyncTask) {
super(original);
this.webSession = webSession;
this.asyncTask = asyncTask;
}
@Override
public void beginTask(String name, int totalWork) {
super.beginTask(name, totalWork);
asyncTask.setStatus(name);
WebEventUtils.sendAsyncTaskEvent(webSession, asyncTask);
}
@Override
public void subTask(String name) {
super.subTask(name);
asyncTask.setStatus(name);
WebEventUtils.sendAsyncTaskEvent(webSession, asyncTask);
}
}
@@ -92,7 +92,7 @@ public class WebUserOriginInfo implements WebObjectOrigin {
}
try {
SMAuthProvider<?> authProvider = this.authProviderDescriptor.getInstance();
if (authProvider instanceof SMAuthProviderExternal && !authProviderDescriptor.isAuthHidden()) {
if (authProvider instanceof SMAuthProviderExternal) {
// read user's info from credentials, previously we tried to read data from external service using
// SMAuthProviderExternal#getUserDetails
var creds = loadCredentials();
@@ -19,7 +19,7 @@ package io.cloudbeaver.registry;
import io.cloudbeaver.auth.CBAuthConstants;
import io.cloudbeaver.auth.SMAuthProviderFederated;
import io.cloudbeaver.auth.SMSignOutLinkProvider;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebAppUtils;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.auth.SMAuthProvider;
@@ -74,52 +74,46 @@ public class WebAuthProviderConfiguration {
@Property
public String getSignInLink() throws DBException {
SMAuthProvider<?> instance = providerDescriptor.getInstance();
return instance instanceof SMAuthProviderFederated smAuthProviderFederated ?
buildRedirectUrl(smAuthProviderFederated.getSignInLink(getId()))
return instance instanceof SMAuthProviderFederated ?
buildRedirectUrl(((SMAuthProviderFederated) instance).getSignInLink(getId(), config.getParameters()))
: null;
}
private String buildRedirectUrl(String baseUrl) {
return baseUrl + "?" + CBAuthConstants.CB_REDIRECT_URL_REQUEST_PARAM + "=" + ServletAppUtils.getFullServerUrl();
return baseUrl + "?" + CBAuthConstants.CB_REDIRECT_URL_REQUEST_PARAM + "=" + WebAppUtils.getFullServerUrl();
}
@Property
public String getSignOutLink() throws DBException {
SMAuthProvider<?> instance = providerDescriptor.getInstance();
return instance instanceof SMSignOutLinkProvider smSignOutLinkProvider
? smSignOutLinkProvider.getCommonSignOutLink(getId(), config.getParameters())
return instance instanceof SMSignOutLinkProvider
? ((SMSignOutLinkProvider) instance).getCommonSignOutLink(getId(), config.getParameters())
: null;
}
@Property
public String getRedirectLink() throws DBException {
SMAuthProvider<?> instance = providerDescriptor.getInstance();
return instance instanceof SMAuthProviderFederated smAuthProviderFederated
? smAuthProviderFederated.getRedirectLink(getId(), config.getParameters())
: null;
return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getRedirectLink(getId(), config.getParameters()) : null;
}
@Property
public String getMetadataLink() throws DBException {
SMAuthProvider<?> instance = providerDescriptor.getInstance();
return instance instanceof SMAuthProviderFederated smAuthProviderFederated
? smAuthProviderFederated.getMetadataLink(getId(), config.getParameters())
: null;
return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getMetadataLink(getId(), config.getParameters()) : null;
}
@Property
public String getAcsLink() throws DBException {
SMAuthProvider<?> instance = providerDescriptor.getInstance();
return instance instanceof SMAuthProviderFederated smAuthProviderFederated
? smAuthProviderFederated.getAcsLink(getId(), config.getParameters())
: null;
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
? smAuthProviderFederated.getEntityIdLink(getId(), config.getParameters())
return instance instanceof SMAuthProviderFederated
? ((SMAuthProviderFederated) instance).getEntityIdLink(getId(), config.getParameters())
: null;
}
@@ -22,8 +22,6 @@ import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPImage;
import org.jkiss.dbeaver.model.DBPNamedObjectLocalized;
import org.jkiss.dbeaver.model.DBPObjectWithDescriptionLocalized;
import org.jkiss.dbeaver.model.auth.AuthPropertyDescriptor;
import org.jkiss.dbeaver.model.auth.SMAuthProvider;
import org.jkiss.dbeaver.model.impl.AbstractDescriptor;
@@ -75,7 +73,7 @@ public class WebAuthProviderDescriptor extends AbstractDescriptor {
this.isCaseInsensitive = CommonUtils.toBoolean(cfg.getAttribute("caseInsensitive"));
for (IConfigurationElement cfgElement : cfg.getChildren("configuration")) {
List<WebAuthProviderProperty> properties = WebAuthProviderRegistry.readProperties(cfgElement, getId());
List<WebAuthProviderProperty> properties = WebAuthProviderRegistry.readProperties(cfgElement);
for (WebAuthProviderProperty property : properties) {
configurationParameters.put(CommonUtils.toString(property.getId()), property);
}
@@ -19,18 +19,15 @@ package io.cloudbeaver.registry;
import org.eclipse.core.runtime.IConfigurationElement;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.impl.LocalizedPropertyDescriptor;
import org.jkiss.dbeaver.model.impl.PropertyDescriptor;
public class WebAuthProviderProperty extends LocalizedPropertyDescriptor {
public class WebAuthProviderProperty extends PropertyDescriptor {
private final String[] requiredFeatures;
@Nullable
private final String type;
private final String authProviderId;
public WebAuthProviderProperty(String category, IConfigurationElement config, String authProviderId) {
public WebAuthProviderProperty(String category, IConfigurationElement config) {
super(category, config);
this.authProviderId = authProviderId;
String featuresAttr = config.getAttribute("requiredFeatures");
this.requiredFeatures = featuresAttr == null ? new String[0] : featuresAttr.split(",");
this.type = config.getAttribute("type");
@@ -45,13 +42,4 @@ public class WebAuthProviderProperty extends LocalizedPropertyDescriptor {
public String getType() {
return type;
}
@Override
public String getPropertyId() {
if (authProviderId != null) {
return "prop.auth.model." + authProviderId + "." + this.getId();
} else {
return "prop.auth.model." + this.getId();
}
}
}
@@ -81,13 +81,13 @@ public class WebAuthProviderRegistry {
}
}
static List<WebAuthProviderProperty> readProperties(IConfigurationElement root, String authProviderId) {
static List<WebAuthProviderProperty> readProperties(IConfigurationElement root) {
List<WebAuthProviderProperty> properties = new ArrayList<>();
for (IConfigurationElement propGroup : ArrayUtils.safeArray(root.getChildren(PropertyDescriptor.TAG_PROPERTY_GROUP))) {
String category = propGroup.getAttribute(PropertyDescriptor.ATTR_LABEL);
IConfigurationElement[] propElements = propGroup.getChildren(PropertyDescriptor.TAG_PROPERTY);
for (IConfigurationElement prop : propElements) {
WebAuthProviderProperty propertyDescriptor = new WebAuthProviderProperty(category, prop, authProviderId);
WebAuthProviderProperty propertyDescriptor = new WebAuthProviderProperty(category, prop);
properties.add(propertyDescriptor);
}
}
@@ -34,7 +34,7 @@ public class WebCommonAuthProviderPropertyDescriptor extends AbstractDescriptor
public WebCommonAuthProviderPropertyDescriptor(IConfigurationElement cfg) {
super(cfg);
configurationParameters = WebAuthProviderRegistry.readProperties(cfg, null);
configurationParameters = WebAuthProviderRegistry.readProperties(cfg);
String supportedCategoriesAttr = cfg.getAttribute("supportedProviderCategories");
if (CommonUtils.isNotEmpty(supportedCategoriesAttr)) {
supportedProviderCategories.addAll(Arrays.stream(supportedCategoriesAttr.split(",")).toList());
@@ -19,20 +19,11 @@ package io.cloudbeaver.registry;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.connection.DBPDataSourceProviderDescriptor;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.connection.DBPDriverLibrary;
import org.jkiss.dbeaver.registry.DataSourceProviderRegistry;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class WebDriverRegistry {
@@ -51,7 +42,6 @@ public class WebDriverRegistry {
return instance;
}
private final List<DBPDriver> applicableDrivers = new ArrayList<>();
private final Set<String> webDrivers = new HashSet<>();
protected WebDriverRegistry() {
@@ -69,48 +59,8 @@ public class WebDriverRegistry {
}
}
public List<DBPDriver> getApplicableDrivers() {
return applicableDrivers;
public boolean isDriverEnabled(DBPDriver driver) {
return webDrivers.contains(driver.getFullId());
}
/**
* Updates info about applicable drivers (f.e. some changes were made in driver config file).
*/
public void refreshApplicableDrivers() {
this.applicableDrivers.clear();
this.applicableDrivers.addAll(
DataSourceProviderRegistry.getInstance().getEnabledDataSourceProviders().stream()
.map(DBPDataSourceProviderDescriptor::getEnabledDrivers)
.flatMap(List::stream)
.filter(this::isDriverApplicable)
.toList());
log.info("Available drivers: " + applicableDrivers.stream().map(DBPDriver::getFullName).collect(Collectors.joining(",")));
}
protected boolean isDriverApplicable(@NotNull DBPDriver driver) {
List<? extends DBPDriverLibrary> libraries = driver.getDriverLibraries();
if (!webDrivers.contains(driver.getFullId())) {
return false;
}
boolean hasAllFiles = true;
for (DBPDriverLibrary lib : libraries) {
if (!isDriverLibraryFilePresent(lib)) {
hasAllFiles = false;
log.error("\tDriver '" + driver.getId() + "' is missing library '" + lib.getDisplayName() + "'");
} else {
if (lib.getType() == DBPDriverLibrary.FileType.jar) {
return true;
}
}
}
return hasAllFiles;
}
private boolean isDriverLibraryFilePresent(@NotNull DBPDriverLibrary lib) {
if (lib.getType() == DBPDriverLibrary.FileType.license) {
return true;
}
Path localFile = lib.getLocalFile();
return localFile != null && Files.exists(localFile);
}
}
@@ -18,7 +18,7 @@
package io.cloudbeaver.registry;
import io.cloudbeaver.DBWFeatureSet;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebAppUtils;
import org.eclipse.core.runtime.IConfigurationElement;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.DBPImage;
@@ -66,7 +66,7 @@ public class WebFeatureDescriptor extends AbstractContextDescriptor implements D
@Override
public boolean isEnabled() {
return ServletAppUtils.getServletApplication().getAppConfiguration().isFeatureEnabled(this.id);
return WebAppUtils.getWebApplication().getAppConfiguration().isFeatureEnabled(this.id);
}
}
@@ -1,71 +0,0 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudbeaver.registry;
import io.cloudbeaver.DBWFeatureSet;
import org.eclipse.core.runtime.IConfigurationElement;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.DBPImage;
import org.jkiss.dbeaver.model.impl.AbstractContextDescriptor;
/**
* WebFeatureDescriptor
*/
public class WebServerFeatureDescriptor extends AbstractContextDescriptor implements DBWFeatureSet {
public static final String EXTENSION_ID = "io.cloudbeaver.server.feature"; //$NON-NLS-1$
private final String id;
private final String label;
private final String description;
private final DBPImage icon;
public WebServerFeatureDescriptor(IConfigurationElement config)
{
super(config);
this.id = config.getAttribute("id");
this.label = config.getAttribute("label");
this.description = config.getAttribute("description");
this.icon = iconToImage(config.getAttribute("icon"));
}
@NotNull
public String getId() {
return id;
}
@NotNull
public String getLabel() {
return label;
}
public String getDescription() {
return description;
}
@Override
public DBPImage getIcon() {
return icon;
}
@Override
public boolean isEnabled() {
return true;
}
}
@@ -1,68 +0,0 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudbeaver.registry;
import io.cloudbeaver.DBWFeatureSet;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.jkiss.dbeaver.Log;
import java.util.ArrayList;
import java.util.List;
public class WebServerFeatureRegistry {
private static final Log log = Log.getLog(WebServerFeatureRegistry.class);
private static final String TAG_FEATURE = "feature"; //$NON-NLS-1$
private static WebServerFeatureRegistry instance = null;
public synchronized static WebServerFeatureRegistry getInstance() {
if (instance == null) {
instance = new WebServerFeatureRegistry();
instance.loadExtensions(Platform.getExtensionRegistry());
}
return instance;
}
private String[] serverFeatures = new String[0];
private WebServerFeatureRegistry() {
}
private synchronized void loadExtensions(IExtensionRegistry registry) {
IConfigurationElement[] extConfigs = registry.getConfigurationElementsFor(WebServerFeatureDescriptor.EXTENSION_ID);
List<DBWFeatureSet> features = new ArrayList<>();
for (IConfigurationElement ext : extConfigs) {
if (TAG_FEATURE.equals(ext.getName())) {
features.add(
new WebServerFeatureDescriptor(ext));
}
}
this.serverFeatures = features
.stream()
.map(DBWFeatureSet::getId)
.toArray(String[]::new);
}
public String[] getServerFeatures() {
return serverFeatures;
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* 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.
@@ -17,7 +17,7 @@
package io.cloudbeaver.server;
import io.cloudbeaver.DBWConstants;
import io.cloudbeaver.server.websockets.WebSocketPingPongJob;
import io.cloudbeaver.model.app.WebApplication;
import org.eclipse.core.runtime.Plugin;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
@@ -41,18 +41,16 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public abstract class BaseWebPlatform extends BasePlatformImpl {
private static final Log log = Log.getLog(BaseWebPlatform.class);
public abstract class BaseGQLPlatform extends BasePlatformImpl {
private static final Log log = Log.getLog(BaseGQLPlatform.class);
public static final String BASE_TEMP_DIR = "dbeaver";
public static final String TEMP_FILE_FOLDER = "temp-sql-upload-files";
public static final String TEMP_FILE_IMPORT_FOLDER = "temp-import-files";
private Path tempFolder;
private QMRegistryImpl queryManager;
private QMLogFileWriter qmLogWriter;
private DBACertificateStorage certificateStorage;
private ServerGlobalWorkspace workspace;
private WebGlobalWorkspace workspace;
@Override
protected synchronized void initialize() {
@@ -60,8 +58,7 @@ public abstract class BaseWebPlatform extends BasePlatformImpl {
SecurityProviderUtils.registerSecurityProvider();
// Register properties adapter
getApplication().beforeWorkspaceInitialization();
this.workspace = new ServerGlobalWorkspace(this, getApplication());
this.workspace = new WebGlobalWorkspace(this, (WebApplication) getApplication());
this.workspace.initializeProjects();
QMUtils.initApplication(this);
@@ -132,10 +129,6 @@ public abstract class BaseWebPlatform extends BasePlatformImpl {
@NotNull
public abstract WebApplication getApplication();
protected void scheduleServerJobs() {
new WebSocketPingPongJob(WebAppUtils.getWebPlatform()).scheduleMonitor();
}
@Override
public synchronized void dispose() {
super.dispose();
@@ -20,8 +20,6 @@ package io.cloudbeaver.server;
* Various constants
*/
public class CBConstants {
public static final int STATIC_CACHE_SECONDS = 60 * 60 * 24 * 3;
public static final String RUNTIME_DATA_DIR_NAME = ".data";
public static final String RUNTIME_APP_CONFIG_FILE_NAME = ".cloudbeaver.runtime.conf";
public static final String RUNTIME_PRODUCT_CONFIG_FILE_NAME = ".product.runtime.conf";
@@ -46,7 +44,6 @@ public class CBConstants {
public static final String PARAM_STATIC_CONTENT = "staticContent";
public static final String PARAM_RESOURCE_QUOTAS = "resourceQuotas";
public static final String PARAM_RESOURCE_MANAGER_ENABLED = "resourceManagerEnabled";
public static final String PARAM_SECRET_MANAGER_ENABLED = "secretManagerEnabled";
public static final String PARAM_SHOW_READ_ONLY_CONN_INFO = "showReadOnlyConnectionInfo";
public static final String PARAM_CONN_GRANT_ANON_ACCESS = "grantConnectionsAccessToAnonymousTeam";
public static final String PARAM_AUTH_PROVIDERS = "authConfiguration";
@@ -80,6 +80,6 @@ public class WebGlobalProject extends BaseProjectImpl {
@NotNull
@Override
protected DBPDataSourceRegistry createDataSourceRegistry() {
return new DataSourceRegistry<>(this);
return new DataSourceRegistry(this);
}
}
@@ -17,7 +17,8 @@
package io.cloudbeaver.server;
import io.cloudbeaver.WebProjectImpl;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.utils.WebAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
@@ -38,18 +39,18 @@ import java.util.Map;
/**
* Web global workspace.
*/
public class ServerGlobalWorkspace extends BaseWorkspaceImpl {
public class WebGlobalWorkspace extends BaseWorkspaceImpl {
private static final Log log = Log.getLog(ServerGlobalWorkspace.class);
private static final Log log = Log.getLog(WebGlobalWorkspace.class);
protected final Map<String, WebProjectImpl> projects = new LinkedHashMap<>();
private WebGlobalProject globalProject;
private final ServletApplication application;
private final WebApplication application;
public ServerGlobalWorkspace(
public WebGlobalWorkspace(
@NotNull DBPPlatform platform,
@NotNull ServletApplication application
@NotNull WebApplication application
) {
super(platform, application.getWorkspaceDirectory());
this.application = application;
@@ -60,7 +61,7 @@ public class ServerGlobalWorkspace extends BaseWorkspaceImpl {
initializeWorkspaceSession();
// Load global project
String defaultProjectName = application.getDefaultProjectName();
String defaultProjectName = WebAppUtils.getWebApplication().getDefaultProjectName();
if (CommonUtils.isNotEmpty(defaultProjectName)) {
Path globalProjectPath = getAbsolutePath().resolve(defaultProjectName);
if (!Files.exists(globalProjectPath)) {
@@ -16,7 +16,7 @@
*/
package io.cloudbeaver.server;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.impl.preferences.AbstractPreferenceStore;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
@@ -185,7 +185,7 @@ public class WebServerPreferenceStore extends AbstractPreferenceStore {
}
private Map<String, Object> productConf() {
var app = ServletAppUtils.getServletApplication();
var app = WebAppUtils.getWebApplication();
return app.getServerConfiguration().getProductSettings();
}
}
@@ -16,14 +16,14 @@
*/
package io.cloudbeaver.service;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.WebApplication;
import org.jkiss.dbeaver.DBException;
/**
* Servlet service
*/
public interface DBWServiceBindingServlet<APPLICATION extends ServletApplication> extends DBWServiceBinding {
default boolean isApplicable(ServletApplication application) {
public interface DBWServiceBindingServlet<APPLICATION extends WebApplication> extends DBWServiceBinding {
default boolean isApplicable(WebApplication application) {
return true;
}
@@ -16,9 +16,9 @@
*/
package io.cloudbeaver.service;
import io.cloudbeaver.model.app.ServletAppConfiguration;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.ServletServerConfiguration;
import io.cloudbeaver.model.app.WebAppConfiguration;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.model.app.WebServerConfiguration;
import io.cloudbeaver.model.session.WebSession;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -30,16 +30,16 @@ import org.jkiss.dbeaver.DBException;
public interface DBWServiceServerConfigurator extends DBWServiceBinding {
void configureServer(
@NotNull ServletApplication application,
@NotNull WebApplication application,
@Nullable WebSession session,
@NotNull ServletServerConfiguration serverConfiguration,
@NotNull ServletAppConfiguration appConfig
@NotNull WebServerConfiguration serverConfiguration,
@NotNull WebAppConfiguration appConfig
) throws DBException;
default void migrateConfigurationIfNeeded(@NotNull ServletApplication application) throws DBException {
default void migrateConfigurationIfNeeded(@NotNull WebApplication application) throws DBException {
}
void reloadConfiguration(@NotNull ServletAppConfiguration appConfig) throws DBException;
void reloadConfiguration(@NotNull WebAppConfiguration appConfig) throws DBException;
}
@@ -19,8 +19,8 @@ package io.cloudbeaver.utils;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.WebProjectImpl;
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.app.ServletAuthApplication;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.model.app.WebAuthApplication;
import io.cloudbeaver.model.session.WebSession;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
@@ -41,8 +41,8 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ServletAppUtils {
private static final Log log = Log.getLog(ServletAppUtils.class);
public class WebAppUtils {
private static final Log log = Log.getLog(WebAppUtils.class);
public static String getRelativePath(String path, String curDir) {
return getRelativePath(path, Path.of(curDir));
@@ -55,19 +55,19 @@ public class ServletAppUtils {
return curDir.resolve(path).toAbsolutePath().toString();
}
public static ServletApplication getServletApplication() {
return (ServletApplication) DBWorkbench.getPlatform().getApplication();
public static WebApplication getWebApplication() {
return (WebApplication) DBWorkbench.getPlatform().getApplication();
}
public static ServletAuthApplication getAuthApplication() throws DBException {
ServletApplication application = getServletApplication();
if (!ServletAuthApplication.class.isAssignableFrom(application.getClass())) {
public static WebAuthApplication getWebAuthApplication() throws DBException {
WebApplication application = getWebApplication();
if (!WebAuthApplication.class.isAssignableFrom(application.getClass())) {
throw new DBException("The current application doesn't contain authorization configuration");
}
return (ServletAuthApplication) application;
return (WebAuthApplication) application;
}
public static SMAuthenticationManager getAuthManager(ServletApplication application) throws DBException {
public static SMAuthenticationManager getAuthManager(WebApplication application) throws DBException {
var smController = application.createSecurityController(new NoAuthCredentialsProvider());
if (!SMAuthenticationManager.class.isAssignableFrom(smController.getClass())) {
throw new DBException("The current application cannot be used for authorization");
@@ -169,11 +169,11 @@ public class ServletAppUtils {
@NotNull
public static StringBuilder getAuthApiPrefix(String serviceId) throws DBException {
return getAuthApiPrefix(getAuthApplication(), serviceId);
return getAuthApiPrefix(getWebAuthApplication(), serviceId);
}
@NotNull
public static StringBuilder getAuthApiPrefix(ServletAuthApplication webAuthApplication, String serviceId) {
public static StringBuilder getAuthApiPrefix(WebAuthApplication webAuthApplication, String serviceId) {
String authUrl = removeSideSlashes(webAuthApplication.getAuthServiceURL());
StringBuilder apiPrefix = new StringBuilder(authUrl);
apiPrefix.append("/").append(serviceId).append("/");
@@ -190,7 +190,7 @@ public class ServletAppUtils {
sessionCookie.setMaxAge((int) (maxSessionIdleTime / 1000));
}
String path = getServletApplication().getServerConfiguration().getRootURI();
String path = getWebApplication().getServerConfiguration().getRootURI();
if (sameSite != null) {
if (!request.isSecure()) {
@@ -223,7 +223,7 @@ public class ServletAppUtils {
}
public static String getGlobalProjectId() {
String globalConfigurationName = getServletApplication().getDefaultProjectName();
String globalConfigurationName = getWebApplication().getDefaultProjectName();
return RMProjectType.GLOBAL.getPrefix() + "_" + globalConfigurationName;
}
@@ -273,9 +273,9 @@ public class ServletAppUtils {
@NotNull
public static String getFullServerUrl() {
ServletApplication application = ServletAppUtils.getServletApplication();
WebApplication application = WebAppUtils.getWebApplication();
return Stream.of(application.getServerURL(), application.getRootURI())
.map(ServletAppUtils::removeSideSlashes)
.map(WebAppUtils::removeSideSlashes)
.filter(CommonUtils::isNotEmpty)
.collect(Collectors.joining("/"));
}
@@ -16,9 +16,7 @@
*/
package io.cloudbeaver.utils;
import io.cloudbeaver.model.WebAsyncTaskInfo;
import io.cloudbeaver.model.session.WebSession;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.websocket.WSConstants;
import org.jkiss.dbeaver.model.websocket.event.WSEvent;
@@ -27,7 +25,6 @@ import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDatasourceFolderEvent;
import org.jkiss.dbeaver.model.websocket.event.resource.WSResourceProperty;
import org.jkiss.dbeaver.model.websocket.event.resource.WSResourceUpdatedEvent;
import org.jkiss.dbeaver.model.websocket.event.session.WSSessionTaskInfoEvent;
import java.util.List;
@@ -83,7 +80,7 @@ public class WebEventUtils {
if (event == null) {
return;
}
ServletAppUtils.getServletApplication().getEventController().addEvent(event);
WebAppUtils.getWebApplication().getEventController().addEvent(event);
}
public static void addNavigatorNodeUpdatedEvent(
@@ -125,7 +122,7 @@ public class WebEventUtils {
if (event == null) {
return;
}
ServletAppUtils.getServletApplication().getEventController().addEvent(event);
WebAppUtils.getWebApplication().getEventController().addEvent(event);
}
public static void addRmResourceUpdatedEvent(
@@ -182,17 +179,7 @@ public class WebEventUtils {
if (event == null) {
return;
}
ServletAppUtils.getServletApplication().getEventController().addEvent(event);
}
public static void sendAsyncTaskEvent(@NotNull WebSession webSession, @NotNull WebAsyncTaskInfo taskInfo) {
webSession.addSessionEvent(
new WSSessionTaskInfoEvent(
taskInfo.getId(),
taskInfo.getStatus(),
taskInfo.isRunning()
)
);
WebAppUtils.getWebApplication().getEventController().addEvent(event);
}
}
@@ -3,10 +3,10 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Corp
Bundle-Name: Cloudbeaver Community Product
Bundle-SymbolicName: io.cloudbeaver.product.ce;singleton:=true
Bundle-Version: 24.3.4.qualifier
Bundle-Release-Date: 20250203
Bundle-Version: 24.2.5.qualifier
Bundle-Release-Date: 20241118
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
Require-Bundle: io.cloudbeaver.server.ce
Require-Bundle: io.cloudbeaver.server
Automatic-Module-Name: io.cloudbeaver.product.ce
@@ -10,7 +10,7 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.product.ce</artifactId>
<version>24.3.4-SNAPSHOT</version>
<version>24.2.5-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -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.115.qualifier
Bundle-Release-Date: 20250203
Bundle-Version: 1.0.110.qualifier
Bundle-Release-Date: 20241118
Bundle-Vendor: DBeaver Corp
Bundle-ActivationPolicy: lazy
Automatic-Module-Name: io.cloudbeaver.resources.drivers.base
@@ -9,6 +9,6 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.resources.drivers.base</artifactId>
<version>1.0.115-SNAPSHOT</version>
<version>1.0.110-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -1,21 +0,0 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Corp
Bundle-Name: Cloudbeaver CE Server
Bundle-SymbolicName: io.cloudbeaver.server.ce;singleton:=true
Bundle-Version: 24.3.4.qualifier
Bundle-Release-Date: 20250203
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-ActivationPolicy: lazy
Bundle-Activator: io.cloudbeaver.server.CBPlatformActivator
Bundle-ClassPath: .
Require-Bundle: io.cloudbeaver.server;visibility:=reexport
Export-Package: io.cloudbeaver,
io.cloudbeaver.model,
io.cloudbeaver.model.config,
io.cloudbeaver.server,
io.cloudbeaver.service,
io.cloudbeaver.service.core,
io.cloudbeaver.service.session
Import-Package: org.slf4j
Automatic-Module-Name: io.cloudbeaver.server.ce
@@ -1,6 +0,0 @@
source..=src/
output..=target/classes/
bin.includes=.,\
META-INF/,\
schema/,\
plugin.xml
@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension point="org.jkiss.dbeaver.dataSourceHandler">
<handler id="db.access.check" class="io.cloudbeaver.model.WebDatasourceAccessCheckHandler"/>
</extension>
<extension point="io.cloudbeaver.service">
<service id="core_ce" label="Core service" description="Core services" class="io.cloudbeaver.service.core.CECoreModelExtender"/>
</extension>
<extension point="org.jkiss.dbeaver.ws.event.handler">
<eventHandler class="io.cloudbeaver.server.events.WSUserEventHandler">
<topic id="cb_user"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSSubjectPermissionUpdatedEventHandler">
<topic id="cb_subject_permissions"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSUserSecretEventHandlerImpl">
<topic id="cb_user_secret"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSObjectPermissionUpdatedEventHandler">
<topic id="cb_object_permissions"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSRmResourceUpdatedEventHandlerImpl">
<topic id="cb_scripts"/>
</eventHandler>
</extension>
</plugin>
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.cloudbeaver</groupId>
<artifactId>bundles</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.server.ce</artifactId>
<version>24.3.4-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -1,16 +0,0 @@
extend type ServerConfig {
serverURL: String!
rootURI: String!
hostName: String! @deprecated # use container id instead
containerId: String!
defaultAuthRole: String
defaultUserTeam: String # [23.2.2]
sessionExpireTime: Int!
localHostAddress: String
redirectOnFederatedAuth: Boolean!
enabledAuthProviders: [ID!]!
passwordPolicyConfiguration: PasswordPolicyConfig! @since(version: "23.3.3")
}
@@ -1,89 +0,0 @@
/*
* 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.model;
import io.cloudbeaver.model.config.PasswordPolicyConfiguration;
import io.cloudbeaver.server.CBApplication;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.utils.CommonUtils;
public class CBWebServerConfig extends WebServerConfig {
private final CBApplication<?> cbApp;
public CBWebServerConfig(@NotNull CBApplication<?> cbApp) {
super(cbApp);
this.cbApp = cbApp;
}
@Property
public String getServerURL() {
return CommonUtils.notEmpty(cbApp.getServerConfiguration().getServerURL());
}
@Property
public String getRootURI() {
return CommonUtils.notEmpty(cbApp.getServerConfiguration().getRootURI());
}
@Deprecated
@Property
public String getHostName() {
return getContainerId();
}
@Property
public String getContainerId() {
return CommonUtils.notEmpty(cbApp.getContainerId());
}
@Property
public boolean isRedirectOnFederatedAuth() {
return cbApp.getAppConfiguration().isRedirectOnFederatedAuth();
}
@Property
public String getLocalHostAddress() {
return cbApp.getLocalHostAddress();
}
@Property
public long getSessionExpireTime() {
return cbApp.getServerConfiguration().getMaxSessionIdleTime();
}
@Property
public String[] getEnabledAuthProviders() {
return cbApp.getAppConfiguration().getEnabledAuthProviders();
}
@Property
public String getDefaultAuthRole() {
return cbApp.getDefaultAuthRole();
}
@Property
public String getDefaultUserTeam() {
return cbApp.getAppConfiguration().getDefaultUserTeam();
}
@Property
public PasswordPolicyConfiguration getPasswordPolicyConfiguration() {
return cbApp.getSecurityManagerConfiguration().getPasswordPolicyConfiguration();
}
}
@@ -1,118 +0,0 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 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;
import io.cloudbeaver.server.jobs.SessionStateJob;
import io.cloudbeaver.server.jobs.WebDataSourceMonitorJob;
import io.cloudbeaver.server.jobs.WebSessionMonitorJob;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.impl.app.BaseApplicationImpl;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.utils.IOUtils;
import java.io.IOException;
/**
* CBPlatform
*/
public class CBPlatform extends BaseWebPlatform {
// The plug-in ID
public static final String PLUGIN_ID = "io.cloudbeaver.server"; //$NON-NLS-1$
private static final Log log = Log.getLog(CBPlatform.class);
private WebServerPreferenceStore preferenceStore;
public static CBPlatform getInstance() {
return (CBPlatform) DBWorkbench.getPlatform();
}
protected CBPlatform() {
}
@Override
protected synchronized void initialize() {
long startTime = System.currentTimeMillis();
log.info("Initialize web platform...: ");
this.preferenceStore = new WebServerPreferenceStore(WebPlatformActivator.getInstance().getPreferences());
super.initialize();
scheduleServerJobs();
log.info("Web platform initialized (" + (System.currentTimeMillis() - startTime) + "ms)");
}
protected void scheduleServerJobs() {
super.scheduleServerJobs();
new WebSessionMonitorJob(this, getApplication().getSessionManager())
.scheduleMonitor();
new SessionStateJob(this, getApplication().getSessionManager())
.scheduleMonitor();
new WebDataSourceMonitorJob(this, getApplication().getSessionManager())
.scheduleMonitor();
new AbstractJob("Delete temp folder") {
@Override
protected IStatus run(DBRProgressMonitor monitor) {
try {
IOUtils.deleteDirectory(getTempFolder(monitor, TEMP_FILE_FOLDER));
IOUtils.deleteDirectory(getTempFolder(monitor, TEMP_FILE_IMPORT_FOLDER));
} catch (IOException e) {
throw new RuntimeException(e);
}
return Status.OK_STATUS;
}
}.schedule();
}
public synchronized void dispose() {
long startTime = System.currentTimeMillis();
log.debug("Shutdown Core...");
super.dispose();
System.gc();
log.debug("Shutdown completed in " + (System.currentTimeMillis() - startTime) + "ms");
}
@NotNull
@Override
public CBApplication<?> getApplication() {
return (CBApplication) BaseApplicationImpl.getInstance();
}
@NotNull
@Override
public DBPPreferenceStore getPreferenceStore() {
return preferenceStore;
}
@Override
public boolean isShuttingDown() {
return false;
}
}
@@ -1,35 +0,0 @@
/*
* 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.service.core;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.service.DBWBindingContext;
import io.cloudbeaver.service.WebServiceBindingBase;
/**
* extends the base gql model, to avoid unnecessary fields in other applications
*/
public class CECoreModelExtender extends WebServiceBindingBase<DBWVoidService> {
public CECoreModelExtender() {
super(DBWVoidService.class, new DBWVoidService(), "schema/service.core.graphqls");
}
@Override
public void bindWiring(DBWBindingContext model) throws DBWebException {
}
}
@@ -1,22 +0,0 @@
/*
* 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.service.core;
import io.cloudbeaver.service.DBWService;
public class DBWVoidService implements DBWService {
}
@@ -3,17 +3,18 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Corp
Bundle-Name: Cloudbeaver Web Server
Bundle-SymbolicName: io.cloudbeaver.server;singleton:=true
Bundle-Version: 24.3.4.qualifier
Bundle-Release-Date: 20250203
Bundle-Version: 24.2.5.qualifier
Bundle-Release-Date: 20241118
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-ActivationPolicy: lazy
Bundle-Activator: io.cloudbeaver.server.CBPlatformActivator
Bundle-ClassPath: .
Require-Bundle: org.eclipse.core.runtime;visibility:=reexport,
org.apache.commons.jexl,
org.jkiss.utils;visibility:=reexport,
org.jkiss.dbeaver.model.sql;visibility:=reexport,
org.jkiss.dbeaver.data.gis,
org.jkiss.bundle.jakarta.jetty.server;visibility:=reexport,
org.jkiss.bundle.jetty.server;visibility:=reexport,
com.google.gson;visibility:=reexport,
org.jkiss.bundle.graphql.java;visibility:=reexport,
org.jkiss.bundle.apache.dbcp,
@@ -22,7 +23,6 @@ Require-Bundle: org.eclipse.core.runtime;visibility:=reexport,
io.cloudbeaver.service.security;visibility:=reexport
Export-Package: io.cloudbeaver,
io.cloudbeaver.model,
io.cloudbeaver.model.app,
io.cloudbeaver.model.user,
io.cloudbeaver.registry,
io.cloudbeaver.server.events,
@@ -32,10 +32,10 @@ Export-Package: io.cloudbeaver,
io.cloudbeaver.server.graphql,
io.cloudbeaver.server.jobs,
io.cloudbeaver.server.servlets,
io.cloudbeaver.server.websockets,
io.cloudbeaver.server.websockets,
io.cloudbeaver.service,
io.cloudbeaver.service.navigator,
io.cloudbeaver.service.session,
io.cloudbeaver.service.sql
Import-Package: org.slf4j
Bundle-Localization: OSGI-INF/l10n/bundle
Automatic-Module-Name: io.cloudbeaver.server
@@ -1,2 +0,0 @@
log.api.graphql.debug = Enable detailed logging
log.api.graphql.debug.description = Enable detailed logging of GraphQL queries in the server log, including all provided variables
@@ -1,2 +0,0 @@
log.api.graphql.debug = Включить подробное логирование
log.api.graphql.debug.description = Включите подробное логирование запросов GraphQL в журнале сервера, включая все предоставленные переменные
@@ -2,7 +2,6 @@ source.. = src/
output.. = target/classes/
bin.includes = .,\
META-INF/,\
OSGI-INF/,\
schema/,\
static/,\
plugin.xml
@@ -29,6 +29,9 @@
</service>
</extension>
<extension point="org.jkiss.dbeaver.dataSourceHandler">
<handler id="db.access.check" class="io.cloudbeaver.model.WebDatasourceAccessCheckHandler"/>
</extension>
<extension point="io.cloudbeaver.valueSerializer">
<serializer type="geometry" class="io.cloudbeaver.server.data.WebGeometryValueSerializer"/>
</extension>
@@ -43,9 +46,21 @@
<eventHandler class="io.cloudbeaver.server.events.WSFolderUpdatedEventHandlerImpl">
<topic id="cb_datasource_folder"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSRmResourceUpdatedEventHandlerImpl">
<topic id="cb_scripts"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSObjectPermissionUpdatedEventHandler">
<topic id="cb_object_permissions"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSSubjectPermissionUpdatedEventHandler">
<topic id="cb_subject_permissions"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSProjectUpdatedEventHandler">
<topic id="cb_projects"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSUserSecretEventHandlerImpl">
<topic id="cb_user_secret"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSLogEventHandler">
<topic id="cb_session_log"/>
</eventHandler>
@@ -55,14 +70,9 @@
<eventHandler class="io.cloudbeaver.server.events.WSDeleteTempFileHandler">
<topic id="cb_delete_temp_folder"/>
</eventHandler>
</extension>
<extension point="org.jkiss.dbeaver.settings">
<propertyGroup id="log" label="Logger">
<property id="log.api.graphql.debug" label="Enable detailed logging"
type="boolean" scopes="global"
description="Enable detailed logging of GraphQL queries in the server log, including all provided variables"/>
</propertyGroup>
<eventHandler class="io.cloudbeaver.server.events.WSUserEventHandler">
<topic id="cb_user"/>
</eventHandler>
</extension>
</plugin>
+1 -1
View File
@@ -10,7 +10,7 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.server</artifactId>
<version>24.3.4-SNAPSHOT</version>
<version>24.2.5-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -118,7 +118,6 @@ type ProductInfo {
licenseInfo: String
latestVersionInfo: String
productPurchaseURL: String
}
type ServerConfig {
@@ -126,12 +125,19 @@ type ServerConfig {
version: String!
workspaceId: ID!
serverURL: String!
rootURI: String!
hostName: String! @deprecated # use container id instead
containerId: String!
defaultAuthRole: String
defaultUserTeam: String # [23.2.2]
anonymousAccessEnabled: Boolean!
supportsCustomConnections: Boolean!
supportsConnectionBrowser: Boolean!
supportsWorkspaces: Boolean!
resourceManagerEnabled: Boolean!
secretManagerEnabled: Boolean! @since(version: "24.3.2")
publicCredentialsSaveEnabled: Boolean!
adminCredentialsSaveEnabled: Boolean!
@@ -139,14 +145,18 @@ type ServerConfig {
licenseValid: Boolean!
licenseStatus: String @since(version: "24.1.5")
sessionExpireTime: Int!
localHostAddress: String
configurationMode: Boolean!
# initializationMode: Boolean! @since(version: "24.1.5")
developmentMode: Boolean!
redirectOnFederatedAuth: Boolean!
distributed: Boolean!
enabledFeatures: [ID!]!
disabledBetaFeatures: [ID!] @since(version: "24.0.5")
serverFeatures: [ID!] @since(version: "24.3.0")
enabledAuthProviders: [ID!]!
supportedLanguages: [ ServerLanguage! ]!
services: [ WebServiceConfig ]
productConfiguration: Object!
@@ -154,6 +164,7 @@ type ServerConfig {
defaultNavigatorSettings: NavigatorSettings!
disabledDrivers: [ID!]!
resourceQuotas: Object!
passwordPolicyConfiguration: PasswordPolicyConfig! @since(version: "23.3.3")
}
type ProductSettingsGroup @since(version: "24.0.1") {
@@ -198,18 +209,14 @@ type DatabaseAuthModel {
}
type DriverInfo {
# Driver unique full ID. It is `providerId + "." + driverId`.
# It is recommended to use providerId and driverId separately.
id: ID!
name: String
description: String
icon: String
iconBig: String
# Driver ID. It is unique within provider
driverId: ID!
# Driver provider ID. It is globally unique
providerId: ID!
# Driver provider ID
providerId: ID
# Driver Java class name
driverClassName: String
defaultHost: String
@@ -263,8 +270,6 @@ type DriverInfo {
configurationTypes: [DriverConfigurationType]!
downloadable: Boolean! @since(version: "24.3.3")
driverInstalled: Boolean!
driverLibraries: [DriverLibraryInfo!]!
}
@@ -272,13 +277,6 @@ type DriverLibraryInfo {
id: ID!
name: String!
icon: String
libraryFiles: [DriverFileInfo!]
}
type DriverFileInfo @since(version: "24.3.2") {
id: ID!
fileName: String!
icon: String
}
enum ResultDataFormat {
@@ -356,7 +354,7 @@ type ConnectionInfo {
properties: Object
template: Boolean! @deprecated
template: Boolean!
connected: Boolean!
provided: Boolean!
readOnly: Boolean!
@@ -502,7 +500,7 @@ input ConnectionConfig {
description: String
# ID of template connection
templateId: ID @deprecated
templateId: ID
# ID of database driver
driverId: ID
@@ -529,7 +527,7 @@ input ConnectionConfig {
autocommit: Boolean
# Return template connection state
template: Boolean @deprecated
template: Boolean
# Return read-only connection state
readOnly: Boolean
@@ -589,7 +587,7 @@ extend type Query {
userConnections( projectId: ID, id: ID, projectIds: [ID!] ): [ ConnectionInfo! ]!
# Return list of template connections by project ID
templateConnections( projectId: ID ): [ ConnectionInfo! ]! @deprecated
templateConnections( projectId: ID ): [ ConnectionInfo! ]!
# List of connection folders
connectionFolders( projectId: ID, path: ID ): [ ConnectionFolderInfo! ]!
@@ -631,7 +629,7 @@ extend type Mutation {
deleteConnection( id: ID!, projectId: ID ): Boolean!
# Create new custom connection from template
createConnectionFromTemplate( templateId: ID!, projectId: ID!, connectionName: String ): ConnectionInfo! @deprecated
createConnectionFromTemplate( templateId: ID!, projectId: ID!, connectionName: String ): ConnectionInfo!
# Create new folder for connections
createConnectionFolder(parentFolderPath: ID, folderName: String!, projectId: ID ): ConnectionFolderInfo!
@@ -20,9 +20,6 @@ enum CBServerEventId {
cb_datasource_folder_updated,
cb_datasource_folder_deleted,
cb_datasource_disconnected,
cb_datasource_connected,
cb_rm_resource_created,
cb_rm_resource_updated,
cb_rm_resource_deleted,
@@ -33,11 +30,7 @@ enum CBServerEventId {
cb_object_permissions_updated,
cb_subject_permissions_updated,
cb_database_output_log_updated,
cb_transaction_count @since(version: "24.3.3")
cb_session_task_info_updated @since(version: "24.3.1")
cb_database_output_log_updated
}
# Events sent by client
@@ -60,13 +53,7 @@ enum CBEventTopic {
cb_object_permissions,
cb_subject_permissions,
cb_database_output_log,
cb_session_task, @since(version: "24.3.1")
cb_datasource_connection,
cb_delete_temp_folder,
cb_transaction @since(version: "24.3.3")
cb_delete_temp_folder
}
# Base server event interface
@@ -191,41 +178,6 @@ type WSOutputLogInfo {
# Add more fields as needed
}
# Async task info status event
type WSAsyncTaskInfo @since(version: "24.3.1") {
id: CBServerEventId!
taskId: ID!
statusName: String
running: Boolean!
}
# Datasource disconnect event
type WSDataSourceDisconnectEvent implements CBServerEvent {
id: CBServerEventId!
topicId: CBEventTopic
connectionId: String!
projectId: String!
timestamp: Int!
}
# Datasource connect event
type WSDataSourceConnectEvent implements CBServerEvent {
id: CBServerEventId!
topicId: CBEventTopic
connectionId: String!
projectId: String!
timestamp: Int!
}
# Datasource count event in transactional mode
type WSTransactionalCountEvent implements CBServerEvent {
id: CBServerEventId!
topicId: CBEventTopic
contextId: String!
projectId: String!
connectionId: String!
transactionalCount: Int!
}
extend type Query {
emptyEvent: Boolean
}
@@ -223,24 +223,6 @@ type DynamicTraceProperty {
description: String
}
####################################################
# Transactional info
####################################################
type TransactionLogInfoItem {
id: Int!
time: DateTime!
type: String!
queryString: String!
durationMs: Int!
rows: Int!
result: String!
}
type TransactionLogInfos {
count: Int!
transactionLogInfos: [TransactionLogInfoItem!]!
}
####################################################
# Query and Mutation
####################################################
@@ -349,12 +331,6 @@ extend type Mutation {
dataFormat: ResultDataFormat
): AsyncTaskInfo!
getTransactionLogInfo(
projectId: ID!,
connectionId: ID!,
contextId: ID!
): TransactionLogInfos!
# Close results (free resources)
sqlResultClose(projectId: ID, connectionId: ID!, contextId: ID!, resultId: ID!): Boolean!
@@ -23,20 +23,18 @@ import com.google.gson.Strictness;
import io.cloudbeaver.model.WebConnectionConfig;
import io.cloudbeaver.model.WebNetworkHandlerConfigInput;
import io.cloudbeaver.model.WebPropertyInfo;
import io.cloudbeaver.model.app.ServletApplication;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.model.session.WebActionParameters;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.registry.WebAuthProviderDescriptor;
import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.server.WebAppUtils;
import io.cloudbeaver.server.WebApplication;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBPlatform;
import io.cloudbeaver.service.navigator.WebPropertyFilter;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebCommonUtils;
import io.cloudbeaver.utils.WebDataSourceUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBConstants;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
@@ -132,17 +130,16 @@ public class WebServiceUtils extends WebCommonUtils {
newDataSource.setSavePassword(true);
newDataSource.setName(config.getName());
newDataSource.setDescription(config.getDescription());
newDataSource.setConnectionReadOnly(config.isReadOnly());
if (config.getFolder() != null) {
newDataSource.setFolder(registry.getFolder(config.getFolder()));
}
((DataSourceDescriptor)newDataSource).setTemplate(config.isTemplate());
ServletApplication app = ServletAppUtils.getServletApplication();
if (app instanceof WebApplication webApplication) {
((DataSourceDescriptor) newDataSource).setNavigatorSettings(
webApplication.getAppConfiguration().getDefaultNavigatorSettings());
}
// Set default navigator settings
DataSourceNavigatorSettings navSettings = new DataSourceNavigatorSettings(
CBApplication.getInstance().getAppConfiguration().getDefaultNavigatorSettings());
//navSettings.setShowSystemObjects(false);
((DataSourceDescriptor)newDataSource).setNavigatorSettings(navSettings);
saveAuthProperties(
newDataSource,
@@ -314,6 +311,12 @@ public class WebServiceUtils extends WebCommonUtils {
gson.toJsonTree(settingsMap), DataSourceNavigatorSettings.class);
}
public static void checkServerConfigured() throws DBWebException {
if (CBApplication.getInstance().isConfigurationMode()) {
throw new DBWebException("Server is in configuration mode");
}
}
public static void fireActionParametersOpenEditor(WebSession webSession, DBPDataSourceContainer dataSource, boolean addEditorName) {
Map<String, Object> actionParameters = new HashMap<>();
actionParameters.put("action", "open-sql-editor");
@@ -338,20 +341,13 @@ public class WebServiceUtils extends WebCommonUtils {
}
public static boolean isGlobalProject(DBPProject project) {
return project.getId()
.equals(RMProjectType.GLOBAL.getPrefix() + "_" + ServletAppUtils.getServletApplication()
.getDefaultProjectName());
return project.getId().equals(RMProjectType.GLOBAL.getPrefix() + "_" + CBApplication.getInstance().getDefaultProjectName());
}
public static List<WebAuthProviderDescriptor> getEnabledAuthProviders() {
List<WebAuthProviderDescriptor> result = new ArrayList<>();
String[] authProviders = null;
try {
authProviders = ServletAppUtils.getAuthApplication().getAuthConfiguration().getEnabledAuthProviders();
} catch (DBException e) {
log.error(e.getMessage(), e);
return List.of();
}
CBAppConfig appConfig = CBApplication.getInstance().getAppConfiguration();
String[] authProviders = appConfig.getEnabledAuthProviders();
for (String apId : authProviders) {
WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(apId);
if (authProvider != null) {
@@ -366,7 +362,7 @@ public class WebServiceUtils extends WebCommonUtils {
*/
@NotNull
public static Set<String> getApplicableDriversIds() {
return WebAppUtils.getWebApplication().getDriverRegistry().getApplicableDrivers().stream()
return CBPlatform.getInstance().getApplicableDrivers().stream()
.map(DBPDriver::getId)
.collect(Collectors.toSet());
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* 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.
@@ -18,14 +18,17 @@ package io.cloudbeaver.model;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.model.app.WebAppConfiguration;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.model.utils.ConfigurationUtils;
import io.cloudbeaver.server.WebAppUtils;
import io.cloudbeaver.server.CBApplication;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBConstants;
import org.jkiss.dbeaver.model.connection.*;
import org.jkiss.dbeaver.model.connection.DBPAuthModelDescriptor;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.connection.DBPDriverConfigurationType;
import org.jkiss.dbeaver.model.impl.auth.AuthModelDatabaseNative;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
@@ -39,8 +42,6 @@ import org.jkiss.utils.CommonUtils;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
/**
* Web driver configuration
@@ -52,7 +53,7 @@ public class WebDatabaseDriverInfo {
public static final String URL_DATABASE_FIELD = ".*(?:\\{(?:database|file|folder)}).*";
private final WebSession webSession;
private final DBPDriver driver;
private final String id;
private String id;
public WebDatabaseDriverInfo(WebSession webSession, DBPDriver driver) {
this.webSession = webSession;
@@ -85,11 +86,6 @@ public class WebDatabaseDriverInfo {
return WebServiceUtils.makeIconId(driver.getIconBig());
}
@Property
public String getDriverId() {
return driver.getId();
}
@Property
public String getProviderId() {
return driver.getProviderId();
@@ -257,24 +253,14 @@ public class WebDatabaseDriverInfo {
@Property
public WebPropertyInfo[] getProviderProperties() {
WebPropertyInfo[] additionalWebProperty = Optional.of(WebAppUtils.getWebApplication())
.filter(app -> app.getAppConfiguration().isSecretManagerEnabled())
.map(app -> app.getConnectionController().getExternalInfo(webSession))
.orElse(new WebPropertyInfo[0]);
WebPropertyInfo[] providerProperties = Arrays.stream(driver.getProviderPropertyDescriptors())
return Arrays.stream(driver.getProviderPropertyDescriptors())
.map(p -> new WebPropertyInfo(webSession, p, null))
.toArray(WebPropertyInfo[]::new);
return Stream.concat(
Arrays.stream(additionalWebProperty),
Arrays.stream(providerProperties)
).toArray(WebPropertyInfo[]::new);
}
@Property
public boolean isEnabled() {
WebAppConfiguration config = WebAppUtils.getWebApplication().getAppConfiguration();
CBAppConfig config = CBApplication.getInstance().getAppConfiguration();
return ConfigurationUtils.isDriverEnabled(
driver,
config.getEnabledDrivers(),
@@ -305,21 +291,10 @@ public class WebDatabaseDriverInfo {
@Property
public WebDriverLibraryInfo[] getDriverLibraries() {
return driver.getDriverLibraries().stream()
.filter(library -> !library.isDisabled())
.map(library -> new WebDriverLibraryInfo(driver, library))
.map(dbpDriverLibrary -> new WebDriverLibraryInfo(webSession, dbpDriverLibrary))
.toArray(WebDriverLibraryInfo[]::new);
}
@Property
public boolean isDriverInstalled() {
return driver.isDriverInstalled();
}
@Property
public boolean isDownloadable() {
return driver.getDriverLibraries().stream().anyMatch(DBPDriverLibrary::isDownloadable);
}
@Property
public boolean getUseCustomPage() {
return !ArrayUtils.isEmpty(driver.getMainPropertyDescriptors());
@@ -20,13 +20,14 @@ package io.cloudbeaver.model;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.model.utils.ConfigurationUtils;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.utils.ServletAppUtils;
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 (!ServletAppUtils.getServletApplication().isMultiuser()) {
if (!WebAppUtils.getWebApplication().isMultiuser()) {
return false;
}
CBAppConfig config = CBApplication.getInstance().getAppConfiguration();
@@ -1,53 +0,0 @@
/*
* 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.model;
import io.cloudbeaver.WebServiceUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.DBIcon;
import org.jkiss.dbeaver.model.connection.DBPDriverLibrary;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.registry.driver.DriverDescriptor;
public class WebDriverLibraryFileInfo {
@NotNull
private final DriverDescriptor.DriverFileInfo fileInfo;
public WebDriverLibraryFileInfo(@NotNull DriverDescriptor.DriverFileInfo fileInfo) {
this.fileInfo = fileInfo;
}
@Property
public String getId() {
return fileInfo.getId();
}
@Property
public String getFileName() {
return fileInfo.toString();
}
@Property
public String getIcon() {
if (fileInfo.getType() == DBPDriverLibrary.FileType.license) {
return WebServiceUtils.makeIconId(DBIcon.TYPE_TEXT);
}
return WebServiceUtils.makeIconId(DBIcon.JAR);
}
}
@@ -17,24 +17,18 @@
package io.cloudbeaver.model;
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.model.session.WebSession;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.connection.DBPDriverLibrary;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.registry.driver.DriverDescriptor;
import java.util.List;
public class WebDriverLibraryInfo {
@NotNull
private final DBPDriver driver;
@NotNull
private final WebSession webSession;
private final DBPDriverLibrary driverLibrary;
public WebDriverLibraryInfo(@NotNull DBPDriver driver, @NotNull DBPDriverLibrary driverLibrary) {
this.driver = driver;
public WebDriverLibraryInfo(@NotNull WebSession webSession, @NotNull DBPDriverLibrary driverLibrary) {
this.webSession = webSession;
this.driverLibrary = driverLibrary;
}
@@ -49,18 +43,6 @@ public class WebDriverLibraryInfo {
return driverLibrary.getDisplayName();
}
@Property
@Nullable
public List<WebDriverLibraryFileInfo> getLibraryFiles() {
var libraryFiles = ((DriverDescriptor) driver).getLibraryFiles(driverLibrary);
if (libraryFiles == null) {
return null;
}
return libraryFiles.stream()
.map(WebDriverLibraryFileInfo::new)
.toList();
}
@Property
public String getIcon() {
return WebServiceUtils.makeIconId(driverLibrary.getIcon());
@@ -16,7 +16,7 @@
*/
package io.cloudbeaver.model;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.server.CBApplication;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.Platform;
import org.jkiss.dbeaver.model.meta.Property;
@@ -68,7 +68,7 @@ public class WebProductInfo {
@Property
public String getLicenseInfo() {
return ServletAppUtils.getServletApplication().getInfoDetails(new VoidProgressMonitor());
return CBApplication.getInstance().getInfoDetails(new VoidProgressMonitor());
}
@Property
@@ -77,10 +77,4 @@ public class WebProductInfo {
return CommonUtils.notEmpty(product.getProperty("versionUpdateURL"));
}
@Property
public String getProductPurchaseURL() {
IProduct product = Platform.getProduct();
return CommonUtils.notEmpty(product.getProperty("productPurchaseURL"));
}
}
@@ -16,11 +16,11 @@
*/
package io.cloudbeaver.model;
import io.cloudbeaver.registry.WebServerFeatureRegistry;
import io.cloudbeaver.model.config.PasswordPolicyConfiguration;
import io.cloudbeaver.registry.WebServiceDescriptor;
import io.cloudbeaver.registry.WebServiceRegistry;
import io.cloudbeaver.server.WebApplication;
import org.jkiss.code.NotNull;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBPlatform;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
@@ -39,9 +39,9 @@ import java.util.Map;
*/
public class WebServerConfig {
private final WebApplication application;
private final CBApplication application;
public WebServerConfig(@NotNull WebApplication application) {
public WebServerConfig(CBApplication application) {
this.application = application;
}
@@ -60,6 +60,27 @@ public class WebServerConfig {
return DBWorkbench.getPlatform().getWorkspace().getWorkspaceId();
}
@Property
public String getServerURL() {
return CommonUtils.notEmpty(application.getServerConfiguration().getServerURL());
}
@Property
public String getRootURI() {
return CommonUtils.notEmpty(application.getServerConfiguration().getRootURI());
}
@Deprecated
@Property
public String getHostName() {
return getContainerId();
}
@Property
public String getContainerId() {
return CommonUtils.notEmpty(application.getContainerId());
}
@Property
public boolean isAnonymousAccessEnabled() {
return application.getAppConfiguration().isAnonymousAccessEnabled();
@@ -70,6 +91,16 @@ public class WebServerConfig {
return application.getAppConfiguration().isSupportsCustomConnections();
}
@Property
public boolean isSupportsConnectionBrowser() {
return application.getAppConfiguration().isSupportsConnectionBrowser();
}
@Property
public boolean isSupportsWorkspaces() {
return application.getAppConfiguration().isSupportsUserWorkspaces();
}
@Property
public boolean isPublicCredentialsSaveEnabled() {
return application.getAppConfiguration().isPublicCredentialsSaveEnabled();
@@ -105,14 +136,24 @@ public class WebServerConfig {
return application.getServerConfiguration().isDevelMode();
}
@Property
public boolean isRedirectOnFederatedAuth() {
return application.getAppConfiguration().isRedirectOnFederatedAuth();
}
@Property
public boolean isResourceManagerEnabled() {
return application.getAppConfiguration().isResourceManagerEnabled();
}
@Property
public boolean isSecretManagerEnabled() {
return application.getAppConfiguration().isSecretManagerEnabled();
public long getSessionExpireTime() {
return application.getServerConfiguration().getMaxSessionIdleTime();
}
@Property
public String getLocalHostAddress() {
return application.getLocalHostAddress();
}
@Property
@@ -127,9 +168,8 @@ public class WebServerConfig {
}
@Property
@NotNull
public String[] getServerFeatures() {
return WebServerFeatureRegistry.getInstance().getServerFeatures();
public String[] getEnabledAuthProviders() {
return application.getAppConfiguration().getEnabledAuthProviders();
}
@Property
@@ -153,7 +193,7 @@ public class WebServerConfig {
@Property
public Map<String, Object> getProductConfiguration() {
return application.getProductConfiguration();
return CBPlatform.getInstance().getApplication().getProductConfiguration();
}
@Property
@@ -180,4 +220,19 @@ public class WebServerConfig {
public Boolean isDistributed() {
return application.isDistributed();
}
@Property
public String getDefaultAuthRole() {
return application.getDefaultAuthRole();
}
@Property
public String getDefaultUserTeam() {
return application.getAppConfiguration().getDefaultUserTeam();
}
@Property
public PasswordPolicyConfiguration getPasswordPolicyConfiguration() {
return application.getSecurityManagerConfiguration().getPasswordPolicyConfiguration();
}
}
@@ -1,24 +0,0 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 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.model;
import org.jkiss.code.NotNull;
import java.util.List;
public record WebTransactionLogInfo(@NotNull List<WebTransactionLogItemInfo> transactionLogInfos, int count) {
}
@@ -1,31 +0,0 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 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.model;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
public record WebTransactionLogItemInfo(
@Nullable Integer id,
@NotNull String time,
@NotNull String type,
@NotNull String queryString,
long durationMs,
long rows,
String result
) {
}
@@ -1,28 +0,0 @@
/*
* 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.model.app;
import org.jkiss.code.Nullable;
/**
* Web server configuration.
* Contains only server configuration properties.
*/
public interface WebServerConfiguration extends ServletServerConfiguration {
@Nullable
String getServerName();
}
@@ -14,17 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudbeaver.service.auth.model.user;
package io.cloudbeaver.model.user;
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.auth.SMAuthProviderFederated;
import io.cloudbeaver.auth.provisioning.SMProvisioner;
import io.cloudbeaver.model.app.ServletAuthConfiguration;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.registry.WebAuthProviderConfiguration;
import io.cloudbeaver.registry.WebAuthProviderDescriptor;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.WebAppUtils;
import org.jkiss.code.NotNull;
import io.cloudbeaver.server.CBPlatform;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.security.SMAuthCredentialsProfile;
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;
@@ -38,15 +37,17 @@ import java.util.List;
public class WebAuthProviderInfo {
private static final Log log = Log.getLog(WebAuthProviderInfo.class);
private static final SMAuthProviderCustomConfiguration TEMPLATE_CONFIG = new SMAuthProviderCustomConfiguration("{configuration_id}");
@NotNull
private final WebAuthProviderDescriptor descriptor;
public WebAuthProviderInfo(@NotNull WebAuthProviderDescriptor descriptor) {
public WebAuthProviderInfo(WebAuthProviderDescriptor descriptor) {
this.descriptor = descriptor;
}
WebAuthProviderDescriptor getDescriptor() {
return descriptor;
}
public String getId() {
return descriptor.getId();
}
@@ -64,8 +65,8 @@ public class WebAuthProviderInfo {
}
public boolean isDefaultProvider() {
if (WebAppUtils.getWebApplication().getAppConfiguration() instanceof ServletAuthConfiguration authConfiguration) {
return descriptor.getId().equals(authConfiguration.getDefaultAuthProvider());
if (CBPlatform.getInstance().getApplication().getAppConfiguration() instanceof CBAppConfig cbAppConfig) {
return descriptor.getId().equals(cbAppConfig.getDefaultAuthProvider());
}
return false;
}
@@ -124,10 +125,6 @@ public class WebAuthProviderInfo {
return rf == null ? new String[0] : rf;
}
public WebAuthProviderConfiguration getTemplateConfiguration() {
return new WebAuthProviderConfiguration(descriptor, TEMPLATE_CONFIG);
}
@Override
public String toString() {
return getLabel();
@@ -19,21 +19,20 @@ package io.cloudbeaver.server;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.model.session.WebHeadlessSession;
import io.cloudbeaver.model.session.WebHttpRequestInfo;
import io.cloudbeaver.model.session.WebSession;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Session;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import java.util.Collection;
public interface WebAppSessionManager {
public interface AppWebSessionManager {
BaseWebSession closeSession(@NotNull HttpServletRequest request);
BaseWebSession closeSession(@NotNull String sessionId);
@NotNull
WebSession getWebSession(
@NotNull HttpServletRequest request,
@@ -57,17 +56,9 @@ public interface WebAppSessionManager {
Collection<BaseWebSession> getAllActiveSessions();
WebSession getOrRestoreWebSession(WebHttpRequestInfo httpRequest);
WebSession getOrRestoreSession(Request httpRequest);
WebHeadlessSession getHeadlessSession(
@Nullable String smAccessToken,
@NotNull WebHttpRequestInfo requestInfo,
boolean create
) throws DBException;
WebHeadlessSession getHeadlessSession(Request request, Session session, boolean create) throws DBException;
boolean touchSession(HttpServletRequest request, HttpServletResponse response) throws DBWebException;
default void expireIdleSessions() {
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* 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.
@@ -18,22 +18,18 @@ package io.cloudbeaver.server;
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
import io.cloudbeaver.model.CBWebServerConfig;
import io.cloudbeaver.model.WebServerConfig;
import io.cloudbeaver.model.app.BaseServletApplication;
import io.cloudbeaver.model.app.ServletAuthApplication;
import io.cloudbeaver.model.app.ServletAuthConfiguration;
import io.cloudbeaver.model.app.BaseWebApplication;
import io.cloudbeaver.model.app.WebAuthApplication;
import io.cloudbeaver.model.app.WebAuthConfiguration;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.model.config.CBServerConfig;
import io.cloudbeaver.model.config.SMControllerConfiguration;
import io.cloudbeaver.registry.WebDriverRegistry;
import io.cloudbeaver.registry.WebServiceRegistry;
import io.cloudbeaver.server.jetty.CBJettyServer;
import io.cloudbeaver.service.ConnectionController;
import io.cloudbeaver.service.ConnectionControllerCE;
import io.cloudbeaver.service.DBWServiceInitializer;
import io.cloudbeaver.service.DBWServiceServerConfigurator;
import io.cloudbeaver.service.session.CBSessionManager;
import io.cloudbeaver.service.session.WebSessionManager;
import io.cloudbeaver.utils.WebDataSourceUtils;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
@@ -78,7 +74,7 @@ import java.util.concurrent.ConcurrentHashMap;
* This class controls all aspects of the application's execution
*/
public abstract class CBApplication<T extends CBServerConfig> extends
BaseServletApplication implements ServletAuthApplication, WebApplication {
BaseWebApplication implements WebAuthApplication, GQLApplicationAdapter {
private static final Log log = Log.getLog(CBApplication.class);
@@ -109,7 +105,7 @@ public abstract class CBApplication<T extends CBServerConfig> extends
protected final WSEventController eventController = new WSEventController();
private CBSessionManager sessionManager;
private WebSessionManager sessionManager;
private final Map<String, String> initActions = new ConcurrentHashMap<>();
@@ -179,7 +175,7 @@ public abstract class CBApplication<T extends CBServerConfig> extends
}
@Override
public ServletAuthConfiguration getAuthConfiguration() {
public WebAuthConfiguration getAuthConfiguration() {
return getAppConfiguration();
}
@@ -202,6 +198,7 @@ public abstract class CBApplication<T extends CBServerConfig> extends
@Override
protected void startServer() {
CBPlatform.setApplication(this);
try {
if (!loadServerConfiguration()) {
return;
@@ -663,15 +660,15 @@ public abstract class CBApplication<T extends CBServerConfig> extends
return null;
}
public CBSessionManager getSessionManager() {
public WebSessionManager getSessionManager() {
if (sessionManager == null) {
sessionManager = createSessionManager();
}
return sessionManager;
}
protected CBSessionManager createSessionManager() {
return new CBSessionManager(this);
protected WebSessionManager createSessionManager() {
return new WebSessionManager(this);
}
@NotNull
@@ -712,7 +709,7 @@ public abstract class CBApplication<T extends CBServerConfig> extends
@Override
public Class<? extends DBPPlatformUI> getPlatformUIClass() {
return ServletPlatformUI.class;
return CBPlatformUI.class;
}
public void saveProductConfiguration(
@@ -736,10 +733,9 @@ public abstract class CBApplication<T extends CBServerConfig> extends
public abstract CBServerConfigurationController<T> getServerConfigurationController();
private void refreshDisabledDriversConfig() {
getDriverRegistry().refreshApplicableDrivers();
CBAppConfig config = getAppConfiguration();
Set<String> disabledDrivers = new LinkedHashSet<>(Arrays.asList(config.getDisabledDrivers()));
for (DBPDriver driver : getDriverRegistry().getApplicableDrivers()) {
for (DBPDriver driver : CBPlatform.getInstance().getApplicableDrivers()) {
if (!driver.isEmbedded() || config.isDriverForceEnabled(driver.getFullId())) {
continue;
}
@@ -769,14 +765,4 @@ public abstract class CBApplication<T extends CBServerConfig> extends
public Map<String, String> getInitActions() {
return Map.copyOf(initActions);
}
@Override
public WebServerConfig getWebServerConfig() {
return new CBWebServerConfig(this);
}
@Override
public ConnectionController getConnectionController() {
return new ConnectionControllerCE();
}
}
@@ -17,8 +17,6 @@
package io.cloudbeaver.server;
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
import io.cloudbeaver.model.CBWebServerConfig;
import io.cloudbeaver.model.WebServerConfig;
import io.cloudbeaver.model.config.CBServerConfig;
import io.cloudbeaver.model.rm.local.LocalResourceController;
import io.cloudbeaver.service.security.CBEmbeddedSecurityController;
@@ -116,4 +114,5 @@ public class CBApplicationCE extends CBApplication<CBServerConfig> {
embeddedSecurityController.finishConfiguration(adminName, adminPassword, authInfoList);
}
}
}
@@ -0,0 +1,188 @@
/*
* 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;
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
import io.cloudbeaver.server.jobs.SessionStateJob;
import io.cloudbeaver.server.jobs.WebDataSourceMonitorJob;
import io.cloudbeaver.server.jobs.WebSessionMonitorJob;
import io.cloudbeaver.service.session.WebSessionManager;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBFileController;
import org.jkiss.dbeaver.model.connection.DBPDataSourceProviderDescriptor;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.connection.DBPDriverLibrary;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.registry.DataSourceProviderRegistry;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.utils.IOUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* CBPlatform
*/
public class CBPlatform extends BaseGQLPlatform {
// The plug-in ID
public static final String PLUGIN_ID = "io.cloudbeaver.server"; //$NON-NLS-1$
private static final Log log = Log.getLog(CBPlatform.class);
public static final String TEMP_FILE_FOLDER = "temp-sql-upload-files";
public static final String TEMP_FILE_IMPORT_FOLDER = "temp-import-files";
@Nullable
private static GQLApplicationAdapter application = null;
private WebServerPreferenceStore preferenceStore;
protected final List<DBPDriver> applicableDrivers = new ArrayList<>();
public static CBPlatform getInstance() {
return (CBPlatform) DBWorkbench.getPlatform();
}
protected CBPlatform() {
}
public static void setApplication(@NotNull GQLApplicationAdapter application) {
CBPlatform.application = application;
}
@Override
protected synchronized void initialize() {
long startTime = System.currentTimeMillis();
log.info("Initialize web platform...: ");
this.preferenceStore = new WebServerPreferenceStore(WebPlatformActivator.getInstance().getPreferences());
super.initialize();
refreshApplicableDrivers();
scheduleServerJobs();
log.info("Web platform initialized (" + (System.currentTimeMillis() - startTime) + "ms)");
}
protected void scheduleServerJobs() {
if (getSessionManager() instanceof WebSessionManager webSessionManager) {
new WebSessionMonitorJob(this, webSessionManager)
.scheduleMonitor();
new SessionStateJob(this, webSessionManager)
.scheduleMonitor();
}
new WebDataSourceMonitorJob(this, getSessionManager())
.scheduleMonitor();
new AbstractJob("Delete temp folder") {
@Override
protected IStatus run(DBRProgressMonitor monitor) {
try {
IOUtils.deleteDirectory(getTempFolder(monitor, TEMP_FILE_FOLDER));
IOUtils.deleteDirectory(getTempFolder(monitor, TEMP_FILE_IMPORT_FOLDER));
} catch (IOException e) {
throw new RuntimeException(e);
}
return Status.OK_STATUS;
}
}.schedule();
}
public synchronized void dispose() {
long startTime = System.currentTimeMillis();
log.debug("Shutdown Core...");
super.dispose();
CBPlatform.application = null;
System.gc();
log.debug("Shutdown completed in " + (System.currentTimeMillis() - startTime) + "ms");
}
@NotNull
@Override
public GQLApplicationAdapter getApplication() {
return application;
}
public List<DBPDriver> getApplicableDrivers() {
return applicableDrivers;
}
@NotNull
@Override
public DBPPreferenceStore getPreferenceStore() {
return preferenceStore;
}
@Override
public boolean isShuttingDown() {
return false;
}
public AppWebSessionManager getSessionManager() {
return application.getSessionManager();
}
public void refreshApplicableDrivers() {
this.applicableDrivers.clear();
for (DBPDataSourceProviderDescriptor dspd : DataSourceProviderRegistry.getInstance().getEnabledDataSourceProviders()) {
for (DBPDriver driver : dspd.getEnabledDrivers()) {
List<? extends DBPDriverLibrary> libraries = driver.getDriverLibraries();
{
if (!application.getDriverRegistry().isDriverEnabled(driver)) {
continue;
}
boolean hasAllFiles = true, hasJars = false;
for (DBPDriverLibrary lib : libraries) {
if (!DBWorkbench.isDistributed() && !lib.isOptional() && lib.getType() != DBPDriverLibrary.FileType.license &&
(lib.getLocalFile() == null || !Files.exists(lib.getLocalFile())))
{
hasAllFiles = false;
log.error("\tDriver '" + driver.getId() + "' is missing library '" + lib.getDisplayName() + "'");
} else {
if (lib.getType() == DBPDriverLibrary.FileType.jar) {
hasJars = true;
}
}
}
if (hasAllFiles || hasJars) {
applicableDrivers.add(driver);
}
}
}
}
log.info("Available drivers: " + applicableDrivers.stream().map(DBPDriver::getFullName).collect(Collectors.joining(",")));
}
@NotNull
@Override
public DBFileController createFileController() {
return getApplication().createFileController(new NoAuthCredentialsProvider());
}
}

Some files were not shown because too many files have changed in this diff Show More