Merge branch 'devel' into 8518-cb-add-tolltip-for-the-bind-parameters-dialog

This commit is contained in:
sergeyteleshev
2026-03-25 11:38:13 +01:00
committed by GitHub
11 changed files with 79 additions and 106 deletions
@@ -193,8 +193,12 @@ public class ServletAppUtils {
@NotNull String origin
) throws DBException {
String finalOrigin = webAuthApplication.modifyOrigin(origin);
StringBuilder authUriBuilder = new StringBuilder(removeSideSlashes(finalOrigin));
String serviceUriSegment = removeSideSlashes(webAuthApplication.getAuthServiceUriSegment());
String rootUri = removeSideSlashes(getServletApplication().getRootURI());
if (finalOrigin.endsWith("/" + rootUri) && serviceUriSegment.startsWith(rootUri + "/")) {
finalOrigin = finalOrigin.substring(0, finalOrigin.length() - rootUri.length());
}
StringBuilder authUriBuilder = new StringBuilder(removeSideSlashes(finalOrigin));
if (CommonUtils.isNotEmpty(serviceUriSegment)) {
authUriBuilder.append("/").append(serviceUriSegment);
}
@@ -379,6 +379,63 @@ public class CBSessionManager implements WebAppSessionManager {
}
}
@Nullable
public WebSession getWebSession(
@Nullable String smAccessToken,
@NotNull WebHttpRequestInfo requestInfo,
boolean create
) throws DBException {
if (CommonUtils.isEmpty(smAccessToken)) {
return null;
}
synchronized (sessionMap) {
var tempCredProvider = new SMTokenCredentialProvider(smAccessToken);
SMAuthPermissions authPermissions = application.createSecurityController(tempCredProvider).getTokenPermissions();
var sessionId = requestInfo.getId() != null ? requestInfo.getId()
: authPermissions.getSessionId();
var existSession = sessionMap.get(sessionId);
if (existSession instanceof WebSession webSession) {
var creds = webSession.getUserContext().getActiveUserCredentials();
if (creds == null || !smAccessToken.equals(creds.getSmAccessToken())) {
if (webSession.getUserContext().refresh(
smAccessToken,
null,
authPermissions
)) {
webSession.refreshUserData();
}
}
return webSession;
}
if (existSession != null) {
//session exist but it not web session
return null;
}
if (!create) {
return null;
}
if (requestInfo.getId() == null) {
requestInfo = new WebHttpRequestInfo(
sessionId,
requestInfo.getLocale(),
requestInfo.getLastRemoteAddress(),
requestInfo.getLastRemoteUserAgent()
);
}
var webSession = createWebSessionImpl(requestInfo);
webSession.getUserContext().refresh(
smAccessToken,
null,
authPermissions
);
webSession.refreshUserData();
sessionMap.put(sessionId, webSession);
return webSession;
}
}
/**
* Send session state with remaining alive time to all cached session
*/
@@ -24,7 +24,6 @@ import jakarta.websocket.HandshakeResponse;
import jakarta.websocket.server.HandshakeRequest;
import jakarta.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.ee11.websocket.jakarta.server.internal.JakartaWebSocketCreator;
import org.eclipse.jetty.http.BadMessageException;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
@@ -89,7 +88,7 @@ public class CBWebSocketServerConfigurator extends ServerEndpointConfig.Configur
throw new RuntimeException(e.getMessage(), e);
}
if (sec.getUserProperties().get(PROP_WEB_SESSION) == null) {
throw new BadMessageException("No web session found for websocket request");
throw new RuntimeException("No web session found for websocket request");
}
}
@@ -97,8 +96,8 @@ public class CBWebSocketServerConfigurator extends ServerEndpointConfig.Configur
private String getSessionId(@NotNull HandshakeRequest request) {
// complex auth uses bearer authentication
List<String> authHeaders = WSClientUtils.getHeaders(request.getHeaders(), HttpConstants.HEADER_AUTHORIZATION);
if (!CommonUtils.isEmpty(authHeaders) && authHeaders.get(0).startsWith("Bearer ")) {
return authHeaders.get(0).substring(7);
if (!CommonUtils.isEmpty(authHeaders) && authHeaders.getFirst().startsWith(HttpConstants.BEARER_PREFIX)) {
return authHeaders.getFirst().substring(7);
}
return request.getHttpSession() instanceof HttpSession httpSession ? httpSession.getId() : null;
}
@@ -32,7 +32,6 @@ import io.cloudbeaver.service.security.bruteforce.UserLoginRecord;
import io.cloudbeaver.service.security.db.CBDatabase;
import io.cloudbeaver.service.security.internal.AuthAttemptSessionInfo;
import io.cloudbeaver.service.security.internal.CBAuthSubjectRepo;
import io.cloudbeaver.service.security.internal.SMTokenInfo;
import io.cloudbeaver.utils.WebEventUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -2437,7 +2436,9 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
}
}
private SMTokenInfo readAccessTokenInfo(String smAccessToken) throws DBException {
@NotNull
@Override
public SMTokenInfo readAccessTokenInfo(@NotNull String smAccessToken) throws DBException {
try (Connection dbCon = database.openConnection();
PreparedStatement dbStat = dbCon.prepareStatement(
"""
@@ -1,84 +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.service.security.internal;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
public class SMTokenInfo {
@NotNull
private final String accessToken;
@NotNull
private final String refreshToken;
@NotNull
private final String sessionId;
@NotNull
private final String userId;
@Nullable
private final String authRole;
private final boolean serviceToken;
public SMTokenInfo(
@NotNull String accessToken,
@NotNull String refreshToken,
@NotNull String sessionId,
@NotNull String userId,
@Nullable String authRole,
boolean serviceToken
) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
this.sessionId = sessionId;
this.userId = userId;
this.authRole = authRole;
this.serviceToken = serviceToken;
}
@NotNull
public String getRefreshToken() {
return refreshToken;
}
@NotNull
public String getSessionId() {
return sessionId;
}
@NotNull
public String getUserId() {
return userId;
}
@NotNull
public String getAccessToken() {
return accessToken;
}
@Nullable
public String getAuthRole() {
return authRole;
}
public boolean isServiceToken() {
return serviceToken;
}
}
@@ -12,9 +12,6 @@
.rdg-search-panel {
padding-bottom: 0 !important;
.search-panel__inputs {
max-width: var(--tw-container-lg);
}
}
.rdg-cell-search-match {
@@ -52,6 +52,7 @@
flex-direction: column;
flex: 1 1 420px;
min-width: 120px;
max-width: var(--tw-container-lg);
gap: calc(var(--tw-spacing) / 2);
}
+1 -1
View File
@@ -24,7 +24,7 @@
"koa": ">=2.16.4",
"immutable": ">=4.3.8",
"serialize-javascript": ">=7.0.3",
"flatted": ">=3.4.0"
"flatted": ">=3.4.2"
},
"scripts": {
"test": "dbeaver-test",
@@ -24,7 +24,7 @@ export function getObjectPropertyDisplayValue(property: IObjectPropertyInfo) {
return String(getValue(property.value, controlType));
}
function getValue(value: any, controlType: ObjectPropertyType) {
function getValue(value: any, controlType: ObjectPropertyType): any {
const checkbox = controlType === 'checkbox';
if (value === null || value === undefined) {
@@ -40,7 +40,7 @@ function getValue(value: any, controlType: ObjectPropertyType) {
}
if (Array.isArray(value)) {
return value.join(', ');
return `[${value.map(v => getValue(v, controlType)).join(', ')}]`;
}
return value.value || value.displayName || JSON.stringify(value);
@@ -16,6 +16,7 @@ import type { ITreeSettings } from './useTreeSettings.js';
export interface ITreeFilterOptions {
isNodeMatched?: (nodeId: string, filter: string, isMatched: boolean) => boolean;
isEnabled?: boolean;
}
export interface ITreeFilter {
@@ -38,10 +39,7 @@ interface ITreeFilterStateObject extends ITreeFilter, ITreeFilterState {
settings?: ITreeSettings;
}
export function useTreeFilter(
options: ITreeFilterOptions = {},
settings?: ITreeSettings,
): ITreeFilterWithState {
export function useTreeFilter(options: ITreeFilterOptions = {}, settings?: ITreeSettings): ITreeFilterWithState {
options = useObjectRef(options);
const matchCache = new Map<string, boolean>();
@@ -78,7 +76,7 @@ export function useTreeFilter(
settings,
filter: '',
get enabled() {
return this.settings?.get<boolean>(TREE_SETTINGS_FILTER_ENABLED) ?? false;
return this.settings?.get<boolean>(TREE_SETTINGS_FILTER_ENABLED) ?? options.isEnabled ?? false;
},
isNodeMatched(treeData: ITreeData, nodeId: string): boolean {
const filter = this.filter.trim();
+4 -4
View File
@@ -12693,10 +12693,10 @@ __metadata:
languageName: node
linkType: hard
"flatted@npm:>=3.4.0":
version: 3.4.1
resolution: "flatted@npm:3.4.1"
checksum: 10c0/3987a7f1e39bc7215cece001354313b462cdb4fb2dde0df4f7acd9e5016fbae56ee6fb3f0870b2150145033be8bda4f01af6f87a00946049651131bbfca7dfa6
"flatted@npm:>=3.4.2":
version: 3.4.2
resolution: "flatted@npm:3.4.2"
checksum: 10c0/a65b67aae7172d6cdf63691be7de6c5cd5adbdfdfe2e9da1a09b617c9512ed794037741ee53d93114276bff3f93cd3b0d97d54f9b316e1e4885dde6e9ffdf7ed
languageName: node
linkType: hard