From 4475513341feaaa55ca741df236f7c60e9648101 Mon Sep 17 00:00:00 2001 From: Ruslan Musaev <43766501+HocKu7@users.noreply.github.com> Date: Fri, 21 Aug 2026 11:39:35 +0200 Subject: [PATCH] dbeaver/pro#10243 add reconcile project list on update (#4571) Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com> Co-authored-by: Ainur <59531286+yagudin10@users.noreply.github.com> --- .../model/session/BaseWebSession.java | 11 +++++ .../cloudbeaver/model/session/WebSession.java | 46 ++++++++++++++++++- ...erverConfigurationChangedEventHandler.java | 2 +- .../service/admin/impl/WebServiceAdmin.java | 2 +- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/BaseWebSession.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/BaseWebSession.java index 71c6220600..9895062f99 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/BaseWebSession.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/BaseWebSession.java @@ -155,6 +155,17 @@ public abstract class BaseWebSession extends AbstractSessionPersistent { } } + /** + * Refreshes user permissions, teams and accessible projects. + *

+ * Unlike {@link #refreshUserData()} this method must not re-create heavyweight session state + * (navigator model, session projects, connection caches), so it is safe to call + * for foreign sessions on server-wide events. + */ + public void refreshUserPermissions() { + refreshUserData(); + } + @NotNull @Override public SMAuthSpace getSessionSpace() { 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 4c6645c5a3..3685ec18ad 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 @@ -262,12 +262,54 @@ public class WebSession extends BaseWebSession @Override public void refreshUserData() { - super.refreshUserData(); - refreshSessionAuth(); + refreshUserPermissions(); initNavigatorModel(); } + @Override + public void refreshUserPermissions() { + super.refreshUserData(); + refreshSessionAuth(); + if (getUserId() == null && globalProject != null) { + // refreshSessionAuth() updates accessible connections for named users only, + // for anonymous sessions this was done by initNavigatorModel() + globalProject.refreshAccessibleConnectionIds(); + } + syncSessionProjects(); + } + + /** + * Adds/removes only those session projects whose accessibility actually changed. + *

+ * Unlike {@link #initNavigatorModel()} this keeps existing projects, and therefore + * their live connections and SQL contexts, intact. + */ + private void syncSessionProjects() { + if (getNavigatorModel() == null) { + // model was never initialized for this session - nothing to sync + return; + } + try { + Map actualProjects = new LinkedHashMap<>(); + for (RMProject rmProject : getRmController().listAccessibleProjects()) { + actualProjects.put(rmProject.getId(), rmProject); + } + for (WebSessionProjectImpl project : new ArrayList<>(getWorkspace().getProjects())) { + if (actualProjects.remove(project.getId()) == null && !project.isInMemory()) { + // in-memory (anonymous) projects are never listed by RM + deleteSessionProject(project); + } + } + for (RMProject rmProject : actualProjects.values()) { + createWebProject(rmProject); + } + } catch (DBException e) { + addSessionError(e); + log.error("Error synchronizing accessible projects", e); + } + } + // Note: for admin use only public void resetUserState(boolean needResetUserCache) throws DBException { clearAuthTokens(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/events/WSServerConfigurationChangedEventHandler.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/events/WSServerConfigurationChangedEventHandler.java index f9538429e7..6205d613f3 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/events/WSServerConfigurationChangedEventHandler.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/events/WSServerConfigurationChangedEventHandler.java @@ -24,7 +24,7 @@ public class WSServerConfigurationChangedEventHandler extends WSDefaultEventHand @Override protected void updateSessionData(@NotNull BaseWebSession activeUserSession, @NotNull WSServerConfigurationChangedEvent event) { - activeUserSession.refreshUserData(); + activeUserSession.refreshUserPermissions(); super.updateSessionData(activeUserSession, event); } } diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java index e0d7274f34..884e454c02 100644 --- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java +++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java @@ -699,7 +699,7 @@ public class WebServiceAdmin implements DBWServiceAdmin { webSession.resetUserState(); } else { // Just reload session state - webSession.refreshUserData(); + webSession.refreshUserPermissions(); } WebAppUtils.getWebApplication().getDriverRegistry().refreshApplicableDrivers();