Compare commits
40 Commits
dev-pcap-p
...
dev-applic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e675144a6c | ||
|
|
c57ade402f | ||
|
|
f14763512e | ||
|
|
b480734c94 | ||
|
|
1c35979b24 | ||
|
|
68ccb87c76 | ||
|
|
a98566f5d5 | ||
|
|
634166c4b3 | ||
|
|
ecb57f6c6c | ||
|
|
58b38fbe91 | ||
|
|
582856c066 | ||
|
|
76e52d91e9 | ||
|
|
f3d048c240 | ||
|
|
c3d9750bdc | ||
|
|
afb19a4326 | ||
|
|
519b6e1c2d | ||
|
|
e8b6e902c2 | ||
|
|
a32327ad22 | ||
|
|
f7caf6262c | ||
|
|
8932734ef6 | ||
|
|
3265d73dfe | ||
|
|
e88dc879e2 | ||
|
|
11a4000eb2 | ||
|
|
172bd9e890 | ||
|
|
d5f6aef383 | ||
|
|
875eb83d6e | ||
|
|
b6cbe6094f | ||
|
|
9a21b440b0 | ||
|
|
ba87a497bb | ||
|
|
aaff071420 | ||
|
|
a837a160f9 | ||
|
|
af0d0e55ca | ||
|
|
4b53e78124 | ||
|
|
2c8b299735 | ||
|
|
96483dc432 | ||
|
|
d9ec686bc7 | ||
|
|
17328600aa | ||
|
|
6b78f8e61a | ||
|
|
b5af3de27d | ||
|
|
4a2d7f9adf |
@@ -61,8 +61,9 @@ dev_build:
|
|||||||
- export FILE_NAME=$CI_PROJECT_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA.tar.gz
|
- export FILE_NAME=$CI_PROJECT_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA.tar.gz
|
||||||
- mvn clean install -Dmaven.test.skip=true
|
- mvn clean install -Dmaven.test.skip=true
|
||||||
- cd ./target
|
- cd ./target
|
||||||
- "git log -100 --pretty=format:'%ad : %s' > git-log.html"
|
# - "git log -100 --pretty=format:'%ad : %s' > git-log.html"
|
||||||
- tar -zcvf $FILE_NAME asw-controller.jar git-log.html
|
# - tar -zcvf $FILE_NAME asw-controller.jar git-log.html
|
||||||
|
- tar -zcvf $FILE_NAME asw-controller.jar
|
||||||
- md5sum $FILE_NAME > $CI_PROJECT_NAME-$CI_COMMIT_REF_NAME-latest.tar.gz.md5sum.txt
|
- md5sum $FILE_NAME > $CI_PROJECT_NAME-$CI_COMMIT_REF_NAME-latest.tar.gz.md5sum.txt
|
||||||
# 将 文件 上传到 minio
|
# 将 文件 上传到 minio
|
||||||
- mc alias set asw $MINIO_HOST $MINIO_USER $MINIO_PWD
|
- mc alias set asw $MINIO_HOST $MINIO_USER $MINIO_PWD
|
||||||
|
|||||||
36
pom.xml
36
pom.xml
@@ -79,6 +79,14 @@
|
|||||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||||
<version>1.37.0</version>
|
<version>1.37.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Sa-Token 整合 jwt -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-jwt</artifactId>
|
||||||
|
<version>1.37.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
@@ -143,6 +151,34 @@
|
|||||||
<artifactId>simplemagic</artifactId>
|
<artifactId>simplemagic</artifactId>
|
||||||
<version>1.16</version>
|
<version>1.16</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--Feign client支持-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||||
|
<version>3.1.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
|
<artifactId>fastjson2</artifactId>
|
||||||
|
<version>2.0.51</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!--opensearch-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.opensearch.client</groupId>
|
||||||
|
<artifactId>opensearch-java</artifactId>
|
||||||
|
<version>2.12.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.opensearch.client</groupId>
|
||||||
|
<artifactId>opensearch-rest-client</artifactId>
|
||||||
|
<version>2.12.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package net.geedge.asw.common.config;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class GUIHistoryRouterFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
@Value("${router.prefixes:/static/,/api/}")
|
||||||
|
private String pathPrefixes;
|
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
public GUIHistoryRouterFilter(ResourceLoader resourceLoader) {
|
||||||
|
this.resourceLoader = resourceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
|
||||||
|
List<String> prefixes = Arrays.asList(pathPrefixes.split(","));
|
||||||
|
String path = request.getRequestURI();
|
||||||
|
boolean matches = prefixes.stream().anyMatch(path::startsWith);
|
||||||
|
|
||||||
|
if (!matches) {
|
||||||
|
// If the path does not start with any of the specified prefixes, return index.html
|
||||||
|
Resource resource = resourceLoader.getResource("file:./public/index.html");
|
||||||
|
response.setContentType("text/html");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
Files.copy(resource.getFile().toPath(), response.getOutputStream());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If the path matches any of the prefixes, continue the filter chain
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,23 @@
|
|||||||
package net.geedge.asw.common.config;
|
package net.geedge.asw.common.config;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
|
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||||
|
import cn.dev33.satoken.jwt.SaJwtTemplate;
|
||||||
|
import cn.dev33.satoken.jwt.SaJwtUtil;
|
||||||
|
import cn.dev33.satoken.jwt.StpLogicJwtForStateless;
|
||||||
|
import cn.dev33.satoken.router.SaRouter;
|
||||||
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.jwt.JWT;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
import cn.dev33.satoken.config.SaTokenConfig;
|
import java.util.concurrent.TimeUnit;
|
||||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
|
||||||
import cn.dev33.satoken.router.SaRouter;
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
public class SaTokenConfigure implements WebMvcConfigurer {
|
public class SaTokenConfigure implements WebMvcConfigurer {
|
||||||
@@ -38,6 +44,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
config.setTokenStyle("simple-uuid"); // token 风格
|
config.setTokenStyle("simple-uuid"); // token 风格
|
||||||
config.setIsLog(false); // 是否输出操作日志
|
config.setIsLog(false); // 是否输出操作日志
|
||||||
config.setIsPrint(false);
|
config.setIsPrint(false);
|
||||||
|
// jwt秘钥
|
||||||
|
config.setJwtSecretKey("ypCLARItfzxvdVqRwPcwIasdgAkhoubj");
|
||||||
// config.setIsReadCookie(false);
|
// config.setIsReadCookie(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,4 +58,29 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
SaRouter.match("/api/v1/**").notMatch("/api/v1/login").check(r -> StpUtil.checkLogin());
|
SaRouter.match("/api/v1/**").notMatch("/api/v1/login").check(r -> StpUtil.checkLogin());
|
||||||
})).addPathPatterns("/**");
|
})).addPathPatterns("/**");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public StpLogic getStpLogicJwt() {
|
||||||
|
// Sa-Token 整合 jwt (Stateless 无状态模式)
|
||||||
|
return new StpLogicJwtForStateless();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 SaJwtUtil 生成 token 的算法
|
||||||
|
*/
|
||||||
|
@PostConstruct
|
||||||
|
public void setSaJwtTemplate() {
|
||||||
|
SaJwtUtil.setSaJwtTemplate(new SaJwtTemplate() {
|
||||||
|
@Override
|
||||||
|
public String generateToken(JWT jwt, String keyt) {
|
||||||
|
// header
|
||||||
|
jwt.setHeader("alg", "HS256");
|
||||||
|
jwt.setHeader("typ", "JWT");
|
||||||
|
|
||||||
|
// payload
|
||||||
|
jwt.setPayload("iss", "net.geedge.asw");
|
||||||
|
return super.generateToken(jwt, keyt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,4 +20,10 @@ public class Constants {
|
|||||||
*/
|
*/
|
||||||
public static final List<String> LANG_LIST = T.ListUtil.of("en", "zh");
|
public static final List<String> LANG_LIST = T.ListUtil.of("en", "zh");
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作空间可见性列表
|
||||||
|
*/
|
||||||
|
public static final List<String> VISIBILITY_LIST = T.ListUtil.of("public", "private");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,28 @@ public enum RCode {
|
|||||||
PARAM_CANNOT_EMPTY(100006, "parameter cannot be empty"), // parameter 不能为空
|
PARAM_CANNOT_EMPTY(100006, "parameter cannot be empty"), // parameter 不能为空
|
||||||
USER_NO_LOGIN(100007, "user not login"), // 用户未登录
|
USER_NO_LOGIN(100007, "user not login"), // 用户未登录
|
||||||
SYS_RECORD_NOT_FOUND(100008, "record not found"),// 未找到记录
|
SYS_RECORD_NOT_FOUND(100008, "record not found"),// 未找到记录
|
||||||
|
USER_ID_CANNOT_EMPTY(100009, "user id cannot be empty"),// 用户 ID 不能为空
|
||||||
|
ROLE_ID_CANNOT_EMPTY(100010, "role id cannot be empty"),// 权限 ID 不能为空
|
||||||
|
USER_NOT_EXIST(100011, "user does not exist"),
|
||||||
|
ROLE_NOT_EXIST(100012, "role does not exist"),
|
||||||
|
|
||||||
|
|
||||||
// Application
|
// Application
|
||||||
APP_ID_CANNOT_EMPTY(201001, "application id cannot be empty"),
|
APP_ID_CANNOT_EMPTY(201001, "application id cannot be empty"),
|
||||||
|
APP_NAME_CANNOT_EMPTY(201002, "application name cannot be empty"),
|
||||||
|
APP_LONGNAME_CANNOT_EMPTY(201003, "application longName cannot be empty"),
|
||||||
|
APP_PROPERTIES_CANNOT_EMPTY(201004, "application properties cannot be empty"),
|
||||||
|
APP_SURROGATES_CANNOT_EMPTY(201005, "application surrogates cannot be empty"),
|
||||||
|
APP_DESCRIPTION_CANNOT_EMPTY(201006, "application description cannot be empty"),
|
||||||
|
APP_DUPLICATE_RECORD(201007, "application duplicate record"),
|
||||||
|
APP_NOT_EXIST(201008, "application does not exist"),
|
||||||
|
APP_PACKAGE_NAME_FORMAT_ERROR(201009, "application package name format error"),
|
||||||
|
APP_TAGS_FORMAT_ERROR(201010, "application tags format error"),
|
||||||
|
APP_SIGNATURE_FORMAT_ERROR(201011, "application signature format error"),
|
||||||
|
APP_SIGNATURE_CONTENT_CANNOT_EMPTY(201012, "application signature content cannot be empty"),
|
||||||
|
APP_SIGNATURE_NOT_EXIST(201013, "application signature does not exist"),
|
||||||
|
APP_NOTE_CONTENT_CANNOT_EMPTY(201014, "application note content cannot be empty"),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Package
|
// Package
|
||||||
@@ -39,6 +57,18 @@ public enum RCode {
|
|||||||
|
|
||||||
// Workspace
|
// Workspace
|
||||||
WORKSPACE_ID_CANNOT_EMPTY(401001, "workspace id cannot be empty"),
|
WORKSPACE_ID_CANNOT_EMPTY(401001, "workspace id cannot be empty"),
|
||||||
|
WORKSPACE_NAME_CANNOT_EMPTY(401002, "workspace name cannot be empty"),
|
||||||
|
WORKSPACE_VISIBILITY_CANNOT_EMPTY(401003, "workspace visibility cannot be empty"),
|
||||||
|
WORKSPACE_USER_CANNOT_EMPTY(401004, "workspace user cannot be empty"),
|
||||||
|
WORKSPACE_ALREADY_EXISTS(401005, "workspace already exists"),
|
||||||
|
WORKSPACE_MEMBER_CANNOT_EMPTY(401006, "workspace member cannot be empty"),
|
||||||
|
WORKSPACE_CANNOT_DELETE(401007, "Built-in workspace cannot be deleted"),
|
||||||
|
WORKSPACE_VISIBILITY_ERROR(401008, "workspace visibility error"),
|
||||||
|
WORKSPACE_BUILT_IN(401009, "Built-in workspace cannot be update"),
|
||||||
|
|
||||||
|
//PCAP
|
||||||
|
PCAP_UPLOAD_WEB_SHARK_ERROR(501001, "web shark upload pcap error"),
|
||||||
|
|
||||||
|
|
||||||
SUCCESS(200, "success"); // 成功
|
SUCCESS(200, "success"); // 成功
|
||||||
|
|
||||||
|
|||||||
@@ -387,6 +387,13 @@ public class VerifyUtil {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VerifyUtil json(RCode code) {
|
||||||
|
if (!T.JSONUtil.isTypeJSON(T.StrUtil.toStringOrNull(value))) {
|
||||||
|
throw ASWException.builder().rcode(code).build();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多参数校验,不能同时为空
|
* 多参数校验,不能同时为空
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
package net.geedge.asw.module.app.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import net.geedge.asw.common.util.ASWException;
|
||||||
|
import net.geedge.asw.common.util.R;
|
||||||
|
import net.geedge.asw.common.util.RCode;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationAttachmentEntity;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationNoteEntity;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationSignatureEntity;
|
||||||
|
import net.geedge.asw.module.app.service.ApplicationAttachmentService;
|
||||||
|
import net.geedge.asw.module.app.service.ApplicationNoteService;
|
||||||
|
import net.geedge.asw.module.app.service.ApplicationSignatureService;
|
||||||
|
import net.geedge.asw.module.app.service.IApplicationService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/application")
|
||||||
|
public class ApplicationController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IApplicationService applicationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationSignatureService signatureService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationNoteService noteService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationAttachmentService attachmentService;
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public R detail(@PathVariable("id") String id, String workspaceId) {
|
||||||
|
T.VerifyUtil.is(workspaceId).notNull();
|
||||||
|
ApplicationEntity entity = applicationService.detail(id, workspaceId);
|
||||||
|
if (T.ObjectUtil.isNull(entity)) {
|
||||||
|
throw new ASWException(RCode.APP_NOT_EXIST);
|
||||||
|
}
|
||||||
|
return R.ok().putData("record", entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public R list(@RequestParam Map<String, Object> params) {
|
||||||
|
T.VerifyUtil.is(params).notNull()
|
||||||
|
.and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||||
|
Page page = applicationService.queryList(params);
|
||||||
|
return R.ok(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public R add(@RequestBody ApplicationEntity entity) {
|
||||||
|
T.VerifyUtil.is(entity).notNull()
|
||||||
|
.and(entity.getName()).notEmpty(RCode.APP_NAME_CANNOT_EMPTY)
|
||||||
|
//.and(entity.getSignature()).notEmpty(RCode.APP_SURROGATES_CANNOT_EMPTY)
|
||||||
|
//.and(entity.getNote()).notEmpty(RCode.APP_PROPERTIES_CANNOT_EMPTY)
|
||||||
|
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||||
|
|
||||||
|
ApplicationEntity applicationEntity = applicationService.saveApplication(entity);
|
||||||
|
return R.ok().putData("id", applicationEntity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public R update(@RequestBody ApplicationEntity entity) {
|
||||||
|
T.VerifyUtil.is(entity).notNull()
|
||||||
|
.and(entity.getId()).notEmpty(RCode.ID_CANNOT_EMPTY)
|
||||||
|
.and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY)
|
||||||
|
//.and(entity.getSignature()).notEmpty(RCode.APP_SURROGATES_CANNOT_EMPTY)
|
||||||
|
//.and(entity.getNote()).notEmpty(RCode.APP_PROPERTIES_CANNOT_EMPTY)
|
||||||
|
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||||
|
|
||||||
|
ApplicationEntity applicationEntity = applicationService.updateApplication(entity);
|
||||||
|
return R.ok().putData("id", applicationEntity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PutMapping("/{id}/basic")
|
||||||
|
public R basic(@PathVariable String id, @RequestBody ApplicationEntity entity) {
|
||||||
|
T.VerifyUtil.is(entity).notNull()
|
||||||
|
.and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY)
|
||||||
|
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||||
|
entity.setId(id);
|
||||||
|
ApplicationEntity app = applicationService.updateBasic(entity);
|
||||||
|
return R.ok().putData("id", app.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{applicationId}/signature")
|
||||||
|
public R updateSignature(@PathVariable("applicationId") String applicationId, @RequestBody ApplicationSignatureEntity signature) {
|
||||||
|
T.VerifyUtil.is(signature).notNull()
|
||||||
|
.and(signature.getContent()).notEmpty(RCode.APP_SURROGATES_CANNOT_EMPTY)
|
||||||
|
.and(signature.getContent()).json(RCode.APP_SURROGATES_CANNOT_EMPTY);
|
||||||
|
|
||||||
|
signatureService.saveSignature(signature, applicationId);
|
||||||
|
return R.ok().putData("id", signature.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{applicationId}/note")
|
||||||
|
public R updateNote(@PathVariable("applicationId") String applicationId, @RequestBody ApplicationNoteEntity note) {
|
||||||
|
T.VerifyUtil.is(note).notNull()
|
||||||
|
.and(note.getContent()).notEmpty(RCode.APP_NOTE_CONTENT_CANNOT_EMPTY);
|
||||||
|
|
||||||
|
noteService.saveNote(note, applicationId);
|
||||||
|
return R.ok().putData("id", note.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping
|
||||||
|
public R delete(String[] ids) {
|
||||||
|
T.VerifyUtil.is(ids).notEmpty();
|
||||||
|
applicationService.removeApplication(T.ListUtil.of(ids));
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/{applicationId}/attachment")
|
||||||
|
public R queryAttachment(@PathVariable String applicationId) {
|
||||||
|
T.VerifyUtil.is(applicationId).notNull();
|
||||||
|
|
||||||
|
List<ApplicationAttachmentEntity> list = attachmentService.list(new LambdaQueryWrapper<ApplicationAttachmentEntity>().eq(ApplicationAttachmentEntity::getApplicationId, applicationId));
|
||||||
|
return R.ok().putData("records", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/{applicationId}/attachment")
|
||||||
|
public R uploadAttachment(@PathVariable String applicationId, @RequestParam("files") List<MultipartFile> fileList) {
|
||||||
|
|
||||||
|
List<ApplicationAttachmentEntity> recordList = T.ListUtil.list(true);
|
||||||
|
for (int i = 0; i < fileList.size(); i++) {
|
||||||
|
MultipartFile file = fileList.get(i);
|
||||||
|
ApplicationAttachmentEntity attachmentEntity = attachmentService.saveAttachment(file.getResource(), applicationId);
|
||||||
|
recordList.add(attachmentEntity);
|
||||||
|
}
|
||||||
|
return R.ok().putData("records", recordList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{applicationId}/attachment")
|
||||||
|
public R removedAttachment(@PathVariable String applicationId, @RequestParam String ids) {
|
||||||
|
|
||||||
|
attachmentService.removedAttachment(applicationId, ids);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/{applicationId}/signature")
|
||||||
|
public R querySignature(@PathVariable String applicationId) {
|
||||||
|
T.VerifyUtil.is(applicationId).notNull();
|
||||||
|
List<ApplicationSignatureEntity> signatureList = signatureService.queryList(applicationId);
|
||||||
|
return R.ok().putData("records", signatureList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/explore")
|
||||||
|
public R explore(@RequestParam String workspaceId, @RequestParam String pcapIds) {
|
||||||
|
String discoverUrl = applicationService.generateKibanaDiscoverUrl(workspaceId, pcapIds);
|
||||||
|
return R.ok().putData("url", discoverUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{applicationId}/signature/{oldVersion}/{newVersion}")
|
||||||
|
public R signatureCompare(@PathVariable("applicationId") String applicationId,
|
||||||
|
@PathVariable("oldVersion") String oldVersion,
|
||||||
|
@PathVariable("newVersion") String newVersion) {
|
||||||
|
List<ApplicationSignatureEntity> list = signatureService.compare(applicationId, oldVersion, newVersion);
|
||||||
|
return R.ok().putData("records", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PutMapping("/{applicationId}/signature/{version}/restore")
|
||||||
|
public R restore(@PathVariable("applicationId") String applicationId,
|
||||||
|
@PathVariable("version") String version) {
|
||||||
|
signatureService.restore(applicationId, version);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package net.geedge.asw.module.app.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationAttachmentEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ApplicationAttachmentDao extends BaseMapper<ApplicationAttachmentEntity>{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +1,26 @@
|
|||||||
package net.geedge.asw.module.app.dao;
|
package net.geedge.asw.module.app.dao;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface ApplicationDao extends BaseMapper<ApplicationEntity>{
|
public interface ApplicationDao extends BaseMapper<ApplicationEntity>{
|
||||||
|
|
||||||
|
List<ApplicationEntity> queryList(Page page, Map<String, Object> params);
|
||||||
|
|
||||||
|
@Select("select * from ( select * from application union select * from application_log ) app where app.id = #{id} and app.op_version = #{version}")
|
||||||
|
ApplicationEntity queryByApplicationAndLog(String id, String version);
|
||||||
|
|
||||||
|
List<ApplicationEntity> queryLogList(String id);
|
||||||
|
|
||||||
|
List<ApplicationEntity> compare(@Param("params") Map<String, Object> params);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package net.geedge.asw.module.app.dao;
|
package net.geedge.asw.module.app.dao;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import net.geedge.asw.module.app.entity.SignatureEntity;
|
import net.geedge.asw.module.app.entity.ApplicationLogEntity;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface SignatureDao extends BaseMapper<SignatureEntity>{
|
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ApplicationLogDao extends BaseMapper<ApplicationLogEntity> {
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package net.geedge.asw.module.app.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationNoteEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ApplicationNoteDao extends BaseMapper<ApplicationNoteEntity>{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package net.geedge.asw.module.app.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationSignatureEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ApplicationSignatureDao extends BaseMapper<ApplicationSignatureEntity>{
|
||||||
|
|
||||||
|
List<ApplicationSignatureEntity> queryList(@Param("params") Map<Object, Object> params);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package net.geedge.asw.module.app.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("application_attachment")
|
||||||
|
public class ApplicationAttachmentEntity {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String applicationId;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
private Long createTimestamp;
|
||||||
|
|
||||||
|
private String createUserId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
package net.geedge.asw.module.app.entity;
|
package net.geedge.asw.module.app.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("application")
|
@TableName("application")
|
||||||
@@ -11,17 +15,45 @@ public class ApplicationEntity {
|
|||||||
|
|
||||||
@TableId(type = IdType.ASSIGN_UUID)
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private String longName;
|
|
||||||
private String properties;
|
private String tags;
|
||||||
|
|
||||||
|
private String packageName;
|
||||||
|
|
||||||
|
private String website;
|
||||||
|
|
||||||
|
private String provider;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
private String surrogates;
|
|
||||||
|
|
||||||
private Long createTimestamp;
|
private Long createTimestamp;
|
||||||
|
|
||||||
private Long updateTimestamp;
|
private Long updateTimestamp;
|
||||||
|
|
||||||
private String createUserId;
|
private String createUserId;
|
||||||
|
|
||||||
private String updateUserId;
|
private String updateUserId;
|
||||||
|
|
||||||
private String workspaceId;
|
private String workspaceId;
|
||||||
|
|
||||||
|
private Integer opVersion;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity createUser;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity updateUser;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private ApplicationSignatureEntity signature;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private ApplicationNoteEntity note;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<ApplicationAttachmentEntity> attatchments;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package net.geedge.asw.module.app.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("application_log")
|
||||||
|
public class ApplicationLogEntity {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String tags;
|
||||||
|
|
||||||
|
private String packageName;
|
||||||
|
|
||||||
|
private String website;
|
||||||
|
|
||||||
|
private String provider;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private Long createTimestamp;
|
||||||
|
|
||||||
|
private Long updateTimestamp;
|
||||||
|
|
||||||
|
private String createUserId;
|
||||||
|
|
||||||
|
private String updateUserId;
|
||||||
|
|
||||||
|
private String workspaceId;
|
||||||
|
|
||||||
|
private Integer opVersion;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity createUser;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity updateUser;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private ApplicationSignatureEntity signature;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private ApplicationNoteEntity note;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<ApplicationAttachmentEntity> attatchments;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,24 +6,20 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("signature")
|
@TableName("application_note")
|
||||||
public class SignatureEntity {
|
public class ApplicationNoteEntity {
|
||||||
|
|
||||||
@TableId(type = IdType.ASSIGN_UUID)
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
private String id;
|
private String id;
|
||||||
private String appId;
|
|
||||||
private String name;
|
private String applicationId;
|
||||||
private String tags;
|
|
||||||
private String description;
|
private String content;
|
||||||
private Integer displayFlag;
|
|
||||||
private String conditions;
|
|
||||||
private Long opVersion;
|
|
||||||
|
|
||||||
private Long createTimestamp;
|
private Long createTimestamp;
|
||||||
private Long updateTimestamp;
|
|
||||||
private String createUserId;
|
|
||||||
private String updateUserId;
|
|
||||||
|
|
||||||
private String workspaceId;
|
private String createUserId;
|
||||||
|
|
||||||
|
private Long opVersion;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package net.geedge.asw.module.app.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("application_signature")
|
||||||
|
public class ApplicationSignatureEntity {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String applicationId;
|
||||||
|
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
private Long createTimestamp;
|
||||||
|
|
||||||
|
private String createUserId;
|
||||||
|
|
||||||
|
private Long opVersion;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity createUser;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package net.geedge.asw.module.app.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationAttachmentEntity;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
|
public interface ApplicationAttachmentService extends IService<ApplicationAttachmentEntity>{
|
||||||
|
|
||||||
|
ApplicationAttachmentEntity saveAttachment(Resource fileResource, String applicationId);
|
||||||
|
|
||||||
|
void removedAttachment(String applicationId, String ids);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package net.geedge.asw.module.app.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationNoteEntity;
|
||||||
|
|
||||||
|
public interface ApplicationNoteService extends IService<ApplicationNoteEntity>{
|
||||||
|
|
||||||
|
void saveNote(ApplicationNoteEntity note, String applicationId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package net.geedge.asw.module.app.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationSignatureEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ApplicationSignatureService extends IService<ApplicationSignatureEntity>{
|
||||||
|
|
||||||
|
void saveSignature(ApplicationSignatureEntity signature, String applicationId);
|
||||||
|
|
||||||
|
List<ApplicationSignatureEntity> queryList(String applicationId);
|
||||||
|
|
||||||
|
List<ApplicationSignatureEntity> compare(String applicationId, String oldVersion, String newVersion);
|
||||||
|
|
||||||
|
void restore(String id, String version);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.geedge.asw.module.app.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationLogEntity;
|
||||||
|
|
||||||
|
public interface IApplicationLogService extends IService<ApplicationLogEntity> {
|
||||||
|
}
|
||||||
@@ -1,8 +1,25 @@
|
|||||||
package net.geedge.asw.module.app.service;
|
package net.geedge.asw.module.app.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface IApplicationService extends IService<ApplicationEntity>{
|
public interface IApplicationService extends IService<ApplicationEntity>{
|
||||||
|
|
||||||
|
ApplicationEntity detail(String id, String workspaceId);
|
||||||
|
|
||||||
|
Page queryList(Map<String, Object> params);
|
||||||
|
|
||||||
|
ApplicationEntity saveApplication(ApplicationEntity entity);
|
||||||
|
|
||||||
|
ApplicationEntity updateApplication(ApplicationEntity entity);
|
||||||
|
|
||||||
|
ApplicationEntity updateBasic(ApplicationEntity entity);
|
||||||
|
|
||||||
|
void removeApplication(List<String> ids);
|
||||||
|
|
||||||
|
String generateKibanaDiscoverUrl(String workspaceId, String pcapIds);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package net.geedge.asw.module.app.service;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import net.geedge.asw.module.app.entity.SignatureEntity;
|
|
||||||
|
|
||||||
public interface ISignatureService extends IService<SignatureEntity>{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package net.geedge.asw.module.app.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.log.Log;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import net.geedge.asw.common.util.ASWException;
|
||||||
|
import net.geedge.asw.common.util.RCode;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
|
import net.geedge.asw.module.app.dao.ApplicationAttachmentDao;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationAttachmentEntity;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||||
|
import net.geedge.asw.module.app.service.ApplicationAttachmentService;
|
||||||
|
import net.geedge.asw.module.app.service.IApplicationService;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ApplicationAttachmentServiceImpl extends ServiceImpl<ApplicationAttachmentDao, ApplicationAttachmentEntity> implements ApplicationAttachmentService {
|
||||||
|
|
||||||
|
private static final Log log = Log.get();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IApplicationService applicationService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationAttachmentEntity saveAttachment(Resource fileResource, String applicationId) {
|
||||||
|
|
||||||
|
ApplicationEntity app = applicationService.getById(applicationId);
|
||||||
|
ApplicationAttachmentEntity entity = new ApplicationAttachmentEntity();
|
||||||
|
try {
|
||||||
|
entity.setName(fileResource.getFilename());
|
||||||
|
entity.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
entity.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
entity.setApplicationId(applicationId);
|
||||||
|
|
||||||
|
// path
|
||||||
|
File destination = T.FileUtil.file(T.WebPathUtil.getRootPath(), app.getId(), fileResource.getFilename());
|
||||||
|
FileUtils.copyInputStreamToFile(fileResource.getInputStream(), destination);
|
||||||
|
entity.setPath(destination.getPath());
|
||||||
|
|
||||||
|
// 根据文件 applicationId path 判断是否已上存在,存在则响应当前实体
|
||||||
|
ApplicationAttachmentEntity attachment = this.getOne(new LambdaQueryWrapper<ApplicationAttachmentEntity>()
|
||||||
|
.eq(ApplicationAttachmentEntity::getApplicationId, applicationId)
|
||||||
|
.eq(ApplicationAttachmentEntity::getPath, destination.getPath()));
|
||||||
|
if (T.ObjectUtil.isNotNull(attachment)) {
|
||||||
|
return attachment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save
|
||||||
|
this.save(entity);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e, "[saveAttachment] [error] [applicationId: {}]", applicationId);
|
||||||
|
throw new ASWException(RCode.ERROR);
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removedAttachment(String applicationId, String ids) {
|
||||||
|
|
||||||
|
List<String> idList = Arrays.asList(ids.split(","));
|
||||||
|
|
||||||
|
for (String id : idList) {
|
||||||
|
ApplicationAttachmentEntity attachment = this.getOne(new LambdaQueryWrapper<ApplicationAttachmentEntity>()
|
||||||
|
.eq(ApplicationAttachmentEntity::getApplicationId, applicationId)
|
||||||
|
.eq(ApplicationAttachmentEntity::getId, id));
|
||||||
|
|
||||||
|
T.FileUtil.del(FileUtil.file(attachment.getPath()));
|
||||||
|
this.removeById(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package net.geedge.asw.module.app.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import net.geedge.asw.module.app.dao.ApplicationLogDao;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationLogEntity;
|
||||||
|
import net.geedge.asw.module.app.service.IApplicationLogService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ApplicationLogServiceImpl extends ServiceImpl<ApplicationLogDao, ApplicationLogEntity> implements IApplicationLogService {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package net.geedge.asw.module.app.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
|
import net.geedge.asw.module.app.dao.ApplicationNoteDao;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationNoteEntity;
|
||||||
|
import net.geedge.asw.module.app.service.ApplicationNoteService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ApplicationNoteServiceImpl extends ServiceImpl<ApplicationNoteDao, ApplicationNoteEntity> implements ApplicationNoteService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void saveNote(ApplicationNoteEntity note, String applicationId) {
|
||||||
|
// query last note
|
||||||
|
ApplicationNoteEntity noteLast = this.getOne(new LambdaQueryWrapper<ApplicationNoteEntity>()
|
||||||
|
.eq(ApplicationNoteEntity::getApplicationId, applicationId)
|
||||||
|
.orderByDesc(ApplicationNoteEntity::getOpVersion)
|
||||||
|
.last("limit 1"));
|
||||||
|
|
||||||
|
if (T.ObjectUtil.isNotEmpty(noteLast)){
|
||||||
|
note.setOpVersion(noteLast.getOpVersion() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//save note
|
||||||
|
note.setApplicationId(applicationId);
|
||||||
|
note.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
note.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
|
||||||
|
this.save(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,328 @@
|
|||||||
package net.geedge.asw.module.app.service.impl;
|
package net.geedge.asw.module.app.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.net.url.UrlBuilder;
|
||||||
|
import cn.hutool.log.Log;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import net.geedge.asw.common.util.ASWException;
|
||||||
|
import net.geedge.asw.common.util.RCode;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
import net.geedge.asw.module.app.dao.ApplicationDao;
|
import net.geedge.asw.module.app.dao.ApplicationDao;
|
||||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
import net.geedge.asw.module.app.entity.*;
|
||||||
import net.geedge.asw.module.app.service.IApplicationService;
|
import net.geedge.asw.module.app.service.*;
|
||||||
|
import net.geedge.asw.module.feign.client.KibanaClient;
|
||||||
|
import net.geedge.asw.module.runner.entity.PcapEntity;
|
||||||
|
import net.geedge.asw.module.runner.service.IPcapService;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||||
|
import net.geedge.asw.module.sys.service.ISysUserService;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ApplicationServiceImpl extends ServiceImpl<ApplicationDao, ApplicationEntity> implements IApplicationService {
|
public class ApplicationServiceImpl extends ServiceImpl<ApplicationDao, ApplicationEntity> implements IApplicationService {
|
||||||
|
|
||||||
|
private static final Log log = Log.get();
|
||||||
|
|
||||||
|
@Value("${kibana.url:127.0.0.1:5601}")
|
||||||
|
private String kibanaUrl;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IApplicationLogService applicationLogService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWorkspaceService workspaceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPcapService pcapService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysUserService userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationSignatureService signatureService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationNoteService noteService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationAttachmentService attachmentService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private KibanaClient kibanaClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationEntity detail(String id, String workspaceId) {
|
||||||
|
ApplicationEntity app = this.getOne(new LambdaQueryWrapper<ApplicationEntity>()
|
||||||
|
.eq(ApplicationEntity::getId, id)
|
||||||
|
.eq(ApplicationEntity::getWorkspaceId, workspaceId));
|
||||||
|
|
||||||
|
ApplicationSignatureEntity signature = signatureService.getOne(new LambdaQueryWrapper<ApplicationSignatureEntity>()
|
||||||
|
.eq(ApplicationSignatureEntity::getApplicationId, app.getId())
|
||||||
|
.orderByDesc(ApplicationSignatureEntity::getOpVersion)
|
||||||
|
.last("limit 1"));
|
||||||
|
app.setSignature(signature);
|
||||||
|
|
||||||
|
ApplicationNoteEntity note = noteService.getOne(new LambdaQueryWrapper<ApplicationNoteEntity>()
|
||||||
|
.eq(ApplicationNoteEntity::getApplicationId, app.getId())
|
||||||
|
.orderByDesc(ApplicationNoteEntity::getOpVersion)
|
||||||
|
.last("limit 1"));
|
||||||
|
app.setNote(note);
|
||||||
|
|
||||||
|
List<ApplicationAttachmentEntity> attachmentEntityList = attachmentService.list(new LambdaQueryWrapper<ApplicationAttachmentEntity>()
|
||||||
|
.eq(ApplicationAttachmentEntity::getApplicationId, app.getId()));
|
||||||
|
app.setAttatchments(attachmentEntityList);
|
||||||
|
|
||||||
|
SysUserEntity createUser = userService.getById(app.getCreateUserId());
|
||||||
|
SysUserEntity updateUser = userService.getById(app.getUpdateUserId());
|
||||||
|
app.setCreateUser(createUser);
|
||||||
|
app.setUpdateUser(updateUser);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page queryList(Map<String, Object> params) {
|
||||||
|
Page page = T.PageUtil.getPage(params);
|
||||||
|
List<ApplicationEntity> packageList = this.getBaseMapper().queryList(page, params);
|
||||||
|
page.setRecords(packageList);
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateParam(ApplicationEntity entity, boolean isUpdate) {
|
||||||
|
ApplicationEntity one = this.getOne(new LambdaQueryWrapper<ApplicationEntity>()
|
||||||
|
.eq(ApplicationEntity::getWorkspaceId, entity.getWorkspaceId())
|
||||||
|
.eq(ApplicationEntity::getName, entity.getName()));
|
||||||
|
|
||||||
|
if (T.ObjectUtil.isNotNull(one) && !isUpdate || T.ObjectUtil.isNotNull(one) && isUpdate && !T.StrUtil.equals(entity.getId(), one.getId())) {
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_DUPLICATE_RECORD).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// package name format
|
||||||
|
if (T.ObjectUtil.isNotEmpty(entity.getPackageName()) && !T.JSONUtil.isTypeJSON(entity.getPackageName())) {
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_PACKAGE_NAME_FORMAT_ERROR).build();
|
||||||
|
} else if (T.ObjectUtil.isEmpty(entity.getPackageName())) {
|
||||||
|
entity.setPackageName("{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// tags name format
|
||||||
|
if (T.StrUtil.isNotEmpty(entity.getTags()) && !T.JSONUtil.isTypeJSON(entity.getTags())) {
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_TAGS_FORMAT_ERROR).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// signature
|
||||||
|
if (T.ObjectUtil.isNotEmpty(entity.getSignature())) {
|
||||||
|
if (!T.StrUtil.isNotEmpty(entity.getSignature().getContent())){
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_SIGNATURE_CONTENT_CANNOT_EMPTY).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!T.JSONUtil.isTypeJSON(entity.getSignature().getContent())){
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_SIGNATURE_CONTENT_CANNOT_EMPTY).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// note
|
||||||
|
if (T.ObjectUtil.isNotEmpty(entity.getNote()) && !T.StrUtil.isNotEmpty(entity.getNote().getContent())) {
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_NOTE_CONTENT_CANNOT_EMPTY).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ApplicationEntity saveApplication(ApplicationEntity entity) {
|
||||||
|
|
||||||
|
this.validateParam(entity, false);
|
||||||
|
|
||||||
|
// save
|
||||||
|
entity.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
entity.setUpdateTimestamp(System.currentTimeMillis());
|
||||||
|
entity.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
entity.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
this.save(entity);
|
||||||
|
|
||||||
|
if (T.ObjectUtil.isNotEmpty(entity.getSignature())){
|
||||||
|
// save signature
|
||||||
|
signatureService.saveSignature(entity.getSignature(), entity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (T.ObjectUtil.isNotEmpty(entity.getNote())){
|
||||||
|
//save note
|
||||||
|
noteService.saveNote(entity.getNote(), entity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ApplicationEntity updateApplication(ApplicationEntity entity) {
|
||||||
|
|
||||||
|
this.validateParam(entity, true);
|
||||||
|
|
||||||
|
ApplicationEntity one = this.getById(entity.getId());
|
||||||
|
entity.setUpdateTimestamp(System.currentTimeMillis());
|
||||||
|
entity.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
entity.setOpVersion(one.getOpVersion() + 1);
|
||||||
|
|
||||||
|
// update
|
||||||
|
this.updateById(entity);
|
||||||
|
|
||||||
|
// save log
|
||||||
|
this.saveApplicationToLog(one);
|
||||||
|
|
||||||
|
if (T.ObjectUtil.isNotEmpty(entity.getSignature())){
|
||||||
|
// save signature
|
||||||
|
signatureService.saveSignature(entity.getSignature(), entity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (T.ObjectUtil.isNotEmpty(entity.getNote())){
|
||||||
|
//save note
|
||||||
|
noteService.saveNote(entity.getNote(), entity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveApplicationToLog(ApplicationEntity one) {
|
||||||
|
ApplicationLogEntity applicationLogEntity = T.BeanUtil.toBean(one, ApplicationLogEntity.class);
|
||||||
|
applicationLogEntity.setUpdateTimestamp(System.currentTimeMillis());
|
||||||
|
applicationLogEntity.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
applicationLogEntity.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
applicationLogEntity.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
applicationLogService.save(applicationLogEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void removeApplication(List<String> ids) {
|
||||||
|
// remove
|
||||||
|
this.removeBatchByIds(ids);
|
||||||
|
applicationLogService.removeBatchByIds(ids);
|
||||||
|
signatureService.remove(new LambdaQueryWrapper<ApplicationSignatureEntity>().in(ApplicationSignatureEntity::getApplicationId, ids));
|
||||||
|
noteService.remove(new LambdaQueryWrapper<ApplicationNoteEntity>().in(ApplicationNoteEntity::getApplicationId, ids));
|
||||||
|
attachmentService.remove(new LambdaQueryWrapper<ApplicationAttachmentEntity>().in(ApplicationAttachmentEntity::getApplicationId, ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. 根据 workspace_name 查询 index-pattern 是否存在
|
||||||
|
* 2. 不存在则创建索引
|
||||||
|
*
|
||||||
|
* 维护格式示例:
|
||||||
|
* {
|
||||||
|
* "type": "index-pattern",
|
||||||
|
* "id": "workspace_id",
|
||||||
|
* "attributes": {
|
||||||
|
* "title": "workspace-{workspace_name}-*"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @param workspaceId
|
||||||
|
* @param pcapIds
|
||||||
|
* @return kibana discover url
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String generateKibanaDiscoverUrl(String workspaceId, String pcapIds) {
|
||||||
|
// verify
|
||||||
|
WorkspaceEntity workspace = workspaceService.getById(workspaceId);
|
||||||
|
T.VerifyUtil.is(workspace).notNull(RCode.SYS_RECORD_NOT_FOUND);
|
||||||
|
|
||||||
|
List<String> pcapIdList = T.StrUtil.split(pcapIds, ",").stream().filter(s -> T.StrUtil.isNotEmpty(s)).collect(Collectors.toList());
|
||||||
|
List<PcapEntity> pcapList = pcapService.list(new LambdaQueryWrapper<PcapEntity>().in(PcapEntity::getId, pcapIdList));
|
||||||
|
T.VerifyUtil.is(pcapList).notEmpty(RCode.SYS_RECORD_NOT_FOUND);
|
||||||
|
|
||||||
|
// index name
|
||||||
|
String indexName = String.format("workspace-%s-*", workspace.getName());
|
||||||
|
|
||||||
|
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
||||||
|
String token = tokenInfo.getTokenValue();
|
||||||
|
|
||||||
|
JSONObject index = kibanaClient.findIndexPattern(token, indexName);
|
||||||
|
JSONArray savedObjects = index.getJSONArray("saved_objects");
|
||||||
|
|
||||||
|
// check if index exists
|
||||||
|
boolean indexExists = savedObjects.stream()
|
||||||
|
.filter(obj -> {
|
||||||
|
JSONObject attributes = ((JSONObject) obj).getJSONObject("attributes");
|
||||||
|
if (T.ObjectUtil.isEmpty(attributes)) return false;
|
||||||
|
String title = attributes.getString("title");
|
||||||
|
return T.StrUtil.equals(indexName, title);
|
||||||
|
})
|
||||||
|
.findFirst()
|
||||||
|
.isPresent();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("[generateKibanaDiscoverUrl] [idnex-pattern: {}] [exists: {}]", indexName, indexExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create index
|
||||||
|
if (T.BooleanUtil.negate(indexExists)) {
|
||||||
|
JSONObject attributes = new JSONObject();
|
||||||
|
attributes.put("title", indexName);
|
||||||
|
|
||||||
|
JSONObject body = new JSONObject();
|
||||||
|
body.put("attributes", attributes);
|
||||||
|
kibanaClient.saveIndexPattern(token, workspaceId, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
// build url
|
||||||
|
String baseUrl = UrlBuilder.ofHttp(kibanaUrl)
|
||||||
|
.addPath("/app/data-explorer/discover")
|
||||||
|
.addQuery("jwt", token)
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
// build query param
|
||||||
|
String param1 = String.format("_a=(discover:(columns:!(_source),isDirty:!f,sort:!()),metadata:(indexPattern:'%s',view:discover))", workspaceId);
|
||||||
|
String param2 = "_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))";
|
||||||
|
|
||||||
|
String filter = pcapList.stream()
|
||||||
|
.map(PcapEntity::getId)
|
||||||
|
.map(pcapId -> "\"" + pcapId + "\"")
|
||||||
|
.collect(Collectors.joining("|", "pcap.id: (", ")"));
|
||||||
|
String param3 = String.format("_q=(filters:!(),query:(language:lucene,query:'%s'))", filter);
|
||||||
|
|
||||||
|
String query = String.format("?%s&%s&%s", param1, param2, param3);
|
||||||
|
String kibanaDiscoverUrl = baseUrl + "#" + query;
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("[generateKibanaDiscoverUrl] [url: {}]", kibanaDiscoverUrl);
|
||||||
|
}
|
||||||
|
return kibanaDiscoverUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationEntity updateBasic(ApplicationEntity entity) {
|
||||||
|
|
||||||
|
ApplicationEntity one = this.getById(entity.getId());
|
||||||
|
if (T.ObjectUtil.isNotNull(one) && !T.StrUtil.equals(entity.getId(), one.getId())) {
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_DUPLICATE_RECORD).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// package name format
|
||||||
|
if (T.ObjectUtil.isNotEmpty(entity.getPackageName()) && !T.JSONUtil.isTypeJSON(entity.getPackageName())) {
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_PACKAGE_NAME_FORMAT_ERROR).build();
|
||||||
|
} else if (T.ObjectUtil.isEmpty(entity.getPackageName())) {
|
||||||
|
entity.setPackageName("{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.setUpdateTimestamp(System.currentTimeMillis());
|
||||||
|
entity.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
entity.setOpVersion(one.getOpVersion() + 1);
|
||||||
|
|
||||||
|
this.saveApplicationToLog(one);
|
||||||
|
this.updateById(entity);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package net.geedge.asw.module.app.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import net.geedge.asw.common.util.ASWException;
|
||||||
|
import net.geedge.asw.common.util.RCode;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
|
import net.geedge.asw.module.app.dao.ApplicationSignatureDao;
|
||||||
|
import net.geedge.asw.module.app.entity.ApplicationSignatureEntity;
|
||||||
|
import net.geedge.asw.module.app.service.ApplicationSignatureService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ApplicationSignatureServiceImpl extends ServiceImpl<ApplicationSignatureDao, ApplicationSignatureEntity> implements ApplicationSignatureService {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void saveSignature(ApplicationSignatureEntity signature, String applicationId) {
|
||||||
|
// query last note
|
||||||
|
ApplicationSignatureEntity signatureLast = this.getOne(new LambdaQueryWrapper<ApplicationSignatureEntity>()
|
||||||
|
.eq(ApplicationSignatureEntity::getApplicationId, applicationId)
|
||||||
|
.orderByDesc(ApplicationSignatureEntity::getOpVersion)
|
||||||
|
.last("limit 1"));
|
||||||
|
|
||||||
|
if (T.ObjectUtil.isNotEmpty(signatureLast)){
|
||||||
|
signature.setOpVersion(signatureLast.getOpVersion() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save signature
|
||||||
|
signature.setApplicationId(applicationId);
|
||||||
|
signature.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
signature.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
|
||||||
|
this.save(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ApplicationSignatureEntity> queryList(String applicationId) {
|
||||||
|
Map<Object, Object> params = T.MapUtil.builder().put("applicationId", applicationId).build();
|
||||||
|
List<ApplicationSignatureEntity> list = this.getBaseMapper().queryList(params);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ApplicationSignatureEntity> compare(String applicationId, String oldVersion, String newVersion) {
|
||||||
|
|
||||||
|
List<String> versionList = Arrays.asList(oldVersion, newVersion);
|
||||||
|
Map<Object, Object> params = T.MapUtil.builder()
|
||||||
|
.put("applicationId", applicationId)
|
||||||
|
.put("versions", versionList)
|
||||||
|
.build();
|
||||||
|
List<ApplicationSignatureEntity> list = this.getBaseMapper().queryList(params);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restore(String applicationId, String version) {
|
||||||
|
ApplicationSignatureEntity signature = this.getOne(new LambdaQueryWrapper<ApplicationSignatureEntity>()
|
||||||
|
.eq(ApplicationSignatureEntity::getApplicationId, applicationId)
|
||||||
|
.eq(ApplicationSignatureEntity::getOpVersion, version));
|
||||||
|
ApplicationSignatureEntity lastSignature = this.getOne(new LambdaQueryWrapper<ApplicationSignatureEntity>()
|
||||||
|
.eq(ApplicationSignatureEntity::getApplicationId, applicationId)
|
||||||
|
.orderByDesc(ApplicationSignatureEntity::getOpVersion)
|
||||||
|
.last("limit 1"));
|
||||||
|
if (T.ObjectUtil.isEmpty(signature)) {
|
||||||
|
throw ASWException.builder().rcode(RCode.APP_SIGNATURE_NOT_EXIST).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore
|
||||||
|
signature.setId(null);
|
||||||
|
signature.setOpVersion(lastSignature.getOpVersion() + 1);
|
||||||
|
this.save(signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package net.geedge.asw.module.app.service.impl;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import net.geedge.asw.module.app.dao.SignatureDao;
|
|
||||||
import net.geedge.asw.module.app.entity.SignatureEntity;
|
|
||||||
import net.geedge.asw.module.app.service.ISignatureService;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class SignatureServiceImpl extends ServiceImpl<SignatureDao, SignatureEntity> implements ISignatureService {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package net.geedge.asw.module.feign;
|
||||||
|
|
||||||
|
import cn.hutool.core.net.url.UrlBuilder;
|
||||||
|
import cn.hutool.log.Log;
|
||||||
|
import feign.Feign;
|
||||||
|
import feign.form.FormEncoder;
|
||||||
|
import net.geedge.asw.module.feign.client.GeoipClient;
|
||||||
|
import net.geedge.asw.module.feign.client.KibanaClient;
|
||||||
|
import net.geedge.asw.module.feign.client.WebSharkClient;
|
||||||
|
import net.geedge.asw.module.feign.client.ZeekClient;
|
||||||
|
import net.geedge.asw.module.feign.support.Fastjson2Decoder;
|
||||||
|
import net.geedge.asw.module.feign.support.Fastjson2Encoder;
|
||||||
|
import net.geedge.asw.module.feign.support.Http2Client;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class FeignClientConfiguration {
|
||||||
|
|
||||||
|
private static final Log log = Log.get();
|
||||||
|
|
||||||
|
@Value("${zeek.url:127.0.0.1:8086}")
|
||||||
|
private String zeekUrl;
|
||||||
|
|
||||||
|
@Value("${geoip.url:127.0.0.1:8087}")
|
||||||
|
private String geoipUrl;
|
||||||
|
|
||||||
|
@Value("${kibana.url:127.0.0.1:5601}")
|
||||||
|
private String kibanaUrl;
|
||||||
|
|
||||||
|
@Value("${webShark.url:127.0.0.1:8085}")
|
||||||
|
private String websharkurl;
|
||||||
|
|
||||||
|
@Bean("zeekClient")
|
||||||
|
public ZeekClient zeekClient() {
|
||||||
|
String url = UrlBuilder.ofHttp(zeekUrl).toString();
|
||||||
|
log.info("[zeekClient] [url: {}]", url);
|
||||||
|
return Feign.builder()
|
||||||
|
.encoder(new FormEncoder())
|
||||||
|
.decoder(new Fastjson2Decoder())
|
||||||
|
.client(new Http2Client())
|
||||||
|
.target(ZeekClient.class, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean("geoipClient")
|
||||||
|
public GeoipClient geoipClient() {
|
||||||
|
String url = UrlBuilder.ofHttp(geoipUrl).toString();
|
||||||
|
log.info("[geoipClient] [url: {}]", url);
|
||||||
|
return Feign.builder()
|
||||||
|
.encoder(new Fastjson2Encoder())
|
||||||
|
.decoder(new Fastjson2Decoder())
|
||||||
|
.client(new Http2Client())
|
||||||
|
.target(GeoipClient.class, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean("kibanaClient")
|
||||||
|
public KibanaClient kibanaClient() {
|
||||||
|
String url = UrlBuilder.ofHttp(kibanaUrl).toString();
|
||||||
|
log.info("[kibanaClient] [url: {}]", url);
|
||||||
|
return Feign.builder()
|
||||||
|
.encoder(new Fastjson2Encoder())
|
||||||
|
.decoder(new Fastjson2Decoder())
|
||||||
|
.client(new Http2Client())
|
||||||
|
.target(KibanaClient.class, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean("webSharkClient")
|
||||||
|
public WebSharkClient webSharkClient() {
|
||||||
|
String url = UrlBuilder.ofHttp(websharkurl).toString();
|
||||||
|
log.info("[webSharkClient] [url: {}]", url);
|
||||||
|
return Feign.builder()
|
||||||
|
.encoder(new FormEncoder())
|
||||||
|
.decoder(new Fastjson2Decoder())
|
||||||
|
.client(new Http2Client())
|
||||||
|
.target(WebSharkClient.class, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package net.geedge.asw.module.feign;
|
||||||
|
|
||||||
|
import cn.hutool.log.Log;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.auth.AuthScope;
|
||||||
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
|
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||||
|
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||||
|
import org.apache.http.impl.nio.reactor.IOReactorConfig;
|
||||||
|
import org.apache.http.ssl.SSLContextBuilder;
|
||||||
|
import org.opensearch.client.RestClient;
|
||||||
|
import org.opensearch.client.RestClientBuilder;
|
||||||
|
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
|
||||||
|
import org.opensearch.client.opensearch.OpenSearchClient;
|
||||||
|
import org.opensearch.client.opensearch.core.InfoResponse;
|
||||||
|
import org.opensearch.client.transport.OpenSearchTransport;
|
||||||
|
import org.opensearch.client.transport.rest_client.RestClientTransport;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class OpenSearchClientConfiguration {
|
||||||
|
|
||||||
|
private static final Log log = Log.get();
|
||||||
|
|
||||||
|
@Value("${opensearch.url:127.0.0.1:7200}")
|
||||||
|
private String hostAndPort;
|
||||||
|
|
||||||
|
@Value("${opensearch.username:admin}")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Value("${opensearch.password:G1egG2U4NrjHRzV}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Bean("openSearchClient")
|
||||||
|
public OpenSearchClient openSearchClient() {
|
||||||
|
try {
|
||||||
|
if (T.StrUtil.hasEmpty(this.hostAndPort, this.username, this.password)) {
|
||||||
|
throw new IllegalArgumentException("OpenSearchClient init info cannot be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||||
|
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
|
||||||
|
|
||||||
|
// Setup SSL context to trust all certificates
|
||||||
|
SSLContext sslContext = SSLContextBuilder.create()
|
||||||
|
.loadTrustMaterial((chain, authType) -> true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String[] split = this.hostAndPort.split(":");
|
||||||
|
String host = split[0];
|
||||||
|
Integer port = Integer.valueOf(split[1]);
|
||||||
|
SSLContext finalSslContext = sslContext;
|
||||||
|
RestClientBuilder builder = RestClient.builder(
|
||||||
|
new HttpHost(host, port, "https"))
|
||||||
|
.setHttpClientConfigCallback(httpAsyncClientBuilder -> {
|
||||||
|
httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
|
||||||
|
.setSSLContext(finalSslContext)
|
||||||
|
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
|
||||||
|
.setDefaultIOReactorConfig(
|
||||||
|
IOReactorConfig.custom()
|
||||||
|
.setIoThreadCount(1)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
return httpAsyncClientBuilder;
|
||||||
|
});
|
||||||
|
|
||||||
|
RestClient restClient = builder.build();
|
||||||
|
OpenSearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
|
||||||
|
OpenSearchClient client = new OpenSearchClient(transport);
|
||||||
|
|
||||||
|
InfoResponse info = client.info();
|
||||||
|
log.info("[openSearchClient] [url: {}] [{}]", this.hostAndPort, info.version().distribution() + ": " + info.version().number());
|
||||||
|
return client;
|
||||||
|
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | IOException e) {
|
||||||
|
log.error("[openSearchClient] [error] [url: {}]", this.hostAndPort);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package net.geedge.asw.module.feign.client;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import feign.Param;
|
||||||
|
import feign.RequestLine;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
|
||||||
|
@FeignClient(name = "geoipClient")
|
||||||
|
public interface GeoipClient {
|
||||||
|
|
||||||
|
@RequestLine("GET /geoip?ips={ip}")
|
||||||
|
JSONArray geoip(@Param("ip") String ipAddress);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package net.geedge.asw.module.feign.client;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import feign.Headers;
|
||||||
|
import feign.Param;
|
||||||
|
import feign.RequestLine;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
|
||||||
|
@FeignClient(name = "kibanaClient")
|
||||||
|
@Headers("Authorization: Bearer {token}")
|
||||||
|
public interface KibanaClient {
|
||||||
|
|
||||||
|
@RequestLine("GET /api/saved_objects/_find?fields=title&per_page=10000&type=index-pattern&search_fields=title&search={name}")
|
||||||
|
JSONObject findIndexPattern(@Param("token") String token, @Param("name") String name);
|
||||||
|
|
||||||
|
@Headers({
|
||||||
|
"Content-Type: application/json",
|
||||||
|
"osd-xsrf: true"
|
||||||
|
})
|
||||||
|
@RequestLine("POST /api/saved_objects/index-pattern/{id}")
|
||||||
|
JSONObject saveIndexPattern(@Param("token") String token, @Param("id") String id, JSONObject body);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package net.geedge.asw.module.feign.client;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import feign.Headers;
|
||||||
|
import feign.Param;
|
||||||
|
import feign.RequestLine;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@FeignClient(name = "webSharkClient")
|
||||||
|
public interface WebSharkClient {
|
||||||
|
|
||||||
|
@RequestLine("POST /webshark/upload")
|
||||||
|
@Headers("Content-Type: multipart/form-data")
|
||||||
|
JSONObject upload(@Param("fileKey") File file);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package net.geedge.asw.module.feign.client;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import feign.Headers;
|
||||||
|
import feign.Param;
|
||||||
|
import feign.RequestLine;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
@FeignClient(name = "zeekClient")
|
||||||
|
public interface ZeekClient {
|
||||||
|
|
||||||
|
@RequestLine("POST /upload")
|
||||||
|
@Headers("Content-Type: multipart/form-data")
|
||||||
|
JSONArray parser(@Param("pcap") File file);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2024 The Feign Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package net.geedge.asw.module.feign.support;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONException;
|
||||||
|
import com.alibaba.fastjson2.JSONReader;
|
||||||
|
import feign.FeignException;
|
||||||
|
import feign.Response;
|
||||||
|
import feign.Util;
|
||||||
|
import feign.codec.Decoder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import static feign.Util.ensureClosed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author changjin wei(魏昌进)
|
||||||
|
*/
|
||||||
|
public class Fastjson2Decoder implements Decoder {
|
||||||
|
|
||||||
|
private final JSONReader.Feature[] features;
|
||||||
|
|
||||||
|
public Fastjson2Decoder() {
|
||||||
|
this(new JSONReader.Feature[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fastjson2Decoder(JSONReader.Feature[] features) {
|
||||||
|
this.features = features;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object decode(Response response, Type type) throws IOException, FeignException {
|
||||||
|
if (response.status() == 404 || response.status() == 204) return Util.emptyValueOf(type);
|
||||||
|
if (response.body() == null) return null;
|
||||||
|
Reader reader = response.body().asReader(response.charset());
|
||||||
|
try {
|
||||||
|
return JSON.parseObject(reader, type, features);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
if (e.getCause() != null && e.getCause() instanceof IOException) {
|
||||||
|
throw IOException.class.cast(e.getCause());
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
ensureClosed(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2024 The Feign Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package net.geedge.asw.module.feign.support;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONWriter;
|
||||||
|
import feign.RequestTemplate;
|
||||||
|
import feign.Util;
|
||||||
|
import feign.codec.EncodeException;
|
||||||
|
import feign.codec.Encoder;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author changjin wei(魏昌进)
|
||||||
|
*/
|
||||||
|
public class Fastjson2Encoder implements Encoder {
|
||||||
|
|
||||||
|
private final JSONWriter.Feature[] features;
|
||||||
|
|
||||||
|
public Fastjson2Encoder() {
|
||||||
|
this(new JSONWriter.Feature[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fastjson2Encoder(JSONWriter.Feature[] features) {
|
||||||
|
this.features = features;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
|
||||||
|
template.body(JSON.toJSONBytes(object, features), Util.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2024 The Feign Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package net.geedge.asw.module.feign.support;
|
||||||
|
|
||||||
|
import feign.*;
|
||||||
|
import feign.Request.Options;
|
||||||
|
import feign.Request.ProtocolVersion;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpClient.Redirect;
|
||||||
|
import java.net.http.HttpClient.Version;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpRequest.BodyPublisher;
|
||||||
|
import java.net.http.HttpRequest.BodyPublishers;
|
||||||
|
import java.net.http.HttpRequest.Builder;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.net.http.HttpResponse.BodyHandlers;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static feign.Util.enumForName;
|
||||||
|
|
||||||
|
public class Http2Client implements Client, AsyncClient<Object> {
|
||||||
|
|
||||||
|
private final HttpClient client;
|
||||||
|
|
||||||
|
private final Map<Integer, SoftReference<HttpClient>> clients = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the new Http2Client using following defaults:
|
||||||
|
* <ul>
|
||||||
|
* <li>Connect Timeout: 10 seconds, as {@link Request.Options#Options()} uses</li>
|
||||||
|
* <li>Follow all 3xx redirects</li>
|
||||||
|
* <li>HTTP 2</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @see Request.Options#Options()
|
||||||
|
*/
|
||||||
|
public Http2Client() {
|
||||||
|
this(HttpClient.newBuilder()
|
||||||
|
.followRedirects(Redirect.ALWAYS)
|
||||||
|
.version(Version.HTTP_2)
|
||||||
|
.connectTimeout(Duration.ofMillis(10000))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Http2Client(Options options) {
|
||||||
|
this(newClientBuilder(options)
|
||||||
|
.version(Version.HTTP_2)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Http2Client(HttpClient client) {
|
||||||
|
this.client = Util.checkNotNull(client, "HttpClient must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response execute(Request request, Options options) throws IOException {
|
||||||
|
final HttpRequest httpRequest;
|
||||||
|
try {
|
||||||
|
httpRequest = newRequestBuilder(request, options)
|
||||||
|
.version(client.version())
|
||||||
|
.build();
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new IOException("Invalid uri " + request.url(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient clientForRequest = getOrCreateClient(options);
|
||||||
|
HttpResponse<InputStream> httpResponse;
|
||||||
|
try {
|
||||||
|
httpResponse = clientForRequest.send(httpRequest, BodyHandlers.ofInputStream());
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return toFeignResponse(request, httpResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Response> execute(Request request,
|
||||||
|
Options options,
|
||||||
|
Optional<Object> requestContext) {
|
||||||
|
HttpRequest httpRequest;
|
||||||
|
try {
|
||||||
|
httpRequest = newRequestBuilder(request, options).build();
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new IllegalArgumentException("Invalid uri " + request.url(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient clientForRequest = getOrCreateClient(options);
|
||||||
|
CompletableFuture<HttpResponse<InputStream>> future =
|
||||||
|
clientForRequest.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofInputStream());
|
||||||
|
return future.thenApply(httpResponse -> toFeignResponse(request, httpResponse));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Response toFeignResponse(Request request, HttpResponse<InputStream> httpResponse) {
|
||||||
|
final OptionalLong length = httpResponse.headers().firstValueAsLong("Content-Length");
|
||||||
|
|
||||||
|
return Response.builder()
|
||||||
|
.protocolVersion(enumForName(ProtocolVersion.class, httpResponse.version()))
|
||||||
|
.body(httpResponse.body(), length.isPresent() ? (int) length.getAsLong() : null)
|
||||||
|
.reason(httpResponse.headers().firstValue("Reason-Phrase").orElse(null))
|
||||||
|
.request(request)
|
||||||
|
.status(httpResponse.statusCode())
|
||||||
|
.headers(castMapCollectType(httpResponse.headers().map()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpClient getOrCreateClient(Options options) {
|
||||||
|
if (doesClientConfigurationDiffer(options)) {
|
||||||
|
// create a new client from the existing one - but with connectTimeout and followRedirect
|
||||||
|
// settings from options
|
||||||
|
final int clientKey = createClientKey(options);
|
||||||
|
|
||||||
|
SoftReference<HttpClient> requestScopedSoftReference = clients.get(clientKey);
|
||||||
|
HttpClient requestScoped =
|
||||||
|
requestScopedSoftReference == null ? null : requestScopedSoftReference.get();
|
||||||
|
|
||||||
|
if (requestScoped == null) {
|
||||||
|
java.net.http.HttpClient.Builder builder = newClientBuilder(options)
|
||||||
|
.sslContext(client.sslContext())
|
||||||
|
.sslParameters(client.sslParameters())
|
||||||
|
.version(client.version());
|
||||||
|
client.authenticator().ifPresent(builder::authenticator);
|
||||||
|
client.cookieHandler().ifPresent(builder::cookieHandler);
|
||||||
|
client.executor().ifPresent(builder::executor);
|
||||||
|
client.proxy().ifPresent(builder::proxy);
|
||||||
|
requestScoped = builder.build();
|
||||||
|
clients.put(clientKey, new SoftReference<>(requestScoped));
|
||||||
|
}
|
||||||
|
return requestScoped;
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doesClientConfigurationDiffer(Options options) {
|
||||||
|
if ((client.followRedirects() == Redirect.ALWAYS) != options.isFollowRedirects()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return client.connectTimeout()
|
||||||
|
.map(timeout -> timeout.toMillis() != options.connectTimeoutMillis())
|
||||||
|
.orElse(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates integer key that represents {@link Options} settings based on
|
||||||
|
* {@link Http2Client#doesClientConfigurationDiffer(Options)} method
|
||||||
|
*
|
||||||
|
* @param options value
|
||||||
|
* @return integer key
|
||||||
|
*/
|
||||||
|
public int createClientKey(feign.Request.Options options) {
|
||||||
|
int key = options.connectTimeoutMillis();
|
||||||
|
if (options.isFollowRedirects()) {
|
||||||
|
key |= 1 << 31; // connectTimeoutMillis always positive, so we can use first sign bit for
|
||||||
|
// isFollowRedirects flag
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static java.net.http.HttpClient.Builder newClientBuilder(Options options) {
|
||||||
|
return HttpClient
|
||||||
|
.newBuilder()
|
||||||
|
.followRedirects(options.isFollowRedirects() ? Redirect.ALWAYS : Redirect.NEVER)
|
||||||
|
.connectTimeout(Duration.ofMillis(options.connectTimeoutMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Builder newRequestBuilder(Request request, Options options) throws URISyntaxException {
|
||||||
|
URI uri = new URI(request.url());
|
||||||
|
|
||||||
|
final BodyPublisher body;
|
||||||
|
final byte[] data = request.body();
|
||||||
|
if (data == null) {
|
||||||
|
body = BodyPublishers.noBody();
|
||||||
|
} else {
|
||||||
|
body = BodyPublishers.ofByteArray(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Builder requestBuilder = HttpRequest.newBuilder()
|
||||||
|
.uri(uri)
|
||||||
|
.timeout(Duration.ofMillis(options.readTimeoutMillis()))
|
||||||
|
.version(client.version());
|
||||||
|
|
||||||
|
final Map<String, Collection<String>> headers = filterRestrictedHeaders(request.headers());
|
||||||
|
if (!headers.isEmpty()) {
|
||||||
|
requestBuilder.headers(asString(headers));
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestBuilder.method(request.httpMethod().toString(), body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There is a bunch o headers that the http2 client do not allow to be set.
|
||||||
|
*
|
||||||
|
* @see jdk.internal.net.http.common.Utils.DISALLOWED_HEADERS_SET
|
||||||
|
*/
|
||||||
|
private static final Set<String> DISALLOWED_HEADERS_SET;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// A case insensitive TreeSet of strings.
|
||||||
|
final TreeSet<String> treeSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
treeSet.addAll(Set.of("connection", "content-length", "expect", "host", "upgrade"));
|
||||||
|
DISALLOWED_HEADERS_SET = Collections.unmodifiableSet(treeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Collection<String>> filterRestrictedHeaders(Map<String, Collection<String>> headers) {
|
||||||
|
final Map<String, Collection<String>> filteredHeaders = headers.keySet()
|
||||||
|
.stream()
|
||||||
|
.filter(headerName -> !DISALLOWED_HEADERS_SET.contains(headerName))
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
Function.identity(),
|
||||||
|
headers::get));
|
||||||
|
|
||||||
|
filteredHeaders.computeIfAbsent("Accept", key -> List.of("*/*"));
|
||||||
|
|
||||||
|
return filteredHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Collection<String>> castMapCollectType(Map<String, List<String>> map) {
|
||||||
|
final Map<String, Collection<String>> result = new HashMap<>();
|
||||||
|
map.forEach((key, value) -> result.put(key, new HashSet<>(value)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] asString(Map<String, Collection<String>> headers) {
|
||||||
|
return headers.entrySet().stream()
|
||||||
|
.flatMap(entry -> entry.getValue()
|
||||||
|
.stream()
|
||||||
|
.map(value -> Arrays.asList(entry.getKey(), value))
|
||||||
|
.flatMap(List::stream))
|
||||||
|
.toArray(String[]::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,29 @@
|
|||||||
package net.geedge.asw.module.runner.controller;
|
package net.geedge.asw.module.runner.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DatePattern;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.net.url.UrlBuilder;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
import cn.hutool.log.Log;
|
import cn.hutool.log.Log;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import net.geedge.asw.common.util.R;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import net.geedge.asw.common.util.RCode;
|
import net.geedge.asw.common.config.SpringContextUtils;
|
||||||
import net.geedge.asw.common.util.T;
|
import net.geedge.asw.common.util.*;
|
||||||
|
import net.geedge.asw.module.feign.client.WebSharkClient;
|
||||||
import net.geedge.asw.module.runner.entity.PcapEntity;
|
import net.geedge.asw.module.runner.entity.PcapEntity;
|
||||||
import net.geedge.asw.module.runner.service.IPcapService;
|
import net.geedge.asw.module.runner.service.IPcapService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/pcap")
|
@RequestMapping("/api/v1/pcap")
|
||||||
@@ -23,6 +34,9 @@ public class PcapController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IPcapService pcapService;
|
private IPcapService pcapService;
|
||||||
|
|
||||||
|
@Value("${webShark.url:127.0.0.1:8085}")
|
||||||
|
private String websharkurl;
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public R detail(@PathVariable("id") String id) {
|
public R detail(@PathVariable("id") String id) {
|
||||||
PcapEntity pcapEntity = pcapService.queryInfo(id);
|
PcapEntity pcapEntity = pcapService.queryInfo(id);
|
||||||
@@ -39,20 +53,119 @@ public class PcapController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public R add(@RequestParam(value = "file", required = true) MultipartFile file,
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@RequestParam(required = false) String tags,
|
public R add(@RequestParam(value = "files", required = true) List<MultipartFile> fileList,
|
||||||
|
@RequestParam(value = "descriptions", required = false) List<String> descriptionList,
|
||||||
@RequestParam(required = false) String workbookId,
|
@RequestParam(required = false) String workbookId,
|
||||||
@RequestParam(required = false) String workspaceId) throws IOException {
|
@RequestParam(required = false) String workspaceId) throws IOException {
|
||||||
T.VerifyUtil.is(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
T.VerifyUtil.is(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||||
|
|
||||||
PcapEntity pcapEntity = pcapService.savePcap(file.getResource(), tags, workbookId, workspaceId);
|
List<Object> recordList = T.ListUtil.list(true);
|
||||||
return R.ok().putData("id", pcapEntity.getId());
|
for (int i = 0; i < fileList.size(); i++) {
|
||||||
|
MultipartFile file = fileList.get(i);
|
||||||
|
String description = T.StrUtil.emptyToDefault(T.CollUtil.get(descriptionList, i), "");
|
||||||
|
PcapEntity pcapEntity = pcapService.savePcap(file.getResource(), description, workbookId, workspaceId);
|
||||||
|
recordList.add(
|
||||||
|
T.MapUtil.builder()
|
||||||
|
.put("id", pcapEntity.getId())
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return R.ok().putData("records", recordList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@PutMapping
|
||||||
public R delete(@PathVariable("id") String id) {
|
@Transactional(rollbackFor = Exception.class)
|
||||||
pcapService.deletePcap(id);
|
public R update(@RequestBody List<Map<String, String>> body) {
|
||||||
|
List<Object> recordList = T.ListUtil.list(true);
|
||||||
|
for (Map<String, String> map : body) {
|
||||||
|
String id = T.MapUtil.getStr(map, "id", "");
|
||||||
|
if (T.StrUtil.isEmpty(id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String description = T.MapUtil.getStr(map, "description", "");
|
||||||
|
pcapService.update(new LambdaUpdateWrapper<PcapEntity>()
|
||||||
|
.eq(PcapEntity::getId, id)
|
||||||
|
.set(PcapEntity::getDescription, description)
|
||||||
|
);
|
||||||
|
recordList.add(
|
||||||
|
T.MapUtil.builder()
|
||||||
|
.put("id", id)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return R.ok().putData("records", recordList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping
|
||||||
|
public R delete(String[] ids) {
|
||||||
|
T.VerifyUtil.is(ids).notEmpty();
|
||||||
|
|
||||||
|
pcapService.deletePcap(ids);
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/parse2session")
|
||||||
|
public R parse2session(String[] ids) {
|
||||||
|
T.VerifyUtil.is(ids).notEmpty();
|
||||||
|
|
||||||
|
pcapService.parse2session(ids);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/download")
|
||||||
|
public void download(HttpServletResponse response, String ids) throws IOException {
|
||||||
|
T.VerifyUtil.is(ids).notEmpty();
|
||||||
|
List<String> pcapIdList = Arrays.asList(ids.split(","));
|
||||||
|
List<PcapEntity> pcapList = pcapService.listByIds(pcapIdList);
|
||||||
|
if (T.CollectionUtil.isNotEmpty(pcapList) && pcapList.size() == 1) {
|
||||||
|
PcapEntity first = pcapList.getFirst();
|
||||||
|
File pcapFile = T.FileUtil.file(first.getPath());
|
||||||
|
ResponseUtil.downloadFile(response, MediaType.APPLICATION_OCTET_STREAM_VALUE, first.getName(), T.FileUtil.readBytes(pcapFile));
|
||||||
|
}
|
||||||
|
if (pcapList.size() > 1) {
|
||||||
|
File zipFile = T.FileUtil.file(T.StrUtil.concat(true, Constants.TEMP_PATH, "/", "pcap-", DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN) + ".zip"));
|
||||||
|
List<File> fileList = pcapList.stream().map(x -> T.FileUtil.file(x.getPath())).toList();
|
||||||
|
T.ZipUtil.zip(zipFile, false, fileList.toArray(new File[0]));
|
||||||
|
ResponseUtil.downloadFile(response, zipFile.getName(), T.FileUtil.readBytes(zipFile));
|
||||||
|
T.FileUtil.del(zipFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}/webshark")
|
||||||
|
public R webshark(@PathVariable String id) {
|
||||||
|
T.VerifyUtil.is(id).notEmpty();
|
||||||
|
|
||||||
|
HashMap<Object, Object> result = T.MapUtil.newHashMap();
|
||||||
|
PcapEntity pcap = pcapService.getById(id);
|
||||||
|
File pcapFile = T.FileUtil.file(pcap.getPath());
|
||||||
|
String uploadFileName = T.StrUtil.concat(true, id, ".", T.FileUtil.getSuffix(pcapFile));
|
||||||
|
File newFile = FileUtil.copy(pcapFile, FileUtil.file(Constants.TEMP_PATH, uploadFileName), false);
|
||||||
|
try {
|
||||||
|
WebSharkClient webSharkClient = (WebSharkClient) SpringContextUtils.getBean("webSharkClient");
|
||||||
|
JSONObject obj = webSharkClient.upload(newFile);
|
||||||
|
|
||||||
|
String baseUrl = UrlBuilder.ofHttp(websharkurl)
|
||||||
|
.addPath("/webshark")
|
||||||
|
.toString();
|
||||||
|
result.put("fileName", uploadFileName);
|
||||||
|
result.put("url", baseUrl);
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error(e, "webshark upload pcap error, id: {}", pcap.getId());
|
||||||
|
throw new ASWException(RCode.PCAP_UPLOAD_WEB_SHARK_ERROR);
|
||||||
|
}finally {
|
||||||
|
FileUtil.del(newFile);
|
||||||
|
}
|
||||||
|
return R.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PutMapping("/unparse2session")
|
||||||
|
public R unparse2session(String[] ids) {
|
||||||
|
T.VerifyUtil.is(ids).notEmpty();
|
||||||
|
|
||||||
|
pcapService.unparse2session(ids);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package net.geedge.asw.module.runner.dao;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import net.geedge.asw.module.runner.entity.DecodeRecordEntity;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface DecodeRecordDao extends BaseMapper<DecodeRecordEntity>{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package net.geedge.asw.module.runner.entity;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@TableName("decode_record")
|
|
||||||
public class DecodeRecordEntity {
|
|
||||||
|
|
||||||
@TableId(type = IdType.ASSIGN_UUID)
|
|
||||||
private String id;
|
|
||||||
private String pcapId;
|
|
||||||
private Long streamId;
|
|
||||||
private String streamAttributes;
|
|
||||||
private String workspaceId;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||||
import net.geedge.asw.module.app.entity.PackageEntity;
|
import net.geedge.asw.module.app.entity.PackageEntity;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("pcap")
|
@TableName("pcap")
|
||||||
@@ -16,21 +17,19 @@ public class PcapEntity {
|
|||||||
@TableId(type = IdType.ASSIGN_UUID)
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
private String name;
|
||||||
private String tags;
|
|
||||||
private String description;
|
private String description;
|
||||||
private String path;
|
private String path;
|
||||||
private Long size;
|
private Long size;
|
||||||
private Long connections;
|
|
||||||
private Long hosts;
|
|
||||||
private String md5;
|
private String md5;
|
||||||
private Long connectionTimeFirst;
|
|
||||||
private Long connectionTimeLast;
|
|
||||||
private String protocols;
|
|
||||||
private String status;
|
private String status;
|
||||||
|
private String summary;
|
||||||
private Long createTimestamp;
|
private Long createTimestamp;
|
||||||
private String createUserId;
|
private String createUserId;
|
||||||
private String workspaceId;
|
private String workspaceId;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private WorkspaceEntity workspace;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String jobId;
|
private String jobId;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package net.geedge.asw.module.runner.service;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import net.geedge.asw.module.runner.entity.DecodeRecordEntity;
|
|
||||||
|
|
||||||
public interface IDecodeRecordService extends IService<DecodeRecordEntity>{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -17,6 +17,9 @@ public interface IPcapService extends IService<PcapEntity>{
|
|||||||
|
|
||||||
PcapEntity savePcap(Resource fileResource,String... params);
|
PcapEntity savePcap(Resource fileResource,String... params);
|
||||||
|
|
||||||
void deletePcap(String id);
|
void deletePcap(String... ids);
|
||||||
|
|
||||||
|
void parse2session(String... ids);
|
||||||
|
|
||||||
|
void unparse2session(String[] ids);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
package net.geedge.asw.module.runner.service.impl;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import net.geedge.asw.module.runner.dao.DecodeRecordDao;
|
|
||||||
import net.geedge.asw.module.runner.entity.DecodeRecordEntity;
|
|
||||||
import net.geedge.asw.module.runner.service.IDecodeRecordService;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class DecodeRecordServiceImpl extends ServiceImpl<DecodeRecordDao, DecodeRecordEntity> implements IDecodeRecordService {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import net.geedge.asw.common.config.SpringContextUtils;
|
||||||
|
import net.geedge.asw.common.util.ASWException;
|
||||||
import net.geedge.asw.common.util.RCode;
|
import net.geedge.asw.common.util.RCode;
|
||||||
import net.geedge.asw.common.util.T;
|
import net.geedge.asw.common.util.T;
|
||||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||||
@@ -25,8 +27,14 @@ import net.geedge.asw.module.runner.util.PcapParserThread;
|
|||||||
import net.geedge.asw.module.runner.util.RunnerConstant;
|
import net.geedge.asw.module.runner.util.RunnerConstant;
|
||||||
import net.geedge.asw.module.workbook.service.IWorkbookResourceService;
|
import net.geedge.asw.module.workbook.service.IWorkbookResourceService;
|
||||||
import net.geedge.asw.module.workbook.util.WorkbookConstant;
|
import net.geedge.asw.module.workbook.util.WorkbookConstant;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.opensearch.client.opensearch.OpenSearchClient;
|
||||||
|
import org.opensearch.client.opensearch.indices.DeleteIndexRequest;
|
||||||
|
import org.opensearch.client.opensearch.indices.ExistsRequest;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -35,11 +43,20 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements IPcapService {
|
public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements IPcapService {
|
||||||
private static final Log log = Log.get();
|
private static final Log log = Log.get();
|
||||||
|
|
||||||
|
@Value("${sharkdApi.host:127.0.0.1}")
|
||||||
|
private String sharkdApiHostAddr;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IJobService jobService;
|
private IJobService jobService;
|
||||||
|
|
||||||
@@ -58,6 +75,9 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IWorkbookResourceService workbookResourceService;
|
private IWorkbookResourceService workbookResourceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWorkspaceService workspaceService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PcapEntity queryInfo(String id) {
|
public PcapEntity queryInfo(String id) {
|
||||||
PcapEntity pcap = this.getById(id);
|
PcapEntity pcap = this.getById(id);
|
||||||
@@ -101,7 +121,7 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PcapEntity savePcap(Resource fileResource, String... params) {
|
public PcapEntity savePcap(Resource fileResource, String... params) {
|
||||||
String tags = T.ArrayUtil.get(params, 0);
|
String description = T.ArrayUtil.get(params, 0);
|
||||||
String workbookId = T.ArrayUtil.get(params, 1);
|
String workbookId = T.ArrayUtil.get(params, 1);
|
||||||
String workspaceId = T.ArrayUtil.get(params, 2);
|
String workspaceId = T.ArrayUtil.get(params, 2);
|
||||||
String createUserId = T.StrUtil.emptyToDefault(T.ArrayUtil.get(params, 3), StpUtil.getLoginIdAsString());
|
String createUserId = T.StrUtil.emptyToDefault(T.ArrayUtil.get(params, 3), StpUtil.getLoginIdAsString());
|
||||||
@@ -109,7 +129,7 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
|||||||
PcapEntity entity = new PcapEntity();
|
PcapEntity entity = new PcapEntity();
|
||||||
try {
|
try {
|
||||||
entity.setName(fileResource.getFilename());
|
entity.setName(fileResource.getFilename());
|
||||||
entity.setTags(T.StrUtil.emptyToDefault(tags, ""));
|
entity.setDescription(description);
|
||||||
|
|
||||||
byte[] bytes = fileResource.getInputStream().readAllBytes();
|
byte[] bytes = fileResource.getInputStream().readAllBytes();
|
||||||
entity.setSize((long) bytes.length);
|
entity.setSize((long) bytes.length);
|
||||||
@@ -129,10 +149,8 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
|||||||
entity.setMd5(md5Hex);
|
entity.setMd5(md5Hex);
|
||||||
|
|
||||||
// 根据文件 md5值 判断是否已上存在,存在则响应当前实体
|
// 根据文件 md5值 判断是否已上存在,存在则响应当前实体
|
||||||
PcapEntity findPcapByMd5 = this.getOne(new LambdaQueryWrapper<PcapEntity>().eq(PcapEntity::getMd5, md5Hex));
|
PcapEntity findPcapByMd5 = this.getOne(new LambdaQueryWrapper<PcapEntity>().eq(PcapEntity::getMd5, md5Hex).eq(PcapEntity::getWorkspaceId, workspaceId));
|
||||||
if (T.ObjectUtil.isNotNull(findPcapByMd5)) {
|
if (T.ObjectUtil.isNotNull(findPcapByMd5)) {
|
||||||
// 删除本次记录的文件
|
|
||||||
T.FileUtil.del(destination);
|
|
||||||
return findPcapByMd5;
|
return findPcapByMd5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,32 +159,129 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
|||||||
|
|
||||||
// workbook resource
|
// workbook resource
|
||||||
workbookResourceService.saveResource(workbookId, entity.getId(), WorkbookConstant.ResourceType.PCAP.getValue());
|
workbookResourceService.saveResource(workbookId, entity.getId(), WorkbookConstant.ResourceType.PCAP.getValue());
|
||||||
|
|
||||||
// parser
|
|
||||||
PcapParserThread pcapParserThread = new PcapParserThread();
|
|
||||||
pcapParserThread.setPcapEntity(entity);
|
|
||||||
T.ThreadUtil.execAsync(pcapParserThread);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error(e, "[savePcap] [error] [workspaceId: {}]", workspaceId);
|
log.error(e, "[savePcap] [error] [workspaceId: {}]", workspaceId);
|
||||||
|
throw new ASWException(RCode.ERROR);
|
||||||
}
|
}
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deletePcap(String pcapId) {
|
public void deletePcap(String... ids) {
|
||||||
PcapEntity pcap = this.getById(pcapId);
|
for (String id : ids) {
|
||||||
// remove file
|
PcapEntity pcap = this.getById(id);
|
||||||
T.FileUtil.del(pcap.getPath());
|
// remove file
|
||||||
|
T.FileUtil.del(pcap.getPath());
|
||||||
|
|
||||||
// remove
|
// remove
|
||||||
this.removeById(pcapId);
|
this.removeById(id);
|
||||||
|
|
||||||
// update job pcap_id
|
// update job pcap_id
|
||||||
jobService.update(new LambdaUpdateWrapper<JobEntity>()
|
jobService.update(new LambdaUpdateWrapper<JobEntity>()
|
||||||
.set(JobEntity::getPcapId, "")
|
.set(JobEntity::getPcapId, "")
|
||||||
.eq(JobEntity::getPcapId, pcapId)
|
.eq(JobEntity::getPcapId, id)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parse2session(String... ids) {
|
||||||
|
List<Runnable> taskList = T.ListUtil.list(true);
|
||||||
|
Long maxFileSize = 0L;
|
||||||
|
|
||||||
|
// parse thread config properties
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty("sharkdApiHostAddr", this.sharkdApiHostAddr);
|
||||||
|
|
||||||
|
for (String id : ids) {
|
||||||
|
PcapEntity pcapEntity = this.getById(id);
|
||||||
|
if (T.ObjectUtil.isNotNull(pcapEntity)) {
|
||||||
|
WorkspaceEntity workspace = workspaceService.getById(pcapEntity.getWorkspaceId());
|
||||||
|
pcapEntity.setWorkspace(workspace);
|
||||||
|
|
||||||
|
PcapParserThread pcapParserThread = new PcapParserThread();
|
||||||
|
pcapParserThread.setPcapEntity(pcapEntity);
|
||||||
|
pcapParserThread.setProperties(properties);
|
||||||
|
taskList.add(pcapParserThread);
|
||||||
|
|
||||||
|
Long size = pcapEntity.getSize();
|
||||||
|
if (size > maxFileSize) {
|
||||||
|
maxFileSize = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (T.CollUtil.isNotEmpty(taskList)) {
|
||||||
|
List<CompletableFuture<Void>> futures = taskList.stream()
|
||||||
|
.map(task -> CompletableFuture.runAsync(task))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
CompletableFuture<Void> allTasksFuture = CompletableFuture.allOf(
|
||||||
|
futures.toArray(new CompletableFuture[0])
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
allTasksFuture.get(this.calculateParseThreadTimeout(maxFileSize), TimeUnit.SECONDS);
|
||||||
|
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||||
|
log.error(e, "[parse2session] [error]");
|
||||||
|
throw new ASWException(RCode.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unparse2session(String[] ids) {
|
||||||
|
OpenSearchClient openSearchClient = (OpenSearchClient) SpringContextUtils.getBean("openSearchClient");
|
||||||
|
|
||||||
|
for (String id : ids) {
|
||||||
|
PcapEntity pcapEntity = this.getById(id);
|
||||||
|
if (T.ObjectUtil.isNotNull(pcapEntity)) {
|
||||||
|
WorkspaceEntity workspace = workspaceService.getById(pcapEntity.getWorkspaceId());
|
||||||
|
pcapEntity.setWorkspace(workspace);
|
||||||
|
String pcapPath = pcapEntity.getPath();
|
||||||
|
String md5Hex = T.DigestUtil.md5Hex(T.FileUtil.file(pcapPath));
|
||||||
|
|
||||||
|
String workspaceName = pcapEntity.getWorkspace().getName();
|
||||||
|
String indexName = String.format("workspace-%s-%s", workspaceName, md5Hex);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// check if index exists
|
||||||
|
boolean indexExists = openSearchClient.indices()
|
||||||
|
.exists(new ExistsRequest.Builder().index(indexName).build())
|
||||||
|
.value();
|
||||||
|
|
||||||
|
// if index exists, delete
|
||||||
|
if (indexExists) {
|
||||||
|
openSearchClient.indices().delete(new DeleteIndexRequest.Builder().index(indexName).build());
|
||||||
|
log.debug("delete openSearch index: {}", indexName);
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("delete openSearch index error index: {}", indexName);
|
||||||
|
throw new RuntimeException("delete openSearch index error ", e);
|
||||||
|
}
|
||||||
|
pcapEntity.setStatus(RunnerConstant.PcapStatus.UPLOADED.getValue());
|
||||||
|
this.updateById(pcapEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculate Parse Thread Timeout
|
||||||
|
*
|
||||||
|
* @param size
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private long calculateParseThreadTimeout(Long size) {
|
||||||
|
// 小于 1MB 的文件,超时时间为 1分钟
|
||||||
|
if (size <= 1048576) {
|
||||||
|
return 60;
|
||||||
|
// 小于10MB的文件,超时时间为 3分钟
|
||||||
|
} else if (size <= 1048576 * 10) {
|
||||||
|
return 60 * 3;
|
||||||
|
// 其他,超时时间为 10分钟
|
||||||
|
} else {
|
||||||
|
return 60 * 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,27 +1,51 @@
|
|||||||
package net.geedge.asw.module.runner.util;
|
package net.geedge.asw.module.runner.util;
|
||||||
|
|
||||||
import cn.hutool.log.Log;
|
import cn.hutool.log.Log;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import net.geedge.asw.common.config.SpringContextUtils;
|
import net.geedge.asw.common.config.SpringContextUtils;
|
||||||
import net.geedge.asw.common.util.T;
|
import net.geedge.asw.common.util.T;
|
||||||
|
import net.geedge.asw.module.feign.client.GeoipClient;
|
||||||
|
import net.geedge.asw.module.feign.client.ZeekClient;
|
||||||
import net.geedge.asw.module.runner.entity.PcapEntity;
|
import net.geedge.asw.module.runner.entity.PcapEntity;
|
||||||
import net.geedge.asw.module.runner.service.IPcapService;
|
import net.geedge.asw.module.runner.service.IPcapService;
|
||||||
|
import org.apache.commons.lang3.time.StopWatch;
|
||||||
|
import org.opensearch.client.opensearch.OpenSearchClient;
|
||||||
|
import org.opensearch.client.opensearch.core.BulkRequest;
|
||||||
|
import org.opensearch.client.opensearch.core.BulkResponse;
|
||||||
|
import org.opensearch.client.opensearch.core.bulk.BulkResponseItem;
|
||||||
|
import org.opensearch.client.opensearch.indices.CreateIndexRequest;
|
||||||
|
import org.opensearch.client.opensearch.indices.DeleteIndexRequest;
|
||||||
|
import org.opensearch.client.opensearch.indices.ExistsRequest;
|
||||||
|
import org.opensearch.client.opensearch.indices.IndexSettings;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static net.geedge.asw.module.runner.util.RunnerConstant.PcapStatus;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class PcapParserThread implements Runnable {
|
public class PcapParserThread implements Runnable {
|
||||||
|
|
||||||
private Log log = Log.get();
|
private Log log = Log.get();
|
||||||
|
|
||||||
|
private Properties properties;
|
||||||
|
|
||||||
private PcapEntity pcapEntity;
|
private PcapEntity pcapEntity;
|
||||||
private IPcapService pcapService;
|
private IPcapService pcapService;
|
||||||
|
|
||||||
|
private ZeekClient zeekClient;
|
||||||
|
private GeoipClient geoipClient;
|
||||||
|
private OpenSearchClient openSearchClient;
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
pcapService = SpringContextUtils.getBean(IPcapService.class);
|
pcapService = SpringContextUtils.getBean(IPcapService.class);
|
||||||
// analyzing
|
zeekClient = (ZeekClient) SpringContextUtils.getBean("zeekClient");
|
||||||
this.updatePcapStatus(RunnerConstant.PcapStatus.ANALYZING.getValue());
|
geoipClient = (GeoipClient) SpringContextUtils.getBean("geoipClient");
|
||||||
|
openSearchClient = (OpenSearchClient) SpringContextUtils.getBean("openSearchClient");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -31,19 +55,24 @@ public class PcapParserThread implements Runnable {
|
|||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("pcapInfo: {}", T.JSONUtil.toJsonStr(pcapEntity));
|
log.debug("pcapInfo: {}", T.JSONUtil.toJsonStr(pcapEntity));
|
||||||
}
|
}
|
||||||
|
StopWatch sw = new StopWatch();
|
||||||
|
sw.start();
|
||||||
try {
|
try {
|
||||||
log.info("job pcap parser run start");
|
|
||||||
// init
|
// init
|
||||||
this.init();
|
this.init();
|
||||||
|
// parsing
|
||||||
|
this.updateStatus(PcapStatus.PARSING.getValue());
|
||||||
// parser
|
// parser
|
||||||
this.parser();
|
this.parser();
|
||||||
log.info("job pcap parser run end");
|
// indexed
|
||||||
|
this.updateStatus(PcapStatus.INDEXED.getValue());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e, "job pcap parser error, pcap: {}", pcapEntity.getId());
|
// error
|
||||||
|
this.updateStatus(PcapStatus.ERROR.getValue());
|
||||||
|
log.error(e, "job pcap parser error, id: {}", pcapEntity.getId());
|
||||||
} finally {
|
} finally {
|
||||||
// completed
|
sw.stop();
|
||||||
this.updatePcapStatus(RunnerConstant.PcapStatus.COMPLETED.getValue());
|
log.info("job pcap parser end. id: {} Run Time: {}", pcapEntity.getId(), sw.toString());
|
||||||
log.info("job pcap parser end");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,27 +80,187 @@ public class PcapParserThread implements Runnable {
|
|||||||
* parser
|
* parser
|
||||||
*/
|
*/
|
||||||
private void parser() {
|
private void parser() {
|
||||||
String id = pcapEntity.getId();
|
// zeek
|
||||||
String path = pcapEntity.getPath();
|
JSONArray jsonArray = zeekClient.parser(T.FileUtil.file(pcapEntity.getPath()));
|
||||||
SignatureExtract signatureExtract = new SignatureExtract(id, path);
|
if (log.isDebugEnabled()) {
|
||||||
// signature
|
log.debug("[parse] [zeek parse pcap file] [size: {}]", jsonArray.size());
|
||||||
String signature = signatureExtract.signature();
|
}
|
||||||
// 保存结果,和 pcap 文件同目录,文件名:pcap_id_signature.json
|
|
||||||
String parentPath = T.FileUtil.getParent(path, 1);
|
|
||||||
File signatureFile = T.FileUtil.file(parentPath, id + "_signature.json");
|
|
||||||
T.FileUtil.del(signatureFile);
|
|
||||||
T.FileUtil.writeUtf8String(signature, signatureFile);
|
|
||||||
|
|
||||||
// TODO
|
// geoip
|
||||||
|
List<String> ipList = jsonArray.stream()
|
||||||
|
.map(obj -> T.MapUtil.getStr((JSONObject) obj, "id.resp_h", ""))
|
||||||
|
.filter(s -> T.StrUtil.isNotEmpty(s))
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Map<String, JSONObject> geoipInfo = this.queryGeoip(ipList);
|
||||||
|
|
||||||
|
// add custom field
|
||||||
|
String pcapId = pcapEntity.getId();
|
||||||
|
String pcapName = T.FileUtil.getName(pcapEntity.getPath());
|
||||||
|
Long tcpStream = 0L, udpStream = 0L;
|
||||||
|
|
||||||
|
String sharkdApiHostAddr = properties.getProperty("sharkdApiHostAddr", "127.0.0.1");
|
||||||
|
for (Object obj : jsonArray) {
|
||||||
|
JSONObject pojo = (JSONObject) obj;
|
||||||
|
pojo.put("pcap.id", pcapId);
|
||||||
|
pojo.put("pcap.name", pcapName);
|
||||||
|
|
||||||
|
String proto = T.MapUtil.getStr(pojo, "proto", "");
|
||||||
|
if (T.StrUtil.equalsIgnoreCase("tcp", proto)) {
|
||||||
|
Long streamId = tcpStream++;
|
||||||
|
pojo.put("pcap.tcp_stream", streamId);
|
||||||
|
pojo.put("pcap.stream_url", String.format("http://%s/pcap/%s/tcp/%s", sharkdApiHostAddr, pcapId, streamId));
|
||||||
|
}
|
||||||
|
if (T.StrUtil.equalsIgnoreCase("udp", proto)) {
|
||||||
|
Long streamId = udpStream++;
|
||||||
|
pojo.put("pcap.udp_stream", streamId);
|
||||||
|
pojo.put("pcap.stream_url", String.format("http://%s/pcap/%s/udp/%s", sharkdApiHostAddr, pcapId, streamId));
|
||||||
|
}
|
||||||
|
|
||||||
|
String resp = T.MapUtil.getStr(pojo, "id.resp_h", "");
|
||||||
|
if (T.StrUtil.isNotEmpty(resp)) {
|
||||||
|
JSONObject jsonObject = T.MapUtil.get(geoipInfo, resp, JSONObject.class, new JSONObject());
|
||||||
|
pojo.put("id.resp_country", T.MapUtil.getStr(jsonObject, "country", ""));
|
||||||
|
pojo.put("id.resp_asn", T.MapUtil.getStr(jsonObject, "asn", ""));
|
||||||
|
pojo.put("id.resp_asname", T.MapUtil.getStr(jsonObject, "asname", ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// summary
|
||||||
|
this.statisticSummary(jsonArray);
|
||||||
|
|
||||||
|
// opensearch
|
||||||
|
this.uploadToOpenSearch(jsonArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* query geoip
|
||||||
|
*
|
||||||
|
* @param ipList
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<String, JSONObject> queryGeoip(List<String> ipList) {
|
||||||
|
JSONArray result = new JSONArray();
|
||||||
|
int batchSize = 100;
|
||||||
|
for (int i = 0; i < ipList.size(); i += batchSize) {
|
||||||
|
List<String> currentBatch = ipList.subList(i, Math.min(i + batchSize, ipList.size()));
|
||||||
|
String queryParam = currentBatch.stream().collect(Collectors.joining(","));
|
||||||
|
JSONArray array = geoipClient.geoip(queryParam);
|
||||||
|
result.addAll(array);
|
||||||
|
}
|
||||||
|
Map<String, JSONObject> map = result.stream().collect(
|
||||||
|
Collectors.toMap(
|
||||||
|
obj -> T.MapUtil.getStr((JSONObject) obj, "ip"),
|
||||||
|
obj -> (JSONObject) obj
|
||||||
|
));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* statistic summary
|
||||||
|
*
|
||||||
|
* @param jsonArray
|
||||||
|
*/
|
||||||
|
private void statisticSummary(JSONArray jsonArray) {
|
||||||
|
if (T.ObjectUtil.isEmpty(jsonArray)) {
|
||||||
|
log.warn("[statisticSummary] [data array is empty] [id: {}]", pcapEntity.getId());
|
||||||
|
} else {
|
||||||
|
Set<String> services = new HashSet<>();
|
||||||
|
Long packets = 0L;
|
||||||
|
for (Object obj : jsonArray) {
|
||||||
|
JSONObject pojo = (JSONObject) obj;
|
||||||
|
long origPkts = pojo.getLongValue("orig_pkts", 0);
|
||||||
|
long respPkts = pojo.getLongValue("resp_pkts", 0);
|
||||||
|
packets = packets + (origPkts + respPkts);
|
||||||
|
|
||||||
|
services.add(pojo.getString("proto"));
|
||||||
|
services.add(pojo.getString("service"));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject first = (JSONObject) jsonArray.getFirst();
|
||||||
|
JSONObject last = (JSONObject) jsonArray.getLast();
|
||||||
|
|
||||||
|
Map<Object, Object> m = T.MapUtil.builder()
|
||||||
|
.put("startTimestamp", first.getBigDecimal("ts"))
|
||||||
|
.put("endTimestamp", last.getBigDecimal("ts"))
|
||||||
|
.put("sessions", jsonArray.size())
|
||||||
|
.put("packets", packets)
|
||||||
|
.put("services", services)
|
||||||
|
.build();
|
||||||
|
pcapService.update(new LambdaUpdateWrapper<PcapEntity>()
|
||||||
|
.set(PcapEntity::getSummary, T.JSONUtil.toJsonStr(m))
|
||||||
|
.eq(PcapEntity::getId, pcapEntity.getId())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* upload to opensearch
|
||||||
|
*
|
||||||
|
* @param jsonArray
|
||||||
|
*/
|
||||||
|
private void uploadToOpenSearch(JSONArray jsonArray) {
|
||||||
|
String pcapPath = pcapEntity.getPath();
|
||||||
|
String md5Hex = T.DigestUtil.md5Hex(T.FileUtil.file(pcapPath));
|
||||||
|
|
||||||
|
String workspaceName = pcapEntity.getWorkspace().getName();
|
||||||
|
String indexName = String.format("workspace-%s-%s", workspaceName, md5Hex);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// check if index exists
|
||||||
|
boolean indexExists = openSearchClient.indices()
|
||||||
|
.exists(new ExistsRequest.Builder().index(indexName).build())
|
||||||
|
.value();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("[uploadToOpenSearch] [index: {}] [exists: {}]", indexName, indexExists);
|
||||||
|
}
|
||||||
|
// if index exists, delete
|
||||||
|
if (indexExists) {
|
||||||
|
openSearchClient.indices().delete(new DeleteIndexRequest.Builder().index(indexName).build());
|
||||||
|
log.debug("[uploadToOpenSearch] [index: {}] [deleted]", indexName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create index with default settings
|
||||||
|
openSearchClient.indices().create(
|
||||||
|
new CreateIndexRequest.Builder()
|
||||||
|
.index(indexName)
|
||||||
|
.settings(new IndexSettings.Builder().build())
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// upload data in bulk
|
||||||
|
BulkRequest.Builder br = new BulkRequest.Builder();
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
|
||||||
|
String id = String.valueOf(i);
|
||||||
|
br.operations(op -> op.index(
|
||||||
|
idx -> idx.index(indexName)
|
||||||
|
.id(id)
|
||||||
|
.document(jsonObject)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
BulkResponse result = openSearchClient.bulk(br.build());
|
||||||
|
// log errors, if any
|
||||||
|
if (result.errors()) {
|
||||||
|
log.error("[uploadToOpenSearch] [bulk had errors]");
|
||||||
|
for (BulkResponseItem item : result.items()) {
|
||||||
|
if (item.error() != null) {
|
||||||
|
log.error("[uploadToOpenSearch] [error reason]", item.error().reason());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("[uploadToOpenSearch] [error] [index: {}]", indexName);
|
||||||
|
throw new RuntimeException("Failed to upload data to OpenSearch", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update pcap status
|
* update pcap status
|
||||||
*
|
*
|
||||||
* @param status
|
* @param status
|
||||||
*/
|
*/
|
||||||
private void updatePcapStatus(String status) {
|
private void updateStatus(String status) {
|
||||||
pcapService.update(new LambdaUpdateWrapper<PcapEntity>()
|
pcapService.update(new LambdaUpdateWrapper<PcapEntity>()
|
||||||
.set(PcapEntity::getStatus, status)
|
.set(PcapEntity::getStatus, status)
|
||||||
.eq(PcapEntity::getId, pcapEntity.getId())
|
.eq(PcapEntity::getId, pcapEntity.getId())
|
||||||
|
|||||||
@@ -36,9 +36,11 @@ public class RunnerConstant {
|
|||||||
public enum PcapStatus {
|
public enum PcapStatus {
|
||||||
UPLOADED("Uploaded"),
|
UPLOADED("Uploaded"),
|
||||||
|
|
||||||
ANALYZING("Analyzing"),
|
PARSING("Parsing"),
|
||||||
|
|
||||||
COMPLETED("Completed");
|
INDEXED("Indexed"),
|
||||||
|
|
||||||
|
ERROR("Error");
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@Deprecated
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class SignatureExtract {
|
public class SignatureExtract {
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.util.stream.Collectors;
|
|||||||
* tshark 解析 pcap 文件
|
* tshark 解析 pcap 文件
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@Deprecated
|
||||||
public class SignatureUtil {
|
public class SignatureUtil {
|
||||||
|
|
||||||
private static final Log log = Log.get();
|
private static final Log log = Log.get();
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package net.geedge.asw.module.sys.controller;
|
package net.geedge.asw.module.sys.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.jwt.JWT;
|
||||||
|
import cn.hutool.jwt.JWTUtil;
|
||||||
|
import cn.hutool.jwt.signers.JWTSignerUtil;
|
||||||
import net.geedge.asw.common.util.R;
|
import net.geedge.asw.common.util.R;
|
||||||
import net.geedge.asw.common.util.RCode;
|
import net.geedge.asw.common.util.RCode;
|
||||||
import net.geedge.asw.common.util.T;
|
import net.geedge.asw.common.util.T;
|
||||||
@@ -10,7 +14,9 @@ import net.geedge.asw.module.sys.service.ISysAuthService;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1")
|
@RequestMapping("/api/v1")
|
||||||
@@ -19,6 +25,9 @@ public class SysAuthController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISysAuthService authService;
|
private ISysAuthService authService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SaTokenConfig saTokenConfig;
|
||||||
|
|
||||||
record AuthRecord(String userName, String pwd) {}
|
record AuthRecord(String userName, String pwd) {}
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@@ -27,6 +36,30 @@ public class SysAuthController {
|
|||||||
.notEmpty(RCode.SYS_USER_PWD_ERROR);
|
.notEmpty(RCode.SYS_USER_PWD_ERROR);
|
||||||
SysUserEntity userEntity = authService.login(record.userName(), record.pwd());
|
SysUserEntity userEntity = authService.login(record.userName(), record.pwd());
|
||||||
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
||||||
|
|
||||||
|
String tokenValue = tokenInfo.getTokenValue();
|
||||||
|
|
||||||
|
JWT jwt = JWTUtil.parseToken(tokenValue);
|
||||||
|
|
||||||
|
// payload
|
||||||
|
jwt.setPayload("sub", userEntity.getUserName());
|
||||||
|
|
||||||
|
Map<String, Object> permissions = authService.userPermissions();
|
||||||
|
|
||||||
|
String roles = ((List<String>) T.JSONUtil.getByPath(T.JSONUtil.parse(permissions), "records.role.name")).stream()
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
jwt.setPayload("roles", roles);
|
||||||
|
|
||||||
|
Long eff = Long.valueOf(jwt.getPayload("eff").toString());
|
||||||
|
jwt.setPayload("exp", eff == -1L ? -1 : (eff / 1000));
|
||||||
|
jwt.setPayload("iat", System.currentTimeMillis() / 1000);
|
||||||
|
jwt.setPayload("nbf", System.currentTimeMillis() / 1000);
|
||||||
|
|
||||||
|
String sign = jwt.sign(JWTSignerUtil.hs256(saTokenConfig.getJwtSecretKey().getBytes()));
|
||||||
|
tokenInfo.setTokenValue(sign);
|
||||||
|
StpUtil.setTokenValue(sign);
|
||||||
|
|
||||||
userEntity.setPwd(null);
|
userEntity.setPwd(null);
|
||||||
return R.ok().putData("tokenInfo", tokenInfo).putData("user", userEntity);
|
return R.ok().putData("tokenInfo", tokenInfo).putData("user", userEntity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("sys_role")
|
@TableName("sys_role")
|
||||||
public class SysRoleEntity {
|
public class SysRoleEntity {
|
||||||
@@ -20,4 +22,8 @@ public class SysRoleEntity {
|
|||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String[] menuIds;
|
private String[] menuIds;
|
||||||
private Long createTimestamp;
|
private Long createTimestamp;
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<SysMenuEntity> menus;
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<String> buttons;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,21 @@ public class SysUserEntity {
|
|||||||
|
|
||||||
@TableId(type = IdType.ASSIGN_UUID)
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@TableField("user_name")
|
@TableField("user_name")
|
||||||
private String userName;
|
private String userName;
|
||||||
|
|
||||||
private String pwd;
|
private String pwd;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String roleIds;
|
private String roleIds;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private List<SysRoleEntity> roles;
|
private List<SysRoleEntity> roles;
|
||||||
|
|
||||||
|
private String accessLevel;
|
||||||
|
|
||||||
private Long createTimestamp;
|
private Long createTimestamp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package net.geedge.asw.module.sys.service.impl;
|
package net.geedge.asw.module.sys.service.impl;
|
||||||
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.collection.ListUtil;
|
||||||
|
import cn.hutool.core.lang.Pair;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.log.Log;
|
import cn.hutool.log.Log;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import net.geedge.asw.common.util.ASWException;
|
import net.geedge.asw.common.util.ASWException;
|
||||||
import net.geedge.asw.common.util.Constants;
|
import net.geedge.asw.common.util.Constants;
|
||||||
@@ -13,9 +17,16 @@ import net.geedge.asw.module.sys.entity.SysMenuEntity;
|
|||||||
import net.geedge.asw.module.sys.entity.SysRoleEntity;
|
import net.geedge.asw.module.sys.entity.SysRoleEntity;
|
||||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||||
import net.geedge.asw.module.sys.service.ISysAuthService;
|
import net.geedge.asw.module.sys.service.ISysAuthService;
|
||||||
|
import net.geedge.asw.module.workbook.entity.WorkbookMemberEntity;
|
||||||
|
import net.geedge.asw.module.workbook.service.IWorkbookMemberService;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
||||||
|
import net.geedge.asw.module.workspace.service.IWorkspaceMemberService;
|
||||||
|
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -23,57 +34,90 @@ import java.util.stream.Collectors;
|
|||||||
@Service
|
@Service
|
||||||
public class SysAuthServiceImpl implements ISysAuthService {
|
public class SysAuthServiceImpl implements ISysAuthService {
|
||||||
|
|
||||||
private static final Log log = Log.get();
|
private static final Log log = Log.get();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SysUserDao userDao;
|
private SysUserDao userDao;
|
||||||
@Autowired
|
|
||||||
private SysRoleDao roleDao;
|
|
||||||
|
|
||||||
@Override
|
@Autowired
|
||||||
public SysUserEntity login(String userName, String pwd) {
|
private SysRoleDao roleDao;
|
||||||
SysUserEntity userEntity = userDao
|
|
||||||
.selectOne(new QueryWrapper<SysUserEntity>().lambda().eq(SysUserEntity::getUserName, userName));
|
|
||||||
if (T.ObjectUtil.isNull(userEntity)
|
|
||||||
|| !T.StrUtil.equals(userEntity.getPwd(), T.AesUtil.encrypt(pwd, Constants.AES_KEY))) {
|
|
||||||
log.warn("user login error, username: {}", userName);
|
|
||||||
throw ASWException.builder().rcode(RCode.SYS_USER_PWD_ERROR).build();
|
|
||||||
}
|
|
||||||
StpUtil.login(userEntity.getId());
|
|
||||||
log.info("user login success, userName: {}", userName);
|
|
||||||
return userEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Autowired
|
||||||
public void logout() {
|
private IWorkspaceService workspaceService;
|
||||||
StpUtil.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Autowired
|
||||||
* 获取登录用户权限
|
private IWorkspaceMemberService workspaceMemberService;
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> userPermissions() {
|
public SysUserEntity login(String userName, String pwd) {
|
||||||
Map<String, Object> result = T.MapUtil.newHashMap();
|
SysUserEntity userEntity = userDao
|
||||||
String userId = StpUtil.getLoginIdAsString();
|
.selectOne(new QueryWrapper<SysUserEntity>().lambda().eq(SysUserEntity::getUserName, userName));
|
||||||
List<SysRoleEntity> roleList = roleDao.findRoleByUserId(userId);
|
if (T.ObjectUtil.isNull(userEntity)
|
||||||
result.put("roles", roleList);
|
|| !T.StrUtil.equals(userEntity.getPwd(), T.AesUtil.encrypt(pwd, Constants.AES_KEY))) {
|
||||||
// 组织 menu数据
|
log.warn("user login error, username: {}", userName);
|
||||||
List<SysMenuEntity> menuList = roleDao.findMenuByUserId(userId);
|
throw ASWException.builder().rcode(RCode.SYS_USER_PWD_ERROR).build();
|
||||||
List<String> buttonList = menuList.stream().filter(menu -> T.StrUtil.equalsIgnoreCase(menu.getType(), "button"))
|
}
|
||||||
.map(menu -> menu.getName()).collect(Collectors.toList());
|
StpUtil.login(userEntity.getId());
|
||||||
result.put("buttons", buttonList);
|
log.info("user login success, userName: {}", userName);
|
||||||
//生成 menu tree结构
|
return userEntity;
|
||||||
Map<String, List<SysMenuEntity>> groupMap = menuList.stream()
|
}
|
||||||
.filter(menu -> T.StrUtil.equalsIgnoreCase(menu.getType(), "menu"))
|
|
||||||
.collect(Collectors.groupingBy(SysMenuEntity::getPid));
|
@Override
|
||||||
menuList.forEach(menu -> {
|
public void logout() {
|
||||||
menu.setChildren(groupMap.get(menu.getId()));
|
StpUtil.logout();
|
||||||
});
|
}
|
||||||
List<SysMenuEntity> collect = menuList.stream().filter(menu -> T.StrUtil.isBlank(menu.getPid()))
|
|
||||||
.collect(Collectors.toList());
|
/**
|
||||||
result.put("menus", collect);
|
* 获取登录用户权限
|
||||||
|
*/
|
||||||
return result;
|
@Override
|
||||||
}
|
public Map<String, Object> userPermissions() {
|
||||||
|
String userId = StpUtil.getLoginIdAsString();
|
||||||
|
SysUserEntity sysUserEntity = userDao.selectById(userId);
|
||||||
|
String accessLevel = sysUserEntity.getAccessLevel();
|
||||||
|
|
||||||
|
List<WorkspaceEntity> workspaceEntityList = workspaceService.list();
|
||||||
|
if (accessLevel.equalsIgnoreCase("regular")) {
|
||||||
|
List<WorkspaceMemberEntity> workbookMemberEntityList = workspaceMemberService.list(new LambdaQueryWrapper<WorkspaceMemberEntity>().eq(WorkspaceMemberEntity::getUserId, userId));
|
||||||
|
List<String> workspaceIdList = workbookMemberEntityList.stream().map(x -> x.getWorkspaceId()).toList();
|
||||||
|
workspaceEntityList = workspaceService.list(new LambdaQueryWrapper<WorkspaceEntity>().in(WorkspaceEntity::getId, workspaceIdList));
|
||||||
|
// public workspace
|
||||||
|
List<WorkspaceEntity> publicWorkspaces = workspaceService.list(new LambdaQueryWrapper<WorkspaceEntity>().eq(WorkspaceEntity::getVisibility, "public"));
|
||||||
|
workspaceEntityList.addAll(publicWorkspaces);
|
||||||
|
}
|
||||||
|
SysRoleEntity role = roleDao.findRoleByUserId(userId).get(0);
|
||||||
|
// 组织 button 数据
|
||||||
|
List<SysMenuEntity> menuList = roleDao.findMenuByUserId(userId);
|
||||||
|
List<String> buttonList = menuList.stream().filter(menu -> T.StrUtil.equalsIgnoreCase(menu.getType(), "button"))
|
||||||
|
.map(menu -> menu.getName()).collect(Collectors.toList());
|
||||||
|
role.setButtons(buttonList);
|
||||||
|
|
||||||
|
//生成 menu tree结构
|
||||||
|
Map<String, List<SysMenuEntity>> groupMap = menuList.stream()
|
||||||
|
.filter(menu -> !T.StrUtil.equalsIgnoreCase(menu.getPid(), "0"))
|
||||||
|
.collect(Collectors.groupingBy(SysMenuEntity::getPid));
|
||||||
|
|
||||||
|
menuList.forEach(menu -> {
|
||||||
|
menu.setChildren(groupMap.get(menu.getId()));
|
||||||
|
});
|
||||||
|
|
||||||
|
List<SysMenuEntity> collect = menuList.stream()
|
||||||
|
.filter(menu -> T.StrUtil.equals(menu.getPid(), "0"))
|
||||||
|
.filter(menu -> T.StrUtil.equals(menu.getType(), "menu"))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
role.setMenus(collect);
|
||||||
|
|
||||||
|
List records = ListUtil.list(false);
|
||||||
|
for (WorkspaceEntity workspace : workspaceEntityList) {
|
||||||
|
Map<Object, Object> map = MapUtil.builder()
|
||||||
|
.put("workspace", workspace)
|
||||||
|
.put("role", role)
|
||||||
|
.build();
|
||||||
|
records.add(map);
|
||||||
|
}
|
||||||
|
Map<String, Object> result = T.MapUtil.newHashMap();
|
||||||
|
result.put("records", records);
|
||||||
|
result.put("accessLevel", accessLevel);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ public class WorkbookConstant {
|
|||||||
PACKAGE("package"),
|
PACKAGE("package"),
|
||||||
SIGNATURE("signature"),
|
SIGNATURE("signature"),
|
||||||
JOB("job"),
|
JOB("job"),
|
||||||
PCAP("pcap"),
|
PCAP("pcap");
|
||||||
DECODE_RECORD("decode_record");
|
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package net.geedge.asw.module.workspace.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import net.geedge.asw.common.util.R;
|
||||||
|
import net.geedge.asw.common.util.RCode;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
|
import net.geedge.asw.common.util.VerifyUtil;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||||
|
import net.geedge.asw.module.sys.service.ISysUserService;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
||||||
|
import net.geedge.asw.module.workspace.service.IWorkspaceMemberService;
|
||||||
|
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/workspace")
|
||||||
|
public class WorkspaceController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWorkspaceService workspaceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWorkspaceMemberService workspaceMemberService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysUserService userService;
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public R detail(@PathVariable("id") String id) {
|
||||||
|
WorkspaceEntity workspace = workspaceService.getById(id);
|
||||||
|
String createUserId = workspace.getCreateUserId();
|
||||||
|
String updateUserId = workspace.getUpdateUserId();
|
||||||
|
if (T.StrUtil.isNotEmpty(createUserId)) {
|
||||||
|
SysUserEntity createUser = userService.getById(createUserId);
|
||||||
|
workspace.setCreateUser(createUser);
|
||||||
|
}
|
||||||
|
if (T.StrUtil.isNotEmpty(updateUserId)) {
|
||||||
|
SysUserEntity updateUser = userService.getById(updateUserId);
|
||||||
|
workspace.setUpdateUser(updateUser);
|
||||||
|
}
|
||||||
|
return R.ok().putData("record", workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public R list(@RequestParam Map<String, Object> params) {
|
||||||
|
Page page = workspaceService.queryList(params);
|
||||||
|
return R.ok(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public R save(@RequestBody WorkspaceEntity workspace) {
|
||||||
|
VerifyUtil.is(workspace).notNull()
|
||||||
|
.and(workspace.getName()).notEmpty(RCode.WORKSPACE_NAME_CANNOT_EMPTY)
|
||||||
|
.and(workspace.getVisibility()).notEmpty(RCode.WORKSPACE_VISIBILITY_CANNOT_EMPTY);
|
||||||
|
|
||||||
|
WorkspaceEntity workspaceEntity = workspaceService.saveWorkspace(workspace);
|
||||||
|
return R.ok().putData("record", workspaceEntity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public R update(@RequestBody WorkspaceEntity workspace) {
|
||||||
|
VerifyUtil.is(workspace).notNull()
|
||||||
|
.and(workspace.getId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY)
|
||||||
|
.and(workspace.getName()).notEmpty(RCode.WORKSPACE_NAME_CANNOT_EMPTY)
|
||||||
|
.and(workspace.getVisibility()).notEmpty(RCode.WORKSPACE_VISIBILITY_CANNOT_EMPTY);
|
||||||
|
|
||||||
|
WorkspaceEntity workspaceEntity = workspaceService.updateWorkspace(workspace);
|
||||||
|
return R.ok().putData("record", workspaceEntity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping
|
||||||
|
public R delete(@RequestParam String ids) {
|
||||||
|
VerifyUtil.is(ids).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||||
|
workspaceService.deleteWorkspace(ids);
|
||||||
|
return R.ok();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{workspaceId}/member")
|
||||||
|
public R getMember(@PathVariable String workspaceId) {
|
||||||
|
List<WorkspaceMemberEntity> memberEntityList = workspaceMemberService.queryList(workspaceId);
|
||||||
|
return R.ok().putData("record", memberEntityList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/{workspaceId}/member")
|
||||||
|
public R saveMember(@PathVariable String workspaceId, @RequestBody List<WorkspaceMemberEntity> workspaceMembers) {
|
||||||
|
VerifyUtil.is(workspaceMembers).notEmpty(RCode.WORKSPACE_MEMBER_CANNOT_EMPTY)
|
||||||
|
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||||
|
List<WorkspaceMemberEntity> workspaceMemberEntityList = workspaceMemberService.saveMember(workspaceId, workspaceMembers);
|
||||||
|
return R.ok().putData("record", workspaceMemberEntityList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PutMapping("/{workspaceId}/member")
|
||||||
|
public R updateMember(@PathVariable String workspaceId, @RequestBody List<WorkspaceMemberEntity> workspaceMembers) {
|
||||||
|
VerifyUtil.is(workspaceMembers).notEmpty(RCode.WORKSPACE_MEMBER_CANNOT_EMPTY)
|
||||||
|
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||||
|
List<WorkspaceMemberEntity> workspaceMemberEntityList = workspaceMemberService.updateMember(workspaceId, workspaceMembers);
|
||||||
|
return R.ok().putData("record", workspaceMemberEntityList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{workspaceId}/member")
|
||||||
|
public R deleteMember(@PathVariable String workspaceId, @RequestParam String userIds) {
|
||||||
|
VerifyUtil.is(userIds).notEmpty(RCode.USER_ID_CANNOT_EMPTY);
|
||||||
|
List<String> list = Arrays.asList(userIds.split(","));
|
||||||
|
workspaceMemberService.remove(new LambdaQueryWrapper<WorkspaceMemberEntity>()
|
||||||
|
.eq(WorkspaceMemberEntity::getWorkspaceId, workspaceId)
|
||||||
|
.in(WorkspaceMemberEntity::getUserId, list));
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
package net.geedge.asw.module.workspace.dao;
|
package net.geedge.asw.module.workspace.dao;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface WorkspaceDao extends BaseMapper<WorkspaceEntity> {
|
public interface WorkspaceDao extends BaseMapper<WorkspaceEntity> {
|
||||||
|
|
||||||
|
List<WorkspaceEntity> queryList(Page page, Map<String, Object> params);
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||||||
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface WorkspaceMemberDao extends BaseMapper<WorkspaceMemberEntity> {
|
public interface WorkspaceMemberDao extends BaseMapper<WorkspaceMemberEntity> {
|
||||||
|
|
||||||
|
List<WorkspaceMemberEntity> queryList(String workspaceId);
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
package net.geedge.asw.module.workspace.entity;
|
package net.geedge.asw.module.workspace.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysRoleEntity;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("workspace")
|
@TableName("workspace")
|
||||||
@@ -21,6 +26,13 @@ public class WorkspaceEntity {
|
|||||||
private String createUserId;
|
private String createUserId;
|
||||||
private String updateUserId;
|
private String updateUserId;
|
||||||
|
|
||||||
private String workspaceId;
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity createUser;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity updateUser;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<WorkspaceMemberEntity> members;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
package net.geedge.asw.module.workspace.entity;
|
package net.geedge.asw.module.workspace.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysRoleEntity;
|
||||||
|
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("workspace_member")
|
@TableName("workspace_member")
|
||||||
@@ -14,4 +19,13 @@ public class WorkspaceMemberEntity {
|
|||||||
private Long createTimestamp;
|
private Long createTimestamp;
|
||||||
private String createUserId;
|
private String createUserId;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity user;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysRoleEntity role;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private SysUserEntity createUser;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,13 @@ package net.geedge.asw.module.workspace.service;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface IWorkspaceMemberService extends IService<WorkspaceMemberEntity>{
|
public interface IWorkspaceMemberService extends IService<WorkspaceMemberEntity>{
|
||||||
|
|
||||||
|
List<WorkspaceMemberEntity> queryList(String workspaceId);
|
||||||
|
|
||||||
|
List<WorkspaceMemberEntity> saveMember(String workspaceId ,List<WorkspaceMemberEntity> workspaces);
|
||||||
|
|
||||||
|
List<WorkspaceMemberEntity> updateMember(String workspaceId, List<WorkspaceMemberEntity> workspaces);
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,18 @@
|
|||||||
package net.geedge.asw.module.workspace.service;
|
package net.geedge.asw.module.workspace.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface IWorkspaceService extends IService<WorkspaceEntity>{
|
public interface IWorkspaceService extends IService<WorkspaceEntity>{
|
||||||
|
|
||||||
|
Page queryList(Map<String, Object> params);
|
||||||
|
|
||||||
|
WorkspaceEntity saveWorkspace(WorkspaceEntity workspace);
|
||||||
|
|
||||||
|
WorkspaceEntity updateWorkspace(WorkspaceEntity workspace);
|
||||||
|
|
||||||
|
void deleteWorkspace(String ids);
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,78 @@
|
|||||||
package net.geedge.asw.module.workspace.service.impl;
|
package net.geedge.asw.module.workspace.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import net.geedge.asw.common.util.ASWException;
|
||||||
|
import net.geedge.asw.common.util.RCode;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
|
import net.geedge.asw.common.util.VerifyUtil;
|
||||||
|
import net.geedge.asw.module.sys.service.ISysRoleService;
|
||||||
|
import net.geedge.asw.module.sys.service.ISysUserService;
|
||||||
import net.geedge.asw.module.workspace.dao.WorkspaceMemberDao;
|
import net.geedge.asw.module.workspace.dao.WorkspaceMemberDao;
|
||||||
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
||||||
import net.geedge.asw.module.workspace.service.IWorkspaceMemberService;
|
import net.geedge.asw.module.workspace.service.IWorkspaceMemberService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class WorkspaceMemberServiceImpl extends ServiceImpl<WorkspaceMemberDao, WorkspaceMemberEntity> implements IWorkspaceMemberService {
|
public class WorkspaceMemberServiceImpl extends ServiceImpl<WorkspaceMemberDao, WorkspaceMemberEntity> implements IWorkspaceMemberService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWorkspaceMemberService workspaceMemberService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysUserService userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysRoleService roleService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WorkspaceMemberEntity> queryList(String workspaceId) {
|
||||||
|
List<WorkspaceMemberEntity> list = this.baseMapper.queryList(workspaceId);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WorkspaceMemberEntity> saveMember(String workspaceId, List<WorkspaceMemberEntity> workspaces) {
|
||||||
|
validateInfo(workspaceId, workspaces);
|
||||||
|
workspaceMemberService.saveBatch(workspaces);
|
||||||
|
List<WorkspaceMemberEntity> memberEntityList = workspaceMemberService.queryList(workspaceId);
|
||||||
|
return memberEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WorkspaceMemberEntity> updateMember(String workspaceId, List<WorkspaceMemberEntity> workspaces) {
|
||||||
|
validateInfo(workspaceId, workspaces);
|
||||||
|
workspaceMemberService.remove(new LambdaQueryWrapper<WorkspaceMemberEntity>().eq(WorkspaceMemberEntity::getWorkspaceId, workspaceId));
|
||||||
|
workspaceMemberService.saveBatch(workspaces);
|
||||||
|
List<WorkspaceMemberEntity> memberEntityList = workspaceMemberService.queryList(workspaceId);
|
||||||
|
return memberEntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateInfo(String workspaceId, List<WorkspaceMemberEntity> workspaces) {
|
||||||
|
if (T.StrUtil.equalsIgnoreCase(workspaceId, "1")) {
|
||||||
|
throw new ASWException(RCode.WORKSPACE_BUILT_IN);
|
||||||
|
}
|
||||||
|
List<String> userIds = userService.list().stream().map(x -> x.getId()).toList();
|
||||||
|
List<String> roleIds = roleService.list().stream().map(x -> x.getId()).toList();
|
||||||
|
for (WorkspaceMemberEntity workspace : workspaces) {
|
||||||
|
VerifyUtil.is(workspace).notNull()
|
||||||
|
.and(workspace.getUserId()).notEmpty(RCode.USER_ID_CANNOT_EMPTY)
|
||||||
|
.and(workspace.getRoleId()).notEmpty(RCode.ROLE_ID_CANNOT_EMPTY);
|
||||||
|
if (!userIds.contains(workspace.getUserId())) {
|
||||||
|
throw new ASWException(RCode.USER_NOT_EXIST);
|
||||||
|
}
|
||||||
|
if (!roleIds.contains(workspace.getRoleId())) {
|
||||||
|
throw new ASWException(RCode.ROLE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
workspaces.stream().forEach(x -> {
|
||||||
|
x.setWorkspaceId(workspaceId);
|
||||||
|
x.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
x.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,113 @@
|
|||||||
package net.geedge.asw.module.workspace.service.impl;
|
package net.geedge.asw.module.workspace.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import net.geedge.asw.common.util.ASWException;
|
||||||
|
import net.geedge.asw.common.util.Constants;
|
||||||
|
import net.geedge.asw.common.util.RCode;
|
||||||
|
import net.geedge.asw.common.util.T;
|
||||||
import net.geedge.asw.module.workspace.dao.WorkspaceDao;
|
import net.geedge.asw.module.workspace.dao.WorkspaceDao;
|
||||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
||||||
|
import net.geedge.asw.module.workspace.service.IWorkspaceMemberService;
|
||||||
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class WorkspaceServiceImpl extends ServiceImpl<WorkspaceDao, WorkspaceEntity> implements IWorkspaceService {
|
public class WorkspaceServiceImpl extends ServiceImpl<WorkspaceDao, WorkspaceEntity> implements IWorkspaceService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWorkspaceService workspaceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWorkspaceMemberService workspaceMemberService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page queryList(Map<String, Object> params) {
|
||||||
|
Page page = T.PageUtil.getPage(params);
|
||||||
|
List<WorkspaceEntity> workspaceEntityList = this.getBaseMapper().queryList(page, params);
|
||||||
|
page.setRecords(workspaceEntityList);
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public WorkspaceEntity saveWorkspace(WorkspaceEntity workspace) {
|
||||||
|
this.validateWorkspaceInfo(workspace, false);
|
||||||
|
workspace.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
workspace.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
workspace.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
workspace.setUpdateTimestamp(System.currentTimeMillis());
|
||||||
|
workspaceService.save(workspace);
|
||||||
|
|
||||||
|
if (T.CollectionUtil.isNotEmpty(workspace.getMembers())) {
|
||||||
|
List<WorkspaceMemberEntity> members = workspace.getMembers();
|
||||||
|
members.stream().forEach(x -> {
|
||||||
|
x.setWorkspaceId(workspace.getId());
|
||||||
|
x.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
x.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
});
|
||||||
|
workspaceMemberService.saveBatch(members);
|
||||||
|
}
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public WorkspaceEntity updateWorkspace(WorkspaceEntity workspace) {
|
||||||
|
this.validateWorkspaceInfo(workspace, true);
|
||||||
|
workspace.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
workspace.setUpdateTimestamp(System.currentTimeMillis());
|
||||||
|
workspaceService.updateById(workspace);
|
||||||
|
|
||||||
|
if (T.CollectionUtil.isNotEmpty(workspace.getMembers())) {
|
||||||
|
List<WorkspaceMemberEntity> members = workspace.getMembers();
|
||||||
|
members.stream().forEach(x -> {
|
||||||
|
x.setWorkspaceId(workspace.getId());
|
||||||
|
x.setCreateTimestamp(System.currentTimeMillis());
|
||||||
|
x.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||||
|
});
|
||||||
|
workspaceMemberService.remove(new LambdaQueryWrapper<WorkspaceMemberEntity>().eq(WorkspaceMemberEntity::getWorkspaceId, workspace.getId()));
|
||||||
|
workspaceMemberService.saveBatch(members);
|
||||||
|
}
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void deleteWorkspace(String ids) {
|
||||||
|
List workspaceIds = Arrays.asList(ids.split(","));
|
||||||
|
if (workspaceIds.contains("1")) {
|
||||||
|
throw new ASWException(RCode.WORKSPACE_CANNOT_DELETE);
|
||||||
|
}
|
||||||
|
workspaceService.removeBatchByIds(workspaceIds);
|
||||||
|
workspaceMemberService.remove(new LambdaQueryWrapper<WorkspaceMemberEntity>().in(WorkspaceMemberEntity::getWorkspaceId, workspaceIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateWorkspaceInfo(WorkspaceEntity workspace, boolean isUpdate) {
|
||||||
|
|
||||||
|
if (!Constants.VISIBILITY_LIST.contains(workspace.getVisibility())) {
|
||||||
|
throw new ASWException(RCode.WORKSPACE_VISIBILITY_ERROR);
|
||||||
|
}
|
||||||
|
if (T.StrUtil.equals(workspace.getVisibility(), "private") && T.CollectionUtil.isEmpty(workspace.getMembers())) {
|
||||||
|
throw new ASWException(RCode.WORKSPACE_USER_CANNOT_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WorkspaceEntity> list = workspaceService.list(new LambdaQueryWrapper<WorkspaceEntity>().eq(WorkspaceEntity::getName, workspace.getName()));
|
||||||
|
if (!isUpdate && T.CollectionUtil.isNotEmpty(list)) {
|
||||||
|
throw new ASWException(RCode.WORKSPACE_ALREADY_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUpdate && T.CollectionUtil.isNotEmpty(list) && T.StrUtil.equals(workspace.getId(), list.getFirst().getId())) {
|
||||||
|
throw new ASWException(RCode.WORKSPACE_ALREADY_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,20 @@ spring:
|
|||||||
enabled: true
|
enabled: true
|
||||||
main:
|
main:
|
||||||
allow-circular-references: true
|
allow-circular-references: true
|
||||||
|
|
||||||
|
feign:
|
||||||
|
client:
|
||||||
|
config:
|
||||||
|
default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
|
||||||
|
connectTimeout: 5000
|
||||||
|
readTimeout: 5000
|
||||||
|
loggerLevel: BASIC # 日志级别 NONE|BASIC|HEADERS|FULL
|
||||||
|
httpclient:
|
||||||
|
enabled: true
|
||||||
|
max-connections: 200 # httpclient处理的最大连接数量
|
||||||
|
max-connections-per-route: 50 # 单个路径连接的最大数量
|
||||||
|
connection-timeout: 2000 # 超时等待
|
||||||
|
|
||||||
server:
|
server:
|
||||||
# port: 2023
|
# port: 2023
|
||||||
servlet:
|
servlet:
|
||||||
|
|||||||
106
src/main/resources/db/mapper/app/ApplicationMapper.xml
Normal file
106
src/main/resources/db/mapper/app/ApplicationMapper.xml
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="net.geedge.asw.module.app.dao.ApplicationDao">
|
||||||
|
<resultMap id="appResult" type="net.geedge.asw.module.app.entity.ApplicationEntity">
|
||||||
|
<result property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
<result property="tags" column="tags"/>
|
||||||
|
<result property="packageName" column="package_name"/>
|
||||||
|
<result property="website" column="website"/>
|
||||||
|
<result property="provider" column="provider"/>
|
||||||
|
<result property="status" column="status"/>
|
||||||
|
<result property="description" column="description"/>
|
||||||
|
<result property="createTimestamp" column="create_timestamp"/>
|
||||||
|
<result property="updateTimestamp" column="update_timestamp"/>
|
||||||
|
<result property="createUserId" column="create_user_id"/>
|
||||||
|
<result property="updateUserId" column="update_user_id"/>
|
||||||
|
<result property="workspaceId" column="workspace_id"/>
|
||||||
|
<result property="opVersion" column="op_version"/>
|
||||||
|
|
||||||
|
<association property="createUser" columnPrefix="cu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
</association>
|
||||||
|
|
||||||
|
<association property="updateUser" columnPrefix="uu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
</association>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="queryList" resultMap="appResult">
|
||||||
|
SELECT
|
||||||
|
app.*,
|
||||||
|
cu.id as cu_id,
|
||||||
|
cu.name as cu_name,
|
||||||
|
uu.id as uu_id,
|
||||||
|
uu.id as uu_name
|
||||||
|
FROM
|
||||||
|
application app
|
||||||
|
left join sys_user cu on app.create_user_id = cu.id
|
||||||
|
left join sys_user uu on app.update_user_id = uu.id
|
||||||
|
<where>
|
||||||
|
<if test="params.ids != null and params.ids != ''">
|
||||||
|
app.id in
|
||||||
|
<foreach item="id" collection="params.ids.split(',')" separator="," open="(" close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="params.q != null and params.q != ''">
|
||||||
|
AND ( locate(#{params.q}, app.name) OR locate(#{params.q}, app.description) )
|
||||||
|
</if>
|
||||||
|
<if test="params.workspaceId != null and params.workspaceId != ''">
|
||||||
|
AND app.workspace_id = #{params.workspaceId}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
<if test="params.orderBy == null or params.orderBy == ''">
|
||||||
|
ORDER BY app.id
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryLogList" resultMap="appResult">
|
||||||
|
SELECT
|
||||||
|
app.*,
|
||||||
|
cu.id as cu_id,
|
||||||
|
cu.name as cu_name,
|
||||||
|
uu.id as uu_id,
|
||||||
|
uu.id as uu_name
|
||||||
|
FROM
|
||||||
|
(select * from application union select * from application_log) app
|
||||||
|
left join sys_user cu on app.create_user_id = cu.id
|
||||||
|
left join sys_user uu on app.update_user_id = uu.id
|
||||||
|
<where>
|
||||||
|
<if test="id != null and id != ''">
|
||||||
|
AND app.id = #{id}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
ORDER BY app.op_version DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="compare" resultMap="appResult">
|
||||||
|
SELECT
|
||||||
|
app.*,
|
||||||
|
cu.id as cu_id,
|
||||||
|
cu.name as cu_name,
|
||||||
|
uu.id as uu_id,
|
||||||
|
uu.id as uu_name
|
||||||
|
FROM
|
||||||
|
(select * from application union select * from application_log ) app
|
||||||
|
left join sys_user cu on app.create_user_id = cu.id
|
||||||
|
left join sys_user uu on app.update_user_id = uu.id
|
||||||
|
<where>
|
||||||
|
<if test="params.versions != null and params.versions != ''">
|
||||||
|
AND app.op_version in
|
||||||
|
<foreach item="version" collection="params.versions" separator="," open="(" close=")">
|
||||||
|
#{version}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="params.id != null and params.id != ''">
|
||||||
|
AND app.id = #{params.id}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="net.geedge.asw.module.app.dao.ApplicationSignatureDao">
|
||||||
|
<resultMap id="signatureResult" type="net.geedge.asw.module.app.entity.ApplicationSignatureEntity">
|
||||||
|
<result property="id" column="id"/>
|
||||||
|
<result property="applicationId" column="application_id"/>
|
||||||
|
<result property="content" column="content"/>
|
||||||
|
<result property="createTimestamp" column="create_timestamp"/>
|
||||||
|
<result property="createUserId" column="create_user_id"/>
|
||||||
|
<result property="opVersion" column="op_version"/>
|
||||||
|
|
||||||
|
<association property="createUser" columnPrefix="c_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
</association>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="queryList" resultMap="signatureResult">
|
||||||
|
SELECT
|
||||||
|
asg.*,
|
||||||
|
cu.id as c_id,
|
||||||
|
cu.name as c_name
|
||||||
|
FROM
|
||||||
|
application_signature asg
|
||||||
|
left join sys_user cu on asg.create_user_id = cu.id
|
||||||
|
<where>
|
||||||
|
<if test="params.applicationId != null and params.applicationId != ''">
|
||||||
|
AND asg.application_id = #{params.applicationId}
|
||||||
|
</if>
|
||||||
|
<if test="params.versions != null and params.versions != ''">
|
||||||
|
AND asg.op_version in
|
||||||
|
<foreach item="version" collection="params.versions" separator="," open="(" close=")">
|
||||||
|
#{version}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
ORDER BY asg.op_version DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -6,17 +6,12 @@
|
|||||||
<resultMap type="net.geedge.asw.module.runner.entity.PcapEntity" id="pcapResultMap">
|
<resultMap type="net.geedge.asw.module.runner.entity.PcapEntity" id="pcapResultMap">
|
||||||
<id property="id" column="id"/>
|
<id property="id" column="id"/>
|
||||||
<result property="name" column="name"/>
|
<result property="name" column="name"/>
|
||||||
<result property="tags" column="tags"/>
|
|
||||||
<result property="description" column="description"/>
|
<result property="description" column="description"/>
|
||||||
<result property="path" column="path"/>
|
<result property="path" column="path"/>
|
||||||
<result property="size" column="size"/>
|
<result property="size" column="size"/>
|
||||||
<result property="connections" column="connections"/>
|
|
||||||
<result property="hosts" column="hosts"/>
|
|
||||||
<result property="md5" column="md5"/>
|
<result property="md5" column="md5"/>
|
||||||
<result property="connectionTimeFirst" column="connection_time_first"/>
|
|
||||||
<result property="connectionTimeLast" column="connection_time_last"/>
|
|
||||||
<result property="protocols" column="protocols"/>
|
|
||||||
<result property="status" column="status"/>
|
<result property="status" column="status"/>
|
||||||
|
<result property="summary" column="summary"/>
|
||||||
<result property="createTimestamp" column="create_timestamp"/>
|
<result property="createTimestamp" column="create_timestamp"/>
|
||||||
<result property="createUserId" column="create_user_id"/>
|
<result property="createUserId" column="create_user_id"/>
|
||||||
<result property="workspaceId" column="workspace_id"/>
|
<result property="workspaceId" column="workspace_id"/>
|
||||||
@@ -81,6 +76,10 @@
|
|||||||
<foreach item="id" collection="params.ids.split(',')" separator="," open="(" close=")">#{id}</foreach>
|
<foreach item="id" collection="params.ids.split(',')" separator="," open="(" close=")">#{id}</foreach>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
|
<if test="params.q != null and params.q != ''">
|
||||||
|
AND ( locate(#{params.q}, pcap.name) OR locate(#{params.q}, pcap.description) )
|
||||||
|
</if>
|
||||||
|
|
||||||
<if test="params.jobIds != null and params.jobIds != ''">
|
<if test="params.jobIds != null and params.jobIds != ''">
|
||||||
AND job.id in
|
AND job.id in
|
||||||
<foreach item="id" collection="params.jobIds.split(',')" separator="," open="(" close=")">#{id}</foreach>
|
<foreach item="id" collection="params.jobIds.split(',')" separator="," open="(" close=")">#{id}</foreach>
|
||||||
|
|||||||
55
src/main/resources/db/mapper/workspace/WorkspaceMapper.xml
Normal file
55
src/main/resources/db/mapper/workspace/WorkspaceMapper.xml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="net.geedge.asw.module.workspace.dao.WorkspaceDao">
|
||||||
|
|
||||||
|
<resultMap id="workspaceResultMap" type="net.geedge.asw.module.workspace.entity.WorkspaceEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
<result property="tags" column="tags"/>
|
||||||
|
<result property="visibility" column="visibility"/>
|
||||||
|
<result property="description" column="description"/>
|
||||||
|
<result property="createTimestamp" column="create_timestamp"/>
|
||||||
|
<result property="updateTimestamp" column="update_timestamp"/>
|
||||||
|
<result property="createUserId" column="create_user_id"/>
|
||||||
|
<result property="updateUserId" column="update_user_id"/>
|
||||||
|
|
||||||
|
<association property="createUser" columnPrefix="cu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
</association>
|
||||||
|
|
||||||
|
<association property="updateUser" columnPrefix="uu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
</association>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="queryList" resultMap="workspaceResultMap">
|
||||||
|
SELECT
|
||||||
|
ws.*,
|
||||||
|
cu.id AS cu_id,
|
||||||
|
cu.name AS cu_name,
|
||||||
|
uu.id AS uu_id,
|
||||||
|
uu.name AS uu_name
|
||||||
|
FROM
|
||||||
|
workspace ws
|
||||||
|
LEFT JOIN sys_user cu ON ws.create_user_id = cu.id
|
||||||
|
LEFT JOIN sys_user uu ON ws.update_user_id = uu.id
|
||||||
|
<where>
|
||||||
|
<if test="params.ids != null and params.ids != ''">
|
||||||
|
ws.id in
|
||||||
|
<foreach item="id" collection="params.ids.split(',')" separator="," open="(" close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="params.q != null and params.q != ''">
|
||||||
|
AND ( locate(#{params.q}, ws.name) OR locate(#{params.q}, ws.description) OR locate(#{params.q},
|
||||||
|
ws.tags) )
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
<if test="params.orderBy == null or params.orderBy == ''">
|
||||||
|
ORDER BY ws.id
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="net.geedge.asw.module.workspace.dao.WorkspaceMemberDao">
|
||||||
|
|
||||||
|
<resultMap id="workspaceMemberResultMap" type="net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity">
|
||||||
|
|
||||||
|
<result property="workspaceId" column="workspace_id"/>
|
||||||
|
<result property="userId" column="user_id"/>
|
||||||
|
<result property="roleId" column="role_id"/>
|
||||||
|
<result property="createTimestamp" column="create_timestamp"/>
|
||||||
|
<result property="createUserId" column="create_user_id"/>
|
||||||
|
|
||||||
|
<association property="createUser" columnPrefix="cu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
</association>
|
||||||
|
|
||||||
|
<association property="user" columnPrefix="su_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
</association>
|
||||||
|
|
||||||
|
<association property="role" columnPrefix="sr_" javaType="net.geedge.asw.module.sys.entity.SysRoleEntity">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
</association>
|
||||||
|
|
||||||
|
</resultMap>
|
||||||
|
<select id="queryList" resultMap="workspaceMemberResultMap">
|
||||||
|
SELECT
|
||||||
|
wm.*,
|
||||||
|
cu.id AS cu_id,
|
||||||
|
cu.name AS cu_name,
|
||||||
|
su.id AS su_id,
|
||||||
|
su.name AS su_name,
|
||||||
|
sr.id AS sr_id,
|
||||||
|
sr.name AS sr_name
|
||||||
|
FROM
|
||||||
|
workspace_member wm
|
||||||
|
LEFT JOIN sys_user cu ON wm.create_user_id = cu.id
|
||||||
|
LEFT JOIN sys_user su ON wm.user_id = su.id
|
||||||
|
LEFT JOIN sys_role sr ON wm.role_id = sr.id
|
||||||
|
<where>
|
||||||
|
<if test="workspaceId != null and workspaceId != ''">
|
||||||
|
wm.workspace_id = #{workspaceId}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
@@ -51,6 +51,58 @@ INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_
|
|||||||
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (59, '202002', 'PACKAGE_DESCRIPTION_CANNOT_EMPTY', '安装包描述信息不能为空', 'zh', '', 'admin', 1719280800000);
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (59, '202002', 'PACKAGE_DESCRIPTION_CANNOT_EMPTY', '安装包描述信息不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (61, '401001', 'WORKSPACE_ID_CANNOT_EMPTY', 'workspace id cannot be empty', 'en', '', 'admin', 1719280800000);
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (61, '401001', 'WORKSPACE_ID_CANNOT_EMPTY', 'workspace id cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (63, '401001', 'WORKSPACE_ID_CANNOT_EMPTY', '工作空间ID不能为空', 'zh', '', 'admin', 1719280800000);
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (63, '401001', 'WORKSPACE_ID_CANNOT_EMPTY', '工作空间ID不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (65, '401002', 'WORKSPACE_NAME_CANNOT_EMPTY', 'workspace name cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (67, '401002', 'WORKSPACE_NAME_CANNOT_EMPTY', '工作空间名称不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (69, '401003', 'WORKSPACE_VISIBILITY_CANNOT_EMPTY', 'workspace visibility cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (71, '401003', 'WORKSPACE_VISIBILITY_CANNOT_EMPTY', '工作空间可见性不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (73, '401004', 'WORKSPACE_USER_CANNOT_EMPTY', 'workspace user cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (75, '401004', 'WORKSPACE_USER_CANNOT_EMPTY', '工作空间用户不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (77, '401005', 'WORKSPACE_ALREADY_EXISTS', 'workspace already exists', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (79, '401005', 'WORKSPACE_ALREADY_EXISTS', '工作空间已存在', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (81, '401006', 'WORKSPACE_MEMBER_CANNOT_EMPTY', 'workspace member cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (83, '401006', 'WORKSPACE_MEMBER_CANNOT_EMPTY', '工作空间成员不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (85, '401007', 'WORKSPACE_CANNOT_DELETE', 'Built-in workspace cannot be deleted', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (87, '401007', 'WORKSPACE_CANNOT_DELETE', '内置工作空间不能删除', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (89, '100009', 'USER_ID_CANNOT_EMPTY', 'user id cannot be empty ', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (91, '100009', 'USER_ID_CANNOT_EMPTY', '用户 ID 不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (93, '201002', 'APP_NAME_CANNOT_EMPTY', 'application name cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (95, '201002', 'APP_NAME_CANNOT_EMPTY', '应用程序名称不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (97, '201003', 'APP_LONGNAME_CANNOT_EMPTY', 'application longName cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (99, '201003', 'APP_LONGNAME_CANNOT_EMPTY', '应用程序全称不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (101, '201004', 'APP_PROPERTIES_CANNOT_EMPTY', 'application properties cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (103, '201004', 'APP_PROPERTIES_CANNOT_EMPTY', '应用程序属性不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (105, '201005', 'APP_SURROGATES_CANNOT_EMPTY', 'application surrogates cannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (107, '201005', 'APP_SURROGATES_CANNOT_EMPTY', '应用程序代理不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (109, '201006', 'APP_DESCRIPTION_CANNOT_EMPTY', 'application descriptioncannot be empty', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (111, '201006', 'APP_DESCRIPTION_CANNOT_EMPTY', '应用描述不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (113, '201007', 'APP_DUPLICATE_RECORD', 'application duplicate record', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (115, '201007', 'APP_DUPLICATE_RECORD', '应用程序重复记录', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (117, '201008', 'APP_NOT_EXIST', 'application does not exist', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (119, '201008', 'APP_NOT_EXIST', '应用程序不存在', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (121, '401008', 'WORKSPACE_VISIBILITY_ERROR', 'workspace visibility error', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (123, '401008', 'WORKSPACE_VISIBILITY_ERROR', '工作空间可见性错误', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (125, '401009', 'WORKSPACE_BUILT_IN', 'Built-in workspace cannot be update', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (127, '401009', 'WORKSPACE_BUILT_IN', '内置工作空间不可修改', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (129, '100010', 'ROLE_ID_CANNOT_EMPTY', 'role id cannot be empty ', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (131, '100010', 'ROLE_ID_CANNOT_EMPTY', '权限 ID 不能为空', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (133, '100011', 'USER_NOT_EXIST', 'user does not exist', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (135, '100011', 'USER_NOT_EXIST', '用户不存在', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (137, '100012', 'ROLE_NOT_EXIST', 'role does not exist', 'en', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (139, '100012', 'ROLE_NOT_EXIST', '权限不存在', 'zh', '', 'admin', 1719280800000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (141, '501001', 'PCAP_UPLOAD_WEB_SHARK_ERROR', 'web shark upload pcap error', 'en', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (143, '501001', 'PCAP_UPLOAD_WEB_SHARK_ERROR', 'pcap 上传失败', 'zh', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (145, '201009', 'APP_PACKAGE_NAME_FORMAT_ERROR', 'application package name format error', 'en', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (147, '201009', 'APP_PACKAGE_NAME_FORMAT_ERROR', '应用安装包名称格式错误', 'zh', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (149, '201010', 'APP_TAGS_FORMAT_ERROR', 'application tags format error', 'en', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (151, '201010', 'APP_TAGS_FORMAT_ERROR', '应用标签格式错误', 'zh', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (153, '201011', 'APP_SIGNATURE_FORMAT_ERROR', 'application signature format error', 'en', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (155, '201011', 'APP_SIGNATURE_FORMAT_ERROR', '应用特征格式错误', 'zh', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (157, '201012', 'APP_SIGNATURE_CONTENT_CANNOT_EMPTY', 'application signature content cannot be empty', 'en', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (159, '201012', 'APP_SIGNATURE_CONTENT_CANNOT_EMPTY', '应用特征内容不能为空', 'zh', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (161, '201013', 'APP_SIGNATURE_NOT_EXIST', 'application signature does not exist', 'en', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (163, '201013', 'APP_SIGNATURE_NOT_EXIST', '应用特征不存在', 'zh', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (165, '201014', 'APP_NOTE_CONTENT_CANNOT_EMPTY', 'application note content cannot be empty', 'en', '', 'admin', 1724030366000);
|
||||||
|
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (167, '201014', 'APP_NOTE_CONTENT_CANNOT_EMPTY', '应用说明内容不能为空', 'zh', '', 'admin', 1724030366000);
|
||||||
|
|
||||||
|
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|||||||
40
src/main/resources/db/migration/R__AZ_sys_menu.sql
Normal file
40
src/main/resources/db/migration/R__AZ_sys_menu.sql
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* 重置 SYS_MENU 数据
|
||||||
|
*/
|
||||||
|
TRUNCATE sys_menu;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('1000', 'workbooks', 'overall.workbooks', '0', 'menu', '', '/workbooks', 'asw-icon icon-Workbooks', 0, 1722478572000, 0);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('1001', 'workbook_view', 'buttons.view', '1000', 'button', '', '', '', 1, 1722478572000, 1);
|
||||||
|
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2000', 'applications', 'overall.applications', '0', 'menu', '', '/applications', 'asw-icon icon-Applications', 1, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2001', 'application_view', 'buttons.view', '2000', 'button', '', '', '', 1, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2002', 'application_add', 'buttons.add', '2000', 'button', '', '', '', 2, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2003', 'application_edit', 'buttons.edit', '2000', 'button', '', '', '', 3, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2004', 'application_delete', 'buttons.delete', '2000', 'button', '', '', '', 4, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2005', 'application_history', 'buttons.history', '2000', 'button', '', '', '', 5, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2006', 'application_compare', 'buttons.compare', '2000', 'button', '', '', '', 6, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2007', 'application_restore', 'buttons.restore', '2000', 'button', '', '', '', 7, 1722478572000, 1);
|
||||||
|
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('3000', 'pcaps', 'overall.pcaps', '0', 'menu', '', '/pcaps', 'asw-icon icon-Pcaps', 2, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('3001', 'pacp_view', 'buttons.view', '3000', 'button', '', '', '', 1, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('3002', 'pacp_upload', 'buttons.upload', '3000', 'button', '', '', '', 2, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('3003', 'pacp_delete', 'buttons.delete', '3000', 'button', '', '', '', 3, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('3004', 'pacp_parse', 'buttons.parse', '3000', 'button', '', '', '', 4, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('3005', 'pacp_analyze', 'buttons.analyze', '3000', 'button', '', '', '', 5, 1722478572000, 1);
|
||||||
|
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('4000', 'packages', 'overall.packages', '0', 'menu', '', '/packages', 'asw-icon icon-Packages', 3, 1722478572000, 0);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('4001', 'package_view', 'buttons.view', '4000', 'button', '', '', '', 1, 1722478572000, 1);
|
||||||
|
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('5000', 'jobs', 'overall.jobs', '0', 'menu', '', '/jobs', 'asw-icon icon-Jobs', 4, 1722478572000, 0);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('5001', 'job_view', 'buttons.view', '5000', 'button', '', '', '', 1, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('5002', 'job_add', 'buttons.add', '5000', 'button', '', '', '', 2, 1722478572000, 1);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('5003', 'job_delete', 'buttons.delete', '5000', 'button', '', '', '', 3, 1722478572000, 1);
|
||||||
|
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('6000', 'playbooks', 'overall.playbooks', '0', 'menu', '', '/playbooks', 'asw-icon icon-Playbooks', 5, 1722478572000, 0);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('6001', 'playbook_view', 'buttons.view', '6000', 'button', '', '', '', 1, 1722478572000, 1);
|
||||||
|
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('7000', 'runners', 'overall.runners', '0', 'menu', '', '/runners', 'asw-icon icon-Runners', 6, 1722478572000, 0);
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('7001', 'runner_view', 'buttons.view', '7000', 'button', '', '', '', 1, 1722478572000, 1);
|
||||||
|
|
||||||
|
INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('1', 'workspace_add', 'buttons.add', '0', 'button', '', '', '', 1, 1722478572000, 1);
|
||||||
51
src/main/resources/db/migration/R__AZ_sys_role_menu.sql
Normal file
51
src/main/resources/db/migration/R__AZ_sys_role_menu.sql
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* 先清空 sys_role_menu 表中 admin&common 相关数据,再导入
|
||||||
|
*/
|
||||||
|
delete from sys_role_menu where role_id in ('admin' ,'common');
|
||||||
|
|
||||||
|
-- admin
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '1000');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '1001');
|
||||||
|
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '2000');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '2001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '2002');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '2003');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '2004');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '2005');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '2006');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '2007');
|
||||||
|
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '3000');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '3001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '3002');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '3003');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '3004');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '3005');
|
||||||
|
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '4000');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '4001');
|
||||||
|
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '5000');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '5001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '5002');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '5003');
|
||||||
|
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '6000');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '6001');
|
||||||
|
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '7000');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '7001');
|
||||||
|
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('admin', '1');
|
||||||
|
|
||||||
|
|
||||||
|
-- common
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('common', '1001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('common', '2001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('common', '3001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('common', '4001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('common', '5001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('common', '6001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('common', '7001');
|
||||||
|
INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('common', '1');
|
||||||
@@ -8,13 +8,14 @@ CREATE TABLE `sys_user` (
|
|||||||
`name` varchar(255) NOT NULL,
|
`name` varchar(255) NOT NULL,
|
||||||
`user_name` varchar(255) NOT NULL,
|
`user_name` varchar(255) NOT NULL,
|
||||||
`pwd` varchar(255) NOT NULL,
|
`pwd` varchar(255) NOT NULL,
|
||||||
|
`access_level` varchar(255) NOT NULL,
|
||||||
`create_timestamp` bigint(20) NOT NULL,
|
`create_timestamp` bigint(20) NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `idx_user_name` (`user_name`) USING BTREE,
|
UNIQUE KEY `idx_user_name` (`user_name`) USING BTREE,
|
||||||
KEY `idx_name` (`name`) USING BTREE
|
KEY `idx_name` (`name`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
-- 添加内置用户
|
||||||
INSERT INTO `sys_user`(`id`, `name`, `user_name`, `pwd`, `create_timestamp`) VALUES ('admin', 'admin', 'admin', 'ad9d757e620d5d9cd8e32c3dbcf37525', UNIX_TIMESTAMP(NOW())*1000);
|
INSERT INTO `sys_user`(`id`, `name`, `user_name`, `pwd`, `access_level`, `create_timestamp`) VALUES ('admin', 'admin', 'admin', 'ad9d757e620d5d9cd8e32c3dbcf37525', 'administrator', UNIX_TIMESTAMP(NOW())*1000);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1、新增 sys_role 表
|
* 1、新增 sys_role 表
|
||||||
@@ -35,6 +36,10 @@ CREATE TABLE `sys_role` (
|
|||||||
KEY `idx_name` (`name`) USING BTREE
|
KEY `idx_name` (`name`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- 添加内置角色
|
||||||
|
INSERT INTO `sys_role` (`id`, `name`, `i18n`, `remark`, `build_in`, `create_timestamp`) VALUES ('admin', 'admin', 'admin', 'admin', 1, UNIX_TIMESTAMP(NOW())*1000);
|
||||||
|
INSERT INTO `sys_role` (`id`, `name`, `i18n`, `remark`, `build_in`, `create_timestamp`) VALUES ('common', 'common', 'common', 'common', 1, UNIX_TIMESTAMP(NOW())*1000);
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `sys_menu`;
|
DROP TABLE IF EXISTS `sys_menu`;
|
||||||
CREATE TABLE `sys_menu` (
|
CREATE TABLE `sys_menu` (
|
||||||
@@ -59,14 +64,14 @@ CREATE TABLE `sys_user_role` (
|
|||||||
`role_id` varchar(64) NOT NULL
|
`role_id` varchar(64) NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
INSERT INTO `sys_user_role`(`user_id`, `role_id`) VALUES ('admin', 'admin');
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `sys_role_menu`;
|
DROP TABLE IF EXISTS `sys_role_menu`;
|
||||||
CREATE TABLE `sys_role_menu` (
|
CREATE TABLE `sys_role_menu` (
|
||||||
`menu_id` varchar(64) NOT NULL,
|
`menu_id` varchar(64) NOT NULL,
|
||||||
`role_id` varchar(64) NOT NULL
|
`role_id` varchar(64) NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
-- 添加内置角色
|
|
||||||
INSERT INTO `sys_role` (`id`, `name`, `i18n`, `remark`, `build_in`, `create_timestamp`) VALUES ('admin', 'admin', 'admin', 'admin', 1, UNIX_TIMESTAMP(NOW())*1000);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1、新增 sys_config 表
|
* 1、新增 sys_config 表
|
||||||
@@ -217,40 +222,18 @@ DROP TABLE IF EXISTS `pcap`;
|
|||||||
CREATE TABLE `pcap` (
|
CREATE TABLE `pcap` (
|
||||||
`id` varchar(64) NOT NULL COMMENT '主键',
|
`id` varchar(64) NOT NULL COMMENT '主键',
|
||||||
`name` varchar(256) NOT NULL DEFAULT '' COMMENT '文件名称',
|
`name` varchar(256) NOT NULL DEFAULT '' COMMENT '文件名称',
|
||||||
`tags` varchar(256) NOT NULL DEFAULT '' COMMENT '标签',
|
|
||||||
`description` text NOT NULL DEFAULT '' COMMENT '描述信息',
|
`description` text NOT NULL DEFAULT '' COMMENT '描述信息',
|
||||||
`path` varchar(64) NOT NULL DEFAULT '' COMMENT 'PCAP文件路径',
|
`path` varchar(64) NOT NULL DEFAULT '' COMMENT 'PCAP文件路径',
|
||||||
`size` bigint(20) NOT NULL DEFAULT 0 COMMENT '文件大小',
|
`size` bigint(20) NOT NULL DEFAULT 0 COMMENT '文件大小',
|
||||||
`connections` bigint(20) NOT NULL DEFAULT 0 COMMENT '连接数量',
|
|
||||||
`hosts` bigint(20) NOT NULL DEFAULT 0 COMMENT 'IP数量',
|
|
||||||
`md5` varchar(64) NOT NULL DEFAULT '' COMMENT '摘要值,根据文件md5值判断是否已上存在,存在则响应当前id',
|
`md5` varchar(64) NOT NULL DEFAULT '' COMMENT '摘要值,根据文件md5值判断是否已上存在,存在则响应当前id',
|
||||||
`connection_time_first` bigint(20) NOT NULL DEFAULT -1 COMMENT '连接开始时间',
|
|
||||||
`connection_time_last` bigint(20) NOT NULL DEFAULT -1 COMMENT '连接结束时间',
|
|
||||||
`protocols` varchar(64) NOT NULL DEFAULT '' COMMENT '包含的协议,多个逗号分隔',
|
|
||||||
`status` varchar(64) NOT NULL DEFAULT '' COMMENT '状态,可选值 Uploaded,Analyzing,Completed',
|
`status` varchar(64) NOT NULL DEFAULT '' COMMENT '状态,可选值 Uploaded,Analyzing,Completed',
|
||||||
|
`summary` varchar(512) NOT NULL DEFAULT '{}' COMMENT '摘要信息, JSON 格式',
|
||||||
`create_timestamp` bigint(20) NOT NULL COMMENT '创建时间戳',
|
`create_timestamp` bigint(20) NOT NULL COMMENT '创建时间戳',
|
||||||
`create_user_id` varchar(64) NOT NULL COMMENT '创建人',
|
`create_user_id` varchar(64) NOT NULL COMMENT '创建人',
|
||||||
`workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID',
|
`workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
KEY `idx_name` (`name`) USING BTREE,
|
KEY `idx_name` (`name`) USING BTREE,
|
||||||
KEY `idx_md5` (`md5`) USING BTREE,
|
KEY `idx_md5` (`md5`) USING BTREE,
|
||||||
KEY `idx_tags` (`tags`) USING BTREE,
|
|
||||||
KEY `idx_workspace_id` (`workspace_id`) USING BTREE
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增 decode_record 表
|
|
||||||
*/
|
|
||||||
DROP TABLE IF EXISTS `decode_record`;
|
|
||||||
CREATE TABLE `decode_record` (
|
|
||||||
`id` varchar(64) NOT NULL COMMENT '主键',
|
|
||||||
`pcap_id` varchar(64) NOT NULL DEFAULT '' COMMENT 'PCAP文件ID',
|
|
||||||
`stream_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '流ID',
|
|
||||||
`stream_attributes` text NOT NULL DEFAULT '' COMMENT '流属性',
|
|
||||||
`workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID',
|
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
|
||||||
KEY `idx_pcap_id` (`pcap_id`) USING BTREE,
|
|
||||||
KEY `idx_stream_id` (`stream_id`) USING BTREE,
|
|
||||||
KEY `idx_workspace_id` (`workspace_id`) USING BTREE
|
KEY `idx_workspace_id` (`workspace_id`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
@@ -262,21 +245,88 @@ DROP TABLE IF EXISTS `application`;
|
|||||||
CREATE TABLE `application` (
|
CREATE TABLE `application` (
|
||||||
`id` varchar(64) NOT NULL COMMENT '主键',
|
`id` varchar(64) NOT NULL COMMENT '主键',
|
||||||
`name` varchar(256) NOT NULL DEFAULT '' COMMENT '应用名称',
|
`name` varchar(256) NOT NULL DEFAULT '' COMMENT '应用名称',
|
||||||
`long_name` varchar(256) NOT NULL DEFAULT '' COMMENT '应用全称',
|
`tags` TEXT NOT NULL DEFAULT '' COMMENT '标签',
|
||||||
`properties` text NOT NULL DEFAULT '' COMMENT '应用数据',
|
`package_name` VARCHAR(512) NOT NULL DEFAULT '' COMMENT '包名',
|
||||||
|
`website` VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '网站',
|
||||||
|
`provider` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '开发者',
|
||||||
|
`status` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '状态:open,inprogress,done',
|
||||||
`description` text NOT NULL DEFAULT '' COMMENT '描述信息',
|
`description` text NOT NULL DEFAULT '' COMMENT '描述信息',
|
||||||
`surrogates` text NOT NULL DEFAULT '' COMMENT '',
|
|
||||||
`create_timestamp` bigint(20) NOT NULL COMMENT '创建时间戳',
|
`create_timestamp` bigint(20) NOT NULL COMMENT '创建时间戳',
|
||||||
`update_timestamp` bigint(20) NOT NULL COMMENT '更新时间戳',
|
`update_timestamp` bigint(20) NOT NULL COMMENT '更新时间戳',
|
||||||
`create_user_id` varchar(64) NOT NULL COMMENT '创建人',
|
`create_user_id` varchar(64) NOT NULL COMMENT '创建人',
|
||||||
`update_user_id` varchar(64) NOT NULL COMMENT '更新人',
|
`update_user_id` varchar(64) NOT NULL COMMENT '更新人',
|
||||||
`workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID',
|
`workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID',
|
||||||
|
`op_version` int(10) NOT NULL DEFAULT 1 COMMENT '版本号',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
KEY `idx_name` (`name`) USING BTREE,
|
KEY `idx_name` (`name`) USING BTREE,
|
||||||
KEY `idx_long_name` (`long_name`) USING BTREE,
|
|
||||||
KEY `idx_workspace_id` (`workspace_id`) USING BTREE
|
KEY `idx_workspace_id` (`workspace_id`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 application_log 表
|
||||||
|
*/
|
||||||
|
DROP TABLE IF EXISTS `application_log`;
|
||||||
|
CREATE TABLE `application_log` (
|
||||||
|
`id` varchar(64) NOT NULL COMMENT '主键',
|
||||||
|
`name` varchar(256) NOT NULL DEFAULT '' COMMENT '应用名称',
|
||||||
|
`tags` TEXT NOT NULL DEFAULT '' COMMENT '标签',
|
||||||
|
`package_name` VARCHAR(512) NOT NULL DEFAULT '' COMMENT '包名',
|
||||||
|
`website` VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '网站',
|
||||||
|
`provider` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '开发者',
|
||||||
|
`status` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '状态:open,inprogress,done',
|
||||||
|
`description` text NOT NULL DEFAULT '' COMMENT '描述信息',
|
||||||
|
`create_timestamp` bigint(20) NOT NULL COMMENT '创建时间戳',
|
||||||
|
`update_timestamp` bigint(20) NOT NULL COMMENT '更新时间戳',
|
||||||
|
`create_user_id` varchar(64) NOT NULL COMMENT '创建人',
|
||||||
|
`update_user_id` varchar(64) NOT NULL COMMENT '更新人',
|
||||||
|
`workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID',
|
||||||
|
`op_version` int(10) NOT NULL DEFAULT 1 COMMENT '版本号',
|
||||||
|
UNIQUE INDEX `index_id_version` (`id`, `op_version`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 application_signature 表
|
||||||
|
*/
|
||||||
|
DROP TABLE IF EXISTS `application_signature`;
|
||||||
|
CREATE TABLE `application_signature` (
|
||||||
|
`id` VARCHAR(64) NOT NULL COMMENT '主键',
|
||||||
|
`application_id` VARCHAR(64) NOT NULL COMMENT '应用id',
|
||||||
|
`content` TEXT NOT NULL COMMENT '特征 json',
|
||||||
|
`create_timestamp` BIGINT(20) NOT NULL COMMENT '创建时间戳',
|
||||||
|
`create_user_id` VARCHAR(64) NOT NULL COMMENT '创建人',
|
||||||
|
`op_version` INT(10) NOT NULL DEFAULT 1 COMMENT '版本号',
|
||||||
|
UNIQUE INDEX `index_id_version` (`id`, `op_version`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 application_note 表
|
||||||
|
*/
|
||||||
|
DROP TABLE IF EXISTS `application_note`;
|
||||||
|
CREATE TABLE `application_note` (
|
||||||
|
`id` VARCHAR(64) NOT NULL COMMENT '主键',
|
||||||
|
`application_id` VARCHAR(64) NOT NULL COMMENT '应用id',
|
||||||
|
`content` TEXT NOT NULL ,
|
||||||
|
`create_timestamp` BIGINT(20) NOT NULL COMMENT '创建时间戳',
|
||||||
|
`create_user_id` VARCHAR(64) NOT NULL COMMENT '创建人id',
|
||||||
|
`op_version` INT(10) NOT NULL DEFAULT 1 COMMENT '版本号',
|
||||||
|
UNIQUE INDEX `index_id_version` (`id`, `op_version`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 application_attachment 表
|
||||||
|
*/
|
||||||
|
DROP TABLE IF EXISTS `application_attachment`;
|
||||||
|
CREATE TABLE `application_attachment` (
|
||||||
|
`id` VARCHAR(64) NOT NULL COMMENT '主键',
|
||||||
|
`application_id` VARCHAR(64) NOT NULL COMMENT '应用id',
|
||||||
|
`name` VARCHAR(256) NOT NULL COMMENT '文件名',
|
||||||
|
`path` VARCHAR(512) NOT NULL COMMENT '文件路径',
|
||||||
|
`create_timestamp` BIGINT(20) NOT NULL COMMENT '创建时间戳',
|
||||||
|
`create_user_id` VARCHAR(64) NOT NULL COMMENT '创建人id',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增 package 表
|
* 新增 package 表
|
||||||
*/
|
*/
|
||||||
@@ -359,7 +409,7 @@ DROP TABLE IF EXISTS `workbook_resource`;
|
|||||||
CREATE TABLE `workbook_resource` (
|
CREATE TABLE `workbook_resource` (
|
||||||
`id` varchar(64) NOT NULL COMMENT '主键',
|
`id` varchar(64) NOT NULL COMMENT '主键',
|
||||||
`workbook_id` varchar(64) NOT NULL COMMENT 'workbook ID',
|
`workbook_id` varchar(64) NOT NULL COMMENT 'workbook ID',
|
||||||
`resource_type` varchar(64) NOT NULL COMMENT '资源类型 可选值:package,signature,job,pcap,decode_record',
|
`resource_type` varchar(64) NOT NULL COMMENT '资源类型 可选值:package,signature,job,pcap',
|
||||||
`resource_id` varchar(64) NOT NULL COMMENT '资源id',
|
`resource_id` varchar(64) NOT NULL COMMENT '资源id',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
@@ -383,6 +433,8 @@ CREATE TABLE `workspace` (
|
|||||||
KEY `idx_name` (`name`) USING BTREE
|
KEY `idx_name` (`name`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
INSERT INTO `workspace` (`id`, `name`, `tags`, `visibility`, `description`, `create_timestamp`, `update_timestamp`, `create_user_id`, `update_user_id`) VALUES ('1', 'default', '', 'public', '', 1722482392000, 1722482392000, 'admin', 'admin');
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `workspace_member`;
|
DROP TABLE IF EXISTS `workspace_member`;
|
||||||
CREATE TABLE `workspace_member` (
|
CREATE TABLE `workspace_member` (
|
||||||
`workspace_id` varchar(64) NOT NULL,
|
`workspace_id` varchar(64) NOT NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user