Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CB-4686 add new client event for updating session info #2462

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6c4056d
CB-4810 add new client event for updating session info
yagudin10 Mar 8, 2024
7caa874
CB-4810 update request parameters on creating web session
yagudin10 Mar 12, 2024
1cf0d9e
CB-4810 deprecate update session gql functions
yagudin10 Mar 12, 2024
7738c58
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
Mar 14, 2024
754639a
CB-4810 fix tests
yagudin10 Mar 15, 2024
df951b2
CB-4810 add params to session state event
yagudin10 Mar 15, 2024
dbd8d10
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
Mar 15, 2024
4a2eb8c
CB-4810 add params to gql schema
yagudin10 Mar 15, 2024
ad51772
CB-4686 feat: migrates touch session from REST to WebSockets
Mar 16, 2024
2871d56
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
Mar 18, 2024
1f6ba77
CB-4686 fix: do not open websocket if session is expired
Mar 18, 2024
8b6d9c9
Revert "CB-4686 fix: do not open websocket if session is expired"
Mar 19, 2024
f7f3124
CB-4686 setData uses performUpdate for the SessionResource
Mar 19, 2024
7aeffff
CB-4686 unsubscribes from the websocket when session expired event ar…
Mar 19, 2024
9b57c04
Revert "CB-4686 unsubscribes from the websocket when session expired …
Mar 19, 2024
3204665
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
yagudin10 Mar 19, 2024
ea0833a
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
Mar 19, 2024
f3c65a1
CB-4810 rename client event
yagudin10 Mar 19, 2024
09d7a0d
CB-4686 pr fixes
Mar 19, 2024
d0566d9
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
Wroud Mar 20, 2024
474c7b4
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
Mar 20, 2024
0530eb4
CB-4686 makes onDataOutdated execution manual
Mar 20, 2024
d247b23
CB-4686 fix: onDataOutdated.execute executes in the end of the perfor…
Mar 21, 2024
02782b7
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
mr-anton-t Mar 25, 2024
38ec679
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
yagudin10 Mar 25, 2024
e617a99
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
dariamarutkina Mar 26, 2024
b22cdd6
Merge branch 'devel' into CB-4686-migrate-from-scheduled-touch-sessio…
dariamarutkina Mar 26, 2024
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 @@ -125,20 +125,21 @@
private final Map<String, DBWSessionHandler> sessionHandlers;

public WebSession(
@NotNull HttpSession httpSession,
@NotNull HttpServletRequest request,
@NotNull WebAuthApplication application,
@NotNull Map<String, DBWSessionHandler> sessionHandlers
) throws DBException {
super(httpSession.getId(), application);
super(request.getSession().getId(), application);
this.lastAccessTime = this.createTime;
setLocale(CommonUtils.toString(httpSession.getAttribute(ATTR_LOCALE), this.locale));
setLocale(CommonUtils.toString(request.getSession().getAttribute(ATTR_LOCALE), this.locale));
this.sessionHandlers = sessionHandlers;
//force authorization of anonymous session to avoid access error,
//because before authorization could be called by any request,
//but now 'updateInfo' is called only in special requests,
//and the order of requests is not guaranteed.
//look at CB-4747
refreshSessionAuth();
updateSessionParameters(request);
}

@Nullable
Expand Down Expand Up @@ -525,17 +526,10 @@
}
}

public synchronized void updateInfo(
HttpServletRequest request,
HttpServletResponse response
) throws DBWebException {
public synchronized void updateInfo(boolean isOldHttpSessionUsed) {

Check warning on line 529 in server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

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

Missing a Javadoc comment.
log.debug("Update session lifetime " + getSessionId() + " for user " + getUserId());
touchSession();
HttpSession httpSession = request.getSession();
this.lastRemoteAddr = request.getRemoteAddr();
this.lastRemoteUserAgent = request.getHeader("User-Agent");
this.cacheExpired = false;
if (!httpSession.isNew()) {
if (isOldHttpSessionUsed) {
try {
// Persist session
if (!isAuthorizedInSecurityManager()) {
Expand All @@ -555,6 +549,12 @@
}
}

public synchronized void updateSessionParameters(HttpServletRequest request) {

Check warning on line 552 in server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

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

Missing a Javadoc comment.
this.lastRemoteAddr = request.getRemoteAddr();
this.lastRemoteUserAgent = request.getHeader("User-Agent");
this.cacheExpired = false;
}

@Association
public List<WebConnectionInfo> getConnections() {
synchronized (connections) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,9 @@ extend type Mutation {
closeSession: Boolean

# Refreshes session on server and returns its state
touchSession: Boolean @deprecated(reason: "use updateSession instead")
touchSession: Boolean @deprecated(reason: "use events to update session")
# Refreshes session on server and returns session state
updateSession: SessionInfo! @since(version: "24.0.0")
updateSession: SessionInfo! @since(version: "24.0.0") @deprecated(reason: "use events to update session")

# Refresh session connection list
refreshSessionConnections: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ enum CBServerEventId {
enum CBClientEventId {
cb_client_topic_subscribe,
cb_client_topic_unsubscribe,
cb_client_projects_active
cb_client_projects_active,
cb_client_session_ping
}

# Client subscribes on topic to receive only related events
Expand Down Expand Up @@ -114,8 +115,12 @@ type WSSocketConnectedEvent implements CBServerEvent {
type WSSessionStateEvent implements CBServerEvent {
id: CBServerEventId!
topicId: CBEventTopic
lastAccessTime: Int!
remainingTime: Int!
isValid: Boolean
isCacheExpired: Boolean
locale: String!
actionParameters: Object
Wroud marked this conversation as resolved.
Show resolved Hide resolved
}

# Session expired event
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import io.cloudbeaver.DBWebException;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.websocket.CBWebSessionEventHandler;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WriteCallback;
Expand Down Expand Up @@ -76,6 +77,12 @@ public void onWebSocketText(String message) {
this.webSession.getEventsFilter().setSubscribedProjects(projectEvent.getProjectIds());
break;
}
case SESSION_PING: {
if (webSession instanceof WebSession session) {
session.updateInfo(true);
}
break;
}
default:
var e = new DBWebException("Unknown websocket client event: " + clientEvent.getId());
log.error(e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.security.exception.SMAccessTokenExpiredException;
import org.jkiss.dbeaver.runtime.DBWorkbench;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
Expand All @@ -54,6 +55,7 @@ public Object createWebSocket(@NotNull JettyServerUpgradeRequest request, JettyS
var httpRequest = request.getHttpServletRequest();
var webSession = webSessionManager.getOrRestoreSession(httpRequest);
if (webSession != null) {
webSession.updateSessionParameters(httpRequest);
// web client session
return createNewEventsWebSocket(webSession);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
@WebAction(authRequired = false)
boolean touchSession(@NotNull HttpServletRequest request, @NotNull HttpServletResponse servletResponse) throws DBWebException;

@Deprecated

Check warning on line 97 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/DBWServiceCore.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/DBWServiceCore.java#L97

Missing a Javadoc comment.
@WebAction(authRequired = false)
WebSession updateSession(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response)
throws DBWebException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,11 +282,13 @@ public boolean closeSession(HttpServletRequest request) throws DBWebException {
}

@Override
@Deprecated
public boolean touchSession(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response) throws DBWebException {
return CBPlatform.getInstance().getSessionManager().touchSession(request, response);
}

@Override
@Deprecated
public WebSession updateSession(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response)
throws DBWebException {
WebSessionManager sessionManager = CBPlatform.getInstance().getSessionManager();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,12 @@
return application;
}

@Deprecated

Check warning on line 82 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/session/WebSessionManager.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/session/WebSessionManager.java#L82

Missing a Javadoc comment.
public boolean touchSession(@NotNull HttpServletRequest request,
@NotNull HttpServletResponse response) throws DBWebException {
WebSession webSession = getWebSession(request, response, false);
webSession.updateInfo(request, response);
webSession.updateSessionParameters(request);
webSession.updateInfo(!request.getSession().isNew());
return true;
}

Expand All @@ -105,14 +107,14 @@
var baseWebSession = sessionMap.get(sessionId);
if (baseWebSession == null && CBApplication.getInstance().isConfigurationMode()) {
try {
webSession = createWebSessionImpl(httpSession);
webSession = createWebSessionImpl(request);
} catch (DBException e) {
throw new DBWebException("Failed to create web session", e);
}
sessionMap.put(sessionId, webSession);
} else if (baseWebSession == null) {
try {
webSession = createWebSessionImpl(httpSession);
webSession = createWebSessionImpl(request);
} catch (DBException e) {
throw new DBWebException("Failed to create web session", e);
}
Expand Down Expand Up @@ -174,7 +176,7 @@
return null;
}

webSession = createWebSessionImpl(httpSession);
webSession = createWebSessionImpl(request);
restorePreviousUserSession(webSession, oldAuthInfo);

sessionMap.put(sessionId, webSession);
Expand Down Expand Up @@ -208,8 +210,8 @@
}

@NotNull
protected WebSession createWebSessionImpl(@NotNull HttpSession httpSession) throws DBException {
return new WebSession(httpSession, application, getSessionHandlers());
protected WebSession createWebSessionImpl(@NotNull HttpServletRequest request) throws DBException {
return new WebSession(request, application, getSessionHandlers());
}

@NotNull
Expand Down Expand Up @@ -330,7 +332,13 @@
})
.forEach(session -> {
try {
session.addSessionEvent(new WSSessionStateEvent(session.getRemainingTime(), session.isValid()));
session.addSessionEvent(new WSSessionStateEvent(
session.getLastAccessTimeMillis(),
session.getRemainingTime(),
session.isValid(),
((WebSession) session).isCacheExpired(),
((WebSession) session).getLocale(),
((WebSession) session).getActionParameters()));
} catch (Exception e) {
log.error("Failed to refresh session state: " + session.getSessionId(), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ type NewConfiguration = AuthConfiguration & { [NEW_CONFIGURATION_SYMBOL]: boolea

@injectable()
export class AuthConfigurationsResource extends CachedMapResource<string, AuthConfiguration, GetAuthProviderConfigurationsQueryVariables> {
constructor(private readonly graphQLService: GraphQLService, permissionsResource: SessionPermissionsResource) {
constructor(
private readonly graphQLService: GraphQLService,
permissionsResource: SessionPermissionsResource,
) {
super(() => new Map(), []);

permissionsResource.require(this, EAdminPermission.admin).outdateResource(this);
Expand All @@ -51,6 +54,7 @@ export class AuthConfigurationsResource extends CachedMapResource<string, AuthCo
}

this.set(configuration.id, configuration);
this.onDataOutdated.execute(configuration.id);
});

return this.get(config.id)!;
Expand Down
4 changes: 4 additions & 0 deletions webapp/packages/core-authentication/src/UserInfoResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ export class UserInfoResource extends CachedDataResource<UserInfo | null, void,
if (this.data) {
this.data.configurationParameters[key] = value;
}

this.onDataOutdated.execute();
});

return this.data;
Expand Down Expand Up @@ -210,6 +212,8 @@ export class UserInfoResource extends CachedDataResource<UserInfo | null, void,
delete this.data?.configurationParameters[item];
}
});

this.onDataOutdated.execute();
});
return this.data;
}
Expand Down
2 changes: 2 additions & 0 deletions webapp/packages/core-authentication/src/UsersResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso
if (user) {
user.authRole = authRole;
}

this.onDataOutdated.execute(userId);
});

if (!skipUpdate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ export class ConnectionExecutionContextResource extends CachedMapResource<string
}

async create(key: IConnectionInfoParams, defaultCatalog?: string, defaultSchema?: string): Promise<IConnectionExecutionContextInfo> {
return await this.performUpdate(getContextBaseId(key, ''), [], async () => {
const contextKey = getContextBaseId(key, '');
return await this.performUpdate(contextKey, [], async () => {
const { context } = await this.graphQLService.sdk.executionContextCreate({
...key,
defaultCatalog,
Expand All @@ -85,7 +86,10 @@ export class ConnectionExecutionContextResource extends CachedMapResource<string
this.markOutdated(); // TODO: should be removed, currently multiple contexts for same connection may change catalog/schema for all contexts of connection
});

return this.get(baseContext.id)!;
const result = this.get(baseContext.id)!;
this.onDataOutdated.execute(contextKey);

return result;
});
}

Expand All @@ -107,6 +111,7 @@ export class ConnectionExecutionContextResource extends CachedMapResource<string

context.defaultCatalog = defaultCatalog;
context.defaultSchema = defaultSchema;
this.onDataOutdated.execute(contextId);
});

this.markOutdated();
Expand All @@ -126,6 +131,7 @@ export class ConnectionExecutionContextResource extends CachedMapResource<string
connectionId: context.connectionId,
projectId: context.projectId,
});
this.onDataOutdated.execute(contextId);
});

runInAction(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ export const ConnectionFolderProjectKey = resourceKeyAliasFactory('@connection-f

@injectable()
export class ConnectionFolderResource extends CachedMapResource<IConnectionFolderParam, ConnectionFolder> {
constructor(private readonly graphQLService: GraphQLService, sessionDataResource: SessionDataResource, appAuthService: AppAuthService) {
constructor(
private readonly graphQLService: GraphQLService,
sessionDataResource: SessionDataResource,
appAuthService: AppAuthService,
) {
super();

appAuthService.requireAuthentication(this);
Expand Down Expand Up @@ -70,6 +74,7 @@ export class ConnectionFolderResource extends CachedMapResource<IConnectionFolde
folderPath: key.folderId,
});
this.delete(key);
this.onDataOutdated.execute(key);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ export class ConnectionInfoResource extends CachedMapResource<IConnectionInfoPar
projectId: connectionKey.projectId,
connectionId: connectionKey.connectionId,
});

this.onDataOutdated.execute(connectionKey);
return subjects;
});

Expand Down Expand Up @@ -396,6 +398,7 @@ export class ConnectionInfoResource extends CachedMapResource<IConnectionInfoPar
...this.getIncludesMap(key),
});
this.set(createConnectionParam(connection), connection);
this.onDataOutdated.execute(key);
});

return this.get(key)!;
Expand All @@ -413,6 +416,7 @@ export class ConnectionInfoResource extends CachedMapResource<IConnectionInfoPar
});

this.set(createConnectionParam(connection), connection);
this.onDataOutdated.execute(key);
});

return this.get(key)!;
Expand All @@ -428,6 +432,7 @@ export class ConnectionInfoResource extends CachedMapResource<IConnectionInfoPar
});

this.set(createConnectionParam(connection), connection);
this.onDataOutdated.execute(key);
});
return this.get(key)!;
}
Expand All @@ -442,6 +447,7 @@ export class ConnectionInfoResource extends CachedMapResource<IConnectionInfoPar
});

this.set(createConnectionParam(connection), connection);
this.onDataOutdated.execute(key);
});

const connection = this.get(key)!;
Expand All @@ -460,6 +466,7 @@ export class ConnectionInfoResource extends CachedMapResource<IConnectionInfoPar
});
this.delete(key);
});
this.onDataOutdated.execute(key);
}

// async updateSessionConnections(): Promise<boolean> {
Expand Down
Loading
Loading