Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5e7159c
dbeaver/cloudbeaver#4120 support token header
HocKu7 Apr 2, 2026
a2fe997
Merge branch 'devel' into dbeaver/cloudbeaver#4120-support-token-header
HocKu7 Apr 2, 2026
e9816e5
dbeaver/cloudbeaver#4120 support token header
HocKu7 Apr 2, 2026
ecfb5fb
dbeaver/cloudbeaver#4120 support token header
HocKu7 Apr 3, 2026
2ef8546
dbeaver/cloudbeaver#4120 support token header
HocKu7 Apr 3, 2026
c3ef7e2
dbeaver/cloudbeaver#4120 support token header
HocKu7 Apr 3, 2026
178a049
dbeaver/cloudbeaver#4120 support token header
HocKu7 Apr 3, 2026
61d6af1
dbeaver/cloudbeaver#4120 support token header
HocKu7 Apr 7, 2026
f895e85
Merge branch 'devel' into dbeaver/cloudbeaver#4120-support-token-header
HocKu7 Apr 17, 2026
991c548
dbeaver/pro#4120 added tests, now session in session holder
HocKu7 Apr 17, 2026
5d33595
dbeaver/pro#4120 review fix naming
HocKu7 Apr 20, 2026
02bc848
dbeaver/pro#4120 review fixes
HocKu7 Apr 20, 2026
4861126
Merge branch 'refs/heads/devel' into dbeaver/cloudbeaver#4120-support…
HocKu7 Apr 21, 2026
3dff740
dbeaver/cloudbeaver#4120 review fixes
HocKu7 Apr 21, 2026
881ddda
Merge branch 'devel' into dbeaver/cloudbeaver#4120-support-token-header
serge-rider Apr 24, 2026
83ec357
dbeaver/cloudbeaver#4120 session type now final
HocKu7 Apr 24, 2026
cb1d13c
Merge branch 'devel' into dbeaver/cloudbeaver#4120-support-token-header
HocKu7 Apr 27, 2026
6fdf355
dbeaver/cloudbeaver#4120 remove part from ce
HocKu7 Apr 27, 2026
5c2f2ef
dbeaver/cloudbeaver#4120 remove part from ce
HocKu7 Apr 27, 2026
862ea72
Merge branch 'devel' into dbeaver/cloudbeaver#4120-support-token-header
HocKu7 Apr 29, 2026
9e32e7c
dbeaver/cloudbeaver#4120 fix header name
HocKu7 Apr 29, 2026
1dc9370
dbeaver/cloudbeaver#4120 review fix
HocKu7 Apr 30, 2026
91f1f8d
dbeaver/cloudbeaver#4120 review fix
HocKu7 Apr 30, 2026
24f075c
dbeaver/cloudbeaver#4120 fix review
HocKu7 Apr 30, 2026
fbdf2f6
Merge branch 'devel' into dbeaver/cloudbeaver#4120-support-token-header
EvgeniaBzzz May 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
@NotNull
protected final ServletApplication application;
protected volatile long lastAccessTime;
@NotNull
private SessionType sessionType = SessionType.WEB;
Comment thread
HocKu7 marked this conversation as resolved.
Outdated

private final List<CBWebSessionEventHandler> sessionEventHandlers = new CopyOnWriteArrayList<>();
private WebSessionEventsFilter eventsFilter;
Expand Down Expand Up @@ -176,6 +178,15 @@ public long getLastAccessTimeMillis() {
return lastAccessTime;
}

@NotNull
public SessionType getSessionType() {
return sessionType;
}

public void setSessionType(@NotNull SessionType sessionType) {
this.sessionType = sessionType;
}

public void touchSession() {
this.lastAccessTime = System.currentTimeMillis();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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;

public enum SessionType {
WEB,
HEADLESS,
API_TOKEN
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
Expand Down Expand Up @@ -32,6 +32,7 @@ public WebHeadlessSession(
@NotNull ServletAuthApplication application
) throws DBException {
super(id, application);
setSessionType(SessionType.HEADLESS);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,18 @@ public WebSession(
@NotNull WebHttpRequestInfo requestInfo,
@NotNull ServletAuthApplication application,
@NotNull Map<String, DBWSessionHandler<WebSession>> sessionHandlers
) throws DBException {
this(Objects.requireNonNull(requestInfo.getId()), requestInfo, application, sessionHandlers);
}

public WebSession(
@NotNull String sessionId,
@NotNull WebHttpRequestInfo requestInfo,
@NotNull ServletAuthApplication application,
@NotNull Map<String, DBWSessionHandler<WebSession>> sessionHandlers
) throws DBException {
this(
Objects.requireNonNull(requestInfo.getId()),
sessionId,
CommonUtils.toString(requestInfo.getLocale()),
application,
sessionHandlers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,6 @@ public class CBConstants {
public static final String DEFAULT_CLOUD_PROJECT_NAME = "GlobalConfiguration";

public static final String SECURED_VALUE = "******";

public static final String HEADER_API_TOKEN = "X-API-Token";
Comment thread
HocKu7 marked this conversation as resolved.
Outdated
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
Expand Down Expand Up @@ -51,7 +51,7 @@ public class CBSessionManager implements WebAppSessionManager {
private static final Log log = Log.getLog(CBSessionManager.class);

private final CBApplication<?> application;
private final Map<String, BaseWebSession> sessionMap = new HashMap<>();
protected final Map<String, BaseWebSession> sessionMap = new HashMap<>();

public CBSessionManager(CBApplication<?> application) {
this.application = application;
Expand Down Expand Up @@ -441,8 +441,7 @@ public WebSession getWebSession(
*/
public void sendSessionsStates() {
synchronized (sessionMap) {
sessionMap.values()
.parallelStream()
sessionMap.values().parallelStream()
.filter(session -> {
if (session instanceof WebSession webSession) {
return webSession.isAuthorizedInSecurityManager();
Expand All @@ -469,8 +468,7 @@ public void closeUserSession(@NotNull WSAbstractEvent event) {
synchronized (sessionMap) {
for (Iterator<BaseWebSession> iterator = sessionMap.values().iterator(); iterator.hasNext(); ) {
var session = iterator.next();
if (CommonUtils.equalObjects(session.getUserContext().getUserId(),
event.getUserId())) {
if (CommonUtils.equalObjects(session.getUserContext().getUserId(), event.getUserId())) {
if (session instanceof WebHeadlessSession headlessSession) {
headlessSession.addSessionEvent(event);
}
Expand Down Expand Up @@ -527,4 +525,10 @@ protected void closeExpiredSession(@NotNull BaseWebSession session) {
log.debug("> Expire session '" + session.getSessionId() + "'");
session.close();
}

@NotNull
Comment thread
HocKu7 marked this conversation as resolved.
Outdated
@Override
public WebSession getWebSessionByToken(@NotNull HttpServletRequest request, @NotNull String token) throws DBException {
throw new UnsupportedOperationException("Not supported yet.");
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
Expand Down Expand Up @@ -72,4 +72,7 @@ WebHeadlessSession getHeadlessSession(
default void expireIdleSessions() {

}

@NotNull
WebSession getWebSessionByToken(@NotNull HttpServletRequest request, @NotNull String token) throws DBException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import io.cloudbeaver.model.apilog.ApiCallInterceptor;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.registry.WebServiceRegistry;
import io.cloudbeaver.server.CBConstants;
import io.cloudbeaver.server.WebAppSessionManager;
import io.cloudbeaver.server.WebAppUtils;
import io.cloudbeaver.service.DBWBindingContext;
import io.cloudbeaver.service.DBWServiceBindingGraphQL;
Expand All @@ -43,6 +45,7 @@
import jakarta.servlet.http.HttpServletResponse;
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.data.json.JSONUtils;
import org.jkiss.dbeaver.utils.MimeTypes;
Expand Down Expand Up @@ -239,6 +242,32 @@ private void executeQuery(
@Nullable Map<String, Object> variables,
@Nullable String operationName
) throws IOException {


WebAppSessionManager sessionManager = WebAppUtils.getWebApplication().getSessionManager();
String userId = GraphQLLoggerUtil.getUserId(request);
LocalDateTime startTime = LocalDateTime.now();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to pass these params to isQueryHandledBeforeExecution and notifyApiCallInterceptor, they can be extracted from request on demand.

String token = request.getHeader(CBConstants.HEADER_API_TOKEN);
if (token != null) {
try {
sessionManager.getWebSessionByToken(request, token);
} catch (DBException e) {
log.error("Error obtaining web session by token", e);
DBWebException webException = new DBWebException(
"Error obtaining web session by token: " + e.getMessage(),
DBWebException.ERROR_CODE_AUTH_REQUIRED,
e
);
ExecutionResult executionResult = ExecutionResult.newExecutionResult()
.addError(webException)
.build();
notifyApiCallInterceptor(request, variables, operationName, userId, startTime, webException.getMessage());
writeExecutionResult(request, response, executionResult);
return;
}
}

Map<String, Object> mapOfContext =
Map.of(
"request", request,
Expand All @@ -254,8 +283,6 @@ private void executeQuery(
if (operationName != null) {
contextBuilder.operationName(operationName);
}
String userId = GraphQLLoggerUtil.getUserId(request);
LocalDateTime startTime = LocalDateTime.now();
ExecutionInput executionInput = contextBuilder.build();
ExecutionResult executionResult = null;
Exception executionException = null;
Expand All @@ -271,23 +298,44 @@ private void executeQuery(
} else if (executionException != null) {
errorMessage = executionException.getMessage();
}
if (WebAppUtils.getWebApplication() instanceof ApiCallInterceptor apiCallInterceptor) {
apiCallInterceptor.onApiCallEvent(
request,
variables,
CommonUtils.notEmpty(operationName), userId, startTime,
errorMessage,
API_PROTOCOL
);
}
notifyApiCallInterceptor(request, variables, operationName, userId, startTime, errorMessage);
}

if (executionResult != null) {
Map<String, Object> resJSON = executionResult.toSpecification();
String resString = gson.toJson(resJSON);
setDevelHeaders(request, response);
response.setContentType(GraphQLConstants.CONTENT_TYPE_JSON_UTF8);
response.getWriter().print(resString);
writeExecutionResult(request, response, executionResult);
}
}

private void writeExecutionResult(
@NotNull HttpServletRequest request,
@NotNull HttpServletResponse response,
@NotNull ExecutionResult executionResult
) throws IOException {
Map<String, Object> resJSON = executionResult.toSpecification();
String resString = gson.toJson(resJSON);
setDevelHeaders(request, response);
response.setContentType(GraphQLConstants.CONTENT_TYPE_JSON_UTF8);
response.getWriter().print(resString);
}

private void notifyApiCallInterceptor(
@NotNull HttpServletRequest request,
@Nullable Map<String, Object> variables,
@Nullable String operationName,
@Nullable String userId,
@NotNull LocalDateTime startTime,
@Nullable String errorMessage
) {
if (WebAppUtils.getWebApplication() instanceof ApiCallInterceptor apiCallInterceptor) {
apiCallInterceptor.onApiCallEvent(
request,
variables,
CommonUtils.notEmpty(operationName),
userId,
startTime,
errorMessage,
API_PROTOCOL
);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
Expand Down Expand Up @@ -108,11 +108,7 @@ protected static DBWBindingContext getBindingContext(DataFetchingEnvironment env
}

protected static WebSession getWebSession(DataFetchingEnvironment env) throws DBWebException {
if (env.getGraphQlContext().getBoolean(CloudbeaverCliConstants.CLI_MODE)) {
return getSessionFromContextOrThrow(env);
}
return WebAppUtils.getWebApplication().getSessionManager().getWebSession(
GraphQLEndpoint.getServletRequestOrThrow(env), getServletResponse(env));
return getWebSession(env, true);
}

@Nullable
Expand Down
Loading