From 20664c6ba3d632c54a2ada25fb626f07768c44b0 Mon Sep 17 00:00:00 2001 From: "Crane.z" <1481445951@qq.com> Date: Wed, 5 Aug 2026 15:28:16 +0800 Subject: [PATCH] fix(console): preserve execution and audit state --- .../chen/framework/console/QueryConsole.java | 25 +++++++++++++++++-- .../console/state/QueryConsoleState.java | 2 ++ .../chen/framework/session/Session.java | 2 ++ .../framework/session/SessionManager.java | 14 ++++++++--- .../framework/session/impl/BaseSession.java | 13 +++++++--- .../framework/session/impl/JMSSession.java | 1 + 6 files changed, 49 insertions(+), 8 deletions(-) diff --git a/backend/framework/src/main/java/org/jumpserver/chen/framework/console/QueryConsole.java b/backend/framework/src/main/java/org/jumpserver/chen/framework/console/QueryConsole.java index e8ca951..20f906f 100644 --- a/backend/framework/src/main/java/org/jumpserver/chen/framework/console/QueryConsole.java +++ b/backend/framework/src/main/java/org/jumpserver/chen/framework/console/QueryConsole.java @@ -75,6 +75,10 @@ public class QueryConsole extends AbstractConsole { static final String QUERY_INSERT_NOT_SUPPORTED = "QUERY_INSERT_NOT_SUPPORTED"; static final String QUERY_DELETE_NOT_SUPPORTED = "QUERY_DELETE_NOT_SUPPORTED"; static final String CONSOLE_DATA_VIEW_EDIT_NOT_SUPPORTED = "CONSOLE_DATA_VIEW_EDIT_NOT_SUPPORTED"; + private static final String EXECUTION_STATUS_RUNNING = "running"; + private static final String EXECUTION_STATUS_SUCCESS = "success"; + private static final String EXECUTION_STATUS_ERROR = "error"; + private static final String EXECUTION_STATUS_CANCELLED = "cancelled"; private final Datasource datasource; private final boolean consoleMode; @@ -453,7 +457,7 @@ private void onDataViewAction(DataViewAction action) { } try { var context = this.tableEditContextFactory.create(dataView, this.getDatasource().getDruidDbType()); - var result = this.tableChangesPreviewService.preview(context, action.getDataView(), request); + var result = this.tableChangesPreviewService.preview(context, dataView.getTitle(), request); this.getPacketIO().sendPacket(PACKET_SAVE_CHANGES_PREVIEW_RESULT, result); } catch (IllegalArgumentException e) { this.getPacketIO().sendPacket(PACKET_SAVE_CHANGES_PREVIEW_RESULT, this.rejectedPreview(dataView, e.getMessage())); @@ -462,7 +466,7 @@ private void onDataViewAction(DataViewAction action) { } if (DataViewAction.ACTION_SAVE_CHANGES.equals(action.getAction())) { var request = GSON.fromJson(GSON.toJson(action.getData()), SaveChangesRequest.class); - SaveChangesResult result = this.saveQueryChanges(dataView, action.getDataView(), request); + SaveChangesResult result = this.saveQueryChanges(dataView, dataView.getTitle(), request); this.getPacketIO().sendPacket(PACKET_SAVE_CHANGES_RESULT, result); return; } @@ -610,6 +614,7 @@ private SaveChangesResult rejectedSave(DataView dataView, String reason) { } public void onCancel() { + this.getState().setExecutionStatus(EXECUTION_STATUS_CANCELLED); try { var plan = this.currentPlan; if (plan != null && plan.getStatement() != null) { @@ -740,6 +745,7 @@ private Path resolveSQLFileInSessionTemp(String filename) { public void onSQL(String sql) { this.getState().setInQuery(true); + this.getState().setExecutionStatus(EXECUTION_STATUS_RUNNING); this.stateManager.commit(); var session = SessionManager.getCurrentSession(); @@ -763,12 +769,19 @@ public void onSQL(String sql) { } this.ensureCurrentSchema(); } catch (ParserException e) { + this.getState().setExecutionStatus(EXECUTION_STATUS_ERROR); this.getConsoleLogger().error("%s: %s", MessageUtils.get("ParseError"), e.getMessage()); this.getPacketIO().sendPacket("message", Message.error(MessageUtils.get("ParseError"), e.getMessage())); } catch (SQLException e) { + if (!StringUtils.equals(this.getState().getExecutionStatus(), EXECUTION_STATUS_CANCELLED)) { + this.getState().setExecutionStatus(EXECUTION_STATUS_ERROR); + } this.getConsoleLogger().error("%s: %s", MessageUtils.get("ExecuteError"), e.getMessage()); this.getPacketIO().sendPacket("message", Message.error(MessageUtils.get("ExecuteError"), e.getMessage())); } finally { + if (StringUtils.equals(this.getState().getExecutionStatus(), EXECUTION_STATUS_RUNNING)) { + this.getState().setExecutionStatus(EXECUTION_STATUS_SUCCESS); + } this.getState().setInQuery(false); this.getState().setCanCancel(false); this.stateManager.commit(); @@ -782,6 +795,11 @@ private boolean canExecuteStatement(Session session, String sql, ACLResult aclRe if (aclResult.getRiskLevel() == Common.RiskLevel.Reject || aclResult.getRiskLevel() == Common.RiskLevel.ReviewReject || aclResult.getRiskLevel() == Common.RiskLevel.ReviewCancel) { + this.getState().setExecutionStatus( + aclResult.getRiskLevel() == Common.RiskLevel.ReviewCancel + ? EXECUTION_STATUS_CANCELLED + : EXECUTION_STATUS_ERROR + ); this.getConsoleLogger().error("%s", MessageUtils.get("ACLRejectError")); CommandRecord commandRecord = new CommandRecord(sql); commandRecord.setRiskLevel(aclResult.getRiskLevel()); @@ -800,6 +818,7 @@ private boolean confirmStatementWarning(Session session) { dialog.addButton(new Button(MessageUtils.get("Submit"), "submit", countDownLatch::countDown)); dialog.addButton(new Button(MessageUtils.get("Cancel"), "cancel", () -> { hasNext.set(false); + this.getState().setExecutionStatus(EXECUTION_STATUS_CANCELLED); countDownLatch.countDown(); this.getConsoleLogger().warn(MessageUtils.get("ExecutionCanceled")); })); @@ -813,12 +832,14 @@ private boolean confirmStatementWarning(Session session) { try { if (!countDownLatch.await(WARNING_DIALOG_TIMEOUT_SECONDS, TimeUnit.SECONDS)) { hasNext.set(false); + this.getState().setExecutionStatus(EXECUTION_STATUS_CANCELLED); dialogHandle.cancel(); this.getConsoleLogger().warn(MessageUtils.get("ExecutionCanceled")); } return hasNext.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); + this.getState().setExecutionStatus(EXECUTION_STATUS_ERROR); this.getConsoleLogger().error("获取结果失败!"); return false; } finally { diff --git a/backend/framework/src/main/java/org/jumpserver/chen/framework/console/state/QueryConsoleState.java b/backend/framework/src/main/java/org/jumpserver/chen/framework/console/state/QueryConsoleState.java index 40a6679..04e21b3 100644 --- a/backend/framework/src/main/java/org/jumpserver/chen/framework/console/state/QueryConsoleState.java +++ b/backend/framework/src/main/java/org/jumpserver/chen/framework/console/state/QueryConsoleState.java @@ -15,6 +15,7 @@ public class QueryConsoleState extends State { private int timeout; private boolean editorLoading; private boolean canCancel; + private volatile String executionStatus; public QueryConsoleState(String title) { super(title); @@ -23,6 +24,7 @@ public QueryConsoleState(String title) { this.timeout = 30; this.editorLoading = false; this.canCancel = false; + this.executionStatus = ""; } } 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 dbd840d..50e4e84 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 @@ -80,6 +80,8 @@ public interface Session { boolean isActive(); + boolean isClosing(); + void close(); void close(String message, Object... args); diff --git a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/SessionManager.java b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/SessionManager.java index f495e3e..ad2bea0 100644 --- a/backend/framework/src/main/java/org/jumpserver/chen/framework/session/SessionManager.java +++ b/backend/framework/src/main/java/org/jumpserver/chen/framework/session/SessionManager.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; @Slf4j @@ -33,10 +34,17 @@ public static void unregisterSession(String token) { } public static boolean registerConsole(String token, String consoleId, Console console) { - return instance.store.computeIfPresent(token, (ignored, session) -> { - session.getConsoles().put(consoleId, console); + var registered = new AtomicBoolean(false); + instance.store.computeIfPresent(token, (ignored, session) -> { + synchronized (session) { + if (!session.isClosing()) { + session.getConsoles().put(consoleId, console); + registered.set(true); + } + } return session; - }) != null; + }); + return registered.get(); } public int getCurrentSessionCount() { 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 533cce2..fc6aac2 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 @@ -202,6 +202,11 @@ public boolean isActive() { return this.getPacketIO() != null && this.getPacketIO().getWsSession().isOpen(); } + @Override + public boolean isClosing() { + return this.closeStarted.get(); + } + @Override public void close() { if (!this.beginClose()) { @@ -211,15 +216,17 @@ public void close() { } protected final boolean beginClose() { - return this.closeStarted.compareAndSet(false, true); + synchronized (this) { + return this.closeStarted.compareAndSet(false, true); + } } protected final void closeSessionResources() { if (this.getController() != null) { this.getController().cancelAllDialogs(); } - SessionManager.unregisterSession(this.getWebToken()); this.closeConsoles(); + SessionManager.unregisterSession(this.getWebToken()); this.getDatasource().close(); this.getPacketIO().close(); var path = this.getTempPath(); @@ -228,7 +235,7 @@ protected final void closeSessionResources() { } } - private void closeConsoles() { + protected final void closeConsoles() { var detached = new ArrayList>(); while (!this.consoles.isEmpty()) { for (var entry : this.consoles.entrySet()) { 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 7d40494..252f256 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 @@ -277,6 +277,7 @@ private void closeJmsSessionResources() { if (this.getController() != null) { this.getController().cancelAllDialogs(); } + this.closeConsoles(); try { this.replayHandler.release(); this.finishedJmsSession();