sftp 操作日志.

This commit is contained in:
lijiahang
2024-02-23 18:20:48 +08:00
parent 471f149a04
commit f8e96a6b54
45 changed files with 442 additions and 151 deletions

View File

@@ -37,4 +37,8 @@ public interface ExtraFieldConst extends FieldConst {
String CONNECT_TYPE = "connectType"; String CONNECT_TYPE = "connectType";
String HOST_ID = "hostId";
String HOST_NAME = "hostName";
} }

View File

@@ -41,4 +41,10 @@ public interface FieldConst {
String TOKEN = "token"; String TOKEN = "token";
String PATH = "path";
String ADDRESS = "address";
String MOD = "mod";
} }

View File

@@ -1,4 +1,4 @@
package com.orion.ops.framework.biz.operator.log.core.uitls; package com.orion.ops.framework.biz.operator.log.core.utils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeFilter; import com.alibaba.fastjson.serializer.SerializeFilter;

View File

@@ -23,6 +23,19 @@ public class WebSockets {
private WebSockets() { private WebSockets() {
} }
/**
* 获取属性
*
* @param channel channel
* @param attr attr
* @param <E> T
* @return T
*/
@SuppressWarnings("unchecked")
public static <E> E getAttr(WebSocketSession channel, String attr) {
return (E) channel.getAttributes().get(attr);
}
/** /**
* 发送消息 忽略并发报错 * 发送消息 忽略并发报错
* *

View File

@@ -4,7 +4,7 @@ import com.orion.ops.framework.biz.operator.log.core.annotation.Module;
import com.orion.ops.framework.biz.operator.log.core.factory.InitializingOperatorTypes; import com.orion.ops.framework.biz.operator.log.core.factory.InitializingOperatorTypes;
import com.orion.ops.framework.biz.operator.log.core.model.OperatorType; import com.orion.ops.framework.biz.operator.log.core.model.OperatorType;
import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLevel.L; import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLevel.*;
/** /**
* 主机终端 操作日志类型 * 主机终端 操作日志类型
@@ -18,10 +18,37 @@ public class HostTerminalOperatorType extends InitializingOperatorTypes {
public static final String CONNECT = "host-terminal:connect"; public static final String CONNECT = "host-terminal:connect";
public static final String SFTP_MKDIR = "host-terminal:sftp-mkdir";
public static final String SFTP_TOUCH = "host-terminal:sftp-touch";
public static final String SFTP_MOVE = "host-terminal:sftp-move";
public static final String SFTP_REMOVE = "host-terminal:sftp-remove";
public static final String SFTP_TRUNCATE = "host-terminal:sftp-truncate";
public static final String SFTP_CHMOD = "host-terminal:sftp-chmod";
public static final String SFTP_SET_CONTENT = "host-terminal:sftp-set-content";
public static final String SFTP_UPLOAD = "host-terminal:sftp-upload";
public static final String SFTP_DOWNLOAD = "host-terminal:sftp-download";
@Override @Override
public OperatorType[] types() { public OperatorType[] types() {
return new OperatorType[]{ return new OperatorType[]{
new OperatorType(L, CONNECT, "连接主机终端 <sb>${name}</sb>"), new OperatorType(L, CONNECT, "连接主机 ${connectType} <sb>${hostName}</sb>"),
new OperatorType(L, SFTP_MKDIR, "创建文件夹 ${hostName} <sb>${path}</sb>"),
new OperatorType(L, SFTP_TOUCH, "创建文件 ${hostName} <sb>${path}</sb>"),
new OperatorType(M, SFTP_MOVE, "移动文件 ${hostName} <sb>${path}</sb> 至 <sb>${target}</sb>"),
new OperatorType(H, SFTP_REMOVE, "删除文件 ${hostName} <sb>${path}</sb>"),
new OperatorType(H, SFTP_TRUNCATE, "截断文件 ${hostName} <sb>${path}</sb>"),
new OperatorType(M, SFTP_CHMOD, "文件提权 ${hostName} <sb>${path}</sb> <sb>${mod}</sb>"),
new OperatorType(M, SFTP_SET_CONTENT, "修改文件内容 ${hostName} <sb>${path}</sb>"),
new OperatorType(M, SFTP_UPLOAD, "上传文件 ${hostName} <sb>${path}</sb>"),
new OperatorType(M, SFTP_DOWNLOAD, "下载文件 ${hostName} <sb>${path}</sb>"),
}; };
} }

View File

@@ -53,7 +53,7 @@ public class TerminalMessageDispatcher extends AbstractWebSocketHandler {
@Override @Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
String id = session.getId(); String id = session.getId();
log.info("TerminalMessageDispatcher-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason()); log.info("TerminalMessageDispatcher-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason());
// 关闭会话 // 关闭会话
terminalManager.closeAll(id); terminalManager.closeAll(id);
} }

View File

@@ -1,14 +1,21 @@
package com.orion.ops.module.asset.handler.host.terminal.handler; package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.exception.argument.InvalidArgumentException; import com.orion.lang.exception.argument.InvalidArgumentException;
import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
import com.orion.ops.framework.biz.operator.log.core.service.OperatorLogFrameworkService;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.websocket.core.utils.WebSockets; import com.orion.ops.framework.websocket.core.utils.WebSockets;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager; import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload; import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
import com.orion.ops.module.asset.handler.host.terminal.utils.TerminalUtils;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Map;
/** /**
* 终端消息处理器 基类 * 终端消息处理器 基类
@@ -22,6 +29,9 @@ public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> imp
@Resource @Resource
protected TerminalManager terminalManager; protected TerminalManager terminalManager;
@Resource
private OperatorLogFrameworkService operatorLogFrameworkService;
/** /**
* 发送消息 * 发送消息
* *
@@ -47,16 +57,37 @@ public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> imp
} }
/** /**
* 获取属性 * 保存操作日志
* *
* @param channel channel * @param payload payload
* @param attr attr * @param channel channel
* @param <E> T * @param extra extra
* @return T * @param type type
* @param startTime startTime
* @param ex ex
*/ */
@SuppressWarnings("unchecked") protected void saveOperatorLog(T payload,
protected <E> E getAttr(WebSocketSession channel, String attr) { WebSocketSession channel,
return (E) channel.getAttributes().get(attr); Map<String, Object> extra,
String type,
long startTime,
Exception ex) {
String channelId = channel.getId();
String sessionId = payload.getSessionId();
// 获取会话并且设置参数
ITerminalSession session = terminalManager.getSession(channelId, sessionId);
if (session != null) {
TerminalConfig config = session.getConfig();
extra.put(OperatorLogs.HOST_ID, config.getHostId());
extra.put(OperatorLogs.HOST_NAME, config.getHostName());
extra.put(OperatorLogs.ADDRESS, config.getAddress());
}
extra.put(OperatorLogs.CHANNEL_ID, channelId);
extra.put(OperatorLogs.SESSION_ID, sessionId);
// 获取日志
OperatorLogModel model = TerminalUtils.getOperatorLogModel(channel, extra, type, startTime, ex);
// 保存
operatorLogFrameworkService.insert(model);
} }
/** /**

View File

@@ -1,6 +1,9 @@
package com.orion.ops.module.asset.handler.host.terminal.handler; package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpChangeModRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpChangeModRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse; import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
@@ -9,6 +12,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
/** /**
* sftp 修改文件权限 * sftp 修改文件权限
* *
@@ -22,27 +27,37 @@ public class SftpChangeModHandler extends AbstractTerminalHandler<SftpChangeModR
@Override @Override
public void handle(WebSocketSession channel, SftpChangeModRequest payload) { public void handle(WebSocketSession channel, SftpChangeModRequest payload) {
long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
Integer mod = payload.getMod(); Integer mod = payload.getMod();
log.info("SftpChangeModHandler-handle session: {}, path: {}, mod: {}", payload.getSessionId(), path, mod); log.info("SftpChangeModHandler-handle start sessionId: {}, path: {}, mod: {}", sessionId, path, mod);
Exception ex = null; Exception ex = null;
// 修改权限 // 修改权限
try { try {
session.chmod(path, mod); session.chmod(path, mod);
log.info("SftpChangeModHandler-handle success sessionId: {}, path: {}, mod: {}", sessionId, path, mod);
} catch (Exception e) { } catch (Exception e) {
log.error("SftpChangeModHandler-handle error", e); log.error("SftpChangeModHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_CHMOD, OutputTypeEnum.SFTP_CHMOD,
SftpBaseResponse.builder() SftpBaseResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.msg(this.getErrorMessage(ex)) .msg(this.getErrorMessage(ex))
.build()); .build());
// 保存操作日志
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
extra.put(OperatorLogs.MOD, mod);
this.saveOperatorLog(payload, channel,
extra, HostTerminalOperatorType.SFTP_CHMOD,
startTime, ex);
} }
} }

View File

@@ -29,23 +29,25 @@ public class SftpDownloadFlatDirectoryHandler extends AbstractTerminalHandler<Sf
@Override @Override
public void handle(WebSocketSession channel, SftpDownloadFlatDirectoryRequest payload) { public void handle(WebSocketSession channel, SftpDownloadFlatDirectoryRequest payload) {
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String[] paths = payload.getPath().split("\\|"); String[] paths = payload.getPath().split("\\|");
log.info("SftpDownloadFlatDirectoryHandler-handle session: {}, paths: {}", payload.getSessionId(), Arrays.toString(paths)); log.info("SftpDownloadFlatDirectoryHandler-handle start sessionId: {}, paths: {}", sessionId, Arrays.toString(paths));
Exception ex = null; Exception ex = null;
List<SftpFileVO> files = Lists.empty(); List<SftpFileVO> files = Lists.empty();
// 展开文件夹内的全部文件 // 展开文件夹内的全部文件
try { try {
files = session.flatDirectory(paths); files = session.flatDirectory(paths);
log.info("SftpDownloadFlatDirectoryHandler-handle success sessionId: {}, paths: {}", sessionId, Arrays.toString(paths));
} catch (Exception e) { } catch (Exception e) {
log.error("SftpDownloadFlatDirectoryHandler-handle error", e); log.error("SftpDownloadFlatDirectoryHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_DOWNLOAD_FLAT_DIRECTORY, OutputTypeEnum.SFTP_DOWNLOAD_FLAT_DIRECTORY,
SftpDownloadFlatDirectoryResponse.builder() SftpDownloadFlatDirectoryResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.currentPath(payload.getCurrentPath()) .currentPath(payload.getCurrentPath())
.body(JSON.toJSONString(files)) .body(JSON.toJSONString(files))
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())

View File

@@ -23,23 +23,25 @@ public class SftpGetContentHandler extends AbstractTerminalHandler<SftpBaseReque
@Override @Override
public void handle(WebSocketSession channel, SftpBaseRequest payload) { public void handle(WebSocketSession channel, SftpBaseRequest payload) {
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpGetContentHandler-handle session: {}, path: {}", payload.getSessionId(), path); log.info("SftpGetContentHandler-handle start sessionId: {}, path: {}", sessionId, path);
String content = null; String content = null;
Exception ex = null; Exception ex = null;
// 获取内容 // 获取内容
try { try {
content = session.getContent(path); content = session.getContent(path);
log.info("SftpGetContentHandler-handle success sessionId: {}, path: {}", sessionId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("SftpGetContentHandler-handle error", e); log.error("SftpGetContentHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_GET_CONTENT, OutputTypeEnum.SFTP_GET_CONTENT,
SftpGetContentResponse.builder() SftpGetContentResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.content(content) .content(content)
.msg(this.getErrorMessage(ex)) .msg(this.getErrorMessage(ex))

View File

@@ -2,6 +2,7 @@ package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.orion.lang.utils.Strings; import com.orion.lang.utils.Strings;
import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpListRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpListRequest;
@@ -28,11 +29,12 @@ public class SftpListHandler extends AbstractTerminalHandler<SftpListRequest> {
@Override @Override
public void handle(WebSocketSession channel, SftpListRequest payload) { public void handle(WebSocketSession channel, SftpListRequest payload) {
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpListHandler-handle session: {}, path: {}", payload.getSessionId(), path); log.info("SftpListHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;
List<SftpFileVO> list = null; List<SftpFileVO> list = Lists.empty();
try { try {
// 空目录则直接获取 home 目录 // 空目录则直接获取 home 目录
if (Strings.isBlank(path)) { if (Strings.isBlank(path)) {
@@ -40,18 +42,19 @@ public class SftpListHandler extends AbstractTerminalHandler<SftpListRequest> {
} }
// 文件列表 // 文件列表
list = session.list(path, BooleanBit.toBoolean(payload.getShowHiddenFile())); list = session.list(path, BooleanBit.toBoolean(payload.getShowHiddenFile()));
log.info("SftpListHandler-handle success sessionId: {}, path: {}", sessionId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("SftpListHandler-handle error", e); log.error("SftpListHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_LIST, OutputTypeEnum.SFTP_LIST,
SftpListResponse.builder() SftpListResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.path(path) .path(path)
.body(list == null ? null : JSON.toJSONString(list)) .body(JSON.toJSONString(list))
.build()); .build());
} }

View File

@@ -1,6 +1,9 @@
package com.orion.ops.module.asset.handler.host.terminal.handler; package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpBaseRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpBaseRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse; import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
@@ -9,6 +12,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
/** /**
* sftp 创建文件夹 * sftp 创建文件夹
* *
@@ -22,26 +27,35 @@ public class SftpMakeDirectoryHandler extends AbstractTerminalHandler<SftpBaseRe
@Override @Override
public void handle(WebSocketSession channel, SftpBaseRequest payload) { public void handle(WebSocketSession channel, SftpBaseRequest payload) {
long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpMakeDirectoryHandler-handle session: {}, path: {}", payload.getSessionId(), path); log.info("SftpMakeDirectoryHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;
// 创建文件夹 // 创建文件夹
try { try {
session.mkdir(path); session.mkdir(path);
log.info("SftpMakeDirectoryHandler-handle success sessionId: {}, path: {}", sessionId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("SftpMakeDirectoryHandler-handle error", e); log.error("SftpMakeDirectoryHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_MKDIR, OutputTypeEnum.SFTP_MKDIR,
SftpBaseResponse.builder() SftpBaseResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.msg(this.getErrorMessage(ex)) .msg(this.getErrorMessage(ex))
.build()); .build());
// 保存操作日志
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
this.saveOperatorLog(payload, channel,
extra, HostTerminalOperatorType.SFTP_MKDIR,
startTime, ex);
} }
} }

View File

@@ -1,6 +1,9 @@
package com.orion.ops.module.asset.handler.host.terminal.handler; package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpMoveRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpMoveRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse; import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
@@ -9,6 +12,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
/** /**
* sftp 移动文件 * sftp 移动文件
* *
@@ -22,27 +27,37 @@ public class SftpMoveHandler extends AbstractTerminalHandler<SftpMoveRequest> {
@Override @Override
public void handle(WebSocketSession channel, SftpMoveRequest payload) { public void handle(WebSocketSession channel, SftpMoveRequest payload) {
long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
String target = payload.getTarget(); String target = payload.getTarget();
log.info("SftpMoveHandler-handle session: {}, path: {}, target: {}", payload.getSessionId(), path, target); log.info("SftpMoveHandler-handle start sessionId: {}, path: {}, target: {}", sessionId, path, target);
Exception ex = null; Exception ex = null;
// 移动 // 移动
try { try {
session.move(path, target); session.move(path, target);
log.info("SftpMoveHandler-handle success sessionId: {}, path: {}, target: {}", sessionId, path, target);
} catch (Exception e) { } catch (Exception e) {
log.error("SftpMoveHandler-handle error", e); log.error("SftpMoveHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_MOVE, OutputTypeEnum.SFTP_MOVE,
SftpBaseResponse.builder() SftpBaseResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.msg(this.getErrorMessage(ex)) .msg(this.getErrorMessage(ex))
.build()); .build());
// 保存操作日志
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
extra.put(OperatorLogs.TARGET, target);
this.saveOperatorLog(payload, channel,
extra, HostTerminalOperatorType.SFTP_MOVE,
startTime, ex);
} }
} }

View File

@@ -1,6 +1,10 @@
package com.orion.ops.module.asset.handler.host.terminal.handler; package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpBaseRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpBaseRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse; import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
@@ -10,6 +14,7 @@ import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
/** /**
* sftp 删除文件 * sftp 删除文件
@@ -24,26 +29,35 @@ public class SftpRemoveHandler extends AbstractTerminalHandler<SftpBaseRequest>
@Override @Override
public void handle(WebSocketSession channel, SftpBaseRequest payload) { public void handle(WebSocketSession channel, SftpBaseRequest payload) {
long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String[] paths = payload.getPath().split("\\|"); String[] paths = payload.getPath().split("\\|");
log.info("SftpRemoveHandler-handle session: {}, path: {}", payload.getSessionId(), Arrays.toString(paths)); log.info("SftpRemoveHandler-handle start sessionId: {}, path: {}", sessionId, Arrays.toString(paths));
Exception ex = null; Exception ex = null;
// 删除 // 删除
try { try {
session.remove(paths); session.remove(paths);
log.info("SftpRemoveHandler-handle success sessionId: {}, path: {}", sessionId, Arrays.toString(paths));
} catch (Exception e) { } catch (Exception e) {
log.error("SftpRemoveHandler-handle error", e); log.error("SftpRemoveHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_REMOVE, OutputTypeEnum.SFTP_REMOVE,
SftpBaseResponse.builder() SftpBaseResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.msg(this.getErrorMessage(ex)) .msg(this.getErrorMessage(ex))
.build()); .build());
// 保存操作日志
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, String.join(Const.COMMA, paths));
this.saveOperatorLog(payload, channel,
extra, HostTerminalOperatorType.SFTP_REMOVE,
startTime, ex);
} }
} }

View File

@@ -1,6 +1,9 @@
package com.orion.ops.module.asset.handler.host.terminal.handler; package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpSetContentRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpSetContentRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse; import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
@@ -9,6 +12,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
/** /**
* sftp 设置文件内容 * sftp 设置文件内容
* *
@@ -22,26 +27,35 @@ public class SftpSetContentHandler extends AbstractTerminalHandler<SftpSetConten
@Override @Override
public void handle(WebSocketSession channel, SftpSetContentRequest payload) { public void handle(WebSocketSession channel, SftpSetContentRequest payload) {
long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpSetContentHandler-handle session: {}, path: {}", payload.getSessionId(), path); log.info("SftpSetContentHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;
// 修改权限 // 修改内容
try { try {
session.setContent(path, payload.getContent()); session.setContent(path, payload.getContent());
log.info("SftpSetContentHandler-handle success sessionId: {}, path: {}", sessionId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("SftpSetContentHandler-handle error", e); log.error("SftpSetContentHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_SET_CONTENT, OutputTypeEnum.SFTP_SET_CONTENT,
SftpBaseResponse.builder() SftpBaseResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.msg(this.getErrorMessage(ex)) .msg(this.getErrorMessage(ex))
.build()); .build());
// 保存操作日志
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
this.saveOperatorLog(payload, channel,
extra, HostTerminalOperatorType.SFTP_SET_CONTENT,
startTime, ex);
} }
} }

View File

@@ -1,6 +1,9 @@
package com.orion.ops.module.asset.handler.host.terminal.handler; package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpBaseRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpBaseRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse; import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
@@ -9,6 +12,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
/** /**
* sftp 创建文件 * sftp 创建文件
* *
@@ -22,26 +27,35 @@ public class SftpTouchHandler extends AbstractTerminalHandler<SftpBaseRequest> {
@Override @Override
public void handle(WebSocketSession channel, SftpBaseRequest payload) { public void handle(WebSocketSession channel, SftpBaseRequest payload) {
long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpTouchHandler-handle session: {}, path: {}", payload.getSessionId(), path); log.info("SftpTouchHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;
// 创建文件 // 创建文件
try { try {
session.touch(path); session.touch(path);
log.info("SftpTouchHandler-handle success sessionId: {}, path: {}", sessionId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("SftpTouchHandler-handle error", e); log.error("SftpTouchHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_TOUCH, OutputTypeEnum.SFTP_TOUCH,
SftpBaseResponse.builder() SftpBaseResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.msg(this.getErrorMessage(ex)) .msg(this.getErrorMessage(ex))
.build()); .build());
// 保存操作日志
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
this.saveOperatorLog(payload, channel,
extra, HostTerminalOperatorType.SFTP_TOUCH,
startTime, ex);
} }
} }

View File

@@ -1,6 +1,9 @@
package com.orion.ops.module.asset.handler.host.terminal.handler; package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpBaseRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpBaseRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse; import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
@@ -9,6 +12,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
/** /**
* sftp 截断文件 * sftp 截断文件
* *
@@ -22,26 +27,35 @@ public class SftpTruncateHandler extends AbstractTerminalHandler<SftpBaseRequest
@Override @Override
public void handle(WebSocketSession channel, SftpBaseRequest payload) { public void handle(WebSocketSession channel, SftpBaseRequest payload) {
long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpTruncateHandler-handle session: {}, path: {}", payload.getSessionId(), path); log.info("SftpTruncateHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;
// 截断文件 // 截断文件
try { try {
session.truncate(path); session.truncate(path);
log.info("SftpTruncateHandler-handle success sessionId: {}, path: {}", sessionId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("SftpTruncateHandler-handle error", e); log.error("SftpTruncateHandler-handle error sessionId: {}", sessionId, e);
ex = e; ex = e;
} }
// 返回 // 返回
this.send(channel, this.send(channel,
OutputTypeEnum.SFTP_TRUNCATE, OutputTypeEnum.SFTP_TRUNCATE,
SftpBaseResponse.builder() SftpBaseResponse.builder()
.sessionId(payload.getSessionId()) .sessionId(sessionId)
.result(BooleanBit.of(ex == null).getValue()) .result(BooleanBit.of(ex == null).getValue())
.msg(this.getErrorMessage(ex)) .msg(this.getErrorMessage(ex))
.build()); .build());
// 保存操作日志
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
this.saveOperatorLog(payload, channel,
extra, HostTerminalOperatorType.SFTP_TRUNCATE,
startTime, ex);
} }
} }

View File

@@ -3,12 +3,13 @@ package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.exception.argument.InvalidArgumentException; import com.orion.lang.exception.argument.InvalidArgumentException;
import com.orion.lang.utils.Exceptions; import com.orion.lang.utils.Exceptions;
import com.orion.lang.utils.collect.Maps; import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
import com.orion.ops.framework.biz.operator.log.core.service.OperatorLogFrameworkService; import com.orion.ops.framework.biz.operator.log.core.service.OperatorLogFrameworkService;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogFiller; import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.constant.ExtraFieldConst; import com.orion.ops.framework.common.constant.ExtraFieldConst;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.framework.websocket.core.utils.WebSockets;
import com.orion.ops.module.asset.dao.HostDAO; import com.orion.ops.module.asset.dao.HostDAO;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType; import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.entity.domain.HostDO; import com.orion.ops.module.asset.entity.domain.HostDO;
@@ -20,6 +21,7 @@ import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalCheckRequest; import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalCheckRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalCheckResponse; import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalCheckResponse;
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession; import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
import com.orion.ops.module.asset.handler.host.terminal.utils.TerminalUtils;
import com.orion.ops.module.asset.service.HostConnectLogService; import com.orion.ops.module.asset.service.HostConnectLogService;
import com.orion.ops.module.asset.service.HostTerminalService; import com.orion.ops.module.asset.service.HostTerminalService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -55,7 +57,7 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
@Override @Override
public void handle(WebSocketSession channel, TerminalCheckRequest payload) { public void handle(WebSocketSession channel, TerminalCheckRequest payload) {
Long hostId = payload.getHostId(); Long hostId = payload.getHostId();
Long userId = this.getAttr(channel, ExtraFieldConst.USER_ID); Long userId = WebSockets.getAttr(channel, ExtraFieldConst.USER_ID);
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
HostConnectTypeEnum connectType = HostConnectTypeEnum.of(payload.getConnectType()); HostConnectTypeEnum connectType = HostConnectTypeEnum.of(payload.getConnectType());
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
@@ -168,32 +170,19 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
HostConnectTypeEnum connectType) { HostConnectTypeEnum connectType) {
Long hostId = host.getId(); Long hostId = host.getId();
String hostName = host.getName(); String hostName = host.getName();
String username = this.getAttr(channel, ExtraFieldConst.USERNAME); String username = WebSockets.getAttr(channel, ExtraFieldConst.USERNAME);
// 额外参数 // 额外参数
Map<String, Object> extra = Maps.newMap(); Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.ID, hostId); extra.put(OperatorLogs.ID, hostId);
extra.put(OperatorLogs.NAME, hostName); extra.put(OperatorLogs.HOST_NAME, hostName);
extra.put(OperatorLogs.CONNECT_TYPE, connectType.name()); extra.put(OperatorLogs.CONNECT_TYPE, connectType.name());
extra.put(OperatorLogs.CHANNEL_ID, channel.getId()); extra.put(OperatorLogs.CHANNEL_ID, channel.getId());
extra.put(OperatorLogs.SESSION_ID, sessionId); extra.put(OperatorLogs.SESSION_ID, sessionId);
// 日志参数 // 日志参数
OperatorLogFiller logModel = OperatorLogFiller.create() OperatorLogModel logModel = TerminalUtils.getOperatorLogModel(channel, extra,
// 填充用户信息 HostTerminalOperatorType.CONNECT, startTime, ex);
.fillUserInfo(userId, username)
// 填充 traceId
.fillTraceId(this.getAttr(channel, ExtraFieldConst.TRACE_ID))
// 填充请求留痕信息
.fillIdentity(this.getAttr(channel, ExtraFieldConst.IDENTITY))
// 填充使用时间
.fillUsedTime(startTime)
// 填充结果信息
.fillResult(null, ex)
// 填充拓展信息
.fillExtra(extra)
// 填充日志
.fillLogInfo(extra, HostTerminalOperatorType.CONNECT);
// 记录操作日志 // 记录操作日志
operatorLogFrameworkService.insert(logModel.get()); operatorLogFrameworkService.insert(logModel);
// 记录连接日志 // 记录连接日志
HostConnectLogCreateRequest connectLog = HostConnectLogCreateRequest.builder() HostConnectLogCreateRequest connectLog = HostConnectLogCreateRequest.builder()
.userId(userId) .userId(userId)

View File

@@ -18,7 +18,7 @@ public class TerminalCloseHandler extends AbstractTerminalHandler<TerminalBasePa
@Override @Override
public void handle(WebSocketSession channel, TerminalBasePayload payload) { public void handle(WebSocketSession channel, TerminalBasePayload payload) {
log.info("TerminalCloseHandler-handle start session: {}", payload.getSessionId()); log.info("TerminalCloseHandler-handle start sessionId: {}", payload.getSessionId());
// 关闭会话 // 关闭会话
terminalManager.closeSession(channel.getId(), payload.getSessionId()); terminalManager.closeSession(channel.getId(), payload.getSessionId());
} }

View File

@@ -9,6 +9,7 @@ import com.orion.lang.utils.io.Streams;
import com.orion.net.host.SessionStore; import com.orion.net.host.SessionStore;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.enums.BooleanBit; import com.orion.ops.framework.common.enums.BooleanBit;
import com.orion.ops.framework.websocket.core.utils.WebSockets;
import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO;
import com.orion.ops.module.asset.enums.HostConnectStatusEnum; import com.orion.ops.module.asset.enums.HostConnectStatusEnum;
import com.orion.ops.module.asset.enums.HostConnectTypeEnum; import com.orion.ops.module.asset.enums.HostConnectTypeEnum;
@@ -50,7 +51,7 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
log.info("TerminalConnectHandler-handle start sessionId: {}", sessionId); log.info("TerminalConnectHandler-handle start sessionId: {}", sessionId);
// 获取主机连接信息 // 获取主机连接信息
HostTerminalConnectDTO connect = this.getAttr(channel, sessionId); HostTerminalConnectDTO connect = WebSockets.getAttr(channel, sessionId);
if (connect == null) { if (connect == null) {
log.info("TerminalConnectHandler-handle unknown sessionId: {}", sessionId); log.info("TerminalConnectHandler-handle unknown sessionId: {}", sessionId);
this.send(channel, this.send(channel,
@@ -104,6 +105,8 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
// 连接配置 // 连接配置
TerminalConfig config = TerminalConfig.builder() TerminalConfig config = TerminalConfig.builder()
.hostId(connect.getHostId()) .hostId(connect.getHostId())
.hostName(connect.getHostName())
.address(connect.getHostAddress())
.charset(connect.getCharset()) .charset(connect.getCharset())
.fileNameCharset(connect.getFileNameCharset()) .fileNameCharset(connect.getFileNameCharset())
.fileContentCharset(connect.getFileContentCharset()) .fileContentCharset(connect.getFileContentCharset())

View File

@@ -25,6 +25,12 @@ public class TerminalConfig {
@Schema(description = "主机id") @Schema(description = "主机id")
private Long hostId; private Long hostId;
@Schema(description = "主机名称")
private String hostName;
@Schema(description = "主机地址")
private String address;
@Schema(description = "cols") @Schema(description = "cols")
private Integer cols; private Integer cols;

View File

@@ -1,6 +1,7 @@
package com.orion.ops.module.asset.handler.host.terminal.session; package com.orion.ops.module.asset.handler.host.terminal.session;
import com.orion.lang.able.SafeCloseable; import com.orion.lang.able.SafeCloseable;
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
/** /**
* 终端会话定义 * 终端会话定义
@@ -25,6 +26,13 @@ public interface ITerminalSession extends SafeCloseable {
*/ */
String getChannelId(); String getChannelId();
/**
* 获取配置
*
* @return config
*/
TerminalConfig getConfig();
/** /**
* 活跃会话 * 活跃会话
*/ */

View File

@@ -61,10 +61,6 @@ public class SshSession extends TerminalSession implements ISshSession {
@Override @Override
public void resize(int cols, int rows) { public void resize(int cols, int rows) {
// FIXME 没啥用就删了
// if (!executor.isConnected()) {
// executor.connect();
// }
// 大小发生变化 则修改大小 // 大小发生变化 则修改大小
if (cols != config.getCols() || if (cols != config.getCols() ||
rows != config.getRows()) { rows != config.getRows()) {

View File

@@ -23,6 +23,7 @@ public abstract class TerminalSession implements ITerminalSession {
protected final WebSocketSession channel; protected final WebSocketSession channel;
@Getter
protected final TerminalConfig config; protected final TerminalConfig config;
protected volatile boolean close; protected volatile boolean close;

View File

@@ -0,0 +1,58 @@
package com.orion.ops.module.asset.handler.host.terminal.utils;
import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogFiller;
import com.orion.ops.framework.common.constant.ExtraFieldConst;
import com.orion.ops.framework.websocket.core.utils.WebSockets;
import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
/**
* 终端工具类
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/2/23 16:25
*/
public class TerminalUtils {
private TerminalUtils() {
}
/**
* 获取操作日志模型
*
* @param channel channel
* @param extra extra
* @param type type
* @param startTime startTime
* @param ex ex
* @return model
*/
public static OperatorLogModel getOperatorLogModel(WebSocketSession channel,
Map<String, Object> extra,
String type,
long startTime,
Exception ex) {
// 日志参数
return OperatorLogFiller.create()
// 填充用户信息
.fillUserInfo(WebSockets.getAttr(channel, ExtraFieldConst.USER_ID),
WebSockets.getAttr(channel, ExtraFieldConst.USERNAME))
// 填充 traceId
.fillTraceId(WebSockets.getAttr(channel, ExtraFieldConst.TRACE_ID))
// 填充请求留痕信息
.fillIdentity(WebSockets.getAttr(channel, ExtraFieldConst.IDENTITY))
// 填充使用时间
.fillUsedTime(startTime)
// 填充结果信息
.fillResult(null, ex)
// 填充拓展信息
.fillExtra(extra)
// 填充日志
.fillLogInfo(extra, type)
.get();
}
}

View File

@@ -54,9 +54,9 @@ public class TransferMessageDispatcher extends AbstractWebSocketHandler {
@Override @Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
String id = session.getId(); String id = session.getId();
log.info("TransferMessageHandler-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason());
// 关闭会话 // 关闭会话
Streams.close(handlers.get(id)); Streams.close(handlers.get(id));
log.info("TransferMessageHandler-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason());
} }
} }

View File

@@ -5,6 +5,7 @@ import com.orion.lang.utils.io.Streams;
import com.orion.net.host.SessionStore; import com.orion.net.host.SessionStore;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.constant.ExtraFieldConst; import com.orion.ops.framework.common.constant.ExtraFieldConst;
import com.orion.ops.framework.websocket.core.utils.WebSockets;
import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO;
import com.orion.ops.module.asset.enums.HostConnectTypeEnum; import com.orion.ops.module.asset.enums.HostConnectTypeEnum;
import com.orion.ops.module.asset.handler.host.transfer.enums.TransferOperatorType; import com.orion.ops.module.asset.handler.host.transfer.enums.TransferOperatorType;
@@ -47,7 +48,7 @@ public class TransferHandler implements ITransferHandler {
public TransferHandler(WebSocketSession channel) { public TransferHandler(WebSocketSession channel) {
this.channel = channel; this.channel = channel;
this.userId = (Long) channel.getAttributes().get(ExtraFieldConst.USER_ID); this.userId = WebSockets.getAttr(channel, ExtraFieldConst.USER_ID);
this.sessions = new ConcurrentHashMap<>(); this.sessions = new ConcurrentHashMap<>();
} }
@@ -120,11 +121,12 @@ public class TransferHandler implements ITransferHandler {
} }
session.init(); session.init();
sessions.put(sessionKey, session); sessions.put(sessionKey, session);
log.info("TransferHandler.getAndInitSession success channelId: {}, hostId: {}", channel.getId(), hostId);
} }
this.currentSession = session; this.currentSession = session;
return true; return true;
} catch (Exception e) { } catch (Exception e) {
log.error("TransferHandler.getAndInitSession error", e); log.error("TransferHandler.getAndInitSession error channelId: {}", channel.getId(), e);
// 响应结果 // 响应结果
TransferUtils.sendMessage(this.channel, TransferReceiverType.NEXT_TRANSFER, e); TransferUtils.sendMessage(this.channel, TransferReceiverType.NEXT_TRANSFER, e);
return false; return false;

View File

@@ -26,9 +26,6 @@ public class TransferOperatorRequest {
@Schema(description = "type") @Schema(description = "type")
private String type; private String type;
@Schema(description = "fileId")
private String fileId;
@Schema(description = "主机id") @Schema(description = "主机id")
private Long hostId; private Long hostId;

View File

@@ -23,9 +23,6 @@ public class TransferOperatorResponse {
@Schema(description = "type") @Schema(description = "type")
private String type; private String type;
@Schema(description = "fileId")
private String fileId;
@Schema(description = "主机id") @Schema(description = "主机id")
private Long hostId; private Long hostId;

View File

@@ -8,6 +8,7 @@ import com.orion.net.host.sftp.SftpFile;
import com.orion.ops.framework.common.constant.Const; import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.module.asset.define.AssetThreadPools; import com.orion.ops.module.asset.define.AssetThreadPools;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO;
import com.orion.ops.module.asset.handler.host.transfer.enums.TransferReceiverType; import com.orion.ops.module.asset.handler.host.transfer.enums.TransferReceiverType;
import com.orion.ops.module.asset.handler.host.transfer.utils.TransferUtils; import com.orion.ops.module.asset.handler.host.transfer.utils.TransferUtils;
@@ -35,7 +36,11 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes
@Override @Override
public void startDownload(String path) { public void startDownload(String path) {
String channelId = channel.getId();
try { try {
log.info("DownloadSession.startDownload open start channelId: {}, path: {}", channelId, path);
// 保存操作日志
this.saveOperatorLog(HostTerminalOperatorType.SFTP_DOWNLOAD, path);
// 检查连接 // 检查连接
this.init(); this.init();
// 检查文件是否存在 // 检查文件是否存在
@@ -43,8 +48,9 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes
Valid.notNull(file, ErrorMessage.FILE_ABSENT); Valid.notNull(file, ErrorMessage.FILE_ABSENT);
// 打开输入流 // 打开输入流
this.inputStream = executor.openInputStream(path); this.inputStream = executor.openInputStream(path);
log.info("DownloadSession.startDownload open success channelId: {}, path: {}", channelId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("DownloadSession.startDownload error", e); log.error("DownloadSession.startDownload open error channelId: {}, path: {}", channelId, path, e);
// 响应结果 // 响应结果
TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_ERROR, e); TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_ERROR, e);
return; return;
@@ -59,9 +65,9 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes
while (this.inputStream != null && (len = this.inputStream.read(buffer)) != -1) { while (this.inputStream != null && (len = this.inputStream.read(buffer)) != -1) {
this.channel.sendMessage(new BinaryMessage(buffer, 0, len, true)); this.channel.sendMessage(new BinaryMessage(buffer, 0, len, true));
} }
log.info("DownloadSession.startDownload finish"); log.info("DownloadSession.download finish channelId: {}, path: {}", channelId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("DownloadSession.startDownload error", e); log.error("DownloadSession.download error channelId: {}, path: {}", channelId, path, e);
ex = e; ex = e;
} }
// 关闭等待 jsch 内部处理 // 关闭等待 jsch 内部处理
@@ -79,21 +85,13 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes
@Override @Override
public void abortDownload() { public void abortDownload() {
log.info("DownloadSession.abortDownload"); log.info("DownloadSession.abortDownload channelId: {}", channel.getId());
// 关闭流 // 关闭流
this.closeStream(); this.closeStream();
} }
@Override @Override
public void close() { protected void closeStream() {
this.closeStream();
super.close();
}
/**
* 关闭流
*/
private void closeStream() {
// 关闭 inputStream 会被阻塞 ??..?? 只能关闭 executor // 关闭 inputStream 会被阻塞 ??..?? 只能关闭 executor
Streams.close(this.executor); Streams.close(this.executor);
this.executor = null; this.executor = null;

View File

@@ -1,11 +1,19 @@
package com.orion.ops.module.asset.handler.host.transfer.session; package com.orion.ops.module.asset.handler.host.transfer.session;
import com.orion.lang.utils.collect.Maps;
import com.orion.lang.utils.io.Streams; import com.orion.lang.utils.io.Streams;
import com.orion.net.host.SessionStore; import com.orion.net.host.SessionStore;
import com.orion.net.host.sftp.SftpExecutor; import com.orion.net.host.sftp.SftpExecutor;
import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
import com.orion.ops.framework.biz.operator.log.core.service.OperatorLogFrameworkService;
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO;
import com.orion.ops.module.asset.handler.host.terminal.utils.TerminalUtils;
import com.orion.spring.SpringHolder;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
/** /**
* 主机传输会话实现 * 主机传输会话实现
* *
@@ -43,8 +51,33 @@ public abstract class TransferHostSession implements ITransferHostSession {
} }
} }
/**
* 保存操作日志
*
* @param type type
* @param path path
*/
protected void saveOperatorLog(String type, String path) {
// 设置参数
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
extra.put(OperatorLogs.HOST_ID, connectInfo.getHostId());
extra.put(OperatorLogs.HOST_NAME, connectInfo.getHostName());
extra.put(OperatorLogs.ADDRESS, connectInfo.getHostAddress());
// 获取日志
OperatorLogModel model = TerminalUtils.getOperatorLogModel(this.channel, extra, type, System.currentTimeMillis(), null);
// 保存
SpringHolder.getBean(OperatorLogFrameworkService.class).insert(model);
}
/**
* 关闭流
*/
protected abstract void closeStream();
@Override @Override
public void close() { public void close() {
this.closeStream();
Streams.close(executor); Streams.close(executor);
Streams.close(sessionStore); Streams.close(sessionStore);
} }

View File

@@ -4,6 +4,7 @@ import com.orion.lang.exception.argument.InvalidArgumentException;
import com.orion.lang.utils.io.Streams; import com.orion.lang.utils.io.Streams;
import com.orion.net.host.SessionStore; import com.orion.net.host.SessionStore;
import com.orion.net.host.sftp.SftpFile; import com.orion.net.host.sftp.SftpFile;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO;
import com.orion.ops.module.asset.handler.host.transfer.enums.TransferReceiverType; import com.orion.ops.module.asset.handler.host.transfer.enums.TransferReceiverType;
import com.orion.ops.module.asset.handler.host.transfer.utils.TransferUtils; import com.orion.ops.module.asset.handler.host.transfer.utils.TransferUtils;
@@ -31,7 +32,11 @@ public class UploadSession extends TransferHostSession implements IUploadSession
@Override @Override
public void startUpload(String path) { public void startUpload(String path) {
String channelId = channel.getId();
try { try {
log.info("UploadSession.startUpload start channelId: {}, path: {}", channelId, path);
// 保存操作日志
this.saveOperatorLog(HostTerminalOperatorType.SFTP_UPLOAD, path);
// 检查连接 // 检查连接
this.init(); this.init();
// 检查文件是否存在 // 检查文件是否存在
@@ -44,8 +49,9 @@ public class UploadSession extends TransferHostSession implements IUploadSession
this.outputStream = executor.openOutputStream(path); this.outputStream = executor.openOutputStream(path);
// 响应结果 // 响应结果
TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_NEXT_BLOCK, null); TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_NEXT_BLOCK, null);
log.info("UploadSession.startUpload transfer channelId: {}, path: {}", channelId, path);
} catch (Exception e) { } catch (Exception e) {
log.error("UploadSession.uploadStart error", e); log.error("UploadSession.startUpload error channelId: {}, path: {}", channelId, path, e);
this.closeStream(); this.closeStream();
// 响应结果 // 响应结果
TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_ERROR, e); TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_ERROR, e);
@@ -60,7 +66,7 @@ public class UploadSession extends TransferHostSession implements IUploadSession
// 响应结果 // 响应结果
TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_NEXT_BLOCK, null); TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_NEXT_BLOCK, null);
} catch (IOException e) { } catch (IOException e) {
log.error("UploadSession.putContent error", e); log.error("UploadSession.putContent error channelId: {}", channel.getId(), e);
this.closeStream(); this.closeStream();
// 响应结果 // 响应结果
TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_ERROR, e); TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_ERROR, e);
@@ -69,7 +75,7 @@ public class UploadSession extends TransferHostSession implements IUploadSession
@Override @Override
public void uploadFinish() { public void uploadFinish() {
log.info("UploadSession.uploadFinish"); log.info("UploadSession.uploadFinish channelId: {}", channel.getId());
this.closeStream(); this.closeStream();
// 响应结果 // 响应结果
TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_FINISH, null); TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_FINISH, null);
@@ -77,22 +83,14 @@ public class UploadSession extends TransferHostSession implements IUploadSession
@Override @Override
public void uploadError() { public void uploadError() {
log.error("UploadSession.uploadError"); log.error("UploadSession.uploadError channelId: {}", channel.getId());
this.closeStream(); this.closeStream();
// 响应结果 // 响应结果
TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_ERROR, new InvalidArgumentException((String) null)); TransferUtils.sendMessage(this.channel, TransferReceiverType.UPLOAD_ERROR, new InvalidArgumentException((String) null));
} }
@Override @Override
public void close() { protected void closeStream() {
this.closeStream();
super.close();
}
/**
* 关闭流
*/
private void closeStream() {
// 关闭流 // 关闭流
Streams.close(outputStream); Streams.close(outputStream);
this.outputStream = null; this.outputStream = null;

View File

@@ -1,7 +1,7 @@
package com.orion.ops.module.asset.service.impl; package com.orion.ops.module.asset.service.impl;
import com.orion.lang.utils.collect.Lists; import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs; import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.constant.Const; import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.utils.Valid; import com.orion.ops.framework.common.utils.Valid;

View File

@@ -1,6 +1,6 @@
package com.orion.ops.module.asset.service.impl; package com.orion.ops.module.asset.service.impl;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs; import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.constant.Const; import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.enums.EnableStatus; import com.orion.ops.framework.common.enums.EnableStatus;

View File

@@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.orion.lang.define.wrapper.DataGrid; import com.orion.lang.define.wrapper.DataGrid;
import com.orion.lang.utils.Strings; import com.orion.lang.utils.Strings;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs; import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.security.PasswordModifier; import com.orion.ops.framework.common.security.PasswordModifier;
import com.orion.ops.framework.common.utils.Valid; import com.orion.ops.framework.common.utils.Valid;

View File

@@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.DataGrid; import com.orion.lang.define.wrapper.DataGrid;
import com.orion.lang.utils.Strings; import com.orion.lang.utils.Strings;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs; import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.security.PasswordModifier; import com.orion.ops.framework.common.security.PasswordModifier;
import com.orion.ops.framework.common.utils.CryptoUtils; import com.orion.ops.framework.common.utils.CryptoUtils;

View File

@@ -6,7 +6,7 @@ import com.orion.lang.define.wrapper.DataGrid;
import com.orion.lang.utils.Booleans; import com.orion.lang.utils.Booleans;
import com.orion.lang.utils.Strings; import com.orion.lang.utils.Strings;
import com.orion.lang.utils.collect.Lists; import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs; import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.utils.Valid; import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.framework.redis.core.utils.RedisMaps; import com.orion.ops.framework.redis.core.utils.RedisMaps;

View File

@@ -1,26 +1,29 @@
import { useClipboard } from '@vueuse/core'; import { useClipboard } from '@vueuse/core';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
export default function useCopy() { const { copy: c } = useClipboard();
const { copy: c } = useClipboard();
// 复制 // 复制
const copy = async (value: string | undefined, tips: string | boolean = `${value} 已复制`) => { export const copy = async (value: string | undefined, tips: string | boolean = `${value} 已复制`) => {
try { try {
if (!value) { if (!value) {
return; return;
}
await c(value);
if (tips) {
Message.success(tips as string);
}
} catch (e) {
Message.error('复制失败');
} }
}; await c(value);
// 获取剪切板内容 if (tips) {
const readText = () => { Message.success(tips as string);
return navigator.clipboard.readText(); }
}; } catch (e) {
Message.error('复制失败');
}
};
// 获取剪切板内容
export const readText = () => {
return navigator.clipboard.readText();
};
export default function useCopy() {
return { return {
copy, copy,
readText, readText,

View File

@@ -5,7 +5,7 @@
label-align="left" label-align="left"
:itemOptions="{ 6: { span: 2 } }" :itemOptions="{ 6: { span: 2 } }"
@submit="fetchTableData" @submit="fetchTableData"
@reset="fetchTableData" @reset="resetTableData"
@keyup.enter="() => fetchTableData()"> @keyup.enter="() => fetchTableData()">
<!-- 连接用户 --> <!-- 连接用户 -->
<a-form-item field="userId" label="连接用户" label-col-flex="50px"> <a-form-item field="userId" label="连接用户" label-col-flex="50px">
@@ -114,7 +114,7 @@
import { getHostConnectLogPage } from '@/api/asset/host-connect-log'; import { getHostConnectLogPage } from '@/api/asset/host-connect-log';
import useLoading from '@/hooks/loading'; import useLoading from '@/hooks/loading';
import columns from '../types/table.columns'; import columns from '../types/table.columns';
import { connectStatusKey, connectTypeKey } from '../types/const'; import { connectStatusKey, connectTypeKey, HostConnectType } from '../types/const';
import { usePagination } from '@/types/table'; import { usePagination } from '@/types/table';
import { useDictStore } from '@/store'; import { useDictStore } from '@/store';
import useCopy from '@/hooks/copy'; import useCopy from '@/hooks/copy';
@@ -134,7 +134,7 @@
userId: undefined, userId: undefined,
hostId: undefined, hostId: undefined,
hostAddress: undefined, hostAddress: undefined,
type: undefined, type: HostConnectType.SSH,
token: undefined, token: undefined,
status: undefined, status: undefined,
startTimeRange: undefined, startTimeRange: undefined,
@@ -155,6 +155,12 @@
} }
}; };
// 重置
const resetTableData = (page = 1, limit = pagination.pageSize, form = formModel) => {
formModel.type = HostConnectType.SSH;
doFetchTableData({ page, limit, ...form });
};
// 切换页码 // 切换页码
const fetchTableData = (page = 1, limit = pagination.pageSize, form = formModel) => { const fetchTableData = (page = 1, limit = pagination.pageSize, form = formModel) => {
doFetchTableData({ page, limit, ...form }); doFetchTableData({ page, limit, ...form });

View File

@@ -1,3 +1,9 @@
// 主机连接类型
export const HostConnectType = {
SSH: 'SSH',
SFTP: 'SFTP'
};
// 主机连接状态 字典项 // 主机连接状态 字典项
export const connectStatusKey = 'hostConnectStatus'; export const connectStatusKey = 'hostConnectStatus';

View File

@@ -86,7 +86,7 @@ export default class SftpSession implements ISftpSession {
remove(path: string[]) { remove(path: string[]) {
Modal.confirm({ Modal.confirm({
title: '删除确认', title: '删除确认',
content: `确定要删除 ${path} 吗? 确定后将立即删除且无法恢复!`, content: `确定要删除 ${path.join(',')} 吗? 确定后将立即删除且无法恢复!`,
onOk: () => { onOk: () => {
this.resolver.setLoading(true); this.resolver.setLoading(true);
this.channel.send(InputProtocol.SFTP_REMOVE, { this.channel.send(InputProtocol.SFTP_REMOVE, {

View File

@@ -439,7 +439,6 @@ export interface SftpTransferItem {
// 传输操作响应 // 传输操作响应
export interface TransferOperatorResponse { export interface TransferOperatorResponse {
type: string; type: string;
fileId?: string;
hostId?: number; hostId?: number;
success: boolean; success: boolean;
msg?: string; msg?: string;

View File

@@ -103,7 +103,7 @@
<style lang="less" scoped> <style lang="less" scoped>
.tabs-container { .tabs-container {
background: var(--color-bg-2); background: var(--color-bg-2);
margin: 16px 16px 0 16px; margin: 16px;
padding: 16px; padding: 16px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -32,6 +32,7 @@
</template> </template>
<!-- 操作日志 --> <!-- 操作日志 -->
<template #originLogInfo="{ record }"> <template #originLogInfo="{ record }">
<icon-copy class="copy-left" @click="copy(record.originLogInfo, '已复制')" />
<span v-html="replaceHtmlTag(record.logInfo)" /> <span v-html="replaceHtmlTag(record.logInfo)" />
</template> </template>
<!-- 操作 --> <!-- 操作 -->
@@ -64,6 +65,7 @@
import { replaceHtmlTag, clearHtmlTag, dateFormat } from '@/utils'; import { replaceHtmlTag, clearHtmlTag, dateFormat } from '@/utils';
import { pick } from 'lodash'; import { pick } from 'lodash';
import { getCurrentUserOperatorLog } from '@/api/user/mine'; import { getCurrentUserOperatorLog } from '@/api/user/mine';
import useCopy from '@/hooks/copy';
const emits = defineEmits(['viewDetail']); const emits = defineEmits(['viewDetail']);
const props = defineProps({ const props = defineProps({
@@ -83,12 +85,13 @@
} }
}); });
const tableColumns = ref();
const tableRenderData = ref<OperatorLogQueryResponse[]>([]);
const pagination = usePagination(); const pagination = usePagination();
const { loading, setLoading } = useLoading(); const { loading, setLoading } = useLoading();
const { getDictValue } = useDictStore(); const { getDictValue } = useDictStore();
const { copy } = useCopy();
const tableColumns = ref();
const tableRenderData = ref<OperatorLogQueryResponse[]>([]);
// 查看详情 // 查看详情
const viewDetail = (record: OperatorLogQueryResponse) => { const viewDetail = (record: OperatorLogQueryResponse) => {

View File

@@ -49,7 +49,7 @@ const columns = [
ellipsis: true, ellipsis: true,
tooltip: true, tooltip: true,
}, { }, {
title: '创建时间', title: '操作时间',
dataIndex: 'createTime', dataIndex: 'createTime',
slotName: 'createTime', slotName: 'createTime',
align: 'center', align: 'center',