first commit

This commit is contained in:
2026-03-06 14:01:32 +08:00
commit def60e21c7
1074 changed files with 119423 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.orionsec.ops</groupId>
<artifactId>orion-ops-api</artifactId>
<version>1.3.1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>orion-ops-web</name>
<artifactId>orion-ops-web</artifactId>
<modelVersion>4.0.0</modelVersion>
<dependencies>
<!-- service -->
<dependency>
<groupId>cn.orionsec.ops</groupId>
<artifactId>orion-ops-service</artifactId>
<version>${project.version}</version>
</dependency>
<!-- data -->
<dependency>
<groupId>cn.orionsec.ops</groupId>
<artifactId>orion-ops-data</artifactId>
<version>${project.version}</version>
</dependency>
<!-- mapping -->
<dependency>
<groupId>cn.orionsec.ops</groupId>
<artifactId>orion-ops-mapping</artifactId>
<version>${project.version}</version>
</dependency>
<!-- runner -->
<dependency>
<groupId>cn.orionsec.ops</groupId>
<artifactId>orion-ops-runner</artifactId>
<version>${project.version}</version>
</dependency>
<!-- aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/main/resources</directory>
<includes>
<include>**</include>
</includes>
</testResource>
</testResources>
<plugins>
<!-- 普通打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<!-- 分离依赖打包 -->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- <configuration>-->
<!-- <mainClass>cn.orionsec.ops.OrionApplication</mainClass>-->
<!-- <layout>ZIP</layout>-->
<!-- &lt;!&ndash; 注释后和依赖包一起打包 取消注释则不打包依赖 &ndash;&gt;-->
<!-- <includes>-->
<!-- <include>-->
<!-- <groupId>nothing</groupId>-->
<!-- <artifactId>nothing</artifactId>-->
<!-- </include>-->
<!-- </includes>-->
<!-- <excludes>-->
<!-- <exclude>-->
<!-- <groupId>org.projectlombok</groupId>-->
<!-- <artifactId>lombok</artifactId>-->
<!-- </exclude>-->
<!-- </excludes>-->
<!-- </configuration>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <goals>-->
<!-- <goal>repackage</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,17 @@
package cn.orionsec.ops;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource(locations = {"classpath:config/spring-*.xml"})
@MapperScan("cn.orionsec.ops.dao")
public class OrionApplication {
public static void main(String[] args) {
SpringApplication.run(OrionApplication.class, args);
}
}

View File

@@ -0,0 +1,33 @@
package cn.orionsec.ops.config;
import cn.orionsec.ops.interceptor.LogPrintInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
@Configuration
@ConditionalOnBean(LogPrintInterceptor.class)
public class LogPrintConfig {
@Value("${log.interceptor.expression:}")
private String logInterceptorExpression;
@Resource
private LogPrintInterceptor logPrintInterceptor;
@Bean
@ConditionalOnProperty(name = "log.interceptor.expression")
public AspectJExpressionPointcutAdvisor logAdvisor() {
AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
advisor.setExpression(logInterceptorExpression);
advisor.setAdvice(logPrintInterceptor);
return advisor;
}
}

View File

@@ -0,0 +1,74 @@
package cn.orionsec.ops.config;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.PropertiesConst;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.List;
@Configuration
@EnableSwagger2
@EnableKnife4j
@Profile({"dev"})
public class SwaggerConfig {
@Value("${login.token.header}")
private String loginTokenHeader;
@Value("${expose.api.access.header}")
private String accessTokenHeader;
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(this.getApiInfo())
.securitySchemes(this.getSecuritySchemes())
.enable(true)
.select()
.apis(RequestHandlerSelectors.basePackage("cn.orionsec.ops"))
.paths(PathSelectors.any())
.build();
}
/**
* 配置 api 信息
*
* @return api info
*/
private ApiInfo getApiInfo() {
return new ApiInfoBuilder()
.title("orion-ops restful API")
.contact(new Contact(Const.ORION_AUTHOR, Const.ORION_GITEE, Const.ORION_EMAIL))
.version(PropertiesConst.ORION_OPS_VERSION)
.description("orion-ops api 管理")
.build();
}
/**
* 认证配置
*
* @return security scheme
*/
private List<SecurityScheme> getSecuritySchemes() {
ApiKey loginToken = new ApiKey(loginTokenHeader, loginTokenHeader, "header");
ApiKey accessToken = new ApiKey(accessTokenHeader, accessTokenHeader, "header");
return Lists.of(loginToken, accessToken);
}
}

View File

@@ -0,0 +1,247 @@
package cn.orionsec.ops.config;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.exception.*;
import cn.orionsec.kit.lang.exception.argument.CodeArgumentException;
import cn.orionsec.kit.lang.exception.argument.HttpWrapperException;
import cn.orionsec.kit.lang.exception.argument.InvalidArgumentException;
import cn.orionsec.kit.lang.exception.argument.RpcWrapperException;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.interceptor.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.EncryptedDocumentException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.sql.SQLException;
@Slf4j
@Configuration
@RestControllerAdvice
public class WebMvcConfig implements WebMvcConfigurer {
@Resource
private IpFilterInterceptor ipFilterInterceptor;
@Resource
private AuthenticateInterceptor authenticateInterceptor;
@Resource
private RoleInterceptor roleInterceptor;
@Resource
private UserActiveInterceptor userActiveInterceptor;
@Resource
private ExposeApiHeaderInterceptor exposeApiHeaderInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// IP拦截器
registry.addInterceptor(ipFilterInterceptor)
.addPathPatterns("/**")
.order(5);
// 认证拦截器
registry.addInterceptor(authenticateInterceptor)
.addPathPatterns("/orion/api/**")
.order(10);
// 权限拦截器
registry.addInterceptor(roleInterceptor)
.addPathPatterns("/orion/api/**")
.order(20);
// 活跃拦截器
registry.addInterceptor(userActiveInterceptor)
.addPathPatterns("/orion/api/**")
.excludePathPatterns("/orion/api/auth/**")
.order(30);
// 暴露服务请求头拦截器
registry.addInterceptor(exposeApiHeaderInterceptor)
.addPathPatterns("/orion/expose-api/**")
.order(40);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
// 暴露服务允许跨域
registry.addMapping("/orion/expose-api/**")
.allowCredentials(true)
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowedHeaders("*")
.maxAge(3600);
}
/**
* @return 演示模式禁用 api 切面
*/
@Bean
@ConditionalOnProperty(value = "demo.mode", havingValue = "true")
public DemoDisableApiAspect demoDisableApiAspect() {
return new DemoDisableApiAspect();
}
@ExceptionHandler(value = Exception.class)
public HttpWrapper<?> normalExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("normalExceptionHandler url: {}, 抛出异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.EXCEPTION_MESSAGE).data(ex.getMessage());
}
@ExceptionHandler(value = ApplicationException.class)
public HttpWrapper<?> applicationExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("applicationExceptionHandler url: {}, 抛出异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(ex.getMessage());
}
@ExceptionHandler(value = DataAccessResourceFailureException.class)
public HttpWrapper<?> dataAccessResourceFailureExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("dataAccessResourceFailureExceptionHandler url: {}, 抛出异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.NETWORK_FLUCTUATION);
}
@ExceptionHandler(value = {HttpMessageNotReadableException.class, MethodArgumentTypeMismatchException.class,
HttpMessageNotReadableException.class, MethodArgumentNotValidException.class, BindException.class})
public HttpWrapper<?> httpRequestExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("httpRequestExceptionHandler url: {}, http请求异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.INVALID_PARAM);
}
@ExceptionHandler(value = {HttpRequestException.class})
public HttpWrapper<?> httpApiRequestExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("httpApiRequestExceptionHandler url: {}, http-api请求异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.HTTP_API);
}
@ExceptionHandler(value = {InvalidArgumentException.class, IllegalArgumentException.class, DisabledException.class})
public HttpWrapper<?> invalidArgumentExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("invalidArgumentExceptionHandler url: {}, 参数异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(ex.getMessage());
}
@ExceptionHandler(value = {IOException.class, IORuntimeException.class})
public HttpWrapper<?> ioExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("ioExceptionHandler url: {}, io异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.IO_EXCEPTION_MESSAGE).data(ex.getMessage());
}
@ExceptionHandler(value = SQLException.class)
public HttpWrapper<?> sqlExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("sqlExceptionHandler url: {}, sql异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.SQL_EXCEPTION_MESSAGE);
}
@ExceptionHandler(value = {SftpException.class, com.jcraft.jsch.SftpException.class})
public HttpWrapper<?> sftpExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("sftpExceptionHandler url: {}, sftp处理异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.OPERATOR_ERROR).data(ex.getMessage());
}
@ExceptionHandler(value = ParseRuntimeException.class)
public HttpWrapper<?> parseExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("parseExceptionHandler url: {}, 解析异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
if (Exceptions.isCausedBy(ex, EncryptedDocumentException.class)) {
// excel 密码错误
return HttpWrapper.error(MessageConst.OPEN_TEMPLATE_ERROR).data(ex.getMessage());
} else {
return HttpWrapper.error(MessageConst.PARSE_TEMPLATE_DATA_ERROR).data(ex.getMessage());
}
}
@ExceptionHandler(value = EncryptException.class)
public HttpWrapper<?> encryptExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("encryptExceptionHandler url: {}, 数据加密异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.ENCRYPT_ERROR).data(ex.getMessage());
}
@ExceptionHandler(value = DecryptException.class)
public HttpWrapper<?> decryptExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("decryptExceptionHandler url: {}, 数据解密异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.DECRYPT_ERROR).data(ex.getMessage());
}
@ExceptionHandler(value = VcsException.class)
public HttpWrapper<?> vcsExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("vcsExceptionHandler url: {}, vcs处理异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.REPOSITORY_OPERATOR_ERROR).data(ex.getMessage());
}
@ExceptionHandler(value = {TaskExecuteException.class, ExecuteException.class})
public HttpWrapper<?> taskExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("taskExceptionHandler url: {}, task处理异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.TASK_ERROR).data(ex.getMessage());
}
@ExceptionHandler(value = ConnectionRuntimeException.class)
public HttpWrapper<?> connectionExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("connectionExceptionHandler url: {}, connect异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.CONNECT_ERROR).data(ex.getMessage());
}
@ExceptionHandler(value = {TimeoutException.class, java.util.concurrent.TimeoutException.class})
public HttpWrapper<?> timeoutExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("timeoutExceptionHandler url: {}, timeout异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.TIMEOUT_ERROR).data(ex.getMessage());
}
@ExceptionHandler(value = {InterruptedException.class, InterruptedRuntimeException.class, InterruptedIOException.class})
public HttpWrapper<?> interruptExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("interruptExceptionHandler url: {}, interrupt异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.INTERRUPT_ERROR).data(ex.getMessage());
}
@ExceptionHandler(value = UnsafeException.class)
public HttpWrapper<?> unsafeExceptionHandler(HttpServletRequest request, Exception ex) {
log.error("unsafeExceptionHandler url: {}, unsafe异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.UNSAFE_OPERATOR).data(ex.getMessage());
}
@ExceptionHandler(value = LogException.class)
public HttpWrapper<?> logExceptionHandler(HttpServletRequest request, LogException ex) {
log.error("logExceptionHandler url: {}, 处理异常打印日志: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.EXCEPTION_MESSAGE).data(ex.getMessage());
}
@ExceptionHandler(value = ParseCronException.class)
public HttpWrapper<?> parseCronExceptionHandler(ParseCronException ex) {
return HttpWrapper.error(MessageConst.ERROR_EXPRESSION).data(ex.getMessage());
}
@ExceptionHandler(value = MaxUploadSizeExceededException.class)
public HttpWrapper<?> maxUploadSizeExceededExceptionHandler(HttpServletRequest request, MaxUploadSizeExceededException ex) {
log.error("maxUploadSizeExceededExceptionHandler url: {}, 上传异常: {}, message: {}", request.getRequestURI(), ex.getClass(), ex.getMessage(), ex);
return HttpWrapper.error(MessageConst.FILE_TOO_LARGE).data(ex.getMessage());
}
@ExceptionHandler(value = CodeArgumentException.class)
public HttpWrapper<?> codeArgumentExceptionHandler(CodeArgumentException ex) {
return HttpWrapper.of(ex.getCode(), ex.getMessage());
}
@ExceptionHandler(value = HttpWrapperException.class)
public HttpWrapper<?> httpWrapperExceptionHandler(HttpWrapperException ex) {
return ex.getWrapper();
}
@ExceptionHandler(value = RpcWrapperException.class)
public HttpWrapper<?> rpcWrapperExceptionHandler(RpcWrapperException ex) {
return ex.getWrapper().toHttpWrapper();
}
}

View File

@@ -0,0 +1,77 @@
package cn.orionsec.ops.config;
import cn.orionsec.ops.handler.sftp.notify.FileTransferNotifyHandler;
import cn.orionsec.ops.handler.tail.TailFileHandler;
import cn.orionsec.ops.handler.terminal.TerminalMessageHandler;
import cn.orionsec.ops.handler.terminal.watcher.TerminalWatcherHandler;
import cn.orionsec.ops.interceptor.FileTransferNotifyInterceptor;
import cn.orionsec.ops.interceptor.TailFileInterceptor;
import cn.orionsec.ops.interceptor.TerminalAccessInterceptor;
import cn.orionsec.ops.interceptor.TerminalWatcherInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
import javax.annotation.Resource;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Resource
private TerminalMessageHandler terminalMessageHandler;
@Resource
private TerminalAccessInterceptor terminalAccessInterceptor;
@Resource
private TerminalWatcherHandler terminalWatcherHandler;
@Resource
private TerminalWatcherInterceptor terminalWatcherInterceptor;
@Resource
private TailFileHandler tailFileHandler;
@Resource
private TailFileInterceptor tailFileInterceptor;
@Resource
private FileTransferNotifyHandler fileTransferNotifyHandler;
@Resource
private FileTransferNotifyInterceptor fileTransferNotifyInterceptor;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(terminalMessageHandler, "/orion/keep-alive/machine/terminal/{token}")
.addInterceptors(terminalAccessInterceptor)
.setAllowedOrigins("*");
webSocketHandlerRegistry.addHandler(terminalWatcherHandler, "/orion/keep-alive/watcher/terminal/{token}")
.addInterceptors(terminalWatcherInterceptor)
.setAllowedOrigins("*");
webSocketHandlerRegistry.addHandler(tailFileHandler, "/orion/keep-alive/tail/{token}")
.addInterceptors(tailFileInterceptor)
.setAllowedOrigins("*");
webSocketHandlerRegistry.addHandler(fileTransferNotifyHandler, "/orion/keep-alive/sftp/notify/{token}")
.addInterceptors(fileTransferNotifyInterceptor)
.setAllowedOrigins("*");
}
/**
* web socket 缓冲区大小配置
*/
@Bean
public ServletServerContainerFactoryBean servletServerContainerFactoryBean() {
ServletServerContainerFactoryBean factory = new ServletServerContainerFactoryBean();
factory.setMaxBinaryMessageBufferSize(1024 * 1024);
factory.setMaxTextMessageBufferSize(1024 * 1024);
factory.setMaxSessionIdleTimeout(30 * 60000L);
return factory;
}
}

View File

@@ -0,0 +1,69 @@
package cn.orionsec.ops.config;
import cn.orionsec.kit.lang.constant.StandardContentType;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.define.wrapper.RpcWrapper;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.web.servlet.web.Servlets;
import cn.orionsec.ops.annotation.IgnoreWrapper;
import cn.orionsec.ops.annotation.RestWrapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Configuration
public class WrapperResultConfig implements HandlerMethodReturnValueHandler {
@Resource
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
@PostConstruct
public void compare() {
List<HandlerMethodReturnValueHandler> handlers = requestMappingHandlerAdapter.getReturnValueHandlers();
List<HandlerMethodReturnValueHandler> list = Lists.newList();
list.add(this);
if (handlers != null) {
list.addAll(handlers);
}
requestMappingHandlerAdapter.setReturnValueHandlers(list);
}
@Override
public boolean supportsReturnType(MethodParameter methodParameter) {
// 统一返回值
if (!methodParameter.getContainingClass().isAnnotationPresent(RestWrapper.class)) {
return false;
}
return !methodParameter.hasMethodAnnotation(IgnoreWrapper.class);
// && methodParameter.getExecutable().getAnnotatedReturnType().getType() != Void.TYPE;
}
@Override
public void handleReturnValue(Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest) throws Exception {
HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
if (response == null) {
return;
}
HttpWrapper<?> wrapper;
if (o instanceof HttpWrapper) {
wrapper = (HttpWrapper<?>) o;
} else if (o instanceof RpcWrapper) {
wrapper = ((RpcWrapper<?>) o).toHttpWrapper();
} else {
wrapper = new HttpWrapper<>().data(o);
}
modelAndViewContainer.setRequestHandled(true);
response.setContentType(StandardContentType.APPLICATION_JSON);
Servlets.transfer(response, wrapper.toJsonString().getBytes());
}
}

View File

@@ -0,0 +1,79 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.alarm.AlarmGroupRequest;
import cn.orionsec.ops.entity.vo.alarm.AlarmGroupVO;
import cn.orionsec.ops.service.api.AlarmGroupService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "报警组配置")
@RestController
@RestWrapper
@RequestMapping("/orion/api/alarm-group")
public class AlarmGroupController {
@Resource
private AlarmGroupService alarmGroupService;
@PostMapping("/add")
@ApiOperation(value = "添加报警组")
@EventLog(EventType.ADD_ALARM_GROUP)
public Long addAlarmGroup(@RequestBody AlarmGroupRequest request) {
this.validParams(request);
return alarmGroupService.addAlarmGroup(request);
}
@PostMapping("/update")
@ApiOperation(value = "更新报警组")
@EventLog(EventType.UPDATE_ALARM_GROUP)
public Integer updateAlarmGroup(@RequestBody AlarmGroupRequest request) {
Valid.notNull(request.getId());
this.validParams(request);
return alarmGroupService.updateAlarmGroup(request);
}
@PostMapping("/delete")
@ApiOperation(value = "删除报警组")
@EventLog(EventType.DELETE_ALARM_GROUP)
public Integer deleteAlarmGroup(@RequestBody AlarmGroupRequest request) {
Long id = Valid.notNull(request.getId());
return alarmGroupService.deleteAlarmGroup(id);
}
@PostMapping("/list")
@ApiOperation(value = "查询列表")
public DataGrid<AlarmGroupVO> getAlarmGroupList(@RequestBody AlarmGroupRequest request) {
return alarmGroupService.getAlarmGroupList(request);
}
@PostMapping("/get")
@ApiOperation(value = "查询详情")
public AlarmGroupVO getAlarmGroupDetail(@RequestBody AlarmGroupRequest request) {
Long id = Valid.notNull(request.getId());
return alarmGroupService.getAlarmGroupDetail(id);
}
/**
* 验证参数
*
* @param request request
*/
private void validParams(AlarmGroupRequest request) {
Valid.notBlank(request.getName());
Valid.notEmpty(request.getUserIdList());
Valid.notEmpty(request.getNotifyIdList());
}
}

View File

@@ -0,0 +1,43 @@
package cn.orionsec.ops.controller;
import cn.orionsec.ops.annotation.IgnoreLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.entity.request.app.ApplicationActionLogRequest;
import cn.orionsec.ops.entity.vo.app.ApplicationActionLogVO;
import cn.orionsec.ops.service.api.ApplicationActionLogService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "应用操作日志")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-action-log")
public class ApplicationActionLogController {
@Resource
private ApplicationActionLogService applicationActionLogService;
@PostMapping("/detail")
@ApiOperation(value = "获取日志详情")
public ApplicationActionLogVO getActionDetail(@RequestBody ApplicationActionLogRequest request) {
Long id = Valid.notNull(request.getId());
return applicationActionLogService.getDetailById(id);
}
@IgnoreLog
@PostMapping("/status")
@ApiOperation(value = "获取日志状态")
public ApplicationActionLogVO getActionStatus(@RequestBody ApplicationActionLogRequest request) {
Long id = Valid.notNull(request.getId());
return applicationActionLogService.getStatusById(id);
}
}

View File

@@ -0,0 +1,115 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.IgnoreLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.app.ApplicationBuildRequest;
import cn.orionsec.ops.entity.vo.app.ApplicationBuildReleaseListVO;
import cn.orionsec.ops.entity.vo.app.ApplicationBuildStatusVO;
import cn.orionsec.ops.entity.vo.app.ApplicationBuildVO;
import cn.orionsec.ops.service.api.ApplicationBuildService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "应用构建")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-build")
public class ApplicationBuildController {
@Resource
private ApplicationBuildService applicationBuildService;
@PostMapping("/submit")
@ApiOperation(value = "提交执行")
@EventLog(EventType.SUBMIT_BUILD)
public Long submitAppBuild(@RequestBody ApplicationBuildRequest request) {
Valid.allNotNull(request.getAppId(), request.getProfileId());
return applicationBuildService.submitBuildTask(request, true);
}
@PostMapping("/list")
@ApiOperation(value = "获取构建列表")
public DataGrid<ApplicationBuildVO> getBuildList(@RequestBody ApplicationBuildRequest request) {
Valid.notNull(request.getProfileId());
return applicationBuildService.getBuildList(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取构建详情")
public ApplicationBuildVO getBuildDetail(@RequestBody ApplicationBuildRequest request) {
Long id = Valid.notNull(request.getId());
return applicationBuildService.getBuildDetail(id);
}
@IgnoreLog
@PostMapping("/status")
@ApiOperation(value = "查询构建状态")
public ApplicationBuildStatusVO getBuildStatus(@RequestBody ApplicationBuildRequest request) {
Long id = Valid.notNull(request.getId());
return applicationBuildService.getBuildStatus(id);
}
@IgnoreLog
@PostMapping("/list-status")
@ApiOperation(value = "查询构建状态列表")
public List<ApplicationBuildStatusVO> getListStatus(@RequestBody ApplicationBuildRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return applicationBuildService.getBuildStatusList(idList);
}
@PostMapping("/terminate")
@ApiOperation(value = "终止构建")
@EventLog(EventType.BUILD_TERMINATE)
public HttpWrapper<?> terminateTask(@RequestBody ApplicationBuildRequest request) {
Long id = Valid.notNull(request.getId());
applicationBuildService.terminateBuildTask(id);
return HttpWrapper.ok();
}
@PostMapping("/write")
@ApiOperation(value = "输入命令")
public HttpWrapper<?> writeTask(@RequestBody ApplicationBuildRequest request) {
Long id = Valid.notNull(request.getId());
String command = Valid.notEmpty(request.getCommand());
applicationBuildService.writeBuildTask(id, command);
return HttpWrapper.ok();
}
@PostMapping("/delete")
@ApiOperation(value = "删除构建")
@EventLog(EventType.DELETE_BUILD)
public Integer deleteTask(@RequestBody ApplicationBuildRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return applicationBuildService.deleteBuildTask(idList);
}
@PostMapping("/rebuild")
@ApiOperation(value = "删除构建")
@EventLog(EventType.SUBMIT_REBUILD)
public Long rebuildTask(@RequestBody ApplicationBuildRequest request) {
Long id = Valid.notNull(request.getId());
return applicationBuildService.rebuild(id);
}
@PostMapping("/release-list")
@ApiOperation(value = "获取发布构建列表")
public List<ApplicationBuildReleaseListVO> getBuildReleaseList(@RequestBody ApplicationBuildRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
return applicationBuildService.getBuildReleaseList(appId, profileId);
}
}

View File

@@ -0,0 +1,126 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.collect.MutableLinkedHashMap;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.collect.Maps;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.env.EnvViewType;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.app.ApplicationEnvRequest;
import cn.orionsec.ops.entity.vo.app.ApplicationEnvVO;
import cn.orionsec.ops.service.api.ApplicationEnvService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Api(tags = "应用环境变量")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-env")
public class ApplicationEnvController {
@Resource
private ApplicationEnvService applicationEnvService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加环境变量")
public Long addAppEnv(@RequestBody ApplicationEnvRequest request) {
Valid.notNull(request.getAppId());
Valid.notNull(request.getProfileId());
Valid.notBlank(request.getKey());
Valid.notBlank(request.getValue());
return applicationEnvService.addAppEnv(request);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除环境变量")
@EventLog(EventType.DELETE_APP_ENV)
public Integer deleteAppEnv(@RequestBody ApplicationEnvRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return applicationEnvService.deleteAppEnv(idList);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "更新环境变量")
public Integer updateAppEnv(@RequestBody ApplicationEnvRequest request) {
Valid.notNull(request.getId());
return applicationEnvService.updateAppEnv(request);
}
@PostMapping("/list")
@ApiOperation(value = "获取环境变量列表")
public DataGrid<ApplicationEnvVO> listAppEnv(@RequestBody ApplicationEnvRequest request) {
Valid.notNull(request.getAppId());
Valid.notNull(request.getProfileId());
return applicationEnvService.listAppEnv(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取环境变量详情")
public ApplicationEnvVO appEnvDetail(@RequestBody ApplicationEnvRequest request) {
Long id = Valid.notNull(request.getId());
return applicationEnvService.getAppEnvDetail(id);
}
@DemoDisableApi
@PostMapping("/sync")
@ApiOperation(value = "同步环境变量到其他环境")
@EventLog(EventType.SYNC_APP_ENV)
public HttpWrapper<?> syncAppEnv(@RequestBody ApplicationEnvRequest request) {
Long id = Valid.notNull(request.getId());
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
List<Long> targetProfileIdList = Valid.notEmpty(request.getTargetProfileIdList());
applicationEnvService.syncAppEnv(id, appId, profileId, targetProfileIdList);
return HttpWrapper.ok();
}
@PostMapping("/view")
@ApiOperation(value = "获取环境变量视图")
public String view(@RequestBody ApplicationEnvRequest request) {
Valid.notNull(request.getAppId());
Valid.notNull(request.getProfileId());
EnvViewType viewType = Valid.notNull(EnvViewType.of(request.getViewType()));
request.setLimit(Const.N_100000);
// 查询列表
Map<String, String> env = Maps.newLinkedMap();
applicationEnvService.listAppEnv(request).forEach(e -> env.put(e.getKey(), e.getValue()));
return viewType.toValue(env);
}
@DemoDisableApi
@PostMapping("/view-save")
@ApiOperation(value = "保存环境变量视图")
public Integer viewSave(@RequestBody ApplicationEnvRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
EnvViewType viewType = Valid.notNull(EnvViewType.of(request.getViewType()));
String value = Valid.notBlank(request.getValue());
try {
MutableLinkedHashMap<String, String> result = viewType.toMap(value);
applicationEnvService.saveEnv(appId, profileId, result);
return result.size();
} catch (Exception e) {
throw Exceptions.argument(MessageConst.PARSE_ERROR, e);
}
}
}

View File

@@ -0,0 +1,211 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.app.ActionType;
import cn.orionsec.ops.constant.app.StageType;
import cn.orionsec.ops.constant.app.TransferMode;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.app.*;
import cn.orionsec.ops.entity.vo.app.ApplicationDetailVO;
import cn.orionsec.ops.entity.vo.app.ApplicationInfoVO;
import cn.orionsec.ops.entity.vo.app.ApplicationMachineVO;
import cn.orionsec.ops.service.api.ApplicationInfoService;
import cn.orionsec.ops.service.api.ApplicationMachineService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "应用信息")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-info")
public class ApplicationInfoController {
@Resource
private ApplicationInfoService applicationService;
@Resource
private ApplicationMachineService applicationMachineService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加应用")
@EventLog(EventType.ADD_APP)
public Long insertApp(@RequestBody ApplicationInfoRequest request) {
Valid.allNotBlank(request.getName(), request.getTag());
return applicationService.insertApp(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "更新应用")
@EventLog(EventType.UPDATE_APP)
public Integer updateApp(@RequestBody ApplicationInfoRequest request) {
Valid.notNull(request.getId());
return applicationService.updateApp(request);
}
@PostMapping("/sort")
@ApiOperation(value = "更新排序")
public Integer updateAppSort(@RequestBody ApplicationInfoRequest request) {
Long id = Valid.notNull(request.getId());
Integer adjust = Valid.in(request.getSortAdjust(), Const.INCREMENT, Const.DECREMENT);
return applicationService.updateAppSort(id, Const.INCREMENT.equals(adjust));
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除应用")
@EventLog(EventType.DELETE_APP)
public Integer deleteApp(@RequestBody ApplicationInfoRequest request) {
Long id = Valid.notNull(request.getId());
return applicationService.deleteApp(id);
}
@PostMapping("/list")
@ApiOperation(value = "获取应用列表")
public DataGrid<ApplicationInfoVO> listApp(@RequestBody ApplicationInfoRequest request) {
return applicationService.listApp(request);
}
@PostMapping("/list-machine")
@ApiOperation(value = "获取应用机器列表")
public List<ApplicationMachineVO> listAppMachines(@RequestBody ApplicationInfoRequest request) {
Long id = Valid.notNull(request.getId());
Long profileId = Valid.notNull(request.getProfileId());
return applicationService.getAppMachines(id, profileId);
}
@PostMapping("/detail")
@ApiOperation(value = "获取详情应用")
public ApplicationDetailVO appDetail(@RequestBody ApplicationInfoRequest request) {
Long appId = Valid.notNull(request.getId());
return applicationService.getAppDetail(appId, request.getProfileId());
}
@PostMapping("/config")
@ApiOperation(value = "配置应用")
@EventLog(EventType.CONFIG_APP)
public HttpWrapper<?> configApp(@RequestBody ApplicationConfigRequest request) {
Valid.notNull(request.getAppId());
Valid.notNull(request.getProfileId());
this.checkConfig(request);
applicationService.configAppProfile(request);
return HttpWrapper.ok();
}
@PostMapping("/sync")
@ApiOperation(value = "同步配置")
@EventLog(EventType.SYNC_APP)
public HttpWrapper<?> syncAppConfig(@RequestBody ApplicationSyncConfigRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
List<Long> targetProfileList = Valid.notEmpty(request.getTargetProfileIdList());
applicationService.syncAppProfileConfig(appId, profileId, targetProfileList);
return HttpWrapper.ok();
}
@DemoDisableApi
@PostMapping("/copy")
@ApiOperation(value = "复制应用")
@EventLog(EventType.COPY_APP)
public HttpWrapper<?> copyApplication(@RequestBody ApplicationInfoRequest request) {
Long appId = Valid.notNull(request.getId());
applicationService.copyApplication(appId);
return HttpWrapper.ok();
}
@DemoDisableApi
@PostMapping("/delete-machine")
@ApiOperation(value = "删除发布机器")
public Integer deleteAppMachine(@RequestBody ApplicationInfoRequest request) {
Long id = Valid.notNull(request.getId());
return applicationMachineService.deleteById(id);
}
@PostMapping("/get-machine-id")
@ApiOperation(value = "获取发布机器id")
public List<Long> getAppMachineId(@RequestBody ApplicationInfoRequest request) {
Long appId = Valid.notNull(request.getId());
Long profileId = Valid.notNull(request.getProfileId());
return applicationMachineService.getAppProfileMachineIdList(appId, profileId, true);
}
/**
* 检查配置
*
* @param request request
*/
private void checkConfig(ApplicationConfigRequest request) {
StageType stageType = Valid.notNull(StageType.of(request.getStageType()));
List<ApplicationConfigActionRequest> actions;
ApplicationConfigEnvRequest env = Valid.notNull(request.getEnv());
if (StageType.BUILD.equals(stageType)) {
// 构建检查产物路径
Valid.notBlank(env.getBundlePath());
// 检查操作
actions = Valid.notEmpty(request.getBuildActions());
} else if (StageType.RELEASE.equals(stageType)) {
// 发布序列
Valid.notNull(env.getReleaseSerial());
// 异常处理
Valid.notNull(env.getExceptionHandler());
// 发布检查机器id
Valid.notEmpty(request.getMachineIdList());
// 检查操作
actions = Valid.notEmpty(request.getReleaseActions());
} else {
throw Exceptions.unsupported();
}
// 检查操作
for (ApplicationConfigActionRequest action : actions) {
Valid.notBlank(action.getName());
ActionType actionType = Valid.notNull(ActionType.of(action.getType(), stageType.getType()));
// 检查命令
if (ActionType.BUILD_COMMAND.equals(actionType) || ActionType.RELEASE_COMMAND.equals(actionType)) {
Valid.notBlank(action.getCommand());
}
// 检查传输 scp 命令
if (ActionType.RELEASE_TRANSFER.equals(actionType)
&& TransferMode.SCP.getValue().equals(env.getTransferMode())) {
Valid.notBlank(action.getCommand());
}
}
// 检查检出操作唯一性
int checkoutActionCount = actions.stream()
.map(ApplicationConfigActionRequest::getType)
.map(ActionType::of)
.filter(ActionType.BUILD_CHECKOUT::equals)
.mapToInt(s -> Const.N_1)
.sum();
Valid.lte(checkoutActionCount, 1, MessageConst.CHECKOUT_ACTION_PRESENT);
// 检查传输操作唯一性
int transferActionCount = actions.stream()
.map(ApplicationConfigActionRequest::getType)
.map(ActionType::of)
.filter(ActionType.RELEASE_TRANSFER::equals)
.mapToInt(s -> Const.N_1)
.sum();
Valid.lte(transferActionCount, 1, MessageConst.TRANSFER_ACTION_PRESENT);
if (transferActionCount != 0) {
// 传输目录
Valid.notBlank(env.getTransferPath());
}
}
}

View File

@@ -0,0 +1,91 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.app.StageType;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.app.ApplicationPipelineDetailRequest;
import cn.orionsec.ops.entity.request.app.ApplicationPipelineRequest;
import cn.orionsec.ops.entity.vo.app.ApplicationPipelineVO;
import cn.orionsec.ops.service.api.ApplicationPipelineService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "应用流水线")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-pipeline")
public class ApplicationPipelineController {
@Resource
private ApplicationPipelineService applicationPipelineService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "新增应用流水线")
@EventLog(EventType.ADD_PIPELINE)
public Long addPipeline(@RequestBody ApplicationPipelineRequest request) {
this.validParams(request);
return applicationPipelineService.addPipeline(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改应用流水线")
@EventLog(EventType.UPDATE_PIPELINE)
public Integer updatePipeline(@RequestBody ApplicationPipelineRequest request) {
Valid.notNull(request.getId());
this.validParams(request);
return applicationPipelineService.updatePipeline(request);
}
@PostMapping("/list")
@ApiOperation(value = "获取应用流水线列表")
public DataGrid<ApplicationPipelineVO> listPipeline(@RequestBody ApplicationPipelineRequest request) {
Valid.notNull(request.getProfileId());
return applicationPipelineService.listPipeline(request);
}
@PostMapping("/get")
@ApiOperation(value = "详情获取应用流水线")
public ApplicationPipelineVO getPipeline(@RequestBody ApplicationPipelineRequest request) {
Long id = Valid.notNull(request.getId());
return applicationPipelineService.getPipeline(id);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除应用流水线")
@EventLog(EventType.DELETE_PIPELINE)
public Integer deletePipeline(@RequestBody ApplicationPipelineRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return applicationPipelineService.deletePipeline(idList);
}
/**
* 检查参数
*
* @param request request
*/
private void validParams(@RequestBody ApplicationPipelineRequest request) {
Valid.notBlank(request.getName());
Valid.notNull(request.getProfileId());
List<ApplicationPipelineDetailRequest> details = Valid.notEmpty(request.getDetails());
for (ApplicationPipelineDetailRequest detail : details) {
Valid.notNull(detail.getAppId());
Valid.notNull(StageType.of(detail.getStageType()));
}
}
}

View File

@@ -0,0 +1,208 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.IgnoreLog;
import cn.orionsec.ops.annotation.RequireRole;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.app.PipelineStatus;
import cn.orionsec.ops.constant.app.TimedType;
import cn.orionsec.ops.constant.common.AuditStatus;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.user.RoleType;
import cn.orionsec.ops.entity.request.app.ApplicationPipelineTaskDetailRequest;
import cn.orionsec.ops.entity.request.app.ApplicationPipelineTaskRequest;
import cn.orionsec.ops.entity.vo.app.*;
import cn.orionsec.ops.service.api.ApplicationPipelineTaskDetailService;
import cn.orionsec.ops.service.api.ApplicationPipelineTaskLogService;
import cn.orionsec.ops.service.api.ApplicationPipelineTaskService;
import cn.orionsec.ops.task.TaskRegister;
import cn.orionsec.ops.task.TaskType;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Api(tags = "应用流水线任务")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-pipeline-task")
public class ApplicationPipelineTaskController {
@Resource
private ApplicationPipelineTaskService applicationPipelineTaskService;
@Resource
private ApplicationPipelineTaskDetailService applicationPipelineTaskDetailService;
@Resource
private ApplicationPipelineTaskLogService applicationPipelineTaskLogService;
@Resource
private TaskRegister taskRegister;
@PostMapping("/list")
@ApiOperation(value = "获取任务列表")
public DataGrid<ApplicationPipelineTaskListVO> getPipelineTaskList(@RequestBody ApplicationPipelineTaskRequest request) {
Valid.notNull(request.getProfileId());
return applicationPipelineTaskService.getPipelineTaskList(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取任务详情")
public ApplicationPipelineTaskVO getPipelineTaskDetail(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
return applicationPipelineTaskService.getPipelineTaskDetail(id);
}
@PostMapping("/task-details")
@ApiOperation(value = "获取任务执行详情")
public List<ApplicationPipelineTaskDetailVO> getTaskDetails(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
return applicationPipelineTaskDetailService.getTaskDetails(id);
}
@PostMapping("/submit")
@ApiOperation(value = "提交任务")
@EventLog(EventType.SUBMIT_PIPELINE_TASK)
public Long submitPipelineTask(@RequestBody ApplicationPipelineTaskRequest request) {
Valid.notNull(request.getPipelineId());
Valid.notBlank(request.getTitle());
List<ApplicationPipelineTaskDetailRequest> details = Valid.notEmpty(request.getDetails());
for (ApplicationPipelineTaskDetailRequest detail : details) {
Valid.notNull(detail.getId());
}
TimedType timedType = Valid.notNull(TimedType.of(request.getTimedExec()));
if (TimedType.TIMED.equals(timedType)) {
Date timedExecTime = Valid.notNull(request.getTimedExecTime());
Valid.isTrue(timedExecTime.compareTo(new Date()) > 0, MessageConst.TIMED_GREATER_THAN_NOW);
}
Long id = applicationPipelineTaskService.submitPipelineTask(request);
// 提交任务
if (PipelineStatus.WAIT_SCHEDULE.getStatus().equals(request.getStatus())) {
taskRegister.submit(TaskType.PIPELINE, request.getTimedExecTime(), id);
}
return id;
}
@PostMapping("/audit")
@ApiOperation(value = "审核任务")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.AUDIT_PIPELINE_TASK)
public Integer auditPipelineTask(@RequestBody ApplicationPipelineTaskRequest request) {
Valid.notNull(request.getId());
AuditStatus status = Valid.notNull(AuditStatus.of(request.getAuditStatus()));
if (AuditStatus.REJECT.equals(status)) {
Valid.notBlank(request.getAuditReason());
}
return applicationPipelineTaskService.auditPipelineTask(request);
}
@PostMapping("/copy")
@ApiOperation(value = "复制任务")
@EventLog(EventType.COPY_PIPELINE_TASK)
public Long copyPipelineTask(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
return applicationPipelineTaskService.copyPipeline(id);
}
@PostMapping("/exec")
@ApiOperation(value = "执行任务")
@EventLog(EventType.EXEC_PIPELINE_TASK)
public HttpWrapper<?> execPipelineTask(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
applicationPipelineTaskService.execPipeline(id, false);
return HttpWrapper.ok();
}
@PostMapping("/delete")
@ApiOperation(value = "删除任务")
@EventLog(EventType.DELETE_PIPELINE_TASK)
public Integer deletePipelineTask(@RequestBody ApplicationPipelineTaskRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return applicationPipelineTaskService.deletePipeline(idList);
}
@PostMapping("/set-timed")
@ApiOperation(value = "设置定时执行")
@EventLog(EventType.SET_PIPELINE_TIMED_TASK)
public HttpWrapper<?> setTaskTimedExec(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
Date timedExecTime = Valid.notNull(request.getTimedExecTime());
Valid.isTrue(timedExecTime.compareTo(new Date()) > 0, MessageConst.TIMED_GREATER_THAN_NOW);
applicationPipelineTaskService.setPipelineTimedExec(id, timedExecTime);
return HttpWrapper.ok();
}
@PostMapping("/cancel-timed")
@ApiOperation(value = "取消定时")
@EventLog(EventType.CANCEL_PIPELINE_TIMED_TASK)
public HttpWrapper<?> cancelTaskTimedExec(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
applicationPipelineTaskService.cancelPipelineTimedExec(id);
return HttpWrapper.ok();
}
@PostMapping("/terminate")
@ApiOperation(value = "停止执行任务")
@EventLog(EventType.TERMINATE_PIPELINE_TASK)
public HttpWrapper<?> terminateTask(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
applicationPipelineTaskService.terminateExec(id);
return HttpWrapper.ok();
}
@PostMapping("/terminate-detail")
@ApiOperation(value = "停止部分操作")
@EventLog(EventType.TERMINATE_PIPELINE_TASK_DETAIL)
public HttpWrapper<?> terminateTaskDetail(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
Long detailId = Valid.notNull(request.getDetailId());
applicationPipelineTaskService.terminateExecDetail(id, detailId);
return HttpWrapper.ok();
}
@PostMapping("/skip-detail")
@ApiOperation(value = "跳过部分操作")
@EventLog(EventType.SKIP_PIPELINE_TASK_DETAIL)
public HttpWrapper<?> skipTaskDetail(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
Long detailId = Valid.notNull(request.getDetailId());
applicationPipelineTaskService.skipExecDetail(id, detailId);
return HttpWrapper.ok();
}
@IgnoreLog
@PostMapping("/status")
@ApiOperation(value = "获取单个任务状态")
public ApplicationPipelineTaskStatusVO getTaskStatus(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
return applicationPipelineTaskService.getTaskStatus(id);
}
@IgnoreLog
@PostMapping("/list-status")
@ApiOperation(value = "获取多个任务状态")
public List<ApplicationPipelineTaskStatusVO> getTaskStatusList(@RequestBody ApplicationPipelineTaskRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return applicationPipelineTaskService.getTaskStatusList(idList, request.getDetailIdList());
}
@PostMapping("/log")
@ApiOperation(value = "获取任务日志")
public List<ApplicationPipelineTaskLogVO> getTaskLogList(@RequestBody ApplicationPipelineTaskRequest request) {
Long id = Valid.notNull(request.getId());
return applicationPipelineTaskLogService.getLogList(id);
}
}

View File

@@ -0,0 +1,87 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RequireRole;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.user.RoleType;
import cn.orionsec.ops.entity.request.app.ApplicationProfileRequest;
import cn.orionsec.ops.entity.vo.app.ApplicationProfileFastVO;
import cn.orionsec.ops.entity.vo.app.ApplicationProfileVO;
import cn.orionsec.ops.service.api.ApplicationProfileService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "应用环境")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-profile")
public class ApplicationProfileController {
@Resource
private ApplicationProfileService applicationProfileService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加应用环境")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.ADD_PROFILE)
public Long addProfile(@RequestBody ApplicationProfileRequest request) {
Valid.notBlank(request.getName());
Valid.notBlank(request.getTag());
Valid.in(request.getReleaseAudit(), Const.ENABLE, Const.DISABLE);
return applicationProfileService.addProfile(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "更新应用环境")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.UPDATE_PROFILE)
public Integer updateProfile(@RequestBody ApplicationProfileRequest request) {
Valid.notNull(request.getId());
if (request.getReleaseAudit() != null) {
Valid.in(request.getReleaseAudit(), Const.ENABLE, Const.DISABLE);
}
return applicationProfileService.updateProfile(request);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除应用环境")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.DELETE_PROFILE)
public Integer deleteProfile(@RequestBody ApplicationProfileRequest request) {
Long id = Valid.notNull(request.getId());
return applicationProfileService.deleteProfile(id);
}
@PostMapping("/list")
@ApiOperation(value = "获取应用环境列表")
public DataGrid<ApplicationProfileVO> listProfiles(@RequestBody ApplicationProfileRequest request) {
return applicationProfileService.listProfiles(request);
}
@GetMapping("/fast-list")
@ApiOperation(value = "获取应用环境列表 (缓存)")
public List<ApplicationProfileFastVO> listProfiles() {
return applicationProfileService.fastListProfiles();
}
@PostMapping("/detail")
@ApiOperation(value = "获取应用环境详情")
public ApplicationProfileVO getProfile(@RequestBody ApplicationProfileRequest request) {
Long id = Valid.notNull(request.getId());
return applicationProfileService.getProfile(id);
}
}

View File

@@ -0,0 +1,230 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.IgnoreLog;
import cn.orionsec.ops.annotation.RequireRole;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.app.ReleaseStatus;
import cn.orionsec.ops.constant.app.TimedType;
import cn.orionsec.ops.constant.common.AuditStatus;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.user.RoleType;
import cn.orionsec.ops.entity.request.app.ApplicationReleaseAuditRequest;
import cn.orionsec.ops.entity.request.app.ApplicationReleaseRequest;
import cn.orionsec.ops.entity.vo.app.*;
import cn.orionsec.ops.service.api.ApplicationReleaseService;
import cn.orionsec.ops.task.TaskRegister;
import cn.orionsec.ops.task.TaskType;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Api(tags = "应用发布")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-release")
public class ApplicationReleaseController {
@Resource
private ApplicationReleaseService applicationReleaseService;
@Resource
private TaskRegister taskRegister;
@PostMapping("/list")
@ApiOperation(value = "获取发布列表")
public DataGrid<ApplicationReleaseListVO> getReleaseList(@RequestBody ApplicationReleaseRequest request) {
return applicationReleaseService.getReleaseList(request);
}
@PostMapping("/list-machine")
@ApiOperation(value = "获取发布机器列表")
public List<ApplicationReleaseMachineVO> getReleaseMachineList(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getId());
return applicationReleaseService.getReleaseMachineList(id);
}
@PostMapping("/detail")
@ApiOperation(value = "获取发布详情")
public ApplicationReleaseDetailVO getReleaseDetail(@RequestBody ApplicationReleaseRequest request) {
Valid.notNull(request.getId());
return applicationReleaseService.getReleaseDetail(request);
}
@PostMapping("/machine-detail")
@ApiOperation(value = "获取发布机器详情")
public ApplicationReleaseMachineVO getReleaseMachineDetail(@RequestBody ApplicationReleaseRequest request) {
Long releaseMachineId = Valid.notNull(request.getReleaseMachineId());
return applicationReleaseService.getReleaseMachineDetail(releaseMachineId);
}
@PostMapping("/submit")
@ApiOperation(value = "提交发布任务")
@EventLog(EventType.SUBMIT_RELEASE)
public Long submitAppRelease(@RequestBody ApplicationReleaseRequest request) {
Valid.notBlank(request.getTitle());
Valid.notNull(request.getAppId());
Valid.notNull(request.getProfileId());
Valid.notNull(request.getBuildId());
Valid.notEmpty(request.getMachineIdList());
TimedType timedType = Valid.notNull(TimedType.of(request.getTimedRelease()));
if (TimedType.TIMED.equals(timedType)) {
Date timedReleaseTime = Valid.notNull(request.getTimedReleaseTime());
Valid.isTrue(timedReleaseTime.compareTo(new Date()) > 0, MessageConst.TIMED_GREATER_THAN_NOW);
}
// 提交
Long id = applicationReleaseService.submitAppRelease(request);
// 提交任务
if (ReleaseStatus.WAIT_SCHEDULE.getStatus().equals(request.getStatus())) {
taskRegister.submit(TaskType.RELEASE, request.getTimedReleaseTime(), id);
}
return id;
}
@PostMapping("/copy")
@ApiOperation(value = "复制发布任务")
@EventLog(EventType.COPY_RELEASE)
public Long copyAppRelease(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getId());
return applicationReleaseService.copyAppRelease(id);
}
@PostMapping("/audit")
@ApiOperation(value = "发布任务审核")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.AUDIT_RELEASE)
public Integer auditAppRelease(@RequestBody ApplicationReleaseAuditRequest request) {
Valid.notNull(request.getId());
AuditStatus status = Valid.notNull(AuditStatus.of(request.getStatus()));
if (AuditStatus.REJECT.equals(status)) {
Valid.notBlank(request.getReason());
}
return applicationReleaseService.auditAppRelease(request);
}
@PostMapping("/runnable")
@ApiOperation(value = "执行发布任务")
@EventLog(EventType.RUNNABLE_RELEASE)
public HttpWrapper<?> runnableAppRelease(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getId());
applicationReleaseService.runnableAppRelease(id, false, true);
return HttpWrapper.ok();
}
@PostMapping("/set-timed")
@ApiOperation(value = "设置定时发布")
@EventLog(EventType.SET_TIMED_RELEASE)
public HttpWrapper<?> setTimedRelease(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getId());
Date timedReleaseTime = Valid.notNull(request.getTimedReleaseTime());
Valid.isTrue(timedReleaseTime.compareTo(new Date()) > 0, MessageConst.TIMED_GREATER_THAN_NOW);
applicationReleaseService.setTimedRelease(id, timedReleaseTime);
return HttpWrapper.ok();
}
@PostMapping("/cancel-timed")
@ApiOperation(value = "取消定时发布")
@EventLog(EventType.CANCEL_TIMED_RELEASE)
public HttpWrapper<?> cancelTimedRelease(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getId());
applicationReleaseService.cancelAppTimedRelease(id);
return HttpWrapper.ok();
}
@PostMapping("/rollback")
@ApiOperation(value = "回滚发布")
@EventLog(EventType.ROLLBACK_RELEASE)
public Long rollbackAppRelease(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getId());
return applicationReleaseService.rollbackAppRelease(id);
}
@PostMapping("/terminate")
@EventLog(EventType.TERMINATE_RELEASE)
@ApiOperation(value = "停止发布任务")
public HttpWrapper<?> terminateAppRelease(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getId());
applicationReleaseService.terminateRelease(id);
return HttpWrapper.ok();
}
@PostMapping("/terminate-machine")
@ApiOperation(value = "停止机器发布操作")
@EventLog(EventType.TERMINATE_MACHINE_RELEASE)
public HttpWrapper<?> terminateMachine(@RequestBody ApplicationReleaseRequest request) {
Long releaseMachineId = Valid.notNull(request.getReleaseMachineId());
applicationReleaseService.terminateMachine(releaseMachineId);
return HttpWrapper.ok();
}
@PostMapping("/skip-machine")
@ApiOperation(value = "跳过机器发布操作")
@EventLog(EventType.SKIP_MACHINE_RELEASE)
public HttpWrapper<?> skipMachine(@RequestBody ApplicationReleaseRequest request) {
Long releaseMachineId = Valid.notNull(request.getReleaseMachineId());
applicationReleaseService.skipMachine(releaseMachineId);
return HttpWrapper.ok();
}
@PostMapping("/write-machine")
@ApiOperation(value = "机器操作输入命令")
public HttpWrapper<?> writeMachine(@RequestBody ApplicationReleaseRequest request) {
Long releaseMachineId = Valid.notNull(request.getReleaseMachineId());
String command = Valid.notEmpty(request.getCommand());
applicationReleaseService.writeMachine(releaseMachineId, command);
return HttpWrapper.ok();
}
@PostMapping("/delete")
@ApiOperation(value = "删除发布任务")
@EventLog(EventType.DELETE_RELEASE)
public Integer deleteAppRelease(@RequestBody ApplicationReleaseRequest request) {
List<Long> idList = Valid.notNull(request.getIdList());
return applicationReleaseService.deleteRelease(idList);
}
@IgnoreLog
@PostMapping("/list-status")
@ApiOperation(value = "获取发布状态列表")
public List<ApplicationReleaseStatusVO> getReleaseStatusList(@RequestBody ApplicationReleaseRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return applicationReleaseService.getReleaseStatusList(idList, request.getMachineIdList());
}
@IgnoreLog
@PostMapping("/status")
@ApiOperation(value = "获取发布状态")
public ApplicationReleaseStatusVO getReleaseStatus(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getId());
return applicationReleaseService.getReleaseStatus(id);
}
@IgnoreLog
@PostMapping("/list-machine-status")
@ApiOperation(value = "获取发布机器状态列表")
public List<ApplicationReleaseMachineStatusVO> getReleaseMachineStatusList(@RequestBody ApplicationReleaseRequest request) {
List<Long> idList = Valid.notEmpty(request.getReleaseMachineIdList());
return applicationReleaseService.getReleaseMachineStatusList(idList);
}
@IgnoreLog
@PostMapping("/machine-status")
@ApiOperation(value = "获取发布机器状态")
public ApplicationReleaseMachineStatusVO getReleaseMachineStatus(@RequestBody ApplicationReleaseRequest request) {
Long id = Valid.notNull(request.getReleaseMachineId());
return applicationReleaseService.getReleaseMachineStatus(id);
}
}

View File

@@ -0,0 +1,133 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.app.RepositoryAuthType;
import cn.orionsec.ops.constant.app.RepositoryTokenType;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.app.ApplicationRepositoryRequest;
import cn.orionsec.ops.entity.vo.app.ApplicationRepositoryBranchVO;
import cn.orionsec.ops.entity.vo.app.ApplicationRepositoryCommitVO;
import cn.orionsec.ops.entity.vo.app.ApplicationRepositoryInfoVO;
import cn.orionsec.ops.entity.vo.app.ApplicationRepositoryVO;
import cn.orionsec.ops.service.api.ApplicationRepositoryService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "应用版本仓库")
@RestController
@RestWrapper
@RequestMapping("/orion/api/app-repo")
public class ApplicationRepositoryController {
@Resource
private ApplicationRepositoryService applicationRepositoryService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加版本仓库")
@EventLog(EventType.ADD_REPOSITORY)
public Long addRepository(@RequestBody ApplicationRepositoryRequest request) {
Valid.allNotBlank(request.getName(), request.getUrl());
RepositoryAuthType authType = Valid.notNull(RepositoryAuthType.of(request.getAuthType()));
if (RepositoryAuthType.TOKEN.equals(authType)) {
Valid.notNull(RepositoryTokenType.of(request.getTokenType()));
Valid.notBlank(request.getPrivateToken());
}
return applicationRepositoryService.addRepository(request);
}
@DemoDisableApi
@ApiOperation(value = "更新版本仓库")
@PostMapping("/update")
@EventLog(EventType.UPDATE_REPOSITORY)
public Integer updateRepository(@RequestBody ApplicationRepositoryRequest request) {
Valid.notNull(request.getId());
Valid.allNotBlank(request.getName(), request.getUrl());
return applicationRepositoryService.updateRepository(request);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除版本仓库")
@EventLog(EventType.DELETE_REPOSITORY)
public Integer deleteRepository(@RequestBody ApplicationRepositoryRequest request) {
Long id = Valid.notNull(request.getId());
return applicationRepositoryService.deleteRepository(id);
}
@PostMapping("/list")
@ApiOperation(value = "获取版本仓库列表")
public DataGrid<ApplicationRepositoryVO> listRepository(@RequestBody ApplicationRepositoryRequest request) {
return applicationRepositoryService.listRepository(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取版本仓库详情")
public ApplicationRepositoryVO getRepositoryDetail(@RequestBody ApplicationRepositoryRequest request) {
Long id = Valid.notNull(request.getId());
return applicationRepositoryService.getRepositoryDetail(id);
}
@PostMapping("/init")
@ApiOperation(value = "初始化版本仓库")
@EventLog(EventType.INIT_REPOSITORY)
public HttpWrapper<?> initRepository(@RequestBody ApplicationRepositoryRequest request) {
Long id = Valid.notNull(request.getId());
applicationRepositoryService.initEventRepository(id, false);
return HttpWrapper.ok();
}
@PostMapping("/re-init")
@ApiOperation(value = "重新初始化版本仓库")
@EventLog(EventType.RE_INIT_REPOSITORY)
public HttpWrapper<?> reInitRepository(@RequestBody ApplicationRepositoryRequest request) {
Long id = Valid.notNull(request.getId());
applicationRepositoryService.initEventRepository(id, true);
return HttpWrapper.ok();
}
@ApiOperation(value = "获取分支和提交记录列表")
@PostMapping("/info")
public ApplicationRepositoryInfoVO getRepositoryInfo(@RequestBody ApplicationRepositoryRequest request) {
Valid.notNull(request.getId());
return applicationRepositoryService.getRepositoryInfo(request);
}
@PostMapping("/branch")
@ApiOperation(value = "获取分支列表")
public List<ApplicationRepositoryBranchVO> getRepositoryBranchList(@RequestBody ApplicationRepositoryRequest request) {
Long id = Valid.notNull(request.getId());
return applicationRepositoryService.getRepositoryBranchList(id);
}
@PostMapping("/commit")
@ApiOperation(value = "获取提交列表")
public List<ApplicationRepositoryCommitVO> getRepositoryCommitList(@RequestBody ApplicationRepositoryRequest request) {
Long id = Valid.notNull(request.getId());
String branchName = Valid.notBlank(request.getBranchName());
return applicationRepositoryService.getRepositoryCommitList(id, branchName);
}
@PostMapping("/clean")
@ApiOperation(value = "清空应用构建历史版本")
@EventLog(EventType.CLEAN_REPOSITORY)
public HttpWrapper<?> cleanBuildRepository(@RequestBody ApplicationRepositoryRequest request) {
Long id = Valid.notNull(request.getId());
applicationRepositoryService.cleanBuildRepository(id);
return HttpWrapper.ok();
}
}

View File

@@ -0,0 +1,77 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.utils.Objects1;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.web.servlet.web.Servlets;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.IgnoreAuth;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.user.UserLoginRequest;
import cn.orionsec.ops.entity.request.user.UserResetRequest;
import cn.orionsec.ops.entity.vo.user.UserInfoVO;
import cn.orionsec.ops.entity.vo.user.UserLoginVO;
import cn.orionsec.ops.service.api.PassportService;
import cn.orionsec.ops.utils.Currents;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@Api(tags = "用户认证")
@RestController
@RestWrapper
@RequestMapping("/orion/api/auth")
public class AuthenticateController {
@Resource
private PassportService passportService;
@IgnoreAuth
@PostMapping("/login")
@ApiOperation(value = "登录")
@EventLog(EventType.LOGIN)
public UserLoginVO login(@RequestBody UserLoginRequest login, HttpServletRequest request) {
String username = Valid.notBlank(login.getUsername()).trim();
String password = Valid.notBlank(login.getPassword()).trim();
login.setUsername(username);
login.setPassword(password);
login.setIp(Servlets.getRemoteAddr(request));
// 登录
return passportService.login(login);
}
@IgnoreAuth
@GetMapping("/logout")
@ApiOperation(value = "登出")
@EventLog(EventType.LOGOUT)
public HttpWrapper<?> logout() {
passportService.logout();
return HttpWrapper.ok();
}
@DemoDisableApi
@PostMapping("/reset")
@ApiOperation(value = "重置密码")
@EventLog(EventType.RESET_PASSWORD)
public HttpWrapper<?> resetPassword(@RequestBody UserResetRequest request) {
String password = Valid.notBlank(request.getPassword()).trim();
request.setUserId(Objects1.def(request.getUserId(), Currents::getUserId));
request.setPassword(password);
passportService.resetPassword(request);
return HttpWrapper.ok();
}
@GetMapping("/valid")
@ApiOperation(value = "检查用户信息")
public UserInfoVO validToken() {
return Converts.to(Currents.getUser(), UserInfoVO.class);
}
}

View File

@@ -0,0 +1,90 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.IgnoreLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.exec.CommandExecRequest;
import cn.orionsec.ops.entity.vo.exec.CommandExecStatusVO;
import cn.orionsec.ops.entity.vo.exec.CommandExecVO;
import cn.orionsec.ops.entity.vo.exec.CommandTaskSubmitVO;
import cn.orionsec.ops.service.api.CommandExecService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "批量执行")
@RestController
@RestWrapper
@RequestMapping("/orion/api/batch-exec")
public class BatchExecCommandController {
@Resource
private CommandExecService commandExecService;
@PostMapping("/submit")
@ApiOperation(value = "提交批量执行任务")
@EventLog(EventType.EXEC_SUBMIT)
public List<CommandTaskSubmitVO> submitTask(@RequestBody CommandExecRequest request) {
Valid.notBlank(request.getCommand());
Valid.notEmpty(request.getMachineIdList());
return commandExecService.batchSubmitTask(request);
}
@PostMapping("/list")
@ApiOperation(value = "获取执行列表")
public DataGrid<CommandExecVO> list(@RequestBody CommandExecRequest request) {
return commandExecService.execList(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取执行详情")
public CommandExecVO detail(@RequestBody CommandExecRequest request) {
Long id = Valid.notNull(request.getId());
return commandExecService.execDetail(id);
}
@PostMapping("/write")
@ApiOperation(value = "写入命令")
public void write(@RequestBody CommandExecRequest request) {
Long id = Valid.notNull(request.getId());
String command = Valid.notEmpty(request.getCommand());
commandExecService.writeCommand(id, command);
}
@PostMapping("/terminate")
@ApiOperation(value = "停止执行任务")
@EventLog(EventType.EXEC_TERMINATE)
public HttpWrapper<?> terminate(@RequestBody CommandExecRequest request) {
Long id = Valid.notNull(request.getId());
commandExecService.terminateExec(id);
return HttpWrapper.ok();
}
@PostMapping("/delete")
@ApiOperation(value = "删除任务")
@EventLog(EventType.EXEC_DELETE)
public Integer delete(@RequestBody CommandExecRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return commandExecService.deleteTask(idList);
}
@IgnoreLog
@PostMapping("/list-status")
@ApiOperation(value = "获取状态列表")
public List<CommandExecStatusVO> getListStatus(@RequestBody CommandExecRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return commandExecService.getExecStatusList(idList);
}
}

View File

@@ -0,0 +1,97 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.id.ObjectIds;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.io.Files1;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.system.SystemEnvAttr;
import cn.orionsec.ops.entity.dto.sftp.SftpUploadInfoDTO;
import cn.orionsec.ops.entity.request.sftp.FileUploadRequest;
import cn.orionsec.ops.entity.request.upload.BatchUploadRequest;
import cn.orionsec.ops.entity.vo.upload.BatchUploadCheckVO;
import cn.orionsec.ops.entity.vo.upload.BatchUploadTokenVO;
import cn.orionsec.ops.service.api.BatchUploadService;
import cn.orionsec.ops.service.api.SftpService;
import cn.orionsec.ops.utils.PathBuilders;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
@Api(tags = "批量上传")
@RestController
@RestWrapper
@RequestMapping("/orion/api/batch-upload")
public class BatchUploadController {
@Resource
private BatchUploadService batchUploadService;
@Resource
private SftpService sftpService;
@PostMapping("/check")
@ApiOperation(value = "检查机器以及文件")
public BatchUploadCheckVO checkFilePresent(@RequestBody BatchUploadRequest request) {
Valid.checkNormalize(request.getRemotePath());
Valid.notEmpty(request.getMachineIds());
Valid.notEmpty(request.getNames());
Valid.checkUploadSize(request.getSize());
return batchUploadService.checkMachineFiles(request);
}
@PostMapping("/token")
@ApiOperation(value = "获取上传token")
public BatchUploadTokenVO getUploadAccessToken(@RequestBody BatchUploadRequest request) {
Valid.checkNormalize(request.getRemotePath());
Valid.notEmpty(request.getMachineIds());
return batchUploadService.getUploadAccessToken(request);
}
@PostMapping("/exec")
@ApiOperation(value = "执行上传")
@EventLog(EventType.SFTP_UPLOAD)
public List<String> uploadFile(@RequestParam("accessToken") String accessToken, @RequestParam("files") List<MultipartFile> files) throws IOException {
// 检查文件
Valid.notBlank(accessToken);
Valid.notEmpty(files);
// 检查token
SftpUploadInfoDTO uploadInfo = sftpService.checkUploadAccessToken(accessToken);
String remotePath = uploadInfo.getRemotePath();
List<Long> machineIdList = uploadInfo.getMachineIdList();
List<FileUploadRequest> requestFiles = Lists.newList();
for (Long machineId : machineIdList) {
for (MultipartFile file : files) {
// 传输文件到本地
String fileToken = ObjectIds.nextId();
String localPath = PathBuilders.getSftpUploadFilePath(fileToken);
Path localAbsolutePath = Paths.get(SystemEnvAttr.SWAP_PATH.getValue(), localPath);
Files1.touch(localAbsolutePath);
file.transferTo(localAbsolutePath);
// 请求参数
FileUploadRequest request = new FileUploadRequest();
request.setMachineId(machineId);
request.setLocalPath(localPath);
request.setFileToken(fileToken);
request.setRemotePath(Files1.getPath(remotePath, file.getOriginalFilename()));
request.setSize(file.getSize());
requestFiles.add(request);
}
}
// 提交任务
return batchUploadService.batchUpload(requestFiles);
}
}

View File

@@ -0,0 +1,74 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.template.CommandTemplateRequest;
import cn.orionsec.ops.entity.vo.template.CommandTemplateVO;
import cn.orionsec.ops.service.api.CommandTemplateService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "命令模板")
@RestController
@RestWrapper
@RequestMapping("/orion/api/template")
public class CommandTemplateController {
@Resource
private CommandTemplateService commandTemplateService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "新增命令模板")
@EventLog(EventType.ADD_TEMPLATE)
public Long add(@RequestBody CommandTemplateRequest request) {
Valid.notBlank(request.getName());
Valid.notBlank(request.getValue());
return commandTemplateService.addTemplate(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改命令模板")
@EventLog(EventType.UPDATE_TEMPLATE)
public Integer update(@RequestBody CommandTemplateRequest request) {
Valid.notNull(request.getId());
Valid.notBlank(request.getValue());
return commandTemplateService.updateTemplate(request);
}
@PostMapping("/list")
@ApiOperation(value = "获取命令模板列表")
public DataGrid<CommandTemplateVO> list(@RequestBody CommandTemplateRequest request) {
return commandTemplateService.listTemplate(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取命令模板详情")
public CommandTemplateVO detail(@RequestBody CommandTemplateRequest request) {
Long id = Valid.notNull(request.getId());
return commandTemplateService.templateDetail(id);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除命令模板")
@EventLog(EventType.DELETE_TEMPLATE)
public Integer delete(@RequestBody CommandTemplateRequest request) {
List<Long> idList = Valid.notNull(request.getIdList());
return commandTemplateService.deleteTemplate(idList);
}
}

View File

@@ -0,0 +1,45 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.io.StreamReaders;
import cn.orionsec.ops.OrionApplication;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.user.RoleType;
import cn.orionsec.ops.entity.dto.user.UserDTO;
import cn.orionsec.ops.service.api.CommonService;
import cn.orionsec.ops.utils.Currents;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@Api(tags = "公共接口")
@RestController
@RestWrapper
@RequestMapping("/orion/api/common")
public class CommonController {
@Resource
private CommonService commonService;
@GetMapping("/menu")
@ApiOperation(value = "获取菜单")
public List<?> getMenu() throws IOException {
UserDTO user = Currents.getUser();
String menuFile = RoleType.of(user.getRoleType()).getMenuPath();
InputStream menu = OrionApplication.class.getResourceAsStream(menuFile);
if (menu == null) {
return Lists.empty();
}
return JSON.parseArray(new String(StreamReaders.readAllBytes(menu)));
}
}

View File

@@ -0,0 +1,91 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.DataClearRange;
import cn.orionsec.ops.constant.DataClearType;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.data.DataClearRequest;
import cn.orionsec.ops.service.api.DataClearService;
import cn.orionsec.ops.utils.EventParamsHolder;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "数据清理")
@RestController
@RestWrapper
@RequestMapping("/orion/api/data-clear")
public class DataClearController {
@Resource
private DataClearService dataClearService;
@PostMapping("/clear")
@ApiOperation(value = "清理数据")
@EventLog(EventType.DATA_CLEAR)
public Integer clearData(@RequestBody DataClearRequest request) {
// 检查参数
DataClearType dataClearType = this.validParams(request);
// 设置日志参数
EventParamsHolder.addParam(EventKeys.LABEL, dataClearType.getLabel());
// 清理
switch (dataClearType) {
case BATCH_EXEC:
return dataClearService.clearBatchExec(request);
case TERMINAL_LOG:
return dataClearService.clearTerminalLog(request);
case SCHEDULER_RECORD:
return dataClearService.clearSchedulerRecord(request);
case APP_BUILD:
Valid.notNull(request.getProfileId());
return dataClearService.clearAppBuild(request);
case APP_RELEASE:
Valid.notNull(request.getProfileId());
return dataClearService.clearAppRelease(request);
case APP_PIPELINE_EXEC:
Valid.notNull(request.getProfileId());
return dataClearService.clearAppPipeline(request);
case USER_EVENT_LOG:
return dataClearService.clearEventLog(request);
case MACHINE_ALARM_HISTORY:
Valid.notNull(request.getMachineId());
return dataClearService.clearMachineAlarmHistory(request);
default:
throw Exceptions.unsupported();
}
}
/**
* 验证参数
*
* @param request request
* @return clear type
*/
private DataClearType validParams(DataClearRequest request) {
DataClearRange range = Valid.notNull(DataClearRange.of(request.getRange()));
switch (range) {
case DAY:
Valid.gte(request.getReserveDay(), 0);
break;
case TOTAL:
Valid.gte(request.getReserveTotal(), 0);
break;
case REL_ID:
Valid.notEmpty(request.getRelIdList());
break;
default:
}
return Valid.notNull(DataClearType.of(request.getClearType()));
}
}

View File

@@ -0,0 +1,35 @@
package cn.orionsec.ops.controller;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import cn.orionsec.ops.handler.exporter.IDataExporter;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Api(tags = "数据导出")
@RestController
@RequestMapping("/orion/api/data-export")
public class DataExportController {
@DemoDisableApi
@PostMapping("/export")
@ApiOperation(value = "导出数据")
@EventLog(EventType.DATA_EXPORT)
public void exportData(@RequestBody DataExportRequest request, HttpServletResponse response) throws IOException {
ExportType exportType = Valid.notNull(ExportType.of(request.getExportType()));
IDataExporter.create(exportType, request, response).doExport();
}
}

View File

@@ -0,0 +1,108 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.io.Streams;
import cn.orionsec.kit.office.excel.Excels;
import cn.orionsec.kit.web.servlet.web.Servlets;
import cn.orionsec.ops.OrionApplication;
import cn.orionsec.ops.annotation.*;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.importer.DataImportDTO;
import cn.orionsec.ops.entity.request.data.DataImportRequest;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import cn.orionsec.ops.handler.importer.checker.IDataChecker;
import cn.orionsec.ops.handler.importer.impl.IDataImporter;
import cn.orionsec.ops.service.api.DataImportService;
import cn.orionsec.ops.utils.EventParamsHolder;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
@Api(tags = "数据导入")
@RestController
@RestWrapper
@RequestMapping("/orion/api/data-import")
public class DataImportController {
@Resource
private DataImportService dataImportService;
@IgnoreWrapper
@IgnoreLog
@IgnoreAuth
@GetMapping("/get-template")
@ApiOperation(value = "获取导入模板")
public void getTemplate(Integer type, HttpServletResponse response) throws IOException {
ImportType importType = Valid.notNull(ImportType.of(type));
String templateName = importType.getTemplateName();
Servlets.setAttachmentHeader(response, templateName);
// 读取文件
InputStream in = OrionApplication.class.getResourceAsStream(importType.getTemplatePath());
ServletOutputStream out = response.getOutputStream();
if (in == null) {
out.write(Strings.bytes(Strings.format(MessageConst.FILE_NOT_FOUND, templateName)));
return;
}
Streams.transfer(in, out);
}
@PostMapping("/check-data")
@ApiOperation(value = "检查导入信息")
public DataImportCheckVO checkImportData(@RequestParam("file") MultipartFile file,
@RequestParam("type") Integer type,
@RequestParam(name = "protectPassword", required = false) String protectPassword) throws IOException {
ImportType importType = Valid.notNull(ImportType.of(type));
Workbook workbook;
if (Strings.isBlank(protectPassword)) {
workbook = Excels.openWorkbook(file.getInputStream());
} else {
workbook = Excels.openWorkbook(file.getInputStream(), protectPassword);
}
// 检查数据
return IDataChecker.create(importType, workbook).doCheck();
}
@DemoDisableApi
@PostMapping("/import")
@ApiOperation(value = "导入数据")
@EventLog(EventType.DATA_IMPORT)
public HttpWrapper<?> importData(@RequestBody DataImportRequest request) {
String token = Valid.notNull(request.getImportToken());
// 读取导入数据
DataImportDTO importData = dataImportService.checkImportToken(token);
// 执行导入操作
IDataImporter.create(importData).doImport();
// 设置日志参数
ImportType importType = ImportType.of(importData.getType());
EventParamsHolder.addParam(EventKeys.TOKEN, token);
EventParamsHolder.addParam(EventKeys.TYPE, importType.getType());
EventParamsHolder.addParam(EventKeys.LABEL, importType.getLabel());
return HttpWrapper.ok();
}
@PostMapping("/cancel-import")
@ApiOperation(value = "取消导入")
public HttpWrapper<?> cancelImportData(@RequestBody DataImportRequest request) {
String token = request.getImportToken();
if (Strings.isBlank(token)) {
return HttpWrapper.ok();
}
dataImportService.clearImportToken(token);
return HttpWrapper.ok();
}
}

View File

@@ -0,0 +1,33 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.entity.request.user.EventLogRequest;
import cn.orionsec.ops.entity.vo.user.UserEventLogVO;
import cn.orionsec.ops.service.api.UserEventLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "操作日志")
@RestController
@RestWrapper
@RequestMapping("/orion/api/event-log")
public class EventLogController {
@Resource
private UserEventLogService userEventLogService;
@PostMapping("/list")
@ApiOperation(value = "获取操作日志列表")
public DataGrid<UserEventLogVO> getLogList(@RequestBody EventLogRequest request) {
return userEventLogService.getLogList(request);
}
}

View File

@@ -0,0 +1,52 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.exception.NotFoundException;
import cn.orionsec.kit.web.servlet.web.Servlets;
import cn.orionsec.ops.annotation.IgnoreAuth;
import cn.orionsec.ops.annotation.IgnoreWrapper;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.download.FileDownloadType;
import cn.orionsec.ops.entity.request.file.FileDownloadRequest;
import cn.orionsec.ops.service.api.FileDownloadService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Api(tags = "文件下载")
@RestController
@RestWrapper
@RequestMapping("/orion/api/file-download")
public class FileDownloadController {
@Resource
private FileDownloadService fileDownloadService;
@PostMapping("/token")
@ApiOperation(value = "检查并获取下载文件token")
public String getDownloadToken(@RequestBody FileDownloadRequest request) {
Long id = Valid.notNull(request.getId());
FileDownloadType type = Valid.notNull(FileDownloadType.of(request.getType()));
return fileDownloadService.getDownloadToken(id, type);
}
@IgnoreWrapper
@IgnoreAuth
@GetMapping("/{token}/exec")
@ApiOperation(value = "下载文件")
public void downloadLogFile(@PathVariable String token, HttpServletResponse response) throws IOException {
try {
fileDownloadService.execDownload(token, response);
} catch (NotFoundException e) {
// 文件未找到
Servlets.transfer(response, Const.EMPTY.getBytes(), Const.UNKNOWN);
}
}
}

View File

@@ -0,0 +1,168 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.utils.Charsets;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.io.Files1;
import cn.orionsec.kit.lang.utils.io.Streams;
import cn.orionsec.kit.web.servlet.web.Servlets;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.system.SystemEnvAttr;
import cn.orionsec.ops.constant.tail.FileTailType;
import cn.orionsec.ops.entity.request.file.FileTailRequest;
import cn.orionsec.ops.entity.vo.tail.FileTailConfigVO;
import cn.orionsec.ops.entity.vo.tail.FileTailVO;
import cn.orionsec.ops.service.api.FileTailService;
import cn.orionsec.ops.utils.Utils;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
@Api(tags = "日志文件tail")
@RestController
@RestWrapper
@RequestMapping("/orion/api/file-tail")
public class FileTailController {
@Resource
private FileTailService fileTailService;
@PostMapping("/token")
@ApiOperation(value = "检查并获取日志文件token")
public FileTailVO getTailToken(@RequestBody FileTailRequest request) {
FileTailType type = Valid.notNull(FileTailType.of(request.getType()));
Long relId = Valid.notNull(request.getRelId());
return fileTailService.getTailToken(type, relId);
}
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加日志文件")
@EventLog(EventType.ADD_TAIL_FILE)
public Long addTailFile(@RequestBody FileTailRequest request) {
Valid.notBlank(request.getName());
Valid.notNull(request.getMachineId());
Valid.notBlank(request.getPath());
Valid.notNull(request.getOffset());
Valid.notNull(request.getCharset());
Valid.isTrue(Files1.isPath(request.getPath()));
Valid.isTrue(Charsets.isSupported(request.getCharset()));
return fileTailService.insertTailFile(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改日志文件")
@EventLog(EventType.UPDATE_TAIL_FILE)
public Integer updateTailFile(@RequestBody FileTailRequest request) {
Valid.notNull(request.getId());
if (!Strings.isBlank(request.getPath())) {
Valid.isTrue(Files1.isPath(request.getPath()));
}
if (!Strings.isBlank(request.getCharset())) {
Valid.isTrue(Charsets.isSupported(request.getCharset()));
}
return fileTailService.updateTailFile(request);
}
@PostMapping("/upload")
@ApiOperation(value = "上传日志文件")
@EventLog(EventType.UPLOAD_TAIL_FILE)
public HttpWrapper<?> uploadFile(@RequestParam("files") List<MultipartFile> files) throws IOException {
// 检查文件
Valid.notEmpty(files);
List<FileTailRequest> requestFiles = Lists.newList();
for (MultipartFile file : files) {
String fileName = file.getOriginalFilename();
if (fileName == null) {
fileName = Utils.getRandomSuffix() + Const.DOT + Const.SUFFIX_LOG;
}
Path localAbsolutePath = Paths.get(SystemEnvAttr.TAIL_FILE_UPLOAD_PATH.getValue(), Utils.getRandomSuffix() + Const.DASHED + fileName);
Files1.touch(localAbsolutePath);
file.transferTo(localAbsolutePath);
// 设置文件数据
FileTailRequest request = new FileTailRequest();
request.setName(fileName);
request.setPath(Files1.getPath(localAbsolutePath.toString()));
requestFiles.add(request);
}
// 保存
fileTailService.uploadTailFiles(requestFiles);
return HttpWrapper.ok();
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除日志文件")
@EventLog(EventType.DELETE_TAIL_FILE)
public Integer deleteTailFile(@RequestBody FileTailRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return fileTailService.deleteTailFile(idList);
}
@PostMapping("/list")
@ApiOperation(value = "获取日志文件列表")
public DataGrid<FileTailVO> tailFileList(@RequestBody FileTailRequest request) {
return fileTailService.tailFileList(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取日志文件详情")
public FileTailVO tailFileDetail(@RequestBody FileTailRequest request) {
Long id = Valid.notNull(request.getId());
return fileTailService.tailFileDetail(id);
}
@PostMapping("/clean-ansi")
@ApiOperation(value = "清除ANSI码")
public void cleanAnsiCode(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws IOException {
// 设置 http 响应头
String fileName = file.getOriginalFilename();
if (fileName == null) {
fileName = Utils.getRandomSuffix() + Const.DOT + Const.SUFFIX_LOG;
}
Servlets.setAttachmentHeader(response, fileName);
// 读取文件
try (InputStream in = file.getInputStream()) {
byte[] bytes = Streams.toByteArray(in);
String clearValue = Utils.cleanStainAnsiCode(Strings.str(bytes));
ServletOutputStream out = response.getOutputStream();
out.write(Strings.bytes(clearValue));
out.flush();
}
}
@PostMapping("/config")
@ApiOperation(value = "获取机器默认配置")
public FileTailConfigVO getMachineConfig(@RequestBody FileTailRequest request) {
Long machineId = Valid.notNull(request.getMachineId());
return fileTailService.getMachineConfig(machineId);
}
@PostMapping("/write")
@ApiOperation(value = "写入命令")
public void write(@RequestBody FileTailRequest request) {
String token = Valid.notBlank(request.getToken());
String command = Valid.notEmpty(request.getCommand());
fileTailService.writeCommand(token, command);
}
}

View File

@@ -0,0 +1,48 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.history.HistoryValueType;
import cn.orionsec.ops.entity.request.history.HistoryValueRequest;
import cn.orionsec.ops.entity.vo.history.HistoryValueVO;
import cn.orionsec.ops.service.api.HistoryValueService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "历史值")
@RestController
@RestWrapper
@RequestMapping("/orion/api/history-value")
public class HistoryValueController {
@Resource
private HistoryValueService historyValueService;
@PostMapping("/list")
@ApiOperation(value = "历史值列表")
public DataGrid<HistoryValueVO> list(@RequestBody HistoryValueRequest request) {
Valid.notNull(request.getValueId());
Valid.notNull(HistoryValueType.of(request.getValueType()));
return historyValueService.list(request);
}
@DemoDisableApi
@PostMapping("/rollback")
@ApiOperation(value = "回滚历史值")
public HttpWrapper<?> rollback(@RequestBody HistoryValueRequest request) {
Long id = Valid.notNull(request.getId());
historyValueService.rollback(id);
return HttpWrapper.ok();
}
}

View File

@@ -0,0 +1,84 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.machine.MachineAlarmConfigRequest;
import cn.orionsec.ops.entity.request.machine.MachineAlarmHistoryRequest;
import cn.orionsec.ops.entity.vo.machine.MachineAlarmConfigWrapperVO;
import cn.orionsec.ops.entity.vo.machine.MachineAlarmHistoryVO;
import cn.orionsec.ops.service.api.MachineAlarmConfigService;
import cn.orionsec.ops.service.api.MachineAlarmHistoryService;
import cn.orionsec.ops.service.api.MachineAlarmService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "机器报警")
@RestController
@RestWrapper
@RequestMapping("/orion/api/machine-alarm")
public class MachineAlarmConfigController {
@Resource
private MachineAlarmConfigService machineAlarmConfigService;
@Resource
private MachineAlarmHistoryService machineAlarmHistoryService;
@Resource
private MachineAlarmService machineAlarmService;
@GetMapping("/get-config")
@ApiOperation(value = "获取报警配置")
public MachineAlarmConfigWrapperVO getAlarmConfig(@RequestParam("machineId") Long machineId) {
return machineAlarmConfigService.getAlarmConfigInfo(machineId);
}
@PostMapping("/set-alarm-config")
@ApiOperation(value = "设置报警配置")
@EventLog(EventType.SET_MACHINE_ALARM_CONFIG)
public HttpWrapper<?> setAlarmConfig(@RequestBody MachineAlarmConfigRequest request) {
Valid.notNull(request.getMachineId());
Valid.gte(request.getAlarmThreshold(), 0D, MessageConst.INVALID_PARAM);
Valid.gte(request.getTriggerThreshold(), 0, MessageConst.INVALID_PARAM);
Valid.gte(request.getNotifySilence(), 0, MessageConst.INVALID_PARAM);
machineAlarmConfigService.setAlarmConfig(request);
return HttpWrapper.ok();
}
@PostMapping("/set-group-config")
@ApiOperation(value = "设置报警联系组")
@EventLog(EventType.SET_MACHINE_ALARM_GROUP)
public HttpWrapper<?> setAlarmGroup(@RequestBody MachineAlarmConfigRequest request) {
Long machineId = Valid.notNull(request.getMachineId());
List<Long> groupIdList = Valid.notEmpty(request.getGroupIdList());
machineAlarmConfigService.setAlarmGroup(machineId, groupIdList);
return HttpWrapper.ok();
}
@PostMapping("/history")
@ApiOperation(value = "获取报警历史")
public DataGrid<MachineAlarmHistoryVO> getAlarmHistory(@RequestBody MachineAlarmHistoryRequest request) {
Valid.notNull(request.getMachineId());
return machineAlarmHistoryService.getAlarmHistory(request);
}
@PostMapping("/trigger-alarm-notify")
@ApiOperation(value = "触发报警通知")
@EventLog(EventType.RENOTIFY_MACHINE_ALARM_GROUP)
public HttpWrapper<?> triggerMachineAlarm(@RequestBody MachineAlarmHistoryRequest request) {
Long id = Valid.notNull(request.getId());
machineAlarmService.triggerMachineAlarm(id);
return HttpWrapper.ok();
}
}

View File

@@ -0,0 +1,122 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.collect.MutableLinkedHashMap;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.collect.Maps;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.env.EnvViewType;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.machine.MachineEnvRequest;
import cn.orionsec.ops.entity.vo.machine.MachineEnvVO;
import cn.orionsec.ops.service.api.MachineEnvService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Api(tags = "机器环境变量")
@RestController
@RestWrapper
@RequestMapping("/orion/api/machine-env")
public class MachineEnvController {
@Resource
private MachineEnvService machineEnvService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加环境变量")
public Long add(@RequestBody MachineEnvRequest request) {
Valid.notBlank(request.getKey());
Valid.notNull(request.getValue());
Valid.notNull(request.getMachineId());
return machineEnvService.addEnv(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改环境变量")
public Integer update(@RequestBody MachineEnvRequest request) {
Valid.notNull(request.getId());
Valid.notNull(request.getValue());
return machineEnvService.updateEnv(request);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除环境变量")
@EventLog(EventType.DELETE_MACHINE_ENV)
public Integer delete(@RequestBody MachineEnvRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return machineEnvService.deleteEnv(idList);
}
@PostMapping("/list")
@ApiOperation(value = "获取环境变量列表")
public DataGrid<MachineEnvVO> list(@RequestBody MachineEnvRequest request) {
Valid.notNull(request.getMachineId());
return machineEnvService.listEnv(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取环境变量详情")
public MachineEnvVO detail(@RequestBody MachineEnvRequest request) {
Long id = Valid.notNull(request.getId());
return machineEnvService.getEnvDetail(id);
}
@DemoDisableApi
@PostMapping("/sync")
@ApiOperation(value = "同步环境变量")
@EventLog(EventType.SYNC_MACHINE_ENV)
public HttpWrapper<?> sync(@RequestBody MachineEnvRequest request) {
Valid.notNull(request.getId());
Valid.notNull(request.getMachineId());
Valid.notEmpty(request.getTargetMachineIdList());
machineEnvService.syncMachineEnv(request);
return HttpWrapper.ok();
}
@PostMapping("/view")
@ApiOperation(value = "获取环境变量视图")
public String view(@RequestBody MachineEnvRequest request) {
Valid.notNull(request.getMachineId());
EnvViewType viewType = Valid.notNull(EnvViewType.of(request.getViewType()));
request.setLimit(Const.N_100000);
// 查询列表
Map<String, String> env = Maps.newLinkedMap();
machineEnvService.listEnv(request).forEach(e -> env.put(e.getKey(), e.getValue()));
return viewType.toValue(env);
}
@DemoDisableApi
@PostMapping("/view-save")
@ApiOperation(value = "保存环境变量视图")
public Integer viewSave(@RequestBody MachineEnvRequest request) {
Long machineId = Valid.notNull(request.getMachineId());
String value = Valid.notBlank(request.getValue());
EnvViewType viewType = Valid.notNull(EnvViewType.of(request.getViewType()));
try {
MutableLinkedHashMap<String, String> result = viewType.toMap(value);
machineEnvService.saveEnv(machineId, result);
return result.size();
} catch (Exception e) {
throw Exceptions.argument(MessageConst.PARSE_ERROR, e);
}
}
}

View File

@@ -0,0 +1,86 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.common.TreeMoveType;
import cn.orionsec.ops.entity.request.machine.MachineGroupRelRequest;
import cn.orionsec.ops.entity.request.machine.MachineGroupRequest;
import cn.orionsec.ops.entity.vo.machine.MachineGroupTreeVO;
import cn.orionsec.ops.service.api.MachineGroupRelService;
import cn.orionsec.ops.service.api.MachineGroupService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "机器分组")
@RestController
@RestWrapper
@RequestMapping("/orion/api/machine-group")
public class MachineGroupController {
@Resource
private MachineGroupService machineGroupService;
@Resource
private MachineGroupRelService machineGroupRelService;
@PostMapping("/add")
@ApiOperation(value = "添加分组")
public Long addGroup(@RequestBody MachineGroupRequest request) {
Valid.notNull(request.getParentId());
Valid.notBlank(request.getName());
return machineGroupService.addGroup(request);
}
@PostMapping("/delete")
@ApiOperation(value = "删除分组")
public Integer deleteGroup(@RequestBody MachineGroupRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return machineGroupService.deleteGroup(idList);
}
@PostMapping("/move")
@ApiOperation(value = "移动分组")
public HttpWrapper<?> moveGroup(@RequestBody MachineGroupRequest request) {
Valid.allNotNull(request.getId(), request.getTargetId(), TreeMoveType.of(request.getMoveType()));
machineGroupService.moveGroup(request);
return HttpWrapper.ok();
}
@PostMapping("/rename")
@ApiOperation(value = "修改分组名称")
public Integer renameGroup(@RequestBody MachineGroupRequest request) {
Long id = Valid.notNull(request.getId());
String name = Valid.notBlank(request.getName());
return machineGroupService.renameGroup(id, name);
}
@GetMapping("/tree")
@ApiOperation(value = "获取机器分组树")
public List<MachineGroupTreeVO> getRootTree() {
return machineGroupService.getRootTree();
}
@PostMapping("/add-machine")
@ApiOperation(value = "组内添加机器")
public HttpWrapper<?> addMachineRelByGroup(@RequestBody MachineGroupRelRequest request) {
Long groupId = Valid.notNull(request.getGroupId());
List<Long> machineIdList = Valid.notEmpty(request.getMachineIdList());
machineGroupRelService.addMachineRelByGroup(groupId, machineIdList);
return HttpWrapper.ok();
}
@PostMapping("/delete-machine")
@ApiOperation(value = "删除组内机器")
public Integer deleteByGroupMachineId(@RequestBody MachineGroupRelRequest request) {
List<Long> groupIdList = Valid.notEmpty(request.getGroupIdList());
List<Long> machineIdList = Valid.notEmpty(request.getMachineIdList());
return machineGroupRelService.deleteByGroupMachineId(groupIdList, machineIdList);
}
}

View File

@@ -0,0 +1,154 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.machine.MachineAuthType;
import cn.orionsec.ops.entity.request.machine.MachineInfoRequest;
import cn.orionsec.ops.entity.vo.machine.MachineInfoVO;
import cn.orionsec.ops.service.api.MachineInfoService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "机器信息")
@RestController
@RestWrapper
@RequestMapping("/orion/api/machine")
public class MachineInfoController {
@Resource
private MachineInfoService machineInfoService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加机器")
@EventLog(EventType.ADD_MACHINE)
public Long add(@RequestBody MachineInfoRequest request) {
this.check(request);
MachineAuthType machineAuthTypeEnum = Valid.notNull(MachineAuthType.of(request.getAuthType()));
if (MachineAuthType.PASSWORD.equals(machineAuthTypeEnum)) {
Valid.notBlank(request.getPassword());
}
return machineInfoService.addMachine(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改机器")
@EventLog(EventType.UPDATE_MACHINE)
public int update(@RequestBody MachineInfoRequest request) {
Valid.notNull(request.getId());
this.check(request);
return machineInfoService.updateMachine(request);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除机器")
@EventLog(EventType.DELETE_MACHINE)
public Integer delete(@RequestBody MachineInfoRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
// 设置日志参数
return machineInfoService.deleteMachine(idList);
}
@DemoDisableApi
@PostMapping("/update-status")
@ApiOperation(value = "停用/启用机器")
@EventLog(EventType.CHANGE_MACHINE_STATUS)
public Integer status(@RequestBody MachineInfoRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
Integer status = Valid.notNull(request.getStatus());
Valid.in(status, Const.ENABLE, Const.DISABLE);
return machineInfoService.updateStatus(idList, status);
}
@PostMapping("/list")
@ApiOperation(value = "获取机器列表")
public DataGrid<MachineInfoVO> list(@RequestBody MachineInfoRequest request) {
return machineInfoService.listMachine(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取机器详情")
public MachineInfoVO detail(@RequestBody MachineInfoRequest request) {
Long id = Valid.notNull(request.getId());
return machineInfoService.machineDetail(id);
}
@DemoDisableApi
@PostMapping("/copy")
@ApiOperation(value = "复制机器")
@EventLog(EventType.COPY_MACHINE)
public Long copy(@RequestBody MachineInfoRequest request) {
Long id = Valid.notNull(request.getId());
return machineInfoService.copyMachine(id);
}
@PostMapping("/test-ping")
@ApiOperation(value = "尝试ping机器")
public HttpWrapper<?> ping(@RequestBody MachineInfoRequest request) {
Long id = Valid.notNull(request.getId());
machineInfoService.testPing(id);
return HttpWrapper.ok();
}
@PostMapping("/test-connect")
@ApiOperation(value = "尝试连接机器")
public HttpWrapper<?> connect(@RequestBody MachineInfoRequest request) {
Long id = Valid.notNull(request.getId());
machineInfoService.testConnect(id);
return HttpWrapper.ok();
}
@PostMapping("/direct-test-ping")
@ApiOperation(value = "直接尝试ping机器")
public HttpWrapper<?> directPing(@RequestBody MachineInfoRequest request) {
String host = Valid.notBlank(request.getHost());
machineInfoService.testPing(host);
return HttpWrapper.ok();
}
@PostMapping("/direct-test-connect")
@ApiOperation(value = "直接尝试连接机器")
public HttpWrapper<?> directConnect(@RequestBody MachineInfoRequest request) {
Valid.allNotBlank(request.getHost(), request.getUsername());
Integer sshPort = Valid.notNull(request.getSshPort());
Valid.inRange(sshPort, 2, 65534, MessageConst.ABSENT_PARAM);
MachineAuthType authType = Valid.notNull(MachineAuthType.of(request.getAuthType()));
if (MachineAuthType.PASSWORD.equals(authType)) {
Valid.notBlank(request.getPassword());
} else if (MachineAuthType.SECRET_KEY.equals(authType)) {
Valid.notNull(request.getKeyId());
}
machineInfoService.testConnect(request);
return HttpWrapper.ok();
}
/**
* 合法校验
*/
private void check(MachineInfoRequest request) {
Valid.notBlank(request.getHost());
Integer sshPort = Valid.notNull(request.getSshPort());
Valid.inRange(sshPort, 2, 65534, MessageConst.ABSENT_PARAM);
Valid.notBlank(request.getName());
Valid.notBlank(request.getTag());
Valid.notBlank(request.getUsername());
}
}

View File

@@ -0,0 +1,85 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.machine.MachineKeyRequest;
import cn.orionsec.ops.entity.vo.machine.MachineSecretKeyVO;
import cn.orionsec.ops.service.api.MachineKeyService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "机器密钥")
@RestController
@RestWrapper
@RequestMapping("/orion/api/machine-key")
public class MachineKeyController {
@Resource
private MachineKeyService machineKeyService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加机器密钥")
@EventLog(EventType.ADD_MACHINE_KEY)
public Long addKey(@RequestBody MachineKeyRequest request) {
Valid.notBlank(request.getName());
Valid.notBlank(request.getFile());
return machineKeyService.addSecretKey(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "更新机器密钥")
@EventLog(EventType.UPDATE_MACHINE_KEY)
public Integer updateKey(@RequestBody MachineKeyRequest request) {
Valid.notNull(request.getId());
return machineKeyService.updateSecretKey(request);
}
@DemoDisableApi
@PostMapping("/remove")
@ApiOperation(value = "删除机器密钥")
@EventLog(EventType.DELETE_MACHINE_KEY)
public Integer removeKey(@RequestBody MachineKeyRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return machineKeyService.removeSecretKey(idList);
}
@PostMapping("/list")
@ApiOperation(value = "获取机器密钥列表")
public DataGrid<MachineSecretKeyVO> listKeys(@RequestBody MachineKeyRequest request) {
return machineKeyService.listKeys(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取机器密钥详情")
public MachineSecretKeyVO getKeyDetail(@RequestBody MachineKeyRequest request) {
Long id = Valid.notNull(request.getId());
return machineKeyService.getKeyDetail(id);
}
@DemoDisableApi
@PostMapping("/bind")
@ApiOperation(value = "绑定机器密钥")
@EventLog(EventType.BIND_MACHINE_KEY)
public HttpWrapper<?> bindMachineKey(@RequestBody MachineKeyRequest request) {
Long id = Valid.notNull(request.getId());
List<Long> machineIdList = Valid.notEmpty(request.getMachineIdList());
machineKeyService.bindMachineKey(id, machineIdList);
return HttpWrapper.ok();
}
}

View File

@@ -0,0 +1,75 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.utils.Booleans;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.machine.MachineMonitorRequest;
import cn.orionsec.ops.entity.vo.machine.MachineMonitorVO;
import cn.orionsec.ops.service.api.MachineMonitorService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Api(tags = "机器监控")
@RestController
@RestWrapper
@RequestMapping("/orion/api/monitor")
public class MachineMonitorController {
@Resource
private MachineMonitorService machineMonitorService;
@PostMapping("/list")
@ApiOperation(value = "查询监控列表")
public DataGrid<MachineMonitorVO> getMonitorList(@RequestBody MachineMonitorRequest request) {
return machineMonitorService.getMonitorList(request);
}
@GetMapping("/get-config")
@ApiOperation(value = "查询监控配置")
public MachineMonitorVO getMonitorConfig(@RequestParam Long machineId) {
return machineMonitorService.getMonitorConfig(machineId);
}
@PostMapping("/set-config")
@ApiOperation(value = "设置监控配置")
@EventLog(EventType.UPDATE_MACHINE_MONITOR_CONFIG)
public MachineMonitorVO setMonitorConfig(@RequestBody MachineMonitorRequest request) {
Valid.notNull(request.getId());
Valid.notBlank(request.getUrl());
Valid.notBlank(request.getAccessToken());
return machineMonitorService.updateMonitorConfig(request);
}
@PostMapping("/test")
@ApiOperation(value = "测试连接监控")
public String testConnect(@RequestBody MachineMonitorRequest request) {
String url = Valid.notBlank(request.getUrl());
String accessToken = Valid.notBlank(request.getAccessToken());
return machineMonitorService.getMonitorVersion(url, accessToken);
}
@DemoDisableApi
@PostMapping("/install")
@ApiOperation(value = "安装监控插件")
@EventLog(EventType.INSTALL_UPGRADE_MACHINE_MONITOR)
public MachineMonitorVO installMonitorAgent(@RequestBody MachineMonitorRequest request) {
Long machineId = Valid.notNull(request.getMachineId());
return machineMonitorService.installMonitorAgent(machineId, Booleans.isTrue(request.getUpgrade()));
}
@PostMapping("/check")
@ApiOperation(value = "检查监控插件状态")
public MachineMonitorVO checkMonitorStatus(@RequestBody MachineMonitorRequest request) {
Long machineId = Valid.notNull(request.getMachineId());
return machineMonitorService.checkMonitorStatus(machineId);
}
}

View File

@@ -0,0 +1,95 @@
package cn.orionsec.ops.controller;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.entity.request.machine.MachineMonitorEndpointRequest;
import cn.orionsec.ops.service.api.MachineMonitorEndpointService;
import cn.orionsec.ops.utils.Valid;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Api(tags = "机器监控端点")
@RestController
@RestWrapper
@RequestMapping("/orion/api/monitor-endpoint")
public class MachineMonitorEndpointController {
@Resource
private MachineMonitorEndpointService machineMonitorEndpointService;
@GetMapping("/ping")
@ApiOperation(value = "ping")
public Integer sendPing(@RequestParam("machineId") Long machineId) {
return machineMonitorEndpointService.ping(machineId);
}
@GetMapping("/metrics")
@ApiOperation(value = "获取机器基本指标")
public JSONObject getBaseMetrics(@RequestParam("machineId") Long machineId) {
return machineMonitorEndpointService.getBaseMetrics(machineId);
}
@GetMapping("/load")
@ApiOperation(value = "获取系统负载")
public JSONObject getSystemLoad(@RequestParam("machineId") Long machineId) {
return machineMonitorEndpointService.getSystemLoad(machineId);
}
@GetMapping("/top")
@ApiOperation(value = "获取top进程")
public JSONArray getTopProcesses(@RequestParam("machineId") Long machineId, String name) {
return machineMonitorEndpointService.getTopProcesses(machineId, name);
}
@GetMapping("/disk-name")
@ApiOperation(value = "获取磁盘名称")
public JSONArray getCpuStatistics(@RequestParam("machineId") Long machineId) {
return machineMonitorEndpointService.getDiskName(machineId);
}
@PostMapping("/chart-cpu")
@ApiOperation(value = "获取cpu图表")
public JSONObject getCpuStatistics(@RequestBody MachineMonitorEndpointRequest request) {
this.validChartParams(request);
return machineMonitorEndpointService.getCpuChart(request);
}
@PostMapping("/chart-memory")
@ApiOperation(value = "获取内存图表")
public JSONObject getMemoryStatistics(@RequestBody MachineMonitorEndpointRequest request) {
this.validChartParams(request);
return machineMonitorEndpointService.getMemoryChart(request);
}
@PostMapping("/chart-net")
@ApiOperation(value = "获取网络图表")
public JSONObject getNetStatistics(@RequestBody MachineMonitorEndpointRequest request) {
this.validChartParams(request);
return machineMonitorEndpointService.getNetChart(request);
}
@PostMapping("/chart-disk")
@ApiOperation(value = "获取磁盘图表")
public JSONObject getDiskStatistics(@RequestBody MachineMonitorEndpointRequest request) {
this.validChartParams(request);
return machineMonitorEndpointService.getDiskChart(request);
}
/**
* 验证参数
*
* @param request request
*/
private void validChartParams(MachineMonitorEndpointRequest request) {
Valid.notNull(request.getMachineId());
Valid.notNull(request.getGranularity());
Valid.notNull(request.getStartRange());
Valid.notNull(request.getEndRange());
}
}

View File

@@ -0,0 +1,88 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.machine.ProxyType;
import cn.orionsec.ops.entity.request.machine.MachineProxyRequest;
import cn.orionsec.ops.entity.vo.machine.MachineProxyVO;
import cn.orionsec.ops.service.api.MachineProxyService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "机器代理")
@RestController
@RestWrapper
@RequestMapping("/orion/api/machine-proxy")
public class MachineProxyController {
@Resource
private MachineProxyService machineProxyService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加机器代理")
@EventLog(EventType.ADD_MACHINE_PROXY)
public Long addProxy(@RequestBody MachineProxyRequest request) {
request.setId(null);
this.check(request);
if (!Strings.isBlank(request.getUsername())) {
Valid.notNull(request.getPassword());
}
return machineProxyService.addProxy(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改机器代理")
@EventLog(EventType.UPDATE_MACHINE_PROXY)
public Integer update(@RequestBody MachineProxyRequest request) {
Valid.notNull(request.getId());
this.check(request);
return machineProxyService.updateProxy(request);
}
@PostMapping("/list")
@ApiOperation(value = "获取机器代理列表")
public DataGrid<MachineProxyVO> list(@RequestBody MachineProxyRequest request) {
return machineProxyService.listProxy(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取机器代理详情")
public MachineProxyVO detail(@RequestBody MachineProxyRequest request) {
Long id = Valid.notNull(request.getId());
return machineProxyService.getProxyDetail(id);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除机器代理")
@EventLog(EventType.DELETE_MACHINE_PROXY)
public Integer delete(@RequestBody MachineProxyRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return machineProxyService.deleteProxy(idList);
}
/**
* 合法校验
*/
private void check(MachineProxyRequest request) {
Valid.notBlank(request.getHost());
Valid.notNull(request.getPort());
Valid.notNull(ProxyType.of(request.getType()));
}
}

View File

@@ -0,0 +1,142 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.codec.Base64s;
import cn.orionsec.kit.lang.utils.io.FileReaders;
import cn.orionsec.kit.net.host.ssh.TerminalType;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RequireRole;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.ResultCode;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.user.RoleType;
import cn.orionsec.ops.entity.request.machine.MachineTerminalLogRequest;
import cn.orionsec.ops.entity.request.machine.MachineTerminalManagerRequest;
import cn.orionsec.ops.entity.request.machine.MachineTerminalRequest;
import cn.orionsec.ops.entity.vo.machine.*;
import cn.orionsec.ops.handler.terminal.manager.TerminalSessionManager;
import cn.orionsec.ops.service.api.MachineTerminalService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
@Api(tags = "机器终端")
@RestController
@RestWrapper
@RequestMapping("/orion/api/terminal")
public class MachineTerminalController {
@Resource
private MachineTerminalService machineTerminalService;
@Resource
private TerminalSessionManager terminalSessionManager;
@PostMapping("/access")
@ApiOperation(value = "获取终端accessToken")
@EventLog(EventType.OPEN_TERMINAL)
public TerminalAccessVO getTerminalAccessToken(@RequestBody MachineTerminalRequest request) {
Long machineId = Valid.notNull(request.getMachineId());
return machineTerminalService.getAccessConfig(machineId);
}
@GetMapping("/support/pty")
@ApiOperation(value = "获取支持的终端类型")
public String[] getSupportedPty() {
return Arrays.stream(TerminalType.values())
.map(TerminalType::getType)
.toArray(String[]::new);
}
@GetMapping("/get/{machineId}")
@ApiOperation(value = "获取终端配置")
public MachineTerminalVO getSetting(@PathVariable Long machineId) {
return machineTerminalService.getMachineConfig(machineId);
}
@PostMapping("/update")
@ApiOperation(value = "修改终端配置")
@EventLog(EventType.UPDATE_TERMINAL_CONFIG)
public Integer updateSetting(@RequestBody MachineTerminalRequest request) {
Valid.notNull(request.getId());
String terminalType = request.getTerminalType();
if (!Strings.isBlank(terminalType)) {
Valid.notNull(TerminalType.of(terminalType), MessageConst.INVALID_PTY);
}
if (request.getEnableWebLink() != null) {
Valid.in(request.getEnableWebLink(), Const.ENABLE, Const.DISABLE);
}
return machineTerminalService.updateSetting(request);
}
@PostMapping("/log/list")
@ApiOperation(value = "获取终端日志列表")
public DataGrid<MachineTerminalLogVO> accessLogList(@RequestBody MachineTerminalLogRequest request) {
return machineTerminalService.listAccessLog(request);
}
@PostMapping("/log/delete")
@ApiOperation(value = "删除终端日志")
@EventLog(EventType.DELETE_TERMINAL_LOG)
public Integer deleteLog(@RequestBody MachineTerminalLogRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return machineTerminalService.deleteTerminalLog(idList);
}
@PostMapping("/log/screen")
@ApiOperation(value = "获取终端录屏文件 base64")
public String getLogScreen(@RequestBody MachineTerminalLogRequest request) {
Long id = Valid.notNull(request.getId());
String path = machineTerminalService.getTerminalScreenFilePath(id);
if (path == null) {
throw Exceptions.httpWrapper(HttpWrapper.of(ResultCode.FILE_MISSING));
}
Path file = Paths.get(path);
if (!Files.exists(file)) {
throw Exceptions.httpWrapper(HttpWrapper.of(ResultCode.FILE_MISSING));
}
return Base64s.encodeToString(FileReaders.readAllBytesFast(path));
}
@PostMapping("/manager/session")
@ApiOperation(value = "获取终端会话列表")
@RequireRole(RoleType.ADMINISTRATOR)
public DataGrid<MachineTerminalManagerVO> sessionList(@RequestBody MachineTerminalManagerRequest request) {
return terminalSessionManager.getOnlineTerminal(request);
}
@DemoDisableApi
@PostMapping("/manager/offline")
@ApiOperation(value = "强制下线终端会话")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.FORCE_OFFLINE_TERMINAL)
public void forceOffline(@RequestBody MachineTerminalManagerRequest request) {
String token = Valid.notBlank(request.getToken());
terminalSessionManager.forceOffline(token);
}
@PostMapping("/manager/watcher")
@ApiOperation(value = "获取终端监视token")
@RequireRole(RoleType.ADMINISTRATOR)
public TerminalWatcherVO getTerminalWatcherToken(@RequestBody MachineTerminalManagerRequest request) {
String token = Valid.notBlank(request.getToken());
Integer readonly = Valid.notNull(request.getReadonly());
return terminalSessionManager.getWatcherToken(token, readonly);
}
}

View File

@@ -0,0 +1,118 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.time.cron.Cron;
import cn.orionsec.kit.lang.utils.time.cron.CronSupport;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.scheduler.SchedulerTaskRequest;
import cn.orionsec.ops.entity.vo.scheduler.CronNextVO;
import cn.orionsec.ops.entity.vo.scheduler.SchedulerTaskVO;
import cn.orionsec.ops.service.api.SchedulerTaskService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "调度任务")
@RestController
@RestWrapper
@RequestMapping("/orion/api/scheduler")
public class SchedulerController {
@Resource
private SchedulerTaskService schedulerTaskService;
@PostMapping("/cron-next")
@ApiOperation(value = "获取cron下几次执行时间")
public CronNextVO getCronNextTime(@RequestBody SchedulerTaskRequest request) {
String cron = Valid.notBlank(request.getExpression()).trim();
Integer times = Valid.gt(request.getTimes(), 0);
CronNextVO next = new CronNextVO();
try {
next.setNext(CronSupport.getNextTime(Cron.of(cron), times));
next.setValid(true);
} catch (Exception e) {
next.setNext(Lists.empty());
next.setValid(false);
}
return next;
}
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加调度任务")
@EventLog(EventType.ADD_SCHEDULER_TASK)
public Long addTask(@RequestBody SchedulerTaskRequest request) {
Valid.allNotBlank(request.getName(), request.getCommand(), request.getExpression());
Cron.of(request.getExpression());
Valid.notNull(request.getSerializeType());
Valid.notEmpty(request.getMachineIdList());
return schedulerTaskService.addTask(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改调度任务")
@EventLog(EventType.UPDATE_SCHEDULER_TASK)
public Integer updateTask(@RequestBody SchedulerTaskRequest request) {
Valid.notNull(request.getId());
Valid.allNotBlank(request.getName(), request.getCommand(), request.getExpression());
Cron.of(request.getExpression());
Valid.notEmpty(request.getMachineIdList());
return schedulerTaskService.updateTask(request);
}
@PostMapping("/get")
@ApiOperation(value = "获取调度任务详情")
public SchedulerTaskVO getTaskDetail(@RequestBody SchedulerTaskRequest request) {
Long id = Valid.notNull(request.getId());
return schedulerTaskService.getTaskDetail(id);
}
@PostMapping("/list")
@ApiOperation(value = "获取调度任务列表")
public DataGrid<SchedulerTaskVO> getTaskList(@RequestBody SchedulerTaskRequest request) {
return schedulerTaskService.getTaskList(request);
}
@DemoDisableApi
@PostMapping("/update-status")
@ApiOperation(value = "更新调度任务状态")
@EventLog(EventType.UPDATE_SCHEDULER_TASK_STATUS)
public Integer updateTaskStatus(@RequestBody SchedulerTaskRequest request) {
Long id = Valid.notNull(request.getId());
Integer status = Valid.in(request.getEnableStatus(), Const.ENABLE, Const.DISABLE);
return schedulerTaskService.updateTaskStatus(id, status);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除调度任务")
@EventLog(EventType.DELETE_SCHEDULER_TASK)
public Integer deleteTask(@RequestBody SchedulerTaskRequest request) {
Long id = Valid.notNull(request.getId());
return schedulerTaskService.deleteTask(id);
}
@PostMapping("/manual-trigger")
@ApiOperation(value = "手动触发调度任务")
@EventLog(EventType.MANUAL_TRIGGER_SCHEDULER_TASK)
public HttpWrapper<?> manualTriggerTask(@RequestBody SchedulerTaskRequest request) {
Long id = Valid.notNull(request.getId());
schedulerTaskService.manualTriggerTask(id);
return HttpWrapper.ok();
}
}

View File

@@ -0,0 +1,116 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.IgnoreLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.scheduler.SchedulerTaskRecordRequest;
import cn.orionsec.ops.entity.vo.scheduler.SchedulerTaskMachineRecordStatusVO;
import cn.orionsec.ops.entity.vo.scheduler.SchedulerTaskMachineRecordVO;
import cn.orionsec.ops.entity.vo.scheduler.SchedulerTaskRecordStatusVO;
import cn.orionsec.ops.entity.vo.scheduler.SchedulerTaskRecordVO;
import cn.orionsec.ops.service.api.SchedulerTaskRecordService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "调度任务执行明细")
@RestController
@RestWrapper
@RequestMapping("/orion/api/scheduler-record")
public class SchedulerRecordController {
@Resource
private SchedulerTaskRecordService schedulerTaskRecordService;
@PostMapping("/list")
@ApiOperation(value = "获取调度任务执行列表")
public DataGrid<SchedulerTaskRecordVO> listRecord(@RequestBody SchedulerTaskRecordRequest request) {
return schedulerTaskRecordService.listTaskRecord(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取调度任务执行详情")
public SchedulerTaskRecordVO getRecordDetail(@RequestBody SchedulerTaskRecordRequest request) {
Long id = Valid.notNull(request.getId());
return schedulerTaskRecordService.getDetailById(id);
}
@PostMapping("/machines")
@ApiOperation(value = "查询调度任务执行机器")
public List<SchedulerTaskMachineRecordVO> listMachinesRecord(@RequestBody SchedulerTaskRecordRequest request) {
Long recordId = Valid.notNull(request.getRecordId());
return schedulerTaskRecordService.listMachinesRecord(recordId);
}
@IgnoreLog
@PostMapping("/list-status")
@ApiOperation(value = "查询调度任务执行状态")
public List<SchedulerTaskRecordStatusVO> listRecordStatus(@RequestBody SchedulerTaskRecordRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return schedulerTaskRecordService.listRecordStatus(idList, request.getMachineRecordIdList());
}
@IgnoreLog
@PostMapping("/machines-status")
@ApiOperation(value = "查询调度任务机器执行状态")
public List<SchedulerTaskMachineRecordStatusVO> listMachineRecordStatus(@RequestBody SchedulerTaskRecordRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return schedulerTaskRecordService.listMachineRecordStatus(idList);
}
@PostMapping("/delete")
@ApiOperation(value = "删除调度任务明细")
@EventLog(EventType.DELETE_TASK_RECORD)
public Integer deleteRecord(@RequestBody SchedulerTaskRecordRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return schedulerTaskRecordService.deleteTaskRecord(idList);
}
@PostMapping("/terminate-all")
@ApiOperation(value = "停止执行调度任务")
@EventLog(EventType.TERMINATE_ALL_SCHEDULER_TASK)
public HttpWrapper<?> terminateAll(@RequestBody SchedulerTaskRecordRequest request) {
Long id = Valid.notNull(request.getId());
schedulerTaskRecordService.terminateAll(id);
return HttpWrapper.ok();
}
@PostMapping("/terminate-machine")
@ApiOperation(value = "停止单台机器执行调度任务")
@EventLog(EventType.TERMINATE_SCHEDULER_TASK_MACHINE)
public HttpWrapper<?> terminateMachine(@RequestBody SchedulerTaskRecordRequest request) {
Long machineRecordId = Valid.notNull(request.getMachineRecordId());
schedulerTaskRecordService.terminateMachine(machineRecordId);
return HttpWrapper.ok();
}
@PostMapping("/skip-machine")
@ApiOperation(value = "跳过单台机器执行调度任务")
@EventLog(EventType.SKIP_SCHEDULER_TASK_MACHINE)
public HttpWrapper<?> skipMachine(@RequestBody SchedulerTaskRecordRequest request) {
Long machineRecordId = Valid.notNull(request.getMachineRecordId());
schedulerTaskRecordService.skipMachine(machineRecordId);
return HttpWrapper.ok();
}
@PostMapping("/write-machine")
@ApiOperation(value = "写入命令")
public HttpWrapper<?> writeMachine(@RequestBody SchedulerTaskRecordRequest request) {
Long machineRecordId = Valid.notNull(request.getMachineRecordId());
String command = Valid.notEmpty(request.getCommand());
schedulerTaskRecordService.writeMachine(machineRecordId, command);
return HttpWrapper.ok();
}
}

View File

@@ -0,0 +1,329 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.id.ObjectIds;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.io.Files1;
import cn.orionsec.kit.net.host.sftp.SftpErrorMessage;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.sftp.SftpPackageType;
import cn.orionsec.ops.constant.system.SystemEnvAttr;
import cn.orionsec.ops.entity.dto.sftp.SftpSessionTokenDTO;
import cn.orionsec.ops.entity.dto.sftp.SftpUploadInfoDTO;
import cn.orionsec.ops.entity.request.sftp.*;
import cn.orionsec.ops.entity.vo.sftp.FileListVO;
import cn.orionsec.ops.entity.vo.sftp.FileOpenVO;
import cn.orionsec.ops.entity.vo.sftp.FileTransferLogVO;
import cn.orionsec.ops.service.api.SftpService;
import cn.orionsec.ops.utils.Currents;
import cn.orionsec.ops.utils.PathBuilders;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
@Api(tags = "sftp操作")
@RestController
@RestWrapper
@RequestMapping("/orion/api/sftp")
public class SftpController {
@Resource
private SftpService sftpService;
@PostMapping("/open")
@ApiOperation(value = "打开sftp")
@EventLog(EventType.OPEN_SFTP)
public FileOpenVO open(@RequestBody FileOpenRequest request) {
Long machineId = Valid.notNull(request.getMachineId());
return sftpService.open(machineId);
}
@PostMapping("/list")
@ApiOperation(value = "获取文件列表")
public FileListVO list(@RequestBody FileListRequest request) {
Valid.checkNormalize(request.getPath());
try {
return sftpService.list(request);
} catch (RuntimeException e) {
throw this.convertError(e);
}
}
@PostMapping("/list-dir")
@ApiOperation(value = "获取文件夹列表")
public FileListVO listDir(@RequestBody FileListRequest request) {
Valid.checkNormalize(request.getPath());
try {
return sftpService.listDir(request);
} catch (RuntimeException e) {
throw this.convertError(e);
}
}
@PostMapping("/mkdir")
@ApiOperation(value = "创建文件夹")
@EventLog(EventType.SFTP_MKDIR)
public String mkdir(@RequestBody FileMkdirRequest request) {
Valid.checkNormalize(request.getPath());
return sftpService.mkdir(request);
}
@PostMapping("/touch")
@ApiOperation(value = "创建文件")
@EventLog(EventType.SFTP_TOUCH)
public String touch(@RequestBody FileTouchRequest request) {
Valid.checkNormalize(request.getPath());
return sftpService.touch(request);
}
@PostMapping("/truncate")
@ApiOperation(value = "截断文件")
@EventLog(EventType.SFTP_TRUNCATE)
public void truncate(@RequestBody FileTruncateRequest request) {
Valid.checkNormalize(request.getPath());
try {
sftpService.truncate(request);
} catch (RuntimeException e) {
throw this.convertError(e);
}
}
@PostMapping("/move")
@ApiOperation(value = "移动文件")
@EventLog(EventType.SFTP_MOVE)
public String move(@RequestBody FileMoveRequest request) {
Valid.checkNormalize(request.getSource());
Valid.notBlank(request.getTarget());
try {
return sftpService.move(request);
} catch (RuntimeException e) {
throw this.convertError(e);
}
}
@PostMapping("/remove")
@ApiOperation(value = "删除文件/文件夹")
@EventLog(EventType.SFTP_REMOVE)
public void remove(@RequestBody FileRemoveRequest request) {
List<String> paths = Valid.notEmpty(request.getPaths());
paths.forEach(Valid::checkNormalize);
boolean isSafe = paths.stream().noneMatch(Const.UNSAFE_FS_DIR::contains);
Valid.isSafe(isSafe);
try {
sftpService.remove(request);
} catch (RuntimeException e) {
throw this.convertError(e);
}
}
@PostMapping("/chmod")
@ApiOperation(value = "修改权限")
@EventLog(EventType.SFTP_CHMOD)
public String chmod(@RequestBody FileChmodRequest request) {
Valid.checkNormalize(request.getPath());
Valid.notNull(request.getPermission());
try {
return sftpService.chmod(request);
} catch (RuntimeException e) {
throw this.convertError(e);
}
}
@PostMapping("/chown")
@ApiOperation(value = "修改所有者")
@EventLog(EventType.SFTP_CHOWN)
public void chown(@RequestBody FileChownRequest request) {
Valid.checkNormalize(request.getPath());
Valid.notNull(request.getUid());
try {
sftpService.chown(request);
} catch (RuntimeException e) {
throw this.convertError(e);
}
}
@PostMapping("/chgrp")
@ApiOperation(value = "修改所有组")
@EventLog(EventType.SFTP_CHGRP)
public void changeGroup(@RequestBody FileChangeGroupRequest request) {
Valid.checkNormalize(request.getPath());
Valid.notNull(request.getGid());
try {
sftpService.changeGroup(request);
} catch (RuntimeException e) {
throw this.convertError(e);
}
}
@PostMapping("/check-present")
@ApiOperation(value = "检查文件是否存在")
public List<String> checkFilePresent(@RequestBody FilePresentCheckRequest request) {
Valid.checkNormalize(request.getPath());
Valid.notEmpty(request.getNames());
Valid.checkUploadSize(request.getSize());
return sftpService.checkFilePresent(request);
}
@PostMapping("/upload/token")
@ApiOperation(value = "获取上传文件accessToken")
public String getUploadAccessToken(@RequestBody FileUploadRequest request) {
return sftpService.getUploadAccessToken(request);
}
@PostMapping("/upload/exec")
@ApiOperation(value = "上传文件")
@EventLog(EventType.SFTP_UPLOAD)
public void uploadFile(@RequestParam("accessToken") String accessToken, @RequestParam("files") List<MultipartFile> files) throws IOException {
// 检查文件
Valid.notBlank(accessToken);
Valid.notEmpty(files);
// 检查token
SftpUploadInfoDTO uploadInfo = sftpService.checkUploadAccessToken(accessToken);
Long machineId = uploadInfo.getMachineId();
String remotePath = uploadInfo.getRemotePath();
List<FileUploadRequest> requestFiles = Lists.newList();
for (MultipartFile file : files) {
// 传输文件到本地
String fileToken = ObjectIds.nextId();
String localPath = PathBuilders.getSftpUploadFilePath(fileToken);
Path localAbsolutePath = Paths.get(SystemEnvAttr.SWAP_PATH.getValue(), localPath);
Files1.touch(localAbsolutePath);
file.transferTo(localAbsolutePath);
// 提交任务
FileUploadRequest request = new FileUploadRequest();
request.setMachineId(machineId);
request.setFileToken(fileToken);
request.setLocalPath(localPath);
request.setRemotePath(Files1.getPath(remotePath, file.getOriginalFilename()));
request.setSize(file.getSize());
requestFiles.add(request);
}
sftpService.upload(machineId, requestFiles);
}
@PostMapping("/download/exec")
@ApiOperation(value = "下载文件")
@EventLog(EventType.SFTP_DOWNLOAD)
public void downloadFile(@RequestBody FileDownloadRequest request) {
List<String> paths = Valid.notEmpty(request.getPaths());
paths.forEach(Valid::checkNormalize);
sftpService.download(request);
}
@PostMapping("/package-download/exec")
@ApiOperation(value = "打包下载文件")
@EventLog(EventType.SFTP_DOWNLOAD)
public void packageDownloadFile(@RequestBody FileDownloadRequest request) {
List<String> paths = Valid.notEmpty(request.getPaths());
paths.forEach(Valid::checkNormalize);
sftpService.packageDownload(request);
}
@GetMapping("/transfer/{fileToken}/pause")
@ApiOperation(value = "暂停文件传输")
public void transferPause(@PathVariable("fileToken") String fileToken) {
sftpService.transferPause(fileToken);
}
@GetMapping("/transfer/{fileToken}/resume")
@ApiOperation(value = "恢复文件传输")
public void transferResume(@PathVariable("fileToken") String fileToken) {
sftpService.transferResume(fileToken);
}
@GetMapping("/transfer/{fileToken}/retry")
@ApiOperation(value = "传输失败重试")
public void transferRetry(@PathVariable("fileToken") String fileToken) {
sftpService.transferRetry(fileToken);
}
@GetMapping("/transfer/{fileToken}/re-upload")
@ApiOperation(value = "重新上传文件")
public void transferReUpload(@PathVariable("fileToken") String fileToken) {
sftpService.transferReUpload(fileToken);
}
@GetMapping("/transfer/{fileToken}/re-download")
@ApiOperation(value = "重新下载文件")
public void transferReDownload(@PathVariable("fileToken") String fileToken) {
sftpService.transferReDownload(fileToken);
}
@GetMapping("/transfer/{sessionToken}/pause-all")
@ApiOperation(value = "暂停所有传输")
public void transferPauseAll(@PathVariable("sessionToken") String sessionToken) {
sftpService.transferPauseAll(sessionToken);
}
@GetMapping("/transfer/{sessionToken}/resume-all")
@ApiOperation(value = "恢复所有传输")
public void transferResumeAll(@PathVariable("sessionToken") String sessionToken) {
sftpService.transferResumeAll(sessionToken);
}
@GetMapping("/transfer/{sessionToken}/retry-all")
@ApiOperation(value = "失败重试所有")
public void transferRetryAll(@PathVariable("sessionToken") String sessionToken) {
sftpService.transferRetryAll(sessionToken);
}
@GetMapping("/transfer/{sessionToken}/list")
@ApiOperation(value = "获取传输列表")
public List<FileTransferLogVO> transferList(@PathVariable("sessionToken") String sessionToken) {
SftpSessionTokenDTO tokenInfo = sftpService.getTokenInfo(sessionToken);
Valid.isTrue(Currents.getUserId().equals(tokenInfo.getUserId()));
return sftpService.transferList(tokenInfo.getMachineId());
}
@GetMapping("/transfer/{fileToken}/remove")
@ApiOperation(value = "删除单个传输记录 (包含进行中的)")
public void transferRemove(@PathVariable("fileToken") String fileToken) {
sftpService.transferRemove(fileToken);
}
@GetMapping("/transfer/{sessionToken}/clear")
@ApiOperation(value = "清空全部传输记录 (不包含进行中的)")
public Integer transferClear(@PathVariable("sessionToken") String sessionToken) {
SftpSessionTokenDTO tokenInfo = sftpService.getTokenInfo(sessionToken);
Valid.isTrue(Currents.getUserId().equals(tokenInfo.getUserId()));
return sftpService.transferClear(tokenInfo.getMachineId());
}
@GetMapping("/transfer/{sessionToken}/{packageType}/package")
@ApiOperation(value = "传输打包全部已完成未删除的文件")
@EventLog(EventType.SFTP_PACKAGE)
public void transferPackage(@PathVariable("sessionToken") String sessionToken, @PathVariable("packageType") Integer packageType) {
SftpPackageType sftpPackageType = Valid.notNull(SftpPackageType.of(packageType));
sftpService.transferPackage(sessionToken, sftpPackageType);
}
/**
* 检测文件是否存在
*
* @param e e
* @return RuntimeException
*/
private RuntimeException convertError(RuntimeException e) {
if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) {
return Exceptions.argument(MessageConst.NO_SUCH_FILE);
} else {
return e;
}
}
}

View File

@@ -0,0 +1,120 @@
package cn.orionsec.ops.controller;
import cn.orionsec.ops.annotation.IgnoreLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.entity.request.app.AppBuildStatisticsRequest;
import cn.orionsec.ops.entity.request.app.AppPipelineTaskStatisticsRequest;
import cn.orionsec.ops.entity.request.app.AppReleaseStatisticsRequest;
import cn.orionsec.ops.entity.request.home.HomeStatisticsRequest;
import cn.orionsec.ops.entity.request.scheduler.SchedulerTaskStatisticsRequest;
import cn.orionsec.ops.entity.vo.app.*;
import cn.orionsec.ops.entity.vo.home.HomeStatisticsVO;
import cn.orionsec.ops.entity.vo.scheduler.SchedulerTaskRecordStatisticsVO;
import cn.orionsec.ops.service.api.StatisticsService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "统计操作")
@RestController
@RestWrapper
@RequestMapping("/orion/api/statistics")
public class StatisticsController {
@Resource
private StatisticsService statisticsService;
@PostMapping("/home")
@ApiOperation(value = "首页统计")
public HomeStatisticsVO homeStatistics(@RequestBody HomeStatisticsRequest request) {
return statisticsService.homeStatistics(request);
}
@PostMapping("/scheduler-task")
@ApiOperation(value = "调度任务统计")
public SchedulerTaskRecordStatisticsVO schedulerTaskStatistics(@RequestBody SchedulerTaskStatisticsRequest request) {
Long taskId = Valid.notNull(request.getTaskId());
return statisticsService.schedulerTaskStatistics(taskId);
}
@IgnoreLog
@PostMapping("/app-build/view")
@ApiOperation(value = "获取应用构建统计视图")
public ApplicationBuildStatisticsViewVO appBuildStatisticsView(@RequestBody AppBuildStatisticsRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
return statisticsService.appBuildStatisticsView(appId, profileId);
}
@PostMapping("/app-build/metrics")
@ApiOperation(value = "获取应用构建统计指标")
public ApplicationBuildStatisticsMetricsWrapperVO appBuildStatisticsMetrics(@RequestBody AppBuildStatisticsRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
return statisticsService.appBuildStatisticsMetrics(appId, profileId);
}
@PostMapping("/app-build/chart")
@ApiOperation(value = "获取应用构建统计折线图")
public List<ApplicationBuildStatisticsChartVO> appBuildStatisticsChart(@RequestBody AppBuildStatisticsRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
return statisticsService.appBuildStatisticsChart(appId, profileId);
}
@IgnoreLog
@PostMapping("/app-release/view")
@ApiOperation(value = "获取应用发布统计视图")
public ApplicationReleaseStatisticsViewVO appReleaseStatisticsView(@RequestBody AppReleaseStatisticsRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
return statisticsService.appReleaseStatisticView(appId, profileId);
}
@PostMapping("/app-release/metrics")
@ApiOperation(value = "获取应用发布统计指标")
public ApplicationReleaseStatisticsMetricsWrapperVO appReleaseStatisticsMetrics(@RequestBody AppReleaseStatisticsRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
return statisticsService.appReleaseStatisticMetrics(appId, profileId);
}
@PostMapping("/app-release/chart")
@ApiOperation(value = "获取应用发布统计折线图")
public List<ApplicationReleaseStatisticsChartVO> appReleaseStatisticsChart(@RequestBody AppReleaseStatisticsRequest request) {
Long appId = Valid.notNull(request.getAppId());
Long profileId = Valid.notNull(request.getProfileId());
return statisticsService.appReleaseStatisticChart(appId, profileId);
}
@IgnoreLog
@PostMapping("/app-pipeline/view")
@ApiOperation(value = "获取应用流水线统计视图")
public ApplicationPipelineTaskStatisticsViewVO appReleaseStatisticsView(@RequestBody AppPipelineTaskStatisticsRequest request) {
Long pipelineId = Valid.notNull(request.getPipelineId());
return statisticsService.appPipelineTaskStatisticView(pipelineId);
}
@PostMapping("/app-pipeline/metrics")
@ApiOperation(value = "获取应用流水线统计指标")
public ApplicationPipelineTaskStatisticsMetricsWrapperVO appReleaseStatisticsMetrics(@RequestBody AppPipelineTaskStatisticsRequest request) {
Long pipelineId = Valid.notNull(request.getPipelineId());
return statisticsService.appPipelineTaskStatisticMetrics(pipelineId);
}
@PostMapping("/app-pipeline/chart")
@ApiOperation(value = "获取应用流水线统计折线图")
public List<ApplicationPipelineTaskStatisticsChartVO> appReleaseStatisticsChart(@RequestBody AppPipelineTaskStatisticsRequest request) {
Long pipelineId = Valid.notNull(request.getPipelineId());
return statisticsService.appPipelineTaskStatisticChart(pipelineId);
}
}

View File

@@ -0,0 +1,120 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.kit.web.servlet.web.Servlets;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RequireRole;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.CnConst;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.PropertiesConst;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.system.SystemCleanType;
import cn.orionsec.ops.constant.system.SystemConfigKey;
import cn.orionsec.ops.constant.user.RoleType;
import cn.orionsec.ops.entity.request.system.ConfigIpListRequest;
import cn.orionsec.ops.entity.request.system.SystemFileCleanRequest;
import cn.orionsec.ops.entity.request.system.SystemOptionRequest;
import cn.orionsec.ops.entity.vo.system.*;
import cn.orionsec.ops.service.api.SystemService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Api(tags = "系统设置")
@RestController
@RestWrapper
@RequestMapping("/orion/api/system")
public class SystemController {
@Resource
private SystemService systemService;
@GetMapping("/ip-info")
@ApiOperation(value = "获取ip信息")
public IpListConfigVO getIpInfo(HttpServletRequest request) {
return systemService.getIpInfo(Servlets.getRemoteAddr(request));
}
@DemoDisableApi
@PostMapping("/config-ip")
@ApiOperation(value = "配置ip过滤器列表")
@EventLog(EventType.CONFIG_IP_LIST)
@RequireRole(RoleType.ADMINISTRATOR)
public HttpWrapper<?> configIpList(@RequestBody ConfigIpListRequest request) {
systemService.configIpFilterList(request);
return HttpWrapper.ok();
}
@DemoDisableApi
@PostMapping("/clean-system-file")
@ApiOperation(value = "清理系统文件")
@EventLog(EventType.CLEAN_SYSTEM_FILE)
@RequireRole(RoleType.ADMINISTRATOR)
public HttpWrapper<?> cleanSystemFile(@RequestBody SystemFileCleanRequest request) {
SystemCleanType cleanType = Valid.notNull(SystemCleanType.of(request.getCleanType()));
systemService.cleanSystemFile(cleanType);
return HttpWrapper.ok();
}
@GetMapping("/get-system-analysis")
@ApiOperation(value = "获取系统分析信息")
public SystemAnalysisVO getSystemAnalysis() {
return systemService.getSystemAnalysis();
}
@DemoDisableApi
@GetMapping("/re-analysis")
@ApiOperation(value = "重新进行系统统计分析")
@EventLog(EventType.RE_ANALYSIS_SYSTEM)
@RequireRole(RoleType.ADMINISTRATOR)
public SystemAnalysisVO reAnalysisSystem() {
systemService.analysisSystemSpace();
return systemService.getSystemAnalysis();
}
@DemoDisableApi
@PostMapping("/update-system-option")
@ApiOperation(value = "修改系统配置项")
@EventLog(EventType.UPDATE_SYSTEM_OPTION)
@RequireRole(RoleType.ADMINISTRATOR)
public HttpWrapper<?> updateSystemOption(@RequestBody SystemOptionRequest request) {
SystemConfigKey key = Valid.notNull(SystemConfigKey.of(request.getOption()));
String value = key.getValue(Valid.notBlank(request.getValue()));
systemService.updateSystemOption(key.getEnv(), value);
return HttpWrapper.ok();
}
@GetMapping("/get-system-options")
@ApiOperation(value = "获取系统配置项")
@RequireRole(RoleType.ADMINISTRATOR)
public SystemOptionVO getSystemOptions() {
return systemService.getSystemOptions();
}
@GetMapping("/get-thread-metrics")
@ApiOperation(value = "获取线程池指标")
@RequireRole(RoleType.ADMINISTRATOR)
public List<ThreadPoolMetricsVO> getThreadMetrics() {
return systemService.getThreadPoolMetrics();
}
@GetMapping("/about")
@ApiOperation(value = "获取应用信息")
public SystemAboutVO getSystemAbout() {
return SystemAboutVO.builder()
.orionKitVersion(Const.ORION_KIT_VERSION)
.orionOpsVersion(PropertiesConst.ORION_OPS_VERSION)
.author(Const.ORION_AUTHOR)
.authorCn(CnConst.ORION_OPS_AUTHOR)
.build();
}
}

View File

@@ -0,0 +1,107 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.collect.MutableLinkedHashMap;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.collect.Maps;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.constant.env.EnvViewType;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.request.system.SystemEnvRequest;
import cn.orionsec.ops.entity.vo.system.SystemEnvVO;
import cn.orionsec.ops.service.api.SystemEnvService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Api(tags = "系统环境变量")
@RestController
@RestWrapper
@RequestMapping("/orion/api/system-env")
public class SystemEnvController {
@Resource
private SystemEnvService systemEnvService;
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加环境变量")
@EventLog(EventType.ADD_SYSTEM_ENV)
public Long add(@RequestBody SystemEnvRequest request) {
Valid.notBlank(request.getKey());
Valid.notNull(request.getValue());
return systemEnvService.addEnv(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改环境变量")
@EventLog(EventType.UPDATE_SYSTEM_ENV)
public Integer update(@RequestBody SystemEnvRequest request) {
Valid.notNull(request.getId());
Valid.notNull(request.getValue());
return systemEnvService.updateEnv(request);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除环境变量")
@EventLog(EventType.DELETE_SYSTEM_ENV)
public Integer delete(@RequestBody SystemEnvRequest request) {
List<Long> idList = Valid.notEmpty(request.getIdList());
return systemEnvService.deleteEnv(idList);
}
@PostMapping("/list")
@ApiOperation(value = "获取环境变量列表")
public DataGrid<SystemEnvVO> list(@RequestBody SystemEnvRequest request) {
return systemEnvService.listEnv(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取环境变量详情")
public SystemEnvVO detail(@RequestBody SystemEnvRequest request) {
Long id = Valid.notNull(request.getId());
return systemEnvService.getEnvDetail(id);
}
@PostMapping("/view")
@ApiOperation(value = "获取环境变量视图")
public String view(@RequestBody SystemEnvRequest request) {
EnvViewType viewType = Valid.notNull(EnvViewType.of(request.getViewType()));
request.setLimit(Const.N_100000);
// 查询列表
Map<String, String> env = Maps.newLinkedMap();
systemEnvService.listEnv(request).forEach(e -> env.put(e.getKey(), e.getValue()));
return viewType.toValue(env);
}
@DemoDisableApi
@PostMapping("/view-save")
@ApiOperation(value = "保存环境变量视图")
@EventLog(EventType.SAVE_SYSTEM_ENV)
public Integer viewSave(@RequestBody SystemEnvRequest request) {
String value = Valid.notBlank(request.getValue());
EnvViewType viewType = Valid.notNull(EnvViewType.of(request.getViewType()));
try {
MutableLinkedHashMap<String, String> result = viewType.toMap(value);
systemEnvService.saveEnv(result);
return result.size();
} catch (Exception e) {
throw Exceptions.argument(MessageConst.PARSE_ERROR, e);
}
}
}

View File

@@ -0,0 +1,121 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.utils.Objects1;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RequireRole;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.user.RoleType;
import cn.orionsec.ops.entity.request.user.UserInfoRequest;
import cn.orionsec.ops.entity.vo.user.UserInfoVO;
import cn.orionsec.ops.service.api.UserService;
import cn.orionsec.ops.utils.Currents;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "用户")
@RestController
@RestWrapper
@RequestMapping("/orion/api/user")
public class UserController {
@Resource
private UserService userService;
@PostMapping("/list")
@ApiOperation(value = "获取用户列表")
public DataGrid<UserInfoVO> list(@RequestBody UserInfoRequest request) {
return userService.userList(request);
}
@PostMapping("/detail")
@ApiOperation(value = "获取用户详情")
public UserInfoVO detail(@RequestBody UserInfoRequest request) {
return userService.userDetail(request);
}
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加用户")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.ADD_USER)
public Long addUser(@RequestBody UserInfoRequest request) {
this.check(request);
Valid.notBlank(request.getPassword());
request.setId(null);
return userService.addUser(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "修改用户信息")
@EventLog(EventType.UPDATE_USER)
public Integer update(@RequestBody UserInfoRequest request) {
Integer roleType = request.getRole();
if (roleType != null) {
Valid.notNull(RoleType.of(roleType));
}
request.setId(Objects1.def(request.getId(), Currents::getUserId));
return userService.updateUser(request);
}
@DemoDisableApi
@PostMapping("/update-avatar")
@ApiOperation(value = "修改用户头像")
public Integer updateAvatar(@RequestBody UserInfoRequest request) {
String avatar = Valid.notBlank(request.getAvatar());
return userService.updateAvatar(avatar);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除用户")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.DELETE_USER)
public Integer deleteUser(@RequestBody UserInfoRequest request) {
Long id = Valid.notNull(request.getId());
return userService.deleteUser(id);
}
@DemoDisableApi
@PostMapping("/update-status")
@ApiOperation(value = "停用/启用用户")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.CHANGE_USER_STATUS)
public Integer updateUserStatus(@RequestBody UserInfoRequest request) {
Long id = Valid.notNull(request.getId());
Integer status = Valid.in(Valid.notNull(request.getStatus()), Const.ENABLE, Const.DISABLE);
return userService.updateStatus(id, status);
}
@PostMapping("/unlock")
@ApiOperation(value = "解锁用户")
@RequireRole(RoleType.ADMINISTRATOR)
@EventLog(EventType.UNLOCK_USER)
public Integer unlockUser(@RequestBody UserInfoRequest request) {
Long id = Valid.notNull(request.getId());
return userService.unlockUser(id);
}
/**
* 检查参数
*/
private void check(UserInfoRequest request) {
Valid.notBlank(request.getUsername());
Valid.notBlank(request.getNickname());
Valid.notNull(RoleType.of(request.getRole()));
Valid.notBlank(request.getPhone());
}
}

View File

@@ -0,0 +1,93 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.ops.annotation.IgnoreLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.entity.request.message.WebSideMessageRequest;
import cn.orionsec.ops.entity.vo.message.WebSideMessagePollVO;
import cn.orionsec.ops.entity.vo.message.WebSideMessageVO;
import cn.orionsec.ops.service.api.WebSideMessageService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "站内信")
@RestController
@RestWrapper
@RequestMapping("/orion/api/message")
public class WebSideMessageController {
@Resource
private WebSideMessageService webSideMessageService;
@GetMapping("/unread-count")
@ApiOperation(value = "获取站内信未读数量")
public Integer getUnreadCount() {
return webSideMessageService.getUnreadCount();
}
@GetMapping("/set-all-read")
@ApiOperation(value = "设置站内信全部已读")
public Integer setAllRead() {
return webSideMessageService.setAllRead();
}
@PostMapping("/read")
@ApiOperation(value = "设置已读站内信")
public Integer readMessage(@RequestBody WebSideMessageRequest request) {
List<Long> idList = Valid.notNull(request.getIdList());
return webSideMessageService.readMessage(idList);
}
@GetMapping("/delete-all-read")
@ApiOperation(value = "删除全部已读站内信")
public Integer deleteAllRead() {
return webSideMessageService.deleteAllRead();
}
@PostMapping("/delete")
@ApiOperation(value = "删除站内信")
public Integer deleteMessage(@RequestBody WebSideMessageRequest request) {
List<Long> idList = Valid.notNull(request.getIdList());
return webSideMessageService.deleteMessage(idList);
}
@PostMapping("/detail")
@ApiOperation(value = "获取站内信详情")
public WebSideMessageVO getMessageDetail(@RequestBody WebSideMessageRequest request) {
Long id = Valid.notNull(request.getId());
return webSideMessageService.getMessageDetail(id);
}
@PostMapping("/list")
@ApiOperation(value = "获取站内信列表")
public DataGrid<WebSideMessageVO> getMessageList(@RequestBody WebSideMessageRequest request) {
return webSideMessageService.getMessageList(request);
}
@PostMapping("/get-new-message")
@ApiOperation(value = "获取最新站内信")
public WebSideMessagePollVO getNewMessage(@RequestBody WebSideMessageRequest request) {
return webSideMessageService.getNewMessage(request);
}
@PostMapping("/get-more-message")
@ApiOperation(value = "获取更多站内信")
public List<WebSideMessageVO> getMoreMessage(@RequestBody WebSideMessageRequest request) {
Valid.notNull(request.getMaxId());
return webSideMessageService.getMoreMessage(request);
}
@IgnoreLog
@PostMapping("/poll-new-message")
@ApiOperation(value = "轮询最新站内信")
public WebSideMessagePollVO pollWebSideMessage(@RequestBody WebSideMessageRequest request) {
return webSideMessageService.pollWebSideMessage(request.getMaxId());
}
}

View File

@@ -0,0 +1,83 @@
package cn.orionsec.ops.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.ops.annotation.DemoDisableApi;
import cn.orionsec.ops.annotation.EventLog;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.constant.webhook.WebhookType;
import cn.orionsec.ops.entity.request.webhook.WebhookConfigRequest;
import cn.orionsec.ops.entity.vo.webhook.WebhookConfigVO;
import cn.orionsec.ops.service.api.WebhookConfigService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "webhook配置")
@RestController
@RestWrapper
@RequestMapping("/orion/api/webhook-config")
public class WebhookConfigController {
@Resource
private WebhookConfigService webhookConfigService;
@PostMapping("/list")
@ApiOperation(value = "查询列表")
public DataGrid<WebhookConfigVO> getWebhookList(@RequestBody WebhookConfigRequest request) {
return webhookConfigService.getWebhookList(request);
}
@PostMapping("/get")
@ApiOperation(value = "获取详情")
public WebhookConfigVO getWebhookDetail(@RequestBody WebhookConfigRequest request) {
Long id = Valid.notNull(request.getId());
return webhookConfigService.getWebhookDetail(id);
}
@DemoDisableApi
@PostMapping("/add")
@ApiOperation(value = "添加 webhook")
@EventLog(EventType.ADD_WEBHOOK)
public Long addWebhook(@RequestBody WebhookConfigRequest request) {
this.checkParams(request);
return webhookConfigService.addWebhook(request);
}
@DemoDisableApi
@PostMapping("/update")
@ApiOperation(value = "更新 webhook")
@EventLog(EventType.UPDATE_WEBHOOK)
public Integer updateWebhook(@RequestBody WebhookConfigRequest request) {
Valid.notNull(request.getId());
this.checkParams(request);
return webhookConfigService.updateWebhook(request);
}
@DemoDisableApi
@PostMapping("/delete")
@ApiOperation(value = "删除 webhook")
@EventLog(EventType.DELETE_WEBHOOK)
public Integer deleteWebhook(@RequestBody WebhookConfigRequest request) {
Long id = Valid.notNull(request.getId());
return webhookConfigService.deleteWebhook(id);
}
/**
* 检查参数
*
* @param request request
*/
private void checkParams(WebhookConfigRequest request) {
Valid.notNull(WebhookType.of(request.getType()));
Valid.allNotBlank(request.getName(), request.getUrl());
}
}

View File

@@ -0,0 +1,46 @@
package cn.orionsec.ops.expose;
import cn.orionsec.kit.lang.define.wrapper.HttpWrapper;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.machine.MachineAlarmType;
import cn.orionsec.ops.entity.request.machine.MachineAlarmRequest;
import cn.orionsec.ops.entity.vo.machine.MachineAlarmConfigVO;
import cn.orionsec.ops.service.api.MachineAlarmConfigService;
import cn.orionsec.ops.service.api.MachineAlarmService;
import cn.orionsec.ops.utils.Valid;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "暴露服务-机器报警")
@RestController
@RestWrapper
@RequestMapping("/orion/expose-api/machine-alarm")
public class MachineAlarmExposeController {
@Resource
private MachineAlarmConfigService machineAlarmConfigService;
@Resource
private MachineAlarmService machineAlarmService;
@GetMapping("/get-config")
@ApiOperation(value = "获取报警配置")
public List<MachineAlarmConfigVO> getAlarmConfig(@RequestParam("machineId") Long machineId) {
return machineAlarmConfigService.getAlarmConfig(machineId);
}
@PostMapping("/trigger-alarm")
@ApiOperation(value = "触发机器报警")
public HttpWrapper<?> triggerMachineAlarm(@RequestBody MachineAlarmRequest request) {
Valid.allNotNull(request.getMachineId(), request.getAlarmTime(),
request.getAlarmValue(), MachineAlarmType.of(request.getType()));
machineAlarmService.triggerMachineAlarm(request);
return HttpWrapper.ok();
}
}

View File

@@ -0,0 +1,35 @@
package cn.orionsec.ops.expose;
import cn.orionsec.ops.annotation.RestWrapper;
import cn.orionsec.ops.constant.monitor.MonitorStatus;
import cn.orionsec.ops.entity.domain.MachineMonitorDO;
import cn.orionsec.ops.service.api.MachineMonitorService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "暴露服务-机器监控")
@RestController
@RestWrapper
@RequestMapping("/orion/expose-api/machine-monitor")
public class MachineMonitorExposeController {
@Resource
private MachineMonitorService machineMonitorService;
@GetMapping("/started")
@ApiOperation(value = "监控启动回调")
public Integer getAlarmConfig(@RequestParam("machineId") Long machineId, @RequestParam("version") String version) {
MachineMonitorDO update = new MachineMonitorDO();
update.setMonitorStatus(MonitorStatus.RUNNING.getStatus());
update.setAgentVersion(version);
return machineMonitorService.updateMonitorConfigByMachineId(machineId, update);
}
}

View File

@@ -0,0 +1,10 @@
# redis
spring.redis.host=${REDIS_HOST:192.168.88.101}
spring.redis.port=${REDIS_PORT:6379}
spring.redis.password=${REDIS_PASSWORD:Redis#data}
# mysql
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:192.168.88.101}:3306/orion-ops?useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true
spring.datasource.username=${MYSQL_USER:root}
spring.datasource.password=${MYSQL_PASSWORD:Mysql#data}
# mybatis
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

View File

@@ -0,0 +1,10 @@
# redis
spring.redis.host=${REDIS_HOST:192.168.88.101}
spring.redis.port=${REDIS_PORT:6379}
spring.redis.password=${REDIS_PASSWORD:Redis#data}
# mysql
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:192.168.88.101}:3306/orion-ops?useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true
spring.datasource.username=${MYSQL_USER:root}
spring.datasource.password=${MYSQL_PASSWORD:Mysql#data}
# mybatis
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

View File

@@ -0,0 +1,49 @@
spring.application.name=orion-ops
server.port=9119
spring.data.cassandra.request.timeout=10000
spring.profiles.active=dev
# redis
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=-1
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.min-idle=0
spring.redis.timeout=3000
# datasource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# mybatis
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.mapper-locations=classpath*:mapper/*Mapper.xml
mybatis-plus.global-config.db-config.logic-delete-field=deleted
mybatis-plus.global-config.db-config.logic-not-delete-value=1
mybatis-plus.global-config.db-config.logic-delete-value=2
# tomcat
spring.servlet.multipart.max-file-size=2048MB
spring.servlet.multipart.max-request-size=2096MB
server.tomcat.connection-timeout=18000000
# log
spring.output.ansi.enabled=detect
logging.file.path=${user.home}/orion/logs/orion-ops
logging.file.name=${logging.file.path}/orion-ops.log
logging.logback.rollingpolicy.clean-history-on-start=false
logging.logback.rollingpolicy.file-name-pattern=${logging.file.path}/rolling/orion-ops-rolling-%d{yyyy-MM-dd}.%i.log
logging.logback.rollingpolicy.max-history=30
logging.logback.rollingpolicy.max-file-size=64MB
logging.logback.rollingpolicy.total-size-cap=0B
# app
app.version=1.3.1
login.token.header=O-Login-Token
value.mix.secret.key=${SECRET_KEY:orion_ops}
demo.mode=${DEMO_MODE:false}
log.interceptor.expression=execution (* cn.orionsec.ops.controller.*.*(..)) && !@annotation(cn.orionsec.ops.annotation.IgnoreLog)
log.interceptor.ignore.fields=avatar,password,beforePassword,protectPassword,commandLine,metrics
expose.api.access.header=accessToken
expose.api.access.secret=ops_access
machine.monitor.latest.version=1.1.1
machine.monitor.default.url=http://{}:9220
machine.monitor.default.access.header=accessToken
machine.monitor.default.access.token=agent_access

View File

@@ -0,0 +1,9 @@
_____ ____ ______ _____ __ __ _____ ____ ____
/\ __`\/\ _`\ /\__ _\/\ __`\/\ \/\ \ /\ __`\/\ _`\ /\ _`\
\ \ \/\ \ \ \L\ \/_/\ \/\ \ \/\ \ \ `\\ \ \ \ \/\ \ \ \L\ \ \,\L\_\
\ \ \ \ \ \ , / \ \ \ \ \ \ \ \ \ , ` \ ______\ \ \ \ \ \ ,__/\/_\__ \
\ \ \_\ \ \ \\ \ \_\ \_\ \ \_\ \ \ \`\ \/\______\ \ \_\ \ \ \/ /\ \L\ \
\ \_____\ \_\ \_\/\_____\ \_____\ \_\ \_\/______/\ \_____\ \_\ \ `\____\
\/_____/\/_/\/ /\/_____/\/_____/\/_/\/_/ \/_____/\/_/ \/_____/

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="springHolder" class="cn.orionsec.kit.spring.SpringHolder$ApplicationContextAwareStore"/>
</beans>

View File

@@ -0,0 +1,187 @@
[
{
"name": "控制台",
"path": "/console",
"icon": "dashboard"
},
{
"name": "机器管理",
"icon": "desktop",
"children": [
{
"name": "机器列表",
"path": "/machine/list"
},
{
"name": "机器密钥",
"path": "/machine/key"
},
{
"name": "机器监控",
"path": "/machine/monitor/list"
},
{
"name": "环境变量",
"path": "/machine/env"
},
{
"name": "机器代理",
"path": "/machine/proxy"
},
{
"name": "终端日志",
"path": "/terminal/logs"
},
{
"name": "终端会话",
"path": "/terminal/session"
}
]
},
{
"name": "执行管理",
"icon": "apartment",
"children": [
{
"name": "批量执行",
"path": "/batch/exec/add"
},
{
"name": "执行记录",
"path": "/batch/exec/list"
},
{
"name": "批量上传",
"path": "/batch/upload"
},
{
"name": "日志面板",
"path": "/log/list"
}
]
},
{
"name": "调度任务",
"icon": "schedule",
"children": [
{
"name": "任务列表",
"path": "/scheduler/list"
},
{
"name": "执行记录",
"path": "/scheduler/record"
},
{
"name": "执行统计",
"path": "/scheduler/statistics"
}
]
},
{
"name": "应用管理",
"icon": "appstore",
"children": [
{
"name": "环境管理",
"path": "/app/profile"
},
{
"name": "应用列表",
"path": "/app/list"
},
{
"name": "流水线配置",
"path": "/app/pipeline/list"
},
{
"name": "环境变量",
"path": "/app/env"
},
{
"name": "版本仓库",
"path": "/app/repo"
}
]
},
{
"name": "构建发布",
"icon": "deployment-unit",
"children": [
{
"name": "应用构建",
"path": "/app/build/list"
},
{
"name": "应用发布",
"path": "/app/release/list"
},
{
"name": "流水线任务",
"path": "/app/pipeline/task"
},
{
"name": "构建统计",
"path": "/app/build/statistics"
},
{
"name": "发布统计",
"path": "/app/release/statistics"
},
{
"name": "流水线统计",
"path": "/app/pipeline/statistics"
}
]
},
{
"name": "用户中心",
"icon": "user",
"children": [
{
"name": "用户列表",
"path": "/user/list"
},
{
"name": "报警联系组",
"path": "/alarm/group/list"
},
{
"name": "个人信息",
"path": "/user/detail"
},
{
"name": "操作日志",
"path": "/user/event/logs"
}
]
},
{
"name": "信息管理",
"icon": "container",
"children": [
{
"name": "模板配置",
"path": "/template/list"
},
{
"name": "webhook 配置",
"path": "/webhook/list"
}
]
},
{
"name": "系统管理",
"icon": "control",
"children": [
{
"name": "系统变量",
"path": "/system/env"
},
{
"name": "系统设置",
"path": "/system/setting"
}
]
}
]

View File

@@ -0,0 +1,171 @@
[
{
"name": "控制台",
"path": "/console",
"icon": "dashboard"
},
{
"name": "机器管理",
"icon": "desktop",
"children": [
{
"name": "机器列表",
"path": "/machine/list"
},
{
"name": "机器密钥",
"path": "/machine/key"
},
{
"name": "机器监控",
"path": "/machine/monitor/list"
},
{
"name": "环境变量",
"path": "/machine/env"
},
{
"name": "机器代理",
"path": "/machine/proxy"
},
{
"name": "终端日志",
"path": "/terminal/logs"
}
]
},
{
"name": "执行管理",
"icon": "apartment",
"children": [
{
"name": "批量执行",
"path": "/batch/exec/add"
},
{
"name": "执行记录",
"path": "/batch/exec/list"
},
{
"name": "批量上传",
"path": "/batch/upload"
},
{
"name": "日志面板",
"path": "/log/list"
}
]
},
{
"name": "调度任务",
"icon": "schedule",
"children": [
{
"name": "任务列表",
"path": "/scheduler/list"
},
{
"name": "执行记录",
"path": "/scheduler/record"
},
{
"name": "执行统计",
"path": "/scheduler/statistics"
}
]
},
{
"name": "应用管理",
"icon": "appstore",
"children": [
{
"name": "应用列表",
"path": "/app/list"
},
{
"name": "流水线配置",
"path": "/app/pipeline/list"
},
{
"name": "环境变量",
"path": "/app/env"
},
{
"name": "版本仓库",
"path": "/app/repo"
}
]
},
{
"name": "构建发布",
"icon": "deployment-unit",
"children": [
{
"name": "应用构建",
"path": "/app/build/list"
},
{
"name": "应用发布",
"path": "/app/release/list"
},
{
"name": "流水线任务",
"path": "/app/pipeline/task"
},
{
"name": "构建统计",
"path": "/app/build/statistics"
},
{
"name": "发布统计",
"path": "/app/release/statistics"
},
{
"name": "流水线统计",
"path": "/app/pipeline/statistics"
}
]
},
{
"name": "用户中心",
"icon": "user",
"children": [
{
"name": "用户列表",
"path": "/user/list"
},
{
"name": "报警联系组",
"path": "/alarm/group/list"
},
{
"name": "个人信息",
"path": "/user/detail"
}
]
},
{
"name": "信息管理",
"icon": "container",
"children": [
{
"name": "模板配置",
"path": "/template/list"
},
{
"name": "webhook 配置",
"path": "/webhook/list"
}
]
},
{
"name": "系统管理",
"icon": "control",
"children": [
{
"name": "系统变量",
"path": "/system/env"
}
]
}
]

View File

@@ -0,0 +1,171 @@
[
{
"name": "控制台",
"path": "/console",
"icon": "dashboard"
},
{
"name": "机器管理",
"icon": "desktop",
"children": [
{
"name": "机器列表",
"path": "/machine/list"
},
{
"name": "机器密钥",
"path": "/machine/key"
},
{
"name": "机器监控",
"path": "/machine/monitor/list"
},
{
"name": "环境变量",
"path": "/machine/env"
},
{
"name": "机器代理",
"path": "/machine/proxy"
},
{
"name": "终端日志",
"path": "/terminal/logs"
}
]
},
{
"name": "执行管理",
"icon": "apartment",
"children": [
{
"name": "批量执行",
"path": "/batch/exec/add"
},
{
"name": "执行记录",
"path": "/batch/exec/list"
},
{
"name": "批量上传",
"path": "/batch/upload"
},
{
"name": "日志面板",
"path": "/log/list"
}
]
},
{
"name": "调度任务",
"icon": "schedule",
"children": [
{
"name": "任务列表",
"path": "/scheduler/list"
},
{
"name": "执行记录",
"path": "/scheduler/record"
},
{
"name": "执行统计",
"path": "/scheduler/statistics"
}
]
},
{
"name": "应用管理",
"icon": "appstore",
"children": [
{
"name": "应用列表",
"path": "/app/list"
},
{
"name": "流水线配置",
"path": "/app/pipeline/list"
},
{
"name": "环境变量",
"path": "/app/env"
},
{
"name": "版本仓库",
"path": "/app/repo"
}
]
},
{
"name": "构建发布",
"icon": "deployment-unit",
"children": [
{
"name": "应用构建",
"path": "/app/build/list"
},
{
"name": "应用发布",
"path": "/app/release/list"
},
{
"name": "流水线任务",
"path": "/app/pipeline/task"
},
{
"name": "构建统计",
"path": "/app/build/statistics"
},
{
"name": "发布统计",
"path": "/app/release/statistics"
},
{
"name": "流水线统计",
"path": "/app/pipeline/statistics"
}
]
},
{
"name": "用户中心",
"icon": "user",
"children": [
{
"name": "用户列表",
"path": "/user/list"
},
{
"name": "报警联系组",
"path": "/alarm/group/list"
},
{
"name": "个人信息",
"path": "/user/detail"
}
]
},
{
"name": "信息管理",
"icon": "container",
"children": [
{
"name": "模板配置",
"path": "/template/list"
},
{
"name": "webhook 配置",
"path": "/webhook/list"
}
]
},
{
"name": "系统管理",
"icon": "control",
"children": [
{
"name": "系统变量",
"path": "/system/env"
}
]
}
]