diff --git a/itbaima-monitor-server/pom.xml b/itbaima-monitor-server/pom.xml index 95590ef..94039ed 100644 --- a/itbaima-monitor-server/pom.xml +++ b/itbaima-monitor-server/pom.xml @@ -99,6 +99,15 @@ influxdb-client-java 6.6.0 + + org.springframework.boot + spring-boot-starter-websocket + + + com.jcraft + jsch + 0.1.55 + diff --git a/itbaima-monitor-server/src/main/java/com/example/config/SecurityConfiguration.java b/itbaima-monitor-server/src/main/java/com/example/config/SecurityConfiguration.java index 9ede5fc..d876761 100644 --- a/itbaima-monitor-server/src/main/java/com/example/config/SecurityConfiguration.java +++ b/itbaima-monitor-server/src/main/java/com/example/config/SecurityConfiguration.java @@ -53,6 +53,7 @@ public class SecurityConfiguration { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(conf -> conf + .requestMatchers("/terminal/**").permitAll() .requestMatchers("/api/auth/**", "/error").permitAll() .requestMatchers("/monitor/**").permitAll() .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll() diff --git a/itbaima-monitor-server/src/main/java/com/example/controller/MonitorController.java b/itbaima-monitor-server/src/main/java/com/example/controller/MonitorController.java index 5fe38e7..213b576 100644 --- a/itbaima-monitor-server/src/main/java/com/example/controller/MonitorController.java +++ b/itbaima-monitor-server/src/main/java/com/example/controller/MonitorController.java @@ -5,10 +5,8 @@ import com.example.entity.dto.Account; import com.example.entity.vo.request.RenameClientVO; import com.example.entity.vo.request.RenameNodeVO; import com.example.entity.vo.request.RuntimeDetailVO; -import com.example.entity.vo.response.ClientDetailsVO; -import com.example.entity.vo.response.ClientPreviewVO; -import com.example.entity.vo.response.ClientSimpleVO; -import com.example.entity.vo.response.RuntimeDetailsVO; +import com.example.entity.vo.request.SshConnectionVO; +import com.example.entity.vo.response.*; import com.example.service.AccountService; import com.example.service.ClientService; import com.example.utils.Const; @@ -128,6 +126,29 @@ public class MonitorController { } } + @PostMapping("/ssh-save") + public RestBean saveSshConnection(@RequestBody @Valid SshConnectionVO vo, + @RequestAttribute(Const.ATTR_USER_ID) int userId, + @RequestAttribute(Const.ATTR_USER_ROLE) String userRole) { + if(this.permissionCheck(userId, userRole, vo.getId())) { + service.saveClientSshConnection(vo); + return RestBean.success(); + } else { + return RestBean.noPermission(); + } + } + + @GetMapping("/ssh") + public RestBean sshSettings(int clientId, + @RequestAttribute(Const.ATTR_USER_ID) int userId, + @RequestAttribute(Const.ATTR_USER_ROLE) String userRole) { + if(this.permissionCheck(userId, userRole, clientId)) { + return RestBean.success(service.sshSettings(clientId)); + } else { + return RestBean.noPermission(); + } + } + private List accountAccessClients(int uid) { Account account = accountService.getById(uid); return account.getClientList(); diff --git a/itbaima-monitor-server/src/main/java/com/example/entity/dto/ClientSsh.java b/itbaima-monitor-server/src/main/java/com/example/entity/dto/ClientSsh.java new file mode 100644 index 0000000..c24d11d --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/entity/dto/ClientSsh.java @@ -0,0 +1,16 @@ +package com.example.entity.dto; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.example.entity.BaseData; +import lombok.Data; + +@Data +@TableName("db_client_ssh") +public class ClientSsh implements BaseData { + @TableId + Integer id; + Integer port; + String username; + String password; +} diff --git a/itbaima-monitor-server/src/main/java/com/example/entity/vo/request/SshConnectionVO.java b/itbaima-monitor-server/src/main/java/com/example/entity/vo/request/SshConnectionVO.java new file mode 100644 index 0000000..e82369d --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/entity/vo/request/SshConnectionVO.java @@ -0,0 +1,18 @@ +package com.example.entity.vo.request; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +@Data +public class SshConnectionVO { + int id; + @NotNull + int port; + @NotNull + @Length(min = 1) + String username; + @NotNull + @Length(min = 1) + String password; +} diff --git a/itbaima-monitor-server/src/main/java/com/example/entity/vo/response/SshSettingsVO.java b/itbaima-monitor-server/src/main/java/com/example/entity/vo/response/SshSettingsVO.java new file mode 100644 index 0000000..e73384f --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/entity/vo/response/SshSettingsVO.java @@ -0,0 +1,11 @@ +package com.example.entity.vo.response; + +import lombok.Data; + +@Data +public class SshSettingsVO { + String ip; + int port = 22; + String username; + String password; +} diff --git a/itbaima-monitor-server/src/main/java/com/example/mapper/ClientSshMapper.java b/itbaima-monitor-server/src/main/java/com/example/mapper/ClientSshMapper.java new file mode 100644 index 0000000..2add66d --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/mapper/ClientSshMapper.java @@ -0,0 +1,9 @@ +package com.example.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.entity.dto.ClientSsh; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ClientSshMapper extends BaseMapper { +} diff --git a/itbaima-monitor-server/src/main/java/com/example/service/ClientService.java b/itbaima-monitor-server/src/main/java/com/example/service/ClientService.java index 7630f92..1dffb36 100644 --- a/itbaima-monitor-server/src/main/java/com/example/service/ClientService.java +++ b/itbaima-monitor-server/src/main/java/com/example/service/ClientService.java @@ -2,14 +2,8 @@ package com.example.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.entity.dto.Client; -import com.example.entity.vo.request.ClientDetailVO; -import com.example.entity.vo.request.RenameClientVO; -import com.example.entity.vo.request.RenameNodeVO; -import com.example.entity.vo.request.RuntimeDetailVO; -import com.example.entity.vo.response.ClientDetailsVO; -import com.example.entity.vo.response.ClientPreviewVO; -import com.example.entity.vo.response.ClientSimpleVO; -import com.example.entity.vo.response.RuntimeDetailsVO; +import com.example.entity.vo.request.*; +import com.example.entity.vo.response.*; import java.util.List; @@ -28,4 +22,6 @@ public interface ClientService extends IService { RuntimeDetailsVO clientRuntimeDetailsHistory(int clientId); RuntimeDetailVO clientRuntimeDetailsNow(int clientId); void deleteClient(int clientId); + void saveClientSshConnection(SshConnectionVO vo); + SshSettingsVO sshSettings(int clientId); } diff --git a/itbaima-monitor-server/src/main/java/com/example/service/TerminalService.java b/itbaima-monitor-server/src/main/java/com/example/service/TerminalService.java new file mode 100644 index 0000000..7701c35 --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/service/TerminalService.java @@ -0,0 +1,4 @@ +package com.example.service; + +public interface TerminalService { +} diff --git a/itbaima-monitor-server/src/main/java/com/example/service/impl/ClientServiceImpl.java b/itbaima-monitor-server/src/main/java/com/example/service/impl/ClientServiceImpl.java index eef6979..c4edabd 100644 --- a/itbaima-monitor-server/src/main/java/com/example/service/impl/ClientServiceImpl.java +++ b/itbaima-monitor-server/src/main/java/com/example/service/impl/ClientServiceImpl.java @@ -4,16 +4,12 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.entity.dto.Client; import com.example.entity.dto.ClientDetail; -import com.example.entity.vo.request.ClientDetailVO; -import com.example.entity.vo.request.RenameClientVO; -import com.example.entity.vo.request.RenameNodeVO; -import com.example.entity.vo.request.RuntimeDetailVO; -import com.example.entity.vo.response.ClientDetailsVO; -import com.example.entity.vo.response.ClientPreviewVO; -import com.example.entity.vo.response.ClientSimpleVO; -import com.example.entity.vo.response.RuntimeDetailsVO; +import com.example.entity.dto.ClientSsh; +import com.example.entity.vo.request.*; +import com.example.entity.vo.response.*; import com.example.mapper.ClientDetailMapper; import com.example.mapper.ClientMapper; +import com.example.mapper.ClientSshMapper; import com.example.service.ClientService; import com.example.utils.InfluxDbUtils; import jakarta.annotation.PostConstruct; @@ -37,6 +33,9 @@ public class ClientServiceImpl extends ServiceImpl impleme @Resource private ClientDetailMapper detailMapper; + @Resource + private ClientSshMapper sshMapper; + @Resource private InfluxDbUtils influx; @@ -163,6 +162,33 @@ public class ClientServiceImpl extends ServiceImpl impleme lastRuntime.remove(clientId); } + @Override + public void saveClientSshConnection(SshConnectionVO vo) { + Client client = this.getById(vo.getId()); + if(client == null) return; + ClientSsh ssh = new ClientSsh(); + BeanUtils.copyProperties(vo, ssh); + if(Objects.nonNull(sshMapper.selectById(client.getId()))) { + sshMapper.updateById(ssh); + } else { + sshMapper.insert(ssh); + } + } + + @Override + public SshSettingsVO sshSettings(int clientId) { + ClientDetail detail = detailMapper.selectById(clientId); + ClientSsh ssh = sshMapper.selectById(clientId); + SshSettingsVO vo; + if(ssh == null) { + vo = new SshSettingsVO(); + } else { + vo = ssh.asViewObject(SshSettingsVO.class); + } + vo.setIp(detail.getIp()); + return vo; + } + private boolean isOnline(RuntimeDetailVO runtime) { return runtime != null && System.currentTimeMillis() - runtime.getTimestamp() < 60 * 1000; } diff --git a/itbaima-monitor-server/src/main/java/com/example/service/impl/TerminalServiceImpl.java b/itbaima-monitor-server/src/main/java/com/example/service/impl/TerminalServiceImpl.java new file mode 100644 index 0000000..cd5ce13 --- /dev/null +++ b/itbaima-monitor-server/src/main/java/com/example/service/impl/TerminalServiceImpl.java @@ -0,0 +1,35 @@ +package com.example.service.impl; + +import com.example.service.TerminalService; +import jakarta.websocket.*; +import jakarta.websocket.server.ServerEndpoint; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.io.IOException; + +@Slf4j +@Service +@ServerEndpoint("/terminal/{clientId}") +public class TerminalServiceImpl implements TerminalService { + + @OnOpen + public void onOpen(Session session) throws IOException { + + } + + @OnClose + public void onClose(Session session) { + + } + + @OnMessage + public void onMessage(Session session, String message) { + + } + + @OnError + public void onError(Session session, Throwable error) { + + } +} diff --git a/itbaima-monitor-web/src/component/ClientDetails.vue b/itbaima-monitor-web/src/component/ClientDetails.vue index a53f601..021d465 100644 --- a/itbaima-monitor-web/src/component/ClientDetails.vue +++ b/itbaima-monitor-web/src/component/ClientDetails.vue @@ -5,7 +5,7 @@ import {useClipboard} from "@vueuse/core"; import {ElMessage, ElMessageBox} from "element-plus"; import {cpuNameToImage, fitToRightByteUnit, osNameToIcon, percentageToStatus, rename} from "@/tools"; import RuntimeHistroy from "@/component/RuntimeHistroy.vue"; -import {Delete} from "@element-plus/icons-vue"; +import {Connection, Delete, FolderOpened} from "@element-plus/icons-vue"; import {useStore} from "@/store"; const store = useStore() @@ -16,7 +16,7 @@ const props = defineProps({ update: Function, show: Boolean }) -const emits = defineEmits(['delete']) +const emits = defineEmits(['delete', 'terminal']) const details = reactive({ base: {}, @@ -100,13 +100,16 @@ watch(() => props.id, init, { immediate: true })
-
-
- - 服务器信息 -
- 删除此主机 +
+ SSH远程连接 + 在线SFTP文件管理 + 删除此主机 +
+
+ + 服务器信息
diff --git a/itbaima-monitor-web/src/component/TerminalWindow.vue b/itbaima-monitor-web/src/component/TerminalWindow.vue new file mode 100644 index 0000000..2534b62 --- /dev/null +++ b/itbaima-monitor-web/src/component/TerminalWindow.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/itbaima-monitor-web/src/views/main/Manage.vue b/itbaima-monitor-web/src/views/main/Manage.vue index bc01d3d..2852acc 100644 --- a/itbaima-monitor-web/src/views/main/Manage.vue +++ b/itbaima-monitor-web/src/views/main/Manage.vue @@ -7,6 +7,7 @@ import {Plus} from "@element-plus/icons-vue"; import RegisterCard from "@/component/RegisterCard.vue"; import {useRoute} from "vue-router"; import {useStore} from "@/store"; +import TerminalWindow from "@/component/TerminalWindow.vue"; const store = useStore() const route = useRoute() @@ -42,6 +43,16 @@ const updateList = () => { } setInterval(updateList, 10000) updateList() + +const openTerminal = id => { + terminal.show = true + terminal.id = id + detail.show = false +} +const terminal = reactive({ + show: false, + id: detail.id +})