diff --git a/.github/workflows/jest-tests-runner.yml b/.github/workflows/jest-tests-runner.yml
new file mode 100644
index 0000000000..562f215b03
--- /dev/null
+++ b/.github/workflows/jest-tests-runner.yml
@@ -0,0 +1,31 @@
+name: Run Jest Tests
+
+# Controls when the workflow will run
+on:
+ # Triggers the workflow on push or pull request events but only for the "devel" branch
+ pull_request:
+ branches: [ "devel" ]
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+ # This workflow contains a single job called "build"
+ run-jest-tests:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./webapp
+ # Steps represent a sequence of tasks that will be executed as part of the job
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '16'
+ - run: npm install --legacy-peer-deps
+ - run: npm install lerna -g
+ - run: lerna bootstrap
+ - run: lerna run test --no-bail --stream -- --reporters default github-actions
+
diff --git a/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF
index 1e1baa83f2..9f8a4013cd 100644
--- a/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: %Bundle-Vendor
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: io.cloudbeaver.model;singleton:=true
-Bundle-Version: 1.0.11.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 1.0.12.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/server/bundles/io.cloudbeaver.model/pom.xml b/server/bundles/io.cloudbeaver.model/pom.xml
index 7009a3b182..8f3bc9174f 100644
--- a/server/bundles/io.cloudbeaver.model/pom.xml
+++ b/server/bundles/io.cloudbeaver.model/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.model
- 1.0.11-SNAPSHOT
+ 1.0.12-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/AbstractSessionFederated.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/AbstractSessionFederated.java
index 3b727d3eee..4b9edeca46 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/AbstractSessionFederated.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/AbstractSessionFederated.java
@@ -67,6 +67,7 @@ public abstract class AbstractSessionFederated implements SMSessionFederated {
return parentSession.getSingletonProject();
}
+ @Override
public void close() {
// do nothing
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerProject.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerProject.java
index 4a65801d27..5d638eab22 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerProject.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerProject.java
@@ -24,12 +24,14 @@ import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBIcon;
import org.jkiss.dbeaver.model.DBPImage;
import org.jkiss.dbeaver.model.DBPObject;
+import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.auth.SMSessionContext;
import org.jkiss.dbeaver.model.navigator.DBNNode;
import org.jkiss.dbeaver.model.rm.RMController;
import org.jkiss.dbeaver.model.rm.RMProject;
import org.jkiss.dbeaver.model.rm.RMResource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
+import org.jkiss.utils.CommonUtils;
import java.util.ArrayList;
import java.util.List;
@@ -114,6 +116,21 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
return getNodeName();
}
+
+ @Override
+ public DBPProject getOwnerProject() {
+ List extends DBPProject> globalProjects = getModel().getModelProjects();
+ if (globalProjects == null) {
+ return null;
+ }
+ for (DBPProject modelProject : globalProjects) {
+ if (CommonUtils.equalObjects(modelProject.getId(), project.getId())) {
+ return modelProject;
+ }
+ }
+ return null;
+ }
+
@Nullable
@Override
public DBPObject getObjectDetails(@NotNull DBRProgressMonitor monitor, @NotNull SMSessionContext sessionContext, @NotNull Object dataSource) throws DBException {
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerResource.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerResource.java
index 120b805572..772eb19714 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerResource.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerResource.java
@@ -24,6 +24,7 @@ import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBIcon;
import org.jkiss.dbeaver.model.DBPImage;
import org.jkiss.dbeaver.model.DBPObject;
+import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.auth.SMSessionContext;
import org.jkiss.dbeaver.model.navigator.DBNNode;
import org.jkiss.dbeaver.model.rm.RMController;
@@ -165,6 +166,11 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
return resource;
}
+ @Override
+ public DBPProject getOwnerProject() {
+ return getParentNode().getOwnerProject();
+ }
+
public RMResource getResource() {
return resource;
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java
index d836612a45..9d45432cac 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java
@@ -545,7 +545,7 @@ public class LocalResourceController implements RMController {
if (Files.exists(path)) {
try {
project.setCreateTime(
- OffsetDateTime.ofInstant(Files.getLastModifiedTime(path).toInstant(), ZoneId.of("UTC")));
+ OffsetDateTime.ofInstant(Files.getLastModifiedTime(path).toInstant(), ZoneId.of("UTC")).toInstant().toEpochMilli());
} catch (IOException e) {
log.error(e);
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
index b2dcfb7cec..c0f0872e8f 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
@@ -584,14 +584,19 @@ public class WebSession extends AbstractSessionPersistent implements SMSession,
}
}
- public void close() throws DBException {
+ @Override
+ public void close() {
try {
resetNavigationModel();
resetSessionCache();
} catch (Throwable e) {
log.error(e);
}
- clearAuthTokens();
+ try {
+ clearAuthTokens();
+ } catch (Exception e) {
+ log.error("Error closing web session tokens");
+ }
this.sessionAuthContext.close();
this.userContext.setUser(null);
@@ -599,6 +604,7 @@ public class WebSession extends AbstractSessionPersistent implements SMSession,
this.defaultProject.dispose();
this.defaultProject = null;
}
+ super.close();
}
private void clearAuthTokens() throws DBException {
@@ -959,6 +965,11 @@ public class WebSession extends AbstractSessionPersistent implements SMSession,
return userContext.getActiveUserCredentials();
}
+ @Override
+ public void refreshSMSession() throws DBException {
+ userContext.refreshSMSession();
+ }
+
public VirtualProjectImpl getProjectById(@Nullable String projectId) {
if (projectId == null) {
return defaultProject;
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java
index b943f87412..fa51e53d89 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java
@@ -47,6 +47,7 @@ public class WebUserContext implements SMCredentialsProvider {
private Set userPermissions;
private SMCredentials smCredentials = null;
private String smSessionId;
+ private String refreshToken;
private SMController securityController;
private SMAdminController adminSecurityController;
@@ -64,7 +65,7 @@ public class WebUserContext implements SMCredentialsProvider {
* @param smAuthInfo - auth info from security manager
* @throws DBException - if user already authorized and new token come from another user
*/
- public void refresh(SMAuthInfo smAuthInfo) throws DBException {
+ public synchronized void refresh(SMAuthInfo smAuthInfo) throws DBException {
if (smAuthInfo.getAuthStatus() != SMAuthStatus.SUCCESS) {
throw new DBCException("Authorization did not complete successfully");
}
@@ -77,7 +78,12 @@ public class WebUserContext implements SMCredentialsProvider {
if (isNonAnonymousUserAuthorized && isSessionChanged && !Objects.equals(getUserId(), authPermissions.getUserId())) {
throw new DBCException("Another user is already logged in");
}
- this.smCredentials = new SMCredentials(smAuthInfo.getSmAuthToken(), authPermissions.getUserId(), authPermissions.getPermissions());
+ this.smCredentials = new SMCredentials(
+ smAuthInfo.getSmAuthToken(),
+ authPermissions.getUserId(),
+ authPermissions.getPermissions()
+ );
+ this.refreshToken = smAuthInfo.getSmRefreshToken();
this.userPermissions = authPermissions.getPermissions();
this.securityController = application.getSecurityController(this);
this.adminSecurityController = application.getAdminSecurityController(this);
@@ -89,10 +95,23 @@ public class WebUserContext implements SMCredentialsProvider {
}
+ public synchronized void refreshSMSession() throws DBException {
+ if (smCredentials == null || refreshToken == null) {
+ return;
+ }
+ var newTokens = securityController.refreshSession(refreshToken);
+ this.refreshToken = newTokens.getSmRefreshToken();
+ this.smCredentials = new SMCredentials(
+ newTokens.getSmAccessToken(),
+ smCredentials.getUserId(),
+ smCredentials.getPermissions()
+ );
+ }
+
/**
* reset the state as if the user is not logged in
*/
- public void reset() throws DBException {
+ public synchronized void reset() throws DBException {
if (this.smCredentials != null) {
this.securityController.logout();
}
@@ -155,8 +174,8 @@ public class WebUserContext implements SMCredentialsProvider {
}
if (userPermissions != null &&
!userPermissions.isEmpty() &&
- !userPermissions.contains(DBWConstants.PERMISSION_PUBLIC))
- {
+ !userPermissions.contains(DBWConstants.PERMISSION_PUBLIC)
+ ) {
userPermissions.add(DBWConstants.PERMISSION_PUBLIC);
}
}
diff --git a/server/bundles/io.cloudbeaver.product.ce/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.product.ce/META-INF/MANIFEST.MF
index 7f6fa1e8ff..ff87107d8f 100644
--- a/server/bundles/io.cloudbeaver.product.ce/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.product.ce/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: %Bundle-Vendor
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: io.cloudbeaver.product.ce;singleton:=true
-Bundle-Version: 22.1.5.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 22.2.0.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/server/bundles/io.cloudbeaver.product.ce/pom.xml b/server/bundles/io.cloudbeaver.product.ce/pom.xml
index 488af4c71d..2fa1115bbd 100644
--- a/server/bundles/io.cloudbeaver.product.ce/pom.xml
+++ b/server/bundles/io.cloudbeaver.product.ce/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.product.ce
- 22.1.5-SNAPSHOT
+ 22.2.0-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.resources.drivers.base/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.resources.drivers.base/META-INF/MANIFEST.MF
index ebd677867f..1f103b7798 100644
--- a/server/bundles/io.cloudbeaver.resources.drivers.base/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.resources.drivers.base/META-INF/MANIFEST.MF
@@ -2,8 +2,8 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Base JDBC drivers
Bundle-SymbolicName: io.cloudbeaver.resources.drivers.base;singleton:=true
-Bundle-Version: 1.0.56.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 1.0.57.qualifier
+Bundle-Release-Date: 20220905
Bundle-Vendor: DBeaver Corp
Bundle-ActivationPolicy: lazy
Automatic-Module-Name: io.cloudbeaver.resources.drivers.base
diff --git a/server/bundles/io.cloudbeaver.resources.drivers.base/pom.xml b/server/bundles/io.cloudbeaver.resources.drivers.base/pom.xml
index e4560a2196..c36ec25313 100644
--- a/server/bundles/io.cloudbeaver.resources.drivers.base/pom.xml
+++ b/server/bundles/io.cloudbeaver.resources.drivers.base/pom.xml
@@ -9,6 +9,6 @@
../
io.cloudbeaver.resources.drivers.base
- 1.0.56-SNAPSHOT
+ 1.0.57-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.server/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.server/META-INF/MANIFEST.MF
index e8aed83934..026ed8d394 100644
--- a/server/bundles/io.cloudbeaver.server/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.server/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: %Bundle-Vendor
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: io.cloudbeaver.server;singleton:=true
-Bundle-Version: 22.1.5.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 22.2.0.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-Activator: io.cloudbeaver.server.CBPlatformActivator
diff --git a/server/bundles/io.cloudbeaver.server/pom.xml b/server/bundles/io.cloudbeaver.server/pom.xml
index cc4662e7b1..7fb53e2055 100644
--- a/server/bundles/io.cloudbeaver.server/pom.xml
+++ b/server/bundles/io.cloudbeaver.server/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.server
- 22.1.5-SNAPSHOT
+ 22.2.0-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/session/WebSessionManager.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/session/WebSessionManager.java
index 0991189fa2..b4d5f967cf 100644
--- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/session/WebSessionManager.java
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/session/WebSessionManager.java
@@ -181,11 +181,7 @@ public class WebSessionManager {
for (WebSession session : expiredList) {
log.debug("> Expire session '" + session.getSessionId() + "'");
- try {
- session.close();
- } catch (DBException e) {
- log.debug("Failed close session:" + session.getSessionId(), e);
- }
+ session.close();
}
}
diff --git a/server/bundles/io.cloudbeaver.service.admin/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.admin/META-INF/MANIFEST.MF
index a15d3aef4d..9aff6c1fc9 100644
--- a/server/bundles/io.cloudbeaver.service.admin/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.service.admin/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: %Bundle-Vendor
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: io.cloudbeaver.service.admin;singleton:=true
-Bundle-Version: 1.0.55.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 1.0.56.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/server/bundles/io.cloudbeaver.service.admin/pom.xml b/server/bundles/io.cloudbeaver.service.admin/pom.xml
index 5ee07f5de8..9e6e9dbc8d 100644
--- a/server/bundles/io.cloudbeaver.service.admin/pom.xml
+++ b/server/bundles/io.cloudbeaver.service.admin/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.service.admin
- 1.0.55-SNAPSHOT
+ 1.0.56-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.service.auth/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.auth/META-INF/MANIFEST.MF
index a149955cfd..103219c6b1 100644
--- a/server/bundles/io.cloudbeaver.service.auth/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.service.auth/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: %Bundle-Vendor
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: io.cloudbeaver.service.auth;singleton:=true
-Bundle-Version: 1.0.55.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 1.0.56.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/server/bundles/io.cloudbeaver.service.auth/pom.xml b/server/bundles/io.cloudbeaver.service.auth/pom.xml
index fb90ad4ee1..7d314cd0dc 100644
--- a/server/bundles/io.cloudbeaver.service.auth/pom.xml
+++ b/server/bundles/io.cloudbeaver.service.auth/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.service.auth
- 1.0.55-SNAPSHOT
+ 1.0.56-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.data.transfer/META-INF/MANIFEST.MF
index da7aa9a73d..bee4d39699 100644
--- a/server/bundles/io.cloudbeaver.service.data.transfer/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.service.data.transfer/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: %Bundle-Vendor
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: io.cloudbeaver.service.data.transfer;singleton:=true
-Bundle-Version: 1.0.56.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 1.0.57.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/pom.xml b/server/bundles/io.cloudbeaver.service.data.transfer/pom.xml
index 1a22d17b9e..b3ef67417c 100644
--- a/server/bundles/io.cloudbeaver.service.data.transfer/pom.xml
+++ b/server/bundles/io.cloudbeaver.service.data.transfer/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.service.data.transfer
- 1.0.56-SNAPSHOT
+ 1.0.57-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.service.metadata/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.metadata/META-INF/MANIFEST.MF
index f6968730e8..88ea4b695a 100644
--- a/server/bundles/io.cloudbeaver.service.metadata/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.service.metadata/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: %Bundle-Vendor
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: io.cloudbeaver.service.metadata;singleton:=true
-Bundle-Version: 1.0.59.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 1.0.60.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/server/bundles/io.cloudbeaver.service.metadata/pom.xml b/server/bundles/io.cloudbeaver.service.metadata/pom.xml
index 9458a19040..637fdd40d9 100644
--- a/server/bundles/io.cloudbeaver.service.metadata/pom.xml
+++ b/server/bundles/io.cloudbeaver.service.metadata/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.service.metadata
- 1.0.59-SNAPSHOT
+ 1.0.60-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.service.rm/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.rm/META-INF/MANIFEST.MF
index 7ab5e04ae6..d6bf417a02 100644
--- a/server/bundles/io.cloudbeaver.service.rm/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.service.rm/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: %Bundle-Vendor
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: io.cloudbeaver.service.rm;singleton:=true
-Bundle-Version: 1.0.8.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 1.0.9.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/server/bundles/io.cloudbeaver.service.rm/pom.xml b/server/bundles/io.cloudbeaver.service.rm/pom.xml
index 0f5d35908c..d10ff14b29 100644
--- a/server/bundles/io.cloudbeaver.service.rm/pom.xml
+++ b/server/bundles/io.cloudbeaver.service.rm/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.service.rm
- 1.0.8-SNAPSHOT
+ 1.0.9-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.service.security/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.security/META-INF/MANIFEST.MF
index 3be9d3f51e..44d1050332 100644
--- a/server/bundles/io.cloudbeaver.service.security/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.service.security/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Security Sevice
Bundle-Vendor: DBeaver Corp
Bundle-SymbolicName: io.cloudbeaver.service.security;singleton:=true
-Bundle-Version: 1.0.11.qualifier
-Bundle-Release-Date: 20220822
+Bundle-Version: 1.0.12.qualifier
+Bundle-Release-Date: 20220905
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/server/bundles/io.cloudbeaver.service.security/db/cb_schema_create.sql b/server/bundles/io.cloudbeaver.service.security/db/cb_schema_create.sql
index 5eb4d7fce1..8861cb445f 100644
--- a/server/bundles/io.cloudbeaver.service.security/db/cb_schema_create.sql
+++ b/server/bundles/io.cloudbeaver.service.security/db/cb_schema_create.sql
@@ -238,12 +238,14 @@ CREATE TABLE CB_SESSION_LOG
CREATE TABLE CB_AUTH_TOKEN
(
- TOKEN_ID VARCHAR(128) NOT NULL,
- SESSION_ID VARCHAR(64) NOT NULL,
- USER_ID VARCHAR(128),
+ TOKEN_ID VARCHAR(128) NOT NULL,
+ REFRESH_TOKEN_ID VARCHAR(128),
+ SESSION_ID VARCHAR(64) NOT NULL,
+ USER_ID VARCHAR(128),
- EXPIRATION_TIME TIMESTAMP NOT NULL,
- CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ EXPIRATION_TIME TIMESTAMP NOT NULL,
+ REFRESH_TOKEN_EXPIRATION_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (TOKEN_ID),
FOREIGN KEY (SESSION_ID) REFERENCES CB_SESSION (SESSION_ID) ON DELETE CASCADE,
diff --git a/server/bundles/io.cloudbeaver.service.security/db/cb_schema_update_9.sql b/server/bundles/io.cloudbeaver.service.security/db/cb_schema_update_9.sql
new file mode 100644
index 0000000000..f1a119dd67
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.security/db/cb_schema_update_9.sql
@@ -0,0 +1,5 @@
+ALTER TABLE CB_AUTH_TOKEN
+ ADD REFRESH_TOKEN_ID VARCHAR(128);
+
+ALTER TABLE CB_AUTH_TOKEN
+ ADD REFRESH_TOKEN_EXPIRATION_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
\ No newline at end of file
diff --git a/server/bundles/io.cloudbeaver.service.security/pom.xml b/server/bundles/io.cloudbeaver.service.security/pom.xml
index 992bad4aac..6185d96141 100644
--- a/server/bundles/io.cloudbeaver.service.security/pom.xml
+++ b/server/bundles/io.cloudbeaver.service.security/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.service.security
- 1.0.11-SNAPSHOT
+ 1.0.12-SNAPSHOT
eclipse-plugin
diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthSession.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthSession.java
index a88bc75403..9c6b98478b 100644
--- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthSession.java
+++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthSession.java
@@ -76,4 +76,9 @@ public class LocalAuthSession implements SMSession {
return webSession.getSingletonProject();
}
+ @Override
+ public void close() {
+
+ }
+
}
diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java
index e0611d1458..a6d2c5de00 100644
--- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java
+++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java
@@ -27,6 +27,7 @@ import io.cloudbeaver.model.app.WebAuthConfiguration;
import io.cloudbeaver.model.session.WebAuthInfo;
import io.cloudbeaver.service.security.db.CBDatabase;
import io.cloudbeaver.service.security.internal.AuthAttemptSessionInfo;
+import io.cloudbeaver.service.security.internal.RefreshTokenInfo;
import io.cloudbeaver.utils.WebAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -39,7 +40,9 @@ import org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCTransaction;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.security.*;
+import org.jkiss.dbeaver.model.security.exception.SMAccessTokenExpiredException;
import org.jkiss.dbeaver.model.security.exception.SMException;
+import org.jkiss.dbeaver.model.security.exception.SMRefreshTokenExpiredException;
import org.jkiss.dbeaver.model.security.user.SMAuthPermissions;
import org.jkiss.dbeaver.model.security.user.SMObjectPermissions;
import org.jkiss.dbeaver.model.security.user.SMRole;
@@ -65,7 +68,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
private static final Log log = Log.getLog(CBEmbeddedSecurityController.class);
- private static final int TOKEN_HOURS_ALIVE_TIME = 1;
+ private static final int ACCESS_TOKEN_TTL_IN_MINUTES = 20;
+ private static final int REFRESH_TOKEN_TTL_IN_HOURS = 24;
protected static final String CHAR_BOOL_TRUE = "Y";
protected static final String CHAR_BOOL_FALSE = "N";
@@ -844,10 +848,15 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
var smSessionId = createSmSession(appSessionId, null, sessionParameters, sessionType, dbCon);
- var token = generateAuthToken(smSessionId, null, dbCon);
+ var smTokens = generateNewSessionToken(smSessionId, null, dbCon);
var permissions = getAnonymousUserPermissions();
txn.commit();
- return SMAuthInfo.success(UUID.randomUUID().toString(), token, new SMAuthPermissions(null, smSessionId, permissions), Map.of());
+ return SMAuthInfo.success(
+ UUID.randomUUID().toString(),
+ smTokens.getSmAccessToken(),
+ smTokens.getSmRefreshToken(),
+ new SMAuthPermissions(null, smSessionId, permissions), Map.of()
+ );
}
} catch (SQLException e) {
throw new DBException(e.getMessage(), e);
@@ -1104,9 +1113,15 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
- String smToken = findTokenBySmSession(smSessionId);
- SMAuthPermissions authPermissions = getTokenPermissions(smToken);
- var successAuthStatus = SMAuthInfo.success(authId, smToken, authPermissions, authData);
+ SMTokens smTokens = findTokenBySmSession(smSessionId);
+ SMAuthPermissions authPermissions = getTokenPermissions(smTokens.getSmAccessToken());
+ var successAuthStatus = SMAuthInfo.success(
+ authId,
+ smTokens.getSmAccessToken(),
+ smTokens.getSmRefreshToken(),
+ authPermissions,
+ authData
+ );
updateAuthStatus(authId, SMAuthStatus.EXPIRED, authData, null, authPermissions.getSessionId());
return successAuthStatus;
@@ -1118,10 +1133,29 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
@Override
public void logout() throws DBException {
var currentUserCreds = getCurrentUserCreds();
- invalidateUserSession(currentUserCreds.getSmToken());
+ invalidateUserTokens(currentUserCreds.getSmToken());
}
- private void invalidateUserSession(String smToken) throws DBCException {
+ @Override
+ public SMTokens refreshSession(@NotNull String refreshToken) throws DBException {
+ var currentUserCreds = getCurrentUserCreds();
+ var currentUserAccessToken = currentUserCreds.getSmToken();
+
+ var expectedRefreshTokenInfo = findRefreshToken(currentUserAccessToken);
+
+ if (!expectedRefreshTokenInfo.getRefreshToken().equals(refreshToken)) {
+ throw new SMException("Invalid refresh token");
+ }
+
+ try (var dbCon = database.openConnection()) {
+ invalidateUserTokens(currentUserAccessToken);
+ return generateNewSessionToken(expectedRefreshTokenInfo.getSessionId(), expectedRefreshTokenInfo.getUserId(), dbCon);
+ } catch (SQLException e) {
+ throw new DBException("Error refreshing sm session", e);
+ }
+ }
+
+ private void invalidateUserTokens(String smToken) throws DBCException {
try (Connection dbCon = database.openConnection()) {
JDBCUtils.executeStatement(dbCon, "DELETE FROM CB_AUTH_TOKEN WHERE TOKEN_ID=?", smToken);
} catch (SQLException e) {
@@ -1137,16 +1171,41 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
return currentUserCreds;
}
- private String findTokenBySmSession(String smSessionId) throws DBException {
+ private SMTokens findTokenBySmSession(String smSessionId) throws DBException {
try (Connection dbCon = database.openConnection();
- PreparedStatement dbStat = dbCon.prepareStatement("SELECT TOKEN_ID FROM CB_AUTH_TOKEN WHERE SESSION_ID=?");
+ PreparedStatement dbStat = dbCon.prepareStatement("SELECT TOKEN_ID, REFRESH_TOKEN_ID FROM CB_AUTH_TOKEN WHERE SESSION_ID=?")
) {
dbStat.setString(1, smSessionId);
try (var dbResult = dbStat.executeQuery()) {
if (!dbResult.next()) {
throw new SMException("Token not found");
}
- return dbResult.getString(1);
+ return new SMTokens(dbResult.getString(1), dbResult.getString(2));
+ }
+ } catch (SQLException e) {
+ throw new DBCException("Error reading token info in database", e);
+ }
+ }
+
+ private RefreshTokenInfo findRefreshToken(String smAccessToken) throws DBException {
+ try (Connection dbCon = database.openConnection();
+ PreparedStatement dbStat = dbCon.prepareStatement(
+ "SELECT REFRESH_TOKEN_ID,SESSION_ID,USER_ID,REFRESH_TOKEN_EXPIRATION_TIME FROM CB_AUTH_TOKEN WHERE TOKEN_ID=?"
+ )
+ ) {
+ dbStat.setString(1, smAccessToken);
+ try (var dbResult = dbStat.executeQuery()) {
+ if (!dbResult.next()) {
+ throw new SMException("Refresh token not found");
+ }
+ var refreshToken = dbResult.getString(1);
+ var sessionId = dbResult.getString(2);
+ var userId = dbResult.getString(3);
+ var expiredDate = dbResult.getTimestamp(4);
+ if (Timestamp.from(Instant.now()).after(expiredDate)) {
+ throw new SMRefreshTokenExpiredException("Refresh token expired");
+ }
+ return new RefreshTokenInfo(refreshToken, sessionId, userId);
}
} catch (SQLException e) {
throw new DBCException("Error reading token info in database", e);
@@ -1173,12 +1232,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
AuthAttemptSessionInfo authAttemptSessionInfo = readAuthAttemptSessionInfo(authId);
boolean isMainAuthSession = authAttemptSessionInfo.getSmSessionId() == null;
- String token = null;
+ SMTokens smTokens = null;
SMAuthPermissions permissions = null;
if (!isMainAuthSession) {
//this is an additional authorization and we should to return the original permissions and userId
- token = findTokenBySmSession(authAttemptSessionInfo.getSmSessionId());
- permissions = getTokenPermissions(token);
+ smTokens = findTokenBySmSession(authAttemptSessionInfo.getSmSessionId());
+ permissions = getTokenPermissions(smTokens.getSmAccessToken());
}
String activeUserId = permissions == null ? null : permissions.getUserId();
@@ -1208,7 +1267,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
);
}
- if (token == null && permissions == null) {
+ if (smTokens == null && permissions == null) {
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
String smSessionId;
@@ -1223,7 +1282,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
} else {
smSessionId = authAttemptSessionInfo.getSmSessionId();
}
- token = generateAuthToken(smSessionId, activeUserId, dbCon);
+ smTokens = generateNewSessionToken(smSessionId, activeUserId, dbCon);
permissions = new SMAuthPermissions(activeUserId, smSessionId, getUserPermissions(activeUserId));
txn.commit();
}
@@ -1235,7 +1294,14 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
var authStatus = forceExpireAuthAfterSuccess ? SMAuthStatus.EXPIRED : SMAuthStatus.SUCCESS;
updateAuthStatus(authId, authStatus, storedUserData, null, permissions.getSessionId());
- return SMAuthInfo.success(authId, token, permissions, authInfo.getAuthData());
+ return SMAuthInfo.success(
+ authId,
+ smTokens.getSmAccessToken(),
+ //refresh token must be sent only once
+ isMainAuthSession ? smTokens.getSmRefreshToken() : null,
+ permissions,
+ authInfo.getAuthData()
+ );
}
private AuthAttemptSessionInfo readAuthAttemptSessionInfo(@NotNull String authId) throws DBException {
@@ -1316,28 +1382,40 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
return userId;
}
- protected String generateAuthToken(
+ protected SMTokens generateNewSessionToken(
@NotNull String smSessionId,
@Nullable String userId,
@NotNull Connection dbCon
) throws SQLException, DBException {
JDBCUtils.executeStatement(dbCon, "DELETE FROM CB_AUTH_TOKEN WHERE SESSION_ID=?", smSessionId);
- try (PreparedStatement dbStat = dbCon.prepareStatement(
- "INSERT INTO CB_AUTH_TOKEN(TOKEN_ID, SESSION_ID, USER_ID, EXPIRATION_TIME) " +
- "VALUES(?,?,?,?)")) {
+ return generateNewSessionTokens(smSessionId, userId, dbCon);
+ }
- String authToken = SecurityUtils.generatePassword(32);
- dbStat.setString(1, authToken);
+ private SMTokens generateNewSessionTokens(@NotNull String smSessionId,
+ @Nullable String userId,
+ @NotNull Connection dbCon) throws SQLException {
+ try (PreparedStatement dbStat = dbCon.prepareStatement(
+ "INSERT INTO CB_AUTH_TOKEN(TOKEN_ID,SESSION_ID,USER_ID,EXPIRATION_TIME,REFRESH_TOKEN_ID,REFRESH_TOKEN_EXPIRATION_TIME) " +
+ "VALUES(?,?,?,?,?,?)")) {
+
+ String smAccessToken = SecurityUtils.generatePassword(32);
+ dbStat.setString(1, smAccessToken);
dbStat.setString(2, smSessionId);
if (userId == null) {
dbStat.setNull(3, Types.VARCHAR);
} else {
dbStat.setString(3, userId);
}
- var expirationTime = Timestamp.valueOf(LocalDateTime.now().plusHours(TOKEN_HOURS_ALIVE_TIME));
- dbStat.setTimestamp(4, expirationTime);
+ var accessTokenExpirationTime = Timestamp.valueOf(LocalDateTime.now().plusMinutes(ACCESS_TOKEN_TTL_IN_MINUTES));
+ dbStat.setTimestamp(4, accessTokenExpirationTime);
+
+ String smRefreshToken = SecurityUtils.generatePassword(32);
+ dbStat.setString(5, smRefreshToken);
+ var refreshTokenExpirationTime = Timestamp.valueOf(LocalDateTime.now().plusHours(REFRESH_TOKEN_TTL_IN_HOURS));
+ dbStat.setTimestamp(6, refreshTokenExpirationTime);
+
dbStat.execute();
- return authToken;
+ return new SMTokens(smAccessToken, smRefreshToken);
}
}
@@ -1356,7 +1434,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
userId = dbResult.getString(1);
var expiredDate = dbResult.getTimestamp(2);
if (application.isMultiNode() && Timestamp.from(Instant.now()).after(expiredDate)) {
- throw new SMException("Token expired");
+ throw new SMAccessTokenExpiredException("Token expired");
}
sessionId = dbResult.getString(3);
}
diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java
index 20217c60f5..6bd385c8b6 100644
--- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java
+++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java
@@ -68,7 +68,7 @@ public class CBDatabase {
public static final String SCHEMA_UPDATE_SQL_PATH = "db/cb_schema_update_";
private static final int LEGACY_SCHEMA_VERSION = 1;
- private static final int CURRENT_SCHEMA_VERSION = 8;
+ private static final int CURRENT_SCHEMA_VERSION = 9;
private static final String DEFAULT_DB_USER_NAME = "cb-data";
private static final String DEFAULT_DB_PWD_FILE = ".database-credentials.dat";
diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/RefreshTokenInfo.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/RefreshTokenInfo.java
new file mode 100644
index 0000000000..89d39430cd
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/RefreshTokenInfo.java
@@ -0,0 +1,52 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2022 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.cloudbeaver.service.security.internal;
+
+import org.jkiss.code.NotNull;
+
+public class RefreshTokenInfo {
+ @NotNull
+ private final String refreshToken;
+
+ @NotNull
+ private final String sessionId;
+
+ @NotNull
+ private final String userId;
+
+ public RefreshTokenInfo(@NotNull String refreshToken, @NotNull String sessionId, @NotNull String userId) {
+ this.refreshToken = refreshToken;
+ this.sessionId = sessionId;
+ this.userId = userId;
+ }
+
+ @NotNull
+ public String getRefreshToken() {
+ return refreshToken;
+ }
+
+ @NotNull
+ public String getSessionId() {
+ return sessionId;
+ }
+
+ @NotNull
+ public String getUserId() {
+ return userId;
+ }
+}
diff --git a/server/features/io.cloudbeaver.ce.drivers.feature/feature.xml b/server/features/io.cloudbeaver.ce.drivers.feature/feature.xml
index e5e59870a4..0016374b8b 100644
--- a/server/features/io.cloudbeaver.ce.drivers.feature/feature.xml
+++ b/server/features/io.cloudbeaver.ce.drivers.feature/feature.xml
@@ -2,7 +2,7 @@
diff --git a/server/features/io.cloudbeaver.ce.drivers.feature/pom.xml b/server/features/io.cloudbeaver.ce.drivers.feature/pom.xml
index 158e2b6e27..9d0aa29a64 100644
--- a/server/features/io.cloudbeaver.ce.drivers.feature/pom.xml
+++ b/server/features/io.cloudbeaver.ce.drivers.feature/pom.xml
@@ -9,6 +9,6 @@
../
io.cloudbeaver.ce.drivers.feature
- 1.0.79-SNAPSHOT
+ 1.0.80-SNAPSHOT
eclipse-feature
diff --git a/server/features/io.cloudbeaver.product.ce.feature/feature.xml b/server/features/io.cloudbeaver.product.ce.feature/feature.xml
index 94cf4d5ab5..fb588dfa1d 100644
--- a/server/features/io.cloudbeaver.product.ce.feature/feature.xml
+++ b/server/features/io.cloudbeaver.product.ce.feature/feature.xml
@@ -2,7 +2,7 @@
diff --git a/server/features/io.cloudbeaver.product.ce.feature/pom.xml b/server/features/io.cloudbeaver.product.ce.feature/pom.xml
index f007f17138..78ccca0e67 100644
--- a/server/features/io.cloudbeaver.product.ce.feature/pom.xml
+++ b/server/features/io.cloudbeaver.product.ce.feature/pom.xml
@@ -10,7 +10,7 @@
../
io.cloudbeaver.product.ce.feature
- 22.1.5-SNAPSHOT
+ 22.2.0-SNAPSHOT
eclipse-feature
diff --git a/server/features/io.cloudbeaver.server.feature/feature.xml b/server/features/io.cloudbeaver.server.feature/feature.xml
index a05955f56e..7a4032a6eb 100644
--- a/server/features/io.cloudbeaver.server.feature/feature.xml
+++ b/server/features/io.cloudbeaver.server.feature/feature.xml
@@ -2,7 +2,7 @@
diff --git a/server/features/io.cloudbeaver.server.feature/pom.xml b/server/features/io.cloudbeaver.server.feature/pom.xml
index f7981eec85..a1fda267bc 100644
--- a/server/features/io.cloudbeaver.server.feature/pom.xml
+++ b/server/features/io.cloudbeaver.server.feature/pom.xml
@@ -10,6 +10,6 @@
../
io.cloudbeaver.server.feature
- 22.1.5-SNAPSHOT
+ 22.2.0-SNAPSHOT
eclipse-feature
diff --git a/server/features/io.cloudbeaver.ws.feature/feature.xml b/server/features/io.cloudbeaver.ws.feature/feature.xml
index 79da427f63..5f472b85f8 100644
--- a/server/features/io.cloudbeaver.ws.feature/feature.xml
+++ b/server/features/io.cloudbeaver.ws.feature/feature.xml
@@ -2,7 +2,7 @@
diff --git a/server/features/io.cloudbeaver.ws.feature/pom.xml b/server/features/io.cloudbeaver.ws.feature/pom.xml
index 74c286d66f..3432c0ab49 100644
--- a/server/features/io.cloudbeaver.ws.feature/pom.xml
+++ b/server/features/io.cloudbeaver.ws.feature/pom.xml
@@ -10,6 +10,6 @@
../
io.cloudbeaver.ws.feature
- 1.0.9-SNAPSHOT
+ 1.0.10-SNAPSHOT
eclipse-feature
diff --git a/server/pom.xml b/server/pom.xml
index 6bdc31506d..47c25dd7d5 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -19,7 +19,7 @@
CloudBeaver CE
- 22.1.5
+ 22.2.0
diff --git a/server/product/web-server/CloudbeaverServer.product b/server/product/web-server/CloudbeaverServer.product
index 4c0effb006..45412eb7b4 100644
--- a/server/product/web-server/CloudbeaverServer.product
+++ b/server/product/web-server/CloudbeaverServer.product
@@ -2,7 +2,7 @@
diff --git a/server/product/web-server/pom.xml b/server/product/web-server/pom.xml
index 9a2649c358..c8acd31027 100644
--- a/server/product/web-server/pom.xml
+++ b/server/product/web-server/pom.xml
@@ -9,7 +9,7 @@
1.0.0-SNAPSHOT
../../
- 22.1.5-SNAPSHOT
+ 22.2.0-SNAPSHOT
web-server
eclipse-repository
Cloudbeaver Server Product
diff --git a/webapp/packages/core-app/src/locales/en.ts b/webapp/packages/core-app/src/locales/en.ts
index 6fd8778289..fd7f802d03 100644
--- a/webapp/packages/core-app/src/locales/en.ts
+++ b/webapp/packages/core-app/src/locales/en.ts
@@ -10,35 +10,6 @@ export default [
['app_shared_settingsMenu_theme', 'Theme'],
['app_shared_settingsMenu_lang', 'Language'],
['app_topnavbar_connection_schema_manager_not_selected', '-- not selected --'],
- ['app_navigationTree_openNodeTab', 'Open'],
- ['app_navigationTree_search', 'Search elements...'],
- ['app_navigationTree_limited', 'Elements are limited to {args.limit} items'],
- ['app_navigationTree_action_link_with_editor', 'Link with editor'],
- ['app_navigationTree_action_collapse_all', 'Collapse all'],
- ['app_navigationTree_settings_filter_title', 'Filter'],
- ['app_navigationTree_settings_filter_description', 'Show filtering field'],
- ['app_navigationTree_settings_filter_all_title', 'Show collapsed'],
- ['app_navigationTree_settings_filter_all_description', 'Shows filtered elements in collapsed folders'],
- ['app_navigationTree_settings_state_title', 'Save tree state'],
- ['app_navigationTree_settings_state_description', 'Reopen expanded nodes after page refresh'],
- ['app_navigationTree_settings_folders_title', 'Folders'],
- ['app_navigationTree_settings_folders_description', 'Open any node as tree root node'],
- ['app_navigationTree_node_delete_confirmation', 'You\'re going to delete "{args.name}". Are you sure?'],
- ['app_navigationTree_node_delete_error', 'Failed to delete "{args.name}'],
- ['app_navigationTree_node_rename_error', 'Error occurred while renaming'],
- ['app_navigationTree_node_empty', 'Empty'],
- ['app_navigationTree_node_not_found', 'Node not found'],
- ['app_navigationTree_connection_view', 'Connection view'],
- ['app_navigationTree_connection_view_option_simple', 'Simple'],
- ['app_navigationTree_connection_view_option_advanced', 'Advanced'],
- ['app_navigationTree_connection_view_option_custom', 'Custom'],
- ['app_navigationTree_connection_view_option_showSystemObjects', 'Show system objects'],
- ['app_navigationTree_refresh', 'Refresh'],
- ['app_navigationTree_refresh_error', 'Failed to refresh node'],
- ['app_navigationTree_node_change_name_error', 'Error occurred while changing name'],
- ['app_navigationTree_context_disconnect', 'Disconnect'],
- ['app_navigationTree_connection_group_user', 'User Connections'],
- ['app_navigationTree_connection_group_shared', 'Shared Connections'],
['app_shared_inlineEditor_dialog_title', 'Edit mode'],
['app_shared_inlineEditor_dialog_apply', 'Apply'],
['app_shared_inlineEditor_dialog_cancel', 'Cancel'],
diff --git a/webapp/packages/core-app/src/locales/it.ts b/webapp/packages/core-app/src/locales/it.ts
index baeaa52e81..57bda48d0d 100644
--- a/webapp/packages/core-app/src/locales/it.ts
+++ b/webapp/packages/core-app/src/locales/it.ts
@@ -10,34 +10,6 @@ export default [
['app_shared_settingsMenu_theme', 'Tema'],
['app_shared_settingsMenu_lang', 'Lingua'],
['app_topnavbar_connection_schema_manager_not_selected', '-- non selezionato --'],
- ['app_navigationTree_openNodeTab', 'Apri'],
- ['app_navigationTree_search', 'Search elements...'],
- ['app_navigationTree_limited', 'Elements are limited to {args.limit} items'],
- ['app_navigationTree_action_link_with_editor', 'Link with editor'],
- ['app_navigationTree_action_collapse_all', 'Collapse all'],
- ['app_navigationTree_settings_filter_title', 'Filter'],
- ['app_navigationTree_settings_filter_description', 'Show filtering field'],
- ['app_navigationTree_settings_filter_all_title', 'Show collapsed'],
- ['app_navigationTree_settings_filter_all_description', 'Shows filtered elements in collapsed folders'],
- ['app_navigationTree_node_delete_confirmation', 'You\'re going to delete "{args.name}". Are you sure?'],
- ['app_navigationTree_node_delete_error', 'Failed to delete "{args.name}'],
- ['app_navigationTree_node_rename_error', 'Error occurred while renaming'],
- ['app_navigationTree_settings_state_title', 'Save tree state'],
- ['app_navigationTree_settings_state_description', 'Reopen expanded nodes after page refresh'],
- ['app_navigationTree_settings_folders_title', 'Folders'],
- ['app_navigationTree_settings_folders_description', 'Open any node as tree root node'],
- ['app_navigationTree_node_empty', 'Empty'],
- ['app_navigationTree_node_not_found', 'Node not found'],
- ['app_navigationTree_connection_view', 'Vista di connessione'],
- ['app_navigationTree_connection_view_option_simple', 'Semplice'],
- ['app_navigationTree_connection_view_option_advanced', 'Avanzato'],
- ['app_navigationTree_connection_view_option_custom', 'Manuale'],
- ['app_navigationTree_connection_view_option_showSystemObjects', 'Mostra oggetti di sistema'],
- ['app_navigationTree_refresh', 'Aggiorna'],
- ['app_navigationTree_refresh_error', 'Failed to refresh node'],
- ['app_navigationTree_context_disconnect', 'Scollega'],
- ['app_navigationTree_connection_group_user', 'Connessioni Utente'],
- ['app_navigationTree_connection_group_shared', 'Connessioni Condivise'],
['app_shared_inlineEditor_dialog_title', 'Modalità modifica'],
['app_shared_inlineEditor_dialog_apply', 'Applica'],
['app_shared_inlineEditor_dialog_cancel', 'Cancella'],
diff --git a/webapp/packages/core-app/src/locales/ru.ts b/webapp/packages/core-app/src/locales/ru.ts
index 6e89833e21..65641a84ee 100644
--- a/webapp/packages/core-app/src/locales/ru.ts
+++ b/webapp/packages/core-app/src/locales/ru.ts
@@ -13,38 +13,6 @@ export default [
'app_shared_navigationTabsBar_placeholder',
'Нет открытых объектов для отображения. Дважды нажмите на элемент в дереве навигации, чтобы открыть его.',
],
- ['app_navigationTree_openNodeTab', 'Открыть'],
- ['app_navigationTree_search', 'Искать элементы...'],
- ['app_navigationTree_limited', 'Отображено {args.limit} элементов'],
-
- ['app_navigationTree_action_link_with_editor', 'Синхронизовать с редактором'],
- ['app_navigationTree_action_collapse_all', 'Свернуть все элементы'],
-
- ['app_navigationTree_settings_filter_title', 'Фильтр'],
- ['app_navigationTree_settings_filter_description', 'Показывать фильтр'],
- ['app_navigationTree_settings_filter_all_title', 'Фильтровать скрытые элементы'],
- ['app_navigationTree_settings_filter_all_description', 'Показывает скрытые элементы при использовании фильтра'],
- ['app_navigationTree_settings_state_title', 'Сохранять состояние дерева'],
- ['app_navigationTree_settings_state_description', 'Восстанавливает открытые узлы после обновления страницы'],
- ['app_navigationTree_settings_folders_title', 'Папки'],
- ['app_navigationTree_settings_folders_description', 'Позволяет открыть любой узел как начальный'],
- ['app_navigationTree_node_delete_confirmation', 'Вы собираетесь удалить "{args.name}". Вы уверены?'],
- ['app_navigationTree_node_delete_error', 'Ошибка удаления "{args.name}'],
- ['app_navigationTree_node_rename_error', 'Ошибка переименования ноды'],
-
- ['app_navigationTree_node_empty', 'Пусто'],
- ['app_navigationTree_node_not_found', 'Элемент не найден'],
- ['app_navigationTree_connection_view', 'Отображение'],
- ['app_navigationTree_connection_view_option_simple', 'Упрощенное'],
- ['app_navigationTree_connection_view_option_advanced', 'Продвинутое'],
- ['app_navigationTree_connection_view_option_custom', 'Настраиваемое'],
- ['app_navigationTree_connection_view_option_showSystemObjects', 'Показывать системные объекты'],
- ['app_navigationTree_refresh', 'Обновить'],
- ['app_navigationTree_refresh_error', 'Не удалось обновить узел'],
- ['app_navigationTree_node_change_name_error', 'Не удалось изменить название'],
- ['app_navigationTree_context_disconnect', 'Отключить'],
- ['app_navigationTree_connection_group_user', 'Пользовательские подключения'],
- ['app_navigationTree_connection_group_shared', 'Общие подключения'],
['app_shared_inlineEditor_dialog_title', 'Редактирование'],
['app_shared_inlineEditor_dialog_apply', 'Применить'],
['app_shared_inlineEditor_dialog_cancel', 'Отменить'],
diff --git a/webapp/packages/core-app/src/locales/zh.ts b/webapp/packages/core-app/src/locales/zh.ts
index 122d76ca25..f3abaf8b5d 100644
--- a/webapp/packages/core-app/src/locales/zh.ts
+++ b/webapp/packages/core-app/src/locales/zh.ts
@@ -10,35 +10,6 @@ export default [
['app_shared_settingsMenu_theme', '主题'],
['app_shared_settingsMenu_lang', '语言'],
['app_topnavbar_connection_schema_manager_not_selected', '-- 为选择 --'],
- ['app_navigationTree_search', 'Search elements...'],
- ['app_navigationTree_limited', 'Elements are limited to {args.limit} items'],
- ['app_navigationTree_action_link_with_editor', 'Link with editor'],
- ['app_navigationTree_action_collapse_all', 'Collapse all'],
- ['app_navigationTree_settings_filter_title', 'Filter'],
- ['app_navigationTree_settings_filter_description', 'Show filtering field'],
- ['app_navigationTree_settings_filter_all_title', 'Show collapsed'],
- ['app_navigationTree_settings_filter_all_description', 'Shows filtered elements in collapsed folders'],
- ['app_navigationTree_settings_state_title', 'Save tree state'],
- ['app_navigationTree_settings_state_description', 'Reopen expanded nodes after page refresh'],
- ['app_navigationTree_settings_folders_title', 'Folders'],
- ['app_navigationTree_settings_folders_description', 'Open any node as tree root node'],
- ['app_navigationTree_node_delete_confirmation', 'You\'re going to delete "{args.name}". Are you sure?'],
- ['app_navigationTree_node_delete_error', 'Failed to delete "{args.name}'],
- ['app_navigationTree_node_rename_error', 'Error occurred while renaming'],
- ['app_navigationTree_node_empty', 'Empty'],
- ['app_navigationTree_openNodeTab', '打开'],
- ['app_navigationTree_connection_view', '连接视图'],
- ['app_navigationTree_node_not_found', 'Node not found'],
- ['app_navigationTree_connection_view_option_simple', '简单'],
- ['app_navigationTree_connection_view_option_advanced', '完善'],
- ['app_navigationTree_connection_view_option_custom', '自定义'],
- ['app_navigationTree_connection_view_option_showSystemObjects', '展示系统对象'],
- ['app_navigationTree_refresh', '刷新'],
- ['app_navigationTree_refresh_error', 'Failed to refresh node'],
- ['app_navigationTree_node_change_name_error', '更改名称时发生错误'],
- ['app_navigationTree_context_disconnect', '断开连接'],
- ['app_navigationTree_connection_group_user', '用户连接'],
- ['app_navigationTree_connection_group_shared', '共享连接'],
['app_shared_inlineEditor_dialog_title', '编辑模式'],
['app_shared_inlineEditor_dialog_apply', '应用'],
['app_shared_inlineEditor_dialog_cancel', '取消'],
diff --git a/webapp/packages/core-authentication/src/UserInfoResource.ts b/webapp/packages/core-authentication/src/UserInfoResource.ts
index 961e659f95..447e2d7ee8 100644
--- a/webapp/packages/core-authentication/src/UserInfoResource.ts
+++ b/webapp/packages/core-authentication/src/UserInfoResource.ts
@@ -119,7 +119,7 @@ UserInfoIncludes
return authInfo as AuthInfo;
}
- finishFederatedAuthentication(authId: string, link?: boolean): ITask {
+ finishFederatedAuthentication(authId: string, linkUser?: boolean): ITask {
let activeTask: ITask | undefined;
return new AutoRunningTask(() => this.performUpdate(
@@ -139,7 +139,7 @@ UserInfoIncludes
async () => {
const { authInfo } = await this.graphQLService.sdk.getAuthStatus({
authId,
- linkUser: link,
+ linkUser,
customIncludeOriginDetails: true,
});
return authInfo as AuthInfo;
diff --git a/webapp/packages/core-blocks/src/HTMLTemplates/head.html.ejs b/webapp/packages/core-blocks/src/HTMLTemplates/head.html.ejs
index 95176d4a64..bcebfe5cef 100644
--- a/webapp/packages/core-blocks/src/HTMLTemplates/head.html.ejs
+++ b/webapp/packages/core-blocks/src/HTMLTemplates/head.html.ejs
@@ -7,8 +7,6 @@
-