diff --git a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/Session.java b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/Session.java index cf83bbe..86d59de 100644 --- a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/Session.java +++ b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/Session.java @@ -13,11 +13,16 @@ import java.nio.file.Path; import java.sql.Connection; import java.sql.SQLException; +import java.time.LocalDateTime; import java.util.Locale; import java.util.Map; public interface Session { + void refreshLastActiveTime(); + + LocalDateTime getLastActiveTime(); + boolean canUpload(); boolean canDownload(); diff --git a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/controller/impl/BaseController.java b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/controller/impl/BaseController.java index 201b7c5..629f0f8 100644 --- a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/controller/impl/BaseController.java +++ b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/controller/impl/BaseController.java @@ -1,6 +1,7 @@ package org.jumpserver.chen.framework.session.controller.impl; import lombok.extern.slf4j.Slf4j; +import org.jumpserver.chen.framework.session.SessionManager; import org.jumpserver.chen.framework.session.controller.Controller; import org.jumpserver.chen.framework.session.controller.dialog.Dialog; import org.jumpserver.chen.framework.session.controller.message.Message; @@ -40,11 +41,20 @@ public void handlePacket(Packet packet) { case "dialog_event": this.onDialogEvent((String) packet.getData()); break; + case "input_active": + this.refreshLastActiveTime(); + break; default: break; } } + + private void refreshLastActiveTime() { + var session = SessionManager.getCurrentSession(); + session.refreshLastActiveTime(); + } + @Override public void sendFile(String fileKey) { this.packetIO.sendPacket("download", fileKey); diff --git a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/impl/BaseSession.java b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/impl/BaseSession.java index 01c63d8..d013aa9 100644 --- a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/impl/BaseSession.java +++ b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/impl/BaseSession.java @@ -21,6 +21,7 @@ import java.nio.file.Paths; import java.sql.Connection; import java.sql.SQLException; +import java.time.LocalDateTime; import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -57,6 +58,9 @@ public class BaseSession implements Session { private boolean enableAutoComplete = true; + @Getter + private LocalDateTime lastActiveTime; + public BaseSession(Datasource datasource, String remoteAddr) { this.datasource = datasource; @@ -64,6 +68,11 @@ public BaseSession(Datasource datasource, String remoteAddr) { } + @Override + public void refreshLastActiveTime() { + this.lastActiveTime = LocalDateTime.now(); + } + @Override public boolean canUpload() { return true; diff --git a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/impl/JMSSession.java b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/impl/JMSSession.java index 00431de..3ba5b8d 100644 --- a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/impl/JMSSession.java +++ b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/impl/JMSSession.java @@ -51,8 +51,6 @@ public class JMSSession extends BaseSession { private final long expireTime; - private LocalDateTime lastActiveTime; - private LocalDateTime maxSessionEndTime; private int maxSessionEndHours; private LocalDateTime dynamicEndTime; @@ -205,7 +203,7 @@ private void recordLifecycle(ServiceOuterClass.SessionLifecycleLogRequest.EventT } private void startWaitIdleTime() { - this.lastActiveTime = LocalDateTime.now(); + this.refreshLastActiveTime(); var token = SessionManager.getContextToken(); @@ -224,7 +222,7 @@ private void startWaitIdleTime() { return; } - if (Math.abs(Duration.between(LocalDateTime.now(), this.lastActiveTime).toMinutes()) > this.maxIdleTimeDelta) { + if (Math.abs(Duration.between(LocalDateTime.now(), this.getLastActiveTime()).toMinutes()) > this.maxIdleTimeDelta) { this.close("OverMaxIdleTimeError", "idle_disconnect", this.maxIdleTimeDelta); return; } @@ -310,7 +308,7 @@ private void closeGateway() { @Override public SQLQueryResult withAudit(String command, QueryAuditFunction queryAuditFunction) throws SQLException, CommandRejectException { synchronized (this) { - this.lastActiveTime = LocalDateTime.now(); + this.refreshLastActiveTime(); } if (this.locked) { throw new CommandRejectException(MessageUtils.get("SessionLockedError")); diff --git a/frontend/src/bus/index.js b/frontend/src/bus/index.js new file mode 100644 index 0000000..5c8ded8 --- /dev/null +++ b/frontend/src/bus/index.js @@ -0,0 +1,3 @@ +import Vue from 'vue' + +export const bus = new Vue() diff --git a/frontend/src/components/Controller/index.vue b/frontend/src/components/Controller/index.vue index e606cad..ca5d521 100644 --- a/frontend/src/components/Controller/index.vue +++ b/frontend/src/components/Controller/index.vue @@ -11,7 +11,7 @@ v-if="dialogOptions.body && dialogOptions.bodyType==='html'" v-html="dialogOptions.body" /> -
+
{ + this.lunaEvent.sendEventToLuna(MESSAGES.INPUT_ACTIVE) + }) + + this.lunaEvent.setInputActiveHandler(() => { + console.log('receive other window input active message') + this.sendPacket('input_active') + }) + }, + handleRenewLunaSession() { const lunaEvent = this.lunaEvent diff --git a/frontend/src/components/Main/Explore/QueryConsole/CodeEditor.vue b/frontend/src/components/Main/Explore/QueryConsole/CodeEditor.vue index 8ef8386..699bfd0 100644 --- a/frontend/src/components/Main/Explore/QueryConsole/CodeEditor.vue +++ b/frontend/src/components/Main/Explore/QueryConsole/CodeEditor.vue @@ -64,6 +64,7 @@ import 'codemirror/addon/edit/matchbrackets.js' import { getHints } from '@/api/resource' import SelectSnippetDialog from '@/components/Main/Explore/QueryConsole/SelectSnippetDialog.vue' import SaveSnippetDialog from '@/components/Main/Explore/QueryConsole/SaveSnippetDialog.vue' +import { bus } from '@/bus' const formatterMap = { 'clickhouse': 'sql', @@ -283,6 +284,9 @@ export default { this.cm = cm }, onCmChange(cm, change) { + // 向 luna 发送事件 + bus.$emit('input-active') + const { text, origin } = change[0] if (origin === '+input' && text[0].trim()) { if (this.autoComplete) { diff --git a/frontend/src/utils/luna.js b/frontend/src/utils/luna.js index 8ea6f54..2a2e35a 100644 --- a/frontend/src/utils/luna.js +++ b/frontend/src/utils/luna.js @@ -4,7 +4,8 @@ export const MESSAGES = { CLOSE: 'CLOSE', CONNECTED: 'CONNECTED', KEYEVENT: 'KEYEVENT', - MOUSEEVENT: 'MOUSEEVENT' + MOUSEEVENT: 'MOUSEEVENT', + INPUT_ACTIVE: 'INPUT_ACTIVE' } export class LunaEvent { @@ -25,9 +26,16 @@ export class LunaEvent { this.origin = event.origin this.sendEventToLuna(MESSAGES.PONG) break + case MESSAGES.INPUT_ACTIVE: + this.inputActiveHandler && this.inputActiveHandler() + break } } + setInputActiveHandler(func) { + this.inputActiveHandler = func + } + sendEventToLuna(name, data) { data == null && (data = '') if (this.lunaId != null) {