Skip to content

Commit fb6f3c8

Browse files
HocKu7serge-riderEvgeniaBzzz
authored
#4120 support token header (#4259)
* #4120 support token header * #4120 support token header * #4120 support token header * #4120 support token header * #4120 support token header * #4120 support token header * #4120 support token header * dbeaver/pro#4120 added tests, now session in session holder * dbeaver/pro#4120 review fix naming * dbeaver/pro#4120 review fixes * #4120 review fixes * #4120 session type now final * #4120 remove part from ce * #4120 remove part from ce * #4120 fix header name * #4120 review fix * #4120 review fix * #4120 fix review --------- Co-authored-by: Serge Rider <serge@jkiss.org> Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
1 parent f3eaed9 commit fb6f3c8

11 files changed

Lines changed: 144 additions & 35 deletions

File tree

server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/BaseWebSession.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,21 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
5555
@NotNull
5656
protected final ServletApplication application;
5757
protected volatile long lastAccessTime;
58+
@NotNull
59+
private final SessionType sessionType;
5860

5961
private final List<CBWebSessionEventHandler> sessionEventHandlers = new CopyOnWriteArrayList<>();
6062
private WebSessionEventsFilter eventsFilter;
6163
private final WebSessionWorkspace workspace;
6264

63-
public BaseWebSession(@NotNull String id, @NotNull ServletApplication application) throws DBException {
65+
public BaseWebSession(
66+
@NotNull String id,
67+
@NotNull ServletApplication application,
68+
@NotNull SessionType sessionType
69+
) throws DBException {
6470
this.id = id;
6571
this.application = application;
72+
this.sessionType = sessionType;
6673
this.createTime = System.currentTimeMillis();
6774
this.lastAccessTime = this.createTime;
6875
this.workspace = createWebWorkspace();
@@ -176,6 +183,11 @@ public long getLastAccessTimeMillis() {
176183
return lastAccessTime;
177184
}
178185

186+
@NotNull
187+
public SessionType getSessionType() {
188+
return sessionType;
189+
}
190+
179191
public void touchSession() {
180192
this.lastAccessTime = System.currentTimeMillis();
181193
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* DBeaver - Universal Database Manager
3+
* Copyright (C) 2010-2026 DBeaver Corp and others
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package io.cloudbeaver.model.session;
18+
19+
public enum SessionType {
20+
WEB,
21+
HEADLESS,
22+
API_TOKEN
23+
}

server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebHeadlessSession.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* DBeaver - Universal Database Manager
3-
* Copyright (C) 2010-2024 DBeaver Corp and others
3+
* Copyright (C) 2010-2026 DBeaver Corp and others
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@ public WebHeadlessSession(
3131
@NotNull String id,
3232
@NotNull ServletAuthApplication application
3333
) throws DBException {
34-
super(id, application);
34+
super(id, application, SessionType.HEADLESS);
3535
}
3636

3737
@Override

server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebHttpRequestInfo.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package io.cloudbeaver.model.session;
1818

1919
import jakarta.servlet.http.HttpServletRequest;
20+
import org.jkiss.code.NotNull;
2021
import org.jkiss.code.Nullable;
2122
import org.jkiss.utils.HttpConstants;
2223

@@ -31,24 +32,39 @@ public class WebHttpRequestInfo {
3132
private final String lastRemoteAddress;
3233
@Nullable
3334
private final String lastRemoteUserAgent;
35+
@NotNull
36+
private final SessionType sessionType;
3437

3538
public WebHttpRequestInfo(HttpServletRequest request) {
36-
this.id = request.getSession() == null ? null : request.getSession().getId();
37-
this.locale = request.getAttribute("locale");
38-
this.lastRemoteAddress = request.getRemoteAddr();
39-
this.lastRemoteUserAgent = request.getHeader(USER_AGENT);
39+
this(
40+
request.getSession() == null ? null : request.getSession().getId(),
41+
request.getAttribute("locale"),
42+
request.getRemoteAddr(),
43+
request.getHeader(USER_AGENT)
44+
);
4045
}
4146

4247
public WebHttpRequestInfo(
4348
@Nullable String id,
4449
@Nullable Object locale,
4550
@Nullable String lastRemoteAddress,
4651
@Nullable String lastRemoteUserAgent
52+
) {
53+
this(id, locale, lastRemoteAddress, lastRemoteUserAgent, SessionType.WEB);
54+
}
55+
56+
public WebHttpRequestInfo(
57+
@Nullable String id,
58+
@Nullable Object locale,
59+
@Nullable String lastRemoteAddress,
60+
@Nullable String lastRemoteUserAgent,
61+
@NotNull SessionType sessionType
4762
) {
4863
this.id = id;
4964
this.locale = locale;
5065
this.lastRemoteAddress = lastRemoteAddress;
5166
this.lastRemoteUserAgent = lastRemoteUserAgent;
67+
this.sessionType = sessionType;
5268
}
5369

5470
@Nullable
@@ -70,4 +86,9 @@ public String getLastRemoteAddress() {
7086
public String getLastRemoteUserAgent() {
7187
return lastRemoteUserAgent;
7288
}
89+
90+
@NotNull
91+
public SessionType getSessionType() {
92+
return sessionType;
93+
}
7394
}

server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ public WebSession(
116116
CommonUtils.toString(requestInfo.getLocale()),
117117
application,
118118
sessionHandlers,
119-
requestInfo.getLastRemoteAddress()
119+
requestInfo.getLastRemoteAddress(),
120+
requestInfo.getSessionType()
120121
);
121122
updateSessionParameters(requestInfo);
122123
}
@@ -128,7 +129,18 @@ protected WebSession(
128129
@NotNull Map<String, DBWSessionHandler<WebSession>> sessionHandlers,
129130
@Nullable String remoteAddr
130131
) throws DBException {
131-
super(id, application);
132+
this(id, locale, application, sessionHandlers, remoteAddr, SessionType.WEB);
133+
}
134+
135+
protected WebSession(
136+
@NotNull String id,
137+
@Nullable String locale,
138+
@NotNull ServletApplication application,
139+
@NotNull Map<String, DBWSessionHandler<WebSession>> sessionHandlers,
140+
@Nullable String remoteAddr,
141+
@NotNull SessionType sessionType
142+
) throws DBException {
143+
super(id, application, sessionType);
132144
if (CommonUtils.isEmpty(remoteAddr)) {
133145
throw new DBException("Remote address cannot be empty");
134146
}

server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBApplication.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* DBeaver - Universal Database Manager
3-
* Copyright (C) 2010-2025 DBeaver Corp and others
3+
* Copyright (C) 2010-2026 DBeaver Corp and others
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616
*/
1717
package io.cloudbeaver.server;
1818

19+
import graphql.execution.instrumentation.Instrumentation;
1920
import io.cloudbeaver.WebServiceUtils;
2021
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
2122
import io.cloudbeaver.model.CBWebServerConfig;
@@ -29,6 +30,7 @@
2930
import io.cloudbeaver.model.config.CBServerConfig;
3031
import io.cloudbeaver.registry.WebDriverRegistry;
3132
import io.cloudbeaver.registry.WebServiceRegistry;
33+
import io.cloudbeaver.server.graphql.GraphQLEndpoint;
3234
import io.cloudbeaver.server.jetty.CBJettyServer;
3335
import io.cloudbeaver.service.DBWServiceInitializer;
3436
import io.cloudbeaver.service.DBWServiceServerConfigurator;
@@ -685,6 +687,11 @@ protected CBSessionManager createSessionManager() {
685687
return new CBSessionManager(this);
686688
}
687689

690+
@NotNull
691+
public GraphQLEndpoint createGraphQLEndpoint(@NotNull Instrumentation instrumentation) {
692+
return new GraphQLEndpoint(instrumentation);
693+
}
694+
688695
@NotNull
689696
public WebDriverRegistry getDriverRegistry() {
690697
return WebDriverRegistry.getInstance();

server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/jetty/CBJettyServer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public void runServer() {
128128
ServletHolder eventsServletHolder = new ServletHolder("events", new CBEventsLongPollingServlet());
129129
servletContextHandler.addServlet(eventsServletHolder, serverConfiguration.getServicesURI() + "events/*");
130130

131-
GraphQLEndpoint endpoint = new GraphQLEndpoint(new ServerConfigurationTimeLimitFilter(application));
131+
GraphQLEndpoint endpoint = application.createGraphQLEndpoint(new ServerConfigurationTimeLimitFilter(application));
132132
application.addApplicationContextValue(GraphQL.class.getName(), endpoint.getGraphQL());
133133
String gqlServletPath = serverConfiguration.getServicesURI() + "gql/*";
134134
servletContextHandler.addServlet(
@@ -261,4 +261,4 @@ public synchronized void refreshJettyConfig() {
261261
cbSessionHandler.setSecureCookies(application.getServerConfiguration().isForceHttps());
262262
}
263263
}
264-
}
264+
}

server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/service/session/CBSessionManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public class CBSessionManager implements WebAppSessionManager {
5151
private static final Log log = Log.getLog(CBSessionManager.class);
5252

5353
private final CBApplication<?> application;
54-
private final Map<String, BaseWebSession> sessionMap = new HashMap<>();
54+
protected final Map<String, BaseWebSession> sessionMap = new HashMap<>();
5555

5656
public CBSessionManager(CBApplication<?> application) {
5757
this.application = application;
@@ -527,4 +527,5 @@ protected void closeExpiredSession(@NotNull BaseWebSession session) {
527527
log.debug("> Expire session '" + session.getSessionId() + "'");
528528
session.close();
529529
}
530+
530531
}

server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/WebAppSessionManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* DBeaver - Universal Database Manager
3-
* Copyright (C) 2010-2024 DBeaver Corp and others
3+
* Copyright (C) 2010-2026 DBeaver Corp and others
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.

server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,14 @@ private void executeQuery(
239239
@Nullable Map<String, Object> variables,
240240
@Nullable String operationName
241241
) throws IOException {
242+
243+
String userId = GraphQLLoggerUtil.getUserId(request);
244+
LocalDateTime startTime = LocalDateTime.now();
245+
246+
if (isQueryHandledBeforeExecution(request, response, variables, operationName, userId)) {
247+
return;
248+
}
249+
242250
Map<String, Object> mapOfContext =
243251
Map.of(
244252
"request", request,
@@ -254,8 +262,6 @@ private void executeQuery(
254262
if (operationName != null) {
255263
contextBuilder.operationName(operationName);
256264
}
257-
String userId = GraphQLLoggerUtil.getUserId(request);
258-
LocalDateTime startTime = LocalDateTime.now();
259265
ExecutionInput executionInput = contextBuilder.build();
260266
ExecutionResult executionResult = null;
261267
Exception executionException = null;
@@ -271,23 +277,54 @@ private void executeQuery(
271277
} else if (executionException != null) {
272278
errorMessage = executionException.getMessage();
273279
}
274-
if (WebAppUtils.getWebApplication() instanceof ApiCallInterceptor apiCallInterceptor) {
275-
apiCallInterceptor.onApiCallEvent(
276-
request,
277-
variables,
278-
CommonUtils.notEmpty(operationName), userId, startTime,
279-
errorMessage,
280-
API_PROTOCOL
281-
);
282-
}
280+
notifyApiCallInterceptor(request, variables, operationName, userId, startTime, errorMessage);
283281
}
284282

285283
if (executionResult != null) {
286-
Map<String, Object> resJSON = executionResult.toSpecification();
287-
String resString = gson.toJson(resJSON);
288-
setDevelHeaders(request, response);
289-
response.setContentType(GraphQLConstants.CONTENT_TYPE_JSON_UTF8);
290-
response.getWriter().print(resString);
284+
writeExecutionResult(request, response, executionResult);
285+
}
286+
}
287+
288+
protected boolean isQueryHandledBeforeExecution(
289+
@NotNull HttpServletRequest request,
290+
@NotNull HttpServletResponse response,
291+
@Nullable Map<String, Object> variables,
292+
@Nullable String operationName,
293+
@Nullable String userId
294+
) throws IOException {
295+
return false;
296+
}
297+
298+
protected void writeExecutionResult(
299+
@NotNull HttpServletRequest request,
300+
@NotNull HttpServletResponse response,
301+
@NotNull ExecutionResult executionResult
302+
) throws IOException {
303+
Map<String, Object> resJSON = executionResult.toSpecification();
304+
String resString = gson.toJson(resJSON);
305+
setDevelHeaders(request, response);
306+
response.setContentType(GraphQLConstants.CONTENT_TYPE_JSON_UTF8);
307+
response.getWriter().print(resString);
308+
}
309+
310+
protected void notifyApiCallInterceptor(
311+
@NotNull HttpServletRequest request,
312+
@Nullable Map<String, Object> variables,
313+
@Nullable String operationName,
314+
@Nullable String userId,
315+
@NotNull LocalDateTime startTime,
316+
@Nullable String errorMessage
317+
) {
318+
if (WebAppUtils.getWebApplication() instanceof ApiCallInterceptor apiCallInterceptor) {
319+
apiCallInterceptor.onApiCallEvent(
320+
request,
321+
variables,
322+
CommonUtils.notEmpty(operationName),
323+
userId,
324+
startTime,
325+
errorMessage,
326+
API_PROTOCOL
327+
);
291328
}
292329
}
293330

0 commit comments

Comments
 (0)