Compare commits
30 Commits
dev-pcap-p
...
dev-worksp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62ea5f5542 | ||
|
|
357ee0be62 | ||
|
|
2945c51b0f | ||
|
|
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 |
36
pom.xml
36
pom.xml
@@ -79,6 +79,14 @@
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
<version>1.37.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 整合 jwt -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-jwt</artifactId>
|
||||
<version>1.37.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
@@ -143,6 +151,34 @@
|
||||
<artifactId>simplemagic</artifactId>
|
||||
<version>1.16</version>
|
||||
</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>
|
||||
|
||||
<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;
|
||||
|
||||
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.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
@@ -38,6 +44,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
config.setTokenStyle("simple-uuid"); // token 风格
|
||||
config.setIsLog(false); // 是否输出操作日志
|
||||
config.setIsPrint(false);
|
||||
// jwt秘钥
|
||||
config.setJwtSecretKey("ypCLARItfzxvdVqRwPcwIasdgAkhoubj");
|
||||
// config.setIsReadCookie(false);
|
||||
}
|
||||
|
||||
@@ -50,4 +58,29 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
SaRouter.match("/api/v1/**").notMatch("/api/v1/login").check(r -> StpUtil.checkLogin());
|
||||
})).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> VISIBILITY_LIST = T.ListUtil.of("public", "private");
|
||||
|
||||
}
|
||||
|
||||
@@ -18,10 +18,21 @@ public enum RCode {
|
||||
PARAM_CANNOT_EMPTY(100006, "parameter cannot be empty"), // parameter 不能为空
|
||||
USER_NO_LOGIN(100007, "user not login"), // 用户未登录
|
||||
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
|
||||
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"),
|
||||
|
||||
|
||||
// Package
|
||||
@@ -39,6 +50,15 @@ public enum RCode {
|
||||
|
||||
// Workspace
|
||||
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"),
|
||||
|
||||
|
||||
SUCCESS(200, "success"); // 成功
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
package net.geedge.asw.module.app.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
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.ApplicationEntity;
|
||||
import net.geedge.asw.module.app.service.IApplicationService;
|
||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||
import net.geedge.asw.module.sys.service.ISysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/{workspaceId}/application")
|
||||
public class ApplicationController {
|
||||
|
||||
@Autowired
|
||||
private IApplicationService applicationService;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R detail(@PathVariable String workspaceId,
|
||||
@PathVariable String id) {
|
||||
ApplicationEntity entity = applicationService.getOne(new LambdaQueryWrapper<ApplicationEntity>()
|
||||
.eq(ApplicationEntity::getId, id)
|
||||
.eq(ApplicationEntity::getWorkspaceId, workspaceId));
|
||||
if (T.ObjectUtil.isNull(entity)) {
|
||||
throw new ASWException(RCode.APP_NOT_EXIST);
|
||||
}
|
||||
SysUserEntity createUser = userService.getById(entity.getCreateUserId());
|
||||
SysUserEntity updateUser = userService.getById(entity.getUpdateUserId());
|
||||
entity.setCreateUser(createUser);
|
||||
entity.setUpdateUser(updateUser);
|
||||
return R.ok().putData("record", entity);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/{version}")
|
||||
public R detail(@PathVariable String workspaceId,
|
||||
@PathVariable String id,
|
||||
@PathVariable(required = false) String version) {
|
||||
ApplicationEntity entity = applicationService.queryByApplicationAndLog(id, version, workspaceId);
|
||||
if (T.ObjectUtil.isNull(entity)) {
|
||||
throw new ASWException(RCode.APP_NOT_EXIST);
|
||||
}
|
||||
SysUserEntity createUser = userService.getById(entity.getCreateUserId());
|
||||
SysUserEntity updateUser = userService.getById(entity.getUpdateUserId());
|
||||
entity.setCreateUser(createUser);
|
||||
entity.setUpdateUser(updateUser);
|
||||
return R.ok().putData("record", entity);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping
|
||||
public R list(@PathVariable String workspaceId,
|
||||
@RequestParam Map<String, Object> params) {
|
||||
T.VerifyUtil.is(params).notNull()
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
params.put("workspaceId", workspaceId);
|
||||
Page page = applicationService.queryList(params);
|
||||
return R.ok(page);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public R add(@PathVariable String workspaceId,
|
||||
@RequestBody ApplicationEntity entity) {
|
||||
T.VerifyUtil.is(entity).notNull()
|
||||
.and(entity.getName()).notEmpty(RCode.APP_NAME_CANNOT_EMPTY)
|
||||
//.and(entity.getLongName()).notEmpty(RCode.APP_LONGNAME_CANNOT_EMPTY)
|
||||
//.and(entity.getProperties()).notEmpty(RCode.APP_PROPERTIES_CANNOT_EMPTY)
|
||||
//.and(entity.getSurrogates()).notEmpty(RCode.APP_SURROGATES_CANNOT_EMPTY)
|
||||
//.and(entity.getDescription()).notEmpty(RCode.APP_DESCRIPTION_CANNOT_EMPTY)
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
ApplicationEntity applicationEntity = applicationService.saveApplication(entity);
|
||||
return R.ok().putData("id", applicationEntity.getId());
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public R update(@PathVariable String workspaceId,
|
||||
@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.getLongName()).notEmpty(RCode.APP_LONGNAME_CANNOT_EMPTY)
|
||||
//.and(entity.getProperties()).notEmpty(RCode.APP_PROPERTIES_CANNOT_EMPTY)
|
||||
//.and(entity.getSurrogates()).notEmpty(RCode.APP_SURROGATES_CANNOT_EMPTY)
|
||||
//.and(entity.getDescription()).notEmpty(RCode.APP_DESCRIPTION_CANNOT_EMPTY)
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
ApplicationEntity applicationEntity = applicationService.updateApplication(entity);
|
||||
return R.ok().putData("id", applicationEntity.getId());
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
public R delete(@PathVariable String workspaceId,
|
||||
String[] ids) {
|
||||
T.VerifyUtil.is(ids).notEmpty();
|
||||
applicationService.removeApplication(T.ListUtil.of(ids), workspaceId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/log")
|
||||
public R queryLogList(@PathVariable String workspaceId,
|
||||
@PathVariable("id") String id) {
|
||||
List<ApplicationEntity> applicationEntityList = applicationService.queryLogList(id, workspaceId);
|
||||
return R.ok().putData("record", applicationEntityList);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/{id}/{oldVersion}/{newVersion}")
|
||||
public R applicationCompare(@PathVariable String workspaceId,
|
||||
@PathVariable("id") String id,
|
||||
@PathVariable("oldVersion") String oldVersion,
|
||||
@PathVariable("newVersion") String newVersion) {
|
||||
List<ApplicationEntity> list = applicationService.compare(id, oldVersion, newVersion,workspaceId);
|
||||
return R.ok().putData("record", list);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{id}/{version}/restore")
|
||||
public R restore(@PathVariable String workspaceId,
|
||||
@PathVariable("id") String id,
|
||||
@PathVariable("version") String version) {
|
||||
applicationService.restore(id, version, workspaceId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/analyze")
|
||||
public void analyze(@PathVariable String workspaceId,
|
||||
@RequestParam String pcapIds,
|
||||
HttpServletResponse response) throws IOException {
|
||||
applicationService.redirectDiscoverPage(workspaceId, pcapIds, response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
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.R;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
@@ -12,53 +13,63 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/package")
|
||||
@RequestMapping("/api/v1/{workspaceId}/package")
|
||||
public class PackageController {
|
||||
|
||||
@Autowired
|
||||
private IPackageService packageService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R detail(@PathVariable("id") String id) {
|
||||
PackageEntity entity = packageService.getById(id);
|
||||
public R detail(@PathVariable String workspaceId,
|
||||
@PathVariable("id") String id) {
|
||||
PackageEntity entity = packageService.getOne(new LambdaQueryWrapper<PackageEntity>()
|
||||
.eq(PackageEntity::getId, id)
|
||||
.eq(PackageEntity::getWorkspaceId, workspaceId));
|
||||
return R.ok().putData("record", entity);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public R list(@RequestParam Map<String, Object> params) {
|
||||
public R list(@PathVariable String workspaceId,
|
||||
@RequestParam Map<String, Object> params) {
|
||||
T.VerifyUtil.is(params).notNull()
|
||||
.and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
params.put("workspaceId", workspaceId);
|
||||
Page page = packageService.queryList(params);
|
||||
return R.ok(page);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public R add(@RequestBody PackageEntity entity) {
|
||||
public R add(@PathVariable String workspaceId,
|
||||
@RequestBody PackageEntity entity) {
|
||||
T.VerifyUtil.is(entity).notNull()
|
||||
.and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY)
|
||||
.and(entity.getDescription()).notEmpty(RCode.PACKAGE_DESCRIPTION_CANNOT_EMPTY)
|
||||
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
PackageEntity pkgEntity = packageService.savePackage(entity);
|
||||
return R.ok().putData("id", pkgEntity.getId());
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public R update(@RequestBody PackageEntity entity) {
|
||||
public R update(@PathVariable String workspaceId,
|
||||
@RequestBody PackageEntity entity) {
|
||||
T.VerifyUtil.is(entity).notNull()
|
||||
.and(entity.getId()).notEmpty(RCode.ID_CANNOT_EMPTY)
|
||||
.and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY)
|
||||
.and(entity.getDescription()).notEmpty(RCode.PACKAGE_DESCRIPTION_CANNOT_EMPTY)
|
||||
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
PackageEntity pkgEntity = packageService.updatePackage(entity);
|
||||
return R.ok().putData("id", pkgEntity.getId());
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
public R delete(String[] ids) {
|
||||
public R delete(@PathVariable String workspaceId,
|
||||
String[] ids) {
|
||||
T.VerifyUtil.is(ids).notEmpty();
|
||||
packageService.removePackage(T.ListUtil.of(ids));
|
||||
packageService.removePackage(T.ListUtil.of(ids), workspaceId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
package net.geedge.asw.module.app.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||
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
|
||||
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} and app.workspace_id = #{workspaceId}")
|
||||
ApplicationEntity queryByApplicationAndLog(String id, String version, String workspaceId);
|
||||
|
||||
List<ApplicationEntity> queryLogList(String id, String workspaceId);
|
||||
|
||||
List<ApplicationEntity> compare(@Param("params") Map<String, Object> params);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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.ApplicationLogEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
|
||||
@Mapper
|
||||
public interface ApplicationLogDao extends BaseMapper<ApplicationLogEntity> {
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
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")
|
||||
@@ -23,5 +25,12 @@ public class ApplicationEntity {
|
||||
private String updateUserId;
|
||||
|
||||
private String workspaceId;
|
||||
private Integer opVersion;
|
||||
|
||||
@TableField(exist = false)
|
||||
private SysUserEntity createUser;
|
||||
|
||||
@TableField(exist = false)
|
||||
private SysUserEntity updateUser;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.geedge.asw.module.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@TableName("application_log")
|
||||
public class ApplicationLogEntity {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private String longName;
|
||||
private String properties;
|
||||
private String description;
|
||||
private String surrogates;
|
||||
|
||||
private Long createTimestamp;
|
||||
private Long updateTimestamp;
|
||||
private String createUserId;
|
||||
private String updateUserId;
|
||||
|
||||
private String workspaceId;
|
||||
private Integer opVersion;
|
||||
}
|
||||
@@ -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,32 @@
|
||||
package net.geedge.asw.module.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IApplicationService extends IService<ApplicationEntity>{
|
||||
|
||||
Page queryList(Map<String, Object> params);
|
||||
|
||||
ApplicationEntity saveApplication(ApplicationEntity entity);
|
||||
|
||||
ApplicationEntity updateApplication(ApplicationEntity entity);
|
||||
|
||||
void removeApplication(List<String> ids, String workspaceId);
|
||||
|
||||
ApplicationEntity queryByApplicationAndLog(String id, String version, String workspaceId);
|
||||
|
||||
List<ApplicationEntity> compare(String id, String oldVersion, String newVersion, String workspaceId);
|
||||
|
||||
List<ApplicationEntity> queryLogList(String id, String workspaceId);
|
||||
|
||||
void restore(String id, String version, String workspaceId);
|
||||
|
||||
void redirectDiscoverPage(String workspaceId, String pcapIds, HttpServletResponse response) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ public interface IPackageService extends IService<PackageEntity>{
|
||||
|
||||
PackageEntity updatePackage(PackageEntity entity);
|
||||
|
||||
void removePackage(List<String> ids);
|
||||
void removePackage(List<String> ids, String workspaceId);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -1,13 +1,257 @@
|
||||
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 jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import net.geedge.asw.module.feign.client.KibanaClient;
|
||||
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.entity.ApplicationEntity;
|
||||
import net.geedge.asw.module.app.entity.ApplicationLogEntity;
|
||||
import net.geedge.asw.module.app.service.IApplicationLogService;
|
||||
import net.geedge.asw.module.app.service.IApplicationService;
|
||||
import net.geedge.asw.module.runner.entity.PcapEntity;
|
||||
import net.geedge.asw.module.runner.service.IPcapService;
|
||||
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.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
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;
|
||||
|
||||
@Resource
|
||||
private KibanaClient kibanaClient;
|
||||
|
||||
@Override
|
||||
public ApplicationEntity queryByApplicationAndLog(String id, String version, String workspaceId) {
|
||||
ApplicationEntity entity = this.baseMapper.queryByApplicationAndLog(id, version, workspaceId);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ApplicationEntity saveApplication(ApplicationEntity entity) {
|
||||
ApplicationEntity one = this.getOne(new LambdaQueryWrapper<ApplicationEntity>()
|
||||
.eq(ApplicationEntity::getWorkspaceId, entity.getWorkspaceId())
|
||||
.eq(ApplicationEntity::getName, entity.getName()));
|
||||
if (T.ObjectUtil.isNotNull(one)) {
|
||||
throw ASWException.builder().rcode(RCode.APP_DUPLICATE_RECORD).build();
|
||||
}
|
||||
|
||||
entity.setCreateTimestamp(System.currentTimeMillis());
|
||||
entity.setUpdateTimestamp(System.currentTimeMillis());
|
||||
entity.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||
entity.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||
|
||||
// save
|
||||
this.save(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ApplicationEntity updateApplication(ApplicationEntity entity) {
|
||||
ApplicationEntity one = this.getOne(new LambdaQueryWrapper<ApplicationEntity>()
|
||||
.eq(ApplicationEntity::getWorkspaceId, entity.getWorkspaceId())
|
||||
.eq(ApplicationEntity::getId, entity.getId()));
|
||||
if (T.ObjectUtil.isNull(one)) {
|
||||
throw ASWException.builder().rcode(RCode.APP_NOT_EXIST).build();
|
||||
}
|
||||
|
||||
entity.setUpdateTimestamp(System.currentTimeMillis());
|
||||
entity.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||
entity.setOpVersion(one.getOpVersion() + 1);
|
||||
|
||||
// update
|
||||
this.updateById(entity);
|
||||
|
||||
// save log
|
||||
this.saveApplcationToLog(one);
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void saveApplcationToLog(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, String workspaceId) {
|
||||
// remove
|
||||
this.remove(new LambdaQueryWrapper<ApplicationEntity>()
|
||||
.in(ApplicationEntity::getId, ids)
|
||||
.eq(ApplicationEntity::getWorkspaceId, workspaceId));
|
||||
applicationLogService.remove(new LambdaQueryWrapper<ApplicationLogEntity>()
|
||||
.in(ApplicationLogEntity::getId, ids)
|
||||
.eq(ApplicationLogEntity::getWorkspaceId, workspaceId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ApplicationEntity> queryLogList(String id, String workspaceId) {
|
||||
List<ApplicationEntity> packageList = this.getBaseMapper().queryLogList(id, workspaceId);
|
||||
return packageList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ApplicationEntity> compare(String id, String oldVersion, String newVersion, String workspaceId) {
|
||||
Map<String, Object> params = Map.of("id", id, "versions", Arrays.asList(oldVersion, newVersion),"workspaceId",workspaceId);
|
||||
List<ApplicationEntity> packageList = this.getBaseMapper().compare(params);
|
||||
return packageList;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void restore(String id, String version, String workspaceId) {
|
||||
// save current to log
|
||||
ApplicationEntity curApplication = this.getOne(new LambdaQueryWrapper<ApplicationEntity>()
|
||||
.eq(ApplicationEntity::getId, id)
|
||||
.eq(ApplicationEntity::getWorkspaceId, workspaceId));
|
||||
this.saveApplcationToLog(curApplication);
|
||||
// restore
|
||||
ApplicationLogEntity oldApplication = applicationLogService.getOne(new LambdaQueryWrapper<ApplicationLogEntity>()
|
||||
.eq(ApplicationLogEntity::getId, id)
|
||||
.eq(ApplicationLogEntity::getWorkspaceId, workspaceId)
|
||||
.eq(ApplicationLogEntity::getOpVersion, version));
|
||||
|
||||
oldApplication.setUpdateTimestamp(System.currentTimeMillis());
|
||||
oldApplication.setUpdateUserId(StpUtil.getLoginIdAsString());
|
||||
oldApplication.setOpVersion(curApplication.getOpVersion() + 1);
|
||||
|
||||
ApplicationEntity application = T.BeanUtil.toBean(oldApplication, ApplicationEntity.class);
|
||||
this.updateById(application);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 根据 workspace_name 查询 index-pattern 是否存在
|
||||
* 2. 不存在则创建索引
|
||||
*
|
||||
* 维护格式示例:
|
||||
* {
|
||||
* "type": "index-pattern",
|
||||
* "id": "workspace_id",
|
||||
* "attributes": {
|
||||
* "title": "workspace-{workspace_name}-*"
|
||||
* }
|
||||
* }
|
||||
* @param workspaceId
|
||||
* @param pcapIds
|
||||
* @param response
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void redirectDiscoverPage(String workspaceId, String pcapIds, HttpServletResponse response) throws IOException {
|
||||
// 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("[redirectDiscoverPage] [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 source = pcapList.stream()
|
||||
.map(PcapEntity::getName)
|
||||
.map(fileName -> "\"" + fileName + "\"")
|
||||
.collect(Collectors.joining("|", "source: (", ")"));
|
||||
String param3 = String.format("_q=(filters:!(),query:(language:lucene,query:'%s'))", source);
|
||||
|
||||
String query = String.format("?%s&%s&%s", param1, param2, param3);
|
||||
String redirectUrl = baseUrl + "#" + query;
|
||||
|
||||
if(log.isDebugEnabled()){
|
||||
log.debug("[redirectDiscoverPage] [url: {}]", redirectUrl);
|
||||
}
|
||||
|
||||
// redirect
|
||||
response.sendRedirect(redirectUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,9 +80,11 @@ public class PackageServiceImpl extends ServiceImpl<PackageDao, PackageEntity> i
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void removePackage(List<String> ids) {
|
||||
public void removePackage(List<String> ids, String workspaceId) {
|
||||
// remove
|
||||
this.removeBatchByIds(ids);
|
||||
this.remove(new LambdaQueryWrapper<PackageEntity>()
|
||||
.eq(PackageEntity::getWorkspaceId, workspaceId)
|
||||
.in(PackageEntity::getId, ids));
|
||||
// workbook resource
|
||||
workbookResourceService.removeResource(ids, WorkbookConstant.ResourceType.PACKAGE.getValue());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
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.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;
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 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);
|
||||
}
|
||||
}
|
||||
@@ -13,33 +13,38 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/job")
|
||||
@RequestMapping("/api/v1/{workspaceId}/job")
|
||||
public class JobController {
|
||||
|
||||
@Autowired
|
||||
private IJobService jobService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R detail(@PathVariable("id") String id) {
|
||||
JobEntity jobEntity = jobService.queryInfo(id);
|
||||
public R detail(@PathVariable String workspaceId,
|
||||
@PathVariable("id") String id) {
|
||||
JobEntity jobEntity = jobService.queryInfo(id, workspaceId);
|
||||
return R.ok().putData("record", jobEntity);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public R list(@RequestParam Map<String, Object> params) {
|
||||
public R list(@PathVariable String workspaceId,
|
||||
@RequestParam Map<String, Object> params) {
|
||||
T.VerifyUtil.is(params).notNull()
|
||||
.and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
params.put("workspaceId", workspaceId);
|
||||
Page page = jobService.queryList(params);
|
||||
return R.ok(page);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public R add(@RequestBody JobEntity entity) {
|
||||
public R add(@PathVariable String workspaceId,
|
||||
@RequestBody JobEntity entity) {
|
||||
T.VerifyUtil.is(entity).notNull()
|
||||
.and(entity.getRunnerId()).notEmpty(RCode.RUNNER_ID_CANNOT_EMPTY)
|
||||
.and(entity.getPackageId()).notEmpty(RCode.PACKAGE_ID_CANNOT_EMPTY)
|
||||
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
JobEntity jobEntity = jobService.saveJob(entity);
|
||||
return R.ok().putData("id", jobEntity.getId());
|
||||
}
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
package net.geedge.asw.module.runner.controller;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.log.Log;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
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 jakarta.servlet.http.HttpServletResponse;
|
||||
import net.geedge.asw.common.util.*;
|
||||
import net.geedge.asw.module.runner.entity.PcapEntity;
|
||||
import net.geedge.asw.module.runner.service.IPcapService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/pcap")
|
||||
@RequestMapping("/api/v1/{workspaceId}/pcap")
|
||||
public class PcapController {
|
||||
|
||||
private static final Log log = Log.get();
|
||||
@@ -24,35 +31,101 @@ public class PcapController {
|
||||
private IPcapService pcapService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R detail(@PathVariable("id") String id) {
|
||||
PcapEntity pcapEntity = pcapService.queryInfo(id);
|
||||
public R detail(@PathVariable String workspaceId,
|
||||
@PathVariable("id") String id) {
|
||||
PcapEntity pcapEntity = pcapService.queryInfo(id,workspaceId);
|
||||
return R.ok().putData("record", pcapEntity);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public R list(@RequestParam Map<String, Object> params) {
|
||||
public R list(@PathVariable String workspaceId,
|
||||
@RequestParam Map<String, Object> params) {
|
||||
T.VerifyUtil.is(params).notNull()
|
||||
.and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
params.put("workspaceId",workspaceId);
|
||||
Page page = pcapService.queryList(params);
|
||||
return R.ok(page);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public R add(@RequestParam(value = "file", required = true) MultipartFile file,
|
||||
@RequestParam(required = false) String tags,
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
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 workspaceId) throws IOException {
|
||||
T.VerifyUtil.is(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
PcapEntity pcapEntity = pcapService.savePcap(file.getResource(), tags, workbookId, workspaceId);
|
||||
return R.ok().putData("id", pcapEntity.getId());
|
||||
List<Object> recordList = T.ListUtil.list(true);
|
||||
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}")
|
||||
public R delete(@PathVariable("id") String id) {
|
||||
pcapService.deletePcap(id);
|
||||
@PutMapping
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
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();
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package net.geedge.asw.module.runner.controller;
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.core.lang.Opt;
|
||||
import cn.hutool.log.Log;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
@@ -23,7 +24,7 @@ import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/runner")
|
||||
@RequestMapping("/api/v1/{workspaceId}/runner")
|
||||
public class RunnerController {
|
||||
|
||||
private static final Log log = Log.get();
|
||||
@@ -35,35 +36,44 @@ public class RunnerController {
|
||||
private IRunnerService runnerService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R detail(@PathVariable("id") String id) {
|
||||
RunnerEntity runnerEntity = runnerService.getById(id);
|
||||
public R detail(@PathVariable String workspaceId,
|
||||
@PathVariable("id") String id) {
|
||||
RunnerEntity runnerEntity = runnerService.getOne(new LambdaQueryWrapper<RunnerEntity>()
|
||||
.eq(RunnerEntity::getId, id)
|
||||
.eq(RunnerEntity::getWorkspaceId, workspaceId));
|
||||
return R.ok().putData("record", runnerEntity);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public R list(@RequestParam Map<String, Object> params) {
|
||||
public R list(@PathVariable String workspaceId,
|
||||
@RequestParam Map<String, Object> params) {
|
||||
T.VerifyUtil.is(params).notNull()
|
||||
.and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
params.put("workspaceId", workspaceId);
|
||||
Page page = runnerService.queryList(params);
|
||||
return R.ok(page);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public R add(@RequestBody RunnerEntity entity) {
|
||||
public R add(@PathVariable String workspaceId,
|
||||
@RequestBody RunnerEntity entity) {
|
||||
T.VerifyUtil.is(entity).notNull()
|
||||
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
RunnerEntity runner = runnerService.saveRunner(entity);
|
||||
return R.ok().putData("record", runner);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public R update(@RequestBody RunnerEntity entity) {
|
||||
public R update(@PathVariable String workspaceId,
|
||||
@RequestBody RunnerEntity entity) {
|
||||
T.VerifyUtil.is(entity).notNull()
|
||||
.and(entity.getId()).notEmpty(RCode.ID_CANNOT_EMPTY)
|
||||
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
.and(workspaceId).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
|
||||
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
RunnerEntity runner = runnerService.updateRunner(entity);
|
||||
return R.ok().putData("record", runner);
|
||||
}
|
||||
|
||||
@@ -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 net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||
import net.geedge.asw.module.app.entity.PackageEntity;
|
||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||
|
||||
@Data
|
||||
@TableName("pcap")
|
||||
@@ -16,21 +17,18 @@ public class PcapEntity {
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
private String name;
|
||||
private String tags;
|
||||
private String description;
|
||||
private String path;
|
||||
private Long size;
|
||||
private Long connections;
|
||||
private Long hosts;
|
||||
private String md5;
|
||||
private Long connectionTimeFirst;
|
||||
private Long connectionTimeLast;
|
||||
private String protocols;
|
||||
private String status;
|
||||
private Long createTimestamp;
|
||||
private String createUserId;
|
||||
private String workspaceId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private WorkspaceEntity workspace;
|
||||
|
||||
@TableField(exist = false)
|
||||
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>{
|
||||
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import java.util.Map;
|
||||
|
||||
public interface IJobService extends IService<JobEntity>{
|
||||
|
||||
JobEntity queryInfo(String id);
|
||||
JobEntity queryInfo(String id, String workspaceId);
|
||||
|
||||
Page queryList(Map<String, Object> params);
|
||||
|
||||
|
||||
@@ -5,11 +5,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import net.geedge.asw.module.runner.entity.PcapEntity;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IPcapService extends IService<PcapEntity>{
|
||||
|
||||
PcapEntity queryInfo(String id);
|
||||
PcapEntity queryInfo(String id, String workspaceId);
|
||||
|
||||
Page queryList(Map<String, Object> params);
|
||||
|
||||
@@ -17,6 +18,8 @@ public interface IPcapService extends IService<PcapEntity>{
|
||||
|
||||
PcapEntity savePcap(Resource fileResource,String... params);
|
||||
|
||||
void deletePcap(String id);
|
||||
void deletePcap(String... ids);
|
||||
|
||||
void parse2session(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 {
|
||||
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package net.geedge.asw.module.runner.service.impl;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.log.Log;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
@@ -67,21 +68,31 @@ public class JobServiceImpl extends ServiceImpl<JobDao, JobEntity> implements IJ
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobEntity queryInfo(String id) {
|
||||
JobEntity job = this.getById(id);
|
||||
public JobEntity queryInfo(String id, String workspaceId) {
|
||||
JobEntity job = this.getOne(new LambdaQueryWrapper<JobEntity>()
|
||||
.eq(JobEntity::getId, id)
|
||||
.eq(JobEntity::getWorkspaceId, workspaceId));
|
||||
T.VerifyUtil.is(job).notNull(RCode.SYS_RECORD_NOT_FOUND);
|
||||
|
||||
RunnerEntity runner = runnerService.getById(job.getRunnerId());
|
||||
RunnerEntity runner = runnerService.getOne(new LambdaQueryWrapper<RunnerEntity>()
|
||||
.eq(RunnerEntity::getId, job.getRunnerId())
|
||||
.eq(RunnerEntity::getWorkspaceId, workspaceId));
|
||||
job.setRunner(runner);
|
||||
|
||||
PlaybookEntity playbook = playbookService.getById(job.getPlaybookId());
|
||||
PlaybookEntity playbook = playbookService.getOne(new LambdaQueryWrapper<PlaybookEntity>()
|
||||
.eq(PlaybookEntity::getId, job.getPlaybookId())
|
||||
.eq(PlaybookEntity::getWorkspaceId, workspaceId));
|
||||
job.setPlaybook(playbook);
|
||||
|
||||
PackageEntity pkg = packageService.getById(job.getPackageId());
|
||||
PackageEntity pkg = packageService.getOne(new LambdaQueryWrapper<PackageEntity>()
|
||||
.eq(PackageEntity::getId, job.getPackageId())
|
||||
.eq(PackageEntity::getWorkspaceId, workspaceId));
|
||||
job.setPkg(pkg);
|
||||
|
||||
if (T.ObjectUtil.isNotNull(playbook)) {
|
||||
ApplicationEntity application = applicationService.getById(playbook.getAppId());
|
||||
ApplicationEntity application = applicationService.getOne(new LambdaQueryWrapper<ApplicationEntity>()
|
||||
.eq(ApplicationEntity::getId, playbook.getAppId())
|
||||
.eq(ApplicationEntity::getWorkspaceId, workspaceId));
|
||||
job.setApplication(application);
|
||||
}
|
||||
return job;
|
||||
@@ -106,9 +117,10 @@ public class JobServiceImpl extends ServiceImpl<JobDao, JobEntity> implements IJ
|
||||
// save
|
||||
this.save(entity);
|
||||
|
||||
// workbook resource
|
||||
workbookResourceService.saveResource(entity.getWorkbookId(), entity.getId(), WorkbookConstant.ResourceType.JOB.getValue());
|
||||
|
||||
if (T.StrUtil.isEmpty(entity.getWorkbookId())){
|
||||
// workbook resource
|
||||
workbookResourceService.saveResource(entity.getWorkbookId(), entity.getId(), WorkbookConstant.ResourceType.JOB.getValue());
|
||||
}
|
||||
// trace log file path
|
||||
File traceLogFile = T.FileUtil.file(this.getJobResultPath(entity.getId()), "trace.log");
|
||||
this.update(new LambdaUpdateWrapper<JobEntity>()
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
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.entity.ApplicationEntity;
|
||||
@@ -25,6 +26,8 @@ import net.geedge.asw.module.runner.util.PcapParserThread;
|
||||
import net.geedge.asw.module.runner.util.RunnerConstant;
|
||||
import net.geedge.asw.module.workbook.service.IWorkbookResourceService;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -35,6 +38,11 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
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
|
||||
public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements IPcapService {
|
||||
@@ -58,9 +66,12 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
||||
@Autowired
|
||||
private IWorkbookResourceService workbookResourceService;
|
||||
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
@Override
|
||||
public PcapEntity queryInfo(String id) {
|
||||
PcapEntity pcap = this.getById(id);
|
||||
public PcapEntity queryInfo(String id, String workspaceId) {
|
||||
PcapEntity pcap = this.getOne(new LambdaQueryWrapper<PcapEntity>().eq(PcapEntity::getId, id).eq(PcapEntity::getWorkspaceId, workspaceId));
|
||||
T.VerifyUtil.is(pcap).notNull(RCode.SYS_RECORD_NOT_FOUND);
|
||||
|
||||
JobEntity job = jobService.getOne(new LambdaQueryWrapper<JobEntity>().eq(JobEntity::getPcapId, pcap.getId()));
|
||||
@@ -101,7 +112,7 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
||||
|
||||
@Override
|
||||
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 workspaceId = T.ArrayUtil.get(params, 2);
|
||||
String createUserId = T.StrUtil.emptyToDefault(T.ArrayUtil.get(params, 3), StpUtil.getLoginIdAsString());
|
||||
@@ -109,7 +120,7 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
||||
PcapEntity entity = new PcapEntity();
|
||||
try {
|
||||
entity.setName(fileResource.getFilename());
|
||||
entity.setTags(T.StrUtil.emptyToDefault(tags, ""));
|
||||
entity.setDescription(description);
|
||||
|
||||
byte[] bytes = fileResource.getInputStream().readAllBytes();
|
||||
entity.setSize((long) bytes.length);
|
||||
@@ -129,10 +140,8 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
||||
entity.setMd5(md5Hex);
|
||||
|
||||
// 根据文件 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)) {
|
||||
// 删除本次记录的文件
|
||||
T.FileUtil.del(destination);
|
||||
return findPcapByMd5;
|
||||
}
|
||||
|
||||
@@ -141,32 +150,87 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
||||
|
||||
// workbook resource
|
||||
workbookResourceService.saveResource(workbookId, entity.getId(), WorkbookConstant.ResourceType.PCAP.getValue());
|
||||
|
||||
// parser
|
||||
PcapParserThread pcapParserThread = new PcapParserThread();
|
||||
pcapParserThread.setPcapEntity(entity);
|
||||
T.ThreadUtil.execAsync(pcapParserThread);
|
||||
} catch (IOException e) {
|
||||
log.error(e, "[savePcap] [error] [workspaceId: {}]", workspaceId);
|
||||
throw new ASWException(RCode.ERROR);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deletePcap(String pcapId) {
|
||||
PcapEntity pcap = this.getById(pcapId);
|
||||
// remove file
|
||||
T.FileUtil.del(pcap.getPath());
|
||||
public void deletePcap(String... ids) {
|
||||
for (String id : ids) {
|
||||
PcapEntity pcap = this.getById(id);
|
||||
// remove file
|
||||
T.FileUtil.del(pcap.getPath());
|
||||
|
||||
// remove
|
||||
this.removeById(pcapId);
|
||||
// remove
|
||||
this.removeById(id);
|
||||
|
||||
// update job pcap_id
|
||||
jobService.update(new LambdaUpdateWrapper<JobEntity>()
|
||||
.set(JobEntity::getPcapId, "")
|
||||
.eq(JobEntity::getPcapId, pcapId)
|
||||
);
|
||||
// update job pcap_id
|
||||
jobService.update(new LambdaUpdateWrapper<JobEntity>()
|
||||
.set(JobEntity::getPcapId, "")
|
||||
.eq(JobEntity::getPcapId, id)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parse2session(String... ids) {
|
||||
List<Runnable> taskList = T.ListUtil.list(true);
|
||||
Long maxFileSize = 0L;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,14 +1,33 @@
|
||||
package net.geedge.asw.module.runner.util;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import lombok.Data;
|
||||
import net.geedge.asw.common.config.SpringContextUtils;
|
||||
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.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.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static net.geedge.asw.module.runner.util.RunnerConstant.PcapStatus;
|
||||
|
||||
@Data
|
||||
public class PcapParserThread implements Runnable {
|
||||
@@ -18,10 +37,15 @@ public class PcapParserThread implements Runnable {
|
||||
private PcapEntity pcapEntity;
|
||||
private IPcapService pcapService;
|
||||
|
||||
private ZeekClient zeekClient;
|
||||
private GeoipClient geoipClient;
|
||||
private OpenSearchClient openSearchClient;
|
||||
|
||||
private void init() {
|
||||
pcapService = SpringContextUtils.getBean(IPcapService.class);
|
||||
// analyzing
|
||||
this.updatePcapStatus(RunnerConstant.PcapStatus.ANALYZING.getValue());
|
||||
zeekClient = (ZeekClient) SpringContextUtils.getBean("zeekClient");
|
||||
geoipClient = (GeoipClient) SpringContextUtils.getBean("geoipClient");
|
||||
openSearchClient = (OpenSearchClient) SpringContextUtils.getBean("openSearchClient");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,19 +55,24 @@ public class PcapParserThread implements Runnable {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("pcapInfo: {}", T.JSONUtil.toJsonStr(pcapEntity));
|
||||
}
|
||||
StopWatch sw = new StopWatch();
|
||||
sw.start();
|
||||
try {
|
||||
log.info("job pcap parser run start");
|
||||
// init
|
||||
this.init();
|
||||
// parsing
|
||||
this.updateStatus(PcapStatus.PARSING.getValue());
|
||||
// parser
|
||||
this.parser();
|
||||
log.info("job pcap parser run end");
|
||||
// indexed
|
||||
this.updateStatus(PcapStatus.INDEXED.getValue());
|
||||
} 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 {
|
||||
// completed
|
||||
this.updatePcapStatus(RunnerConstant.PcapStatus.COMPLETED.getValue());
|
||||
log.info("job pcap parser end");
|
||||
sw.stop();
|
||||
log.info("job pcap parser end. id: {} Run Time: {}", pcapEntity.getId(), sw.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,27 +80,140 @@ public class PcapParserThread implements Runnable {
|
||||
* parser
|
||||
*/
|
||||
private void parser() {
|
||||
String id = pcapEntity.getId();
|
||||
String path = pcapEntity.getPath();
|
||||
SignatureExtract signatureExtract = new SignatureExtract(id, path);
|
||||
// signature
|
||||
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);
|
||||
// zeek
|
||||
JSONArray jsonArray = zeekClient.parser(T.FileUtil.file(pcapEntity.getPath()));
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[parse] [zeek parse pcap file] [size: {}]", jsonArray.size());
|
||||
}
|
||||
|
||||
// TODO
|
||||
// geoip
|
||||
List<String> ipList = jsonArray.stream()
|
||||
.flatMap(obj -> Stream.of(
|
||||
T.MapUtil.getStr((JSONObject) obj, "id.orig_h", ""),
|
||||
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 source&geoip_info field
|
||||
String fileName = T.FileUtil.getName(pcapEntity.getPath());
|
||||
for (Object obj : jsonArray) {
|
||||
JSONObject pojo = (JSONObject) obj;
|
||||
pojo.put("source", fileName);
|
||||
|
||||
String orig = T.MapUtil.getStr(pojo, "id.orig_h", "");
|
||||
if (T.StrUtil.isNotEmpty(orig)) {
|
||||
JSONObject jsonObject = T.MapUtil.get(geoipInfo, orig, JSONObject.class, new JSONObject());
|
||||
pojo.put("id.orig_country", T.MapUtil.getStr(jsonObject, "country", ""));
|
||||
pojo.put("id.orig_asn", T.MapUtil.getStr(jsonObject, "asn", ""));
|
||||
pojo.put("id.orig_asname", T.MapUtil.getStr(jsonObject, "asname", ""));
|
||||
}
|
||||
|
||||
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", ""));
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param status
|
||||
*/
|
||||
private void updatePcapStatus(String status) {
|
||||
private void updateStatus(String status) {
|
||||
pcapService.update(new LambdaUpdateWrapper<PcapEntity>()
|
||||
.set(PcapEntity::getStatus, status)
|
||||
.eq(PcapEntity::getId, pcapEntity.getId())
|
||||
|
||||
@@ -36,9 +36,11 @@ public class RunnerConstant {
|
||||
public enum PcapStatus {
|
||||
UPLOADED("Uploaded"),
|
||||
|
||||
ANALYZING("Analyzing"),
|
||||
PARSING("Parsing"),
|
||||
|
||||
COMPLETED("Completed");
|
||||
INDEXED("Indexed"),
|
||||
|
||||
ERROR("Error");
|
||||
|
||||
private String value;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Deprecated
|
||||
@NoArgsConstructor
|
||||
public class SignatureExtract {
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.stream.Collectors;
|
||||
* tshark 解析 pcap 文件
|
||||
*/
|
||||
@Data
|
||||
@Deprecated
|
||||
public class SignatureUtil {
|
||||
|
||||
private static final Log log = Log.get();
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package net.geedge.asw.module.sys.controller;
|
||||
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
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.RCode;
|
||||
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.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1")
|
||||
@@ -19,6 +25,9 @@ public class SysAuthController {
|
||||
@Autowired
|
||||
private ISysAuthService authService;
|
||||
|
||||
@Autowired
|
||||
private SaTokenConfig saTokenConfig;
|
||||
|
||||
record AuthRecord(String userName, String pwd) {}
|
||||
|
||||
@PostMapping("/login")
|
||||
@@ -27,6 +36,30 @@ public class SysAuthController {
|
||||
.notEmpty(RCode.SYS_USER_PWD_ERROR);
|
||||
SysUserEntity userEntity = authService.login(record.userName(), record.pwd());
|
||||
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);
|
||||
return R.ok().putData("tokenInfo", tokenInfo).putData("user", userEntity);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@TableName("sys_role")
|
||||
public class SysRoleEntity {
|
||||
@@ -20,4 +22,8 @@ public class SysRoleEntity {
|
||||
@TableField(exist = false)
|
||||
private String[] menuIds;
|
||||
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)
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
@TableField("user_name")
|
||||
private String userName;
|
||||
|
||||
private String pwd;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String roleIds;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<SysRoleEntity> roles;
|
||||
|
||||
private String accessLevel;
|
||||
|
||||
private Long createTimestamp;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package net.geedge.asw.module.sys.service.impl;
|
||||
|
||||
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 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import net.geedge.asw.common.util.ASWException;
|
||||
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.SysUserEntity;
|
||||
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.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -23,57 +34,90 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
public class SysAuthServiceImpl implements ISysAuthService {
|
||||
|
||||
private static final Log log = Log.get();
|
||||
private static final Log log = Log.get();
|
||||
|
||||
@Autowired
|
||||
private SysUserDao userDao;
|
||||
@Autowired
|
||||
private SysRoleDao roleDao;
|
||||
@Autowired
|
||||
private SysUserDao userDao;
|
||||
|
||||
@Override
|
||||
public SysUserEntity login(String userName, String pwd) {
|
||||
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;
|
||||
}
|
||||
@Autowired
|
||||
private SysRoleDao roleDao;
|
||||
|
||||
@Override
|
||||
public void logout() {
|
||||
StpUtil.logout();
|
||||
}
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
/**
|
||||
* 获取登录用户权限
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> userPermissions() {
|
||||
Map<String, Object> result = T.MapUtil.newHashMap();
|
||||
String userId = StpUtil.getLoginIdAsString();
|
||||
List<SysRoleEntity> roleList = roleDao.findRoleByUserId(userId);
|
||||
result.put("roles", roleList);
|
||||
// 组织 menu数据
|
||||
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());
|
||||
result.put("buttons", buttonList);
|
||||
//生成 menu tree结构
|
||||
Map<String, List<SysMenuEntity>> groupMap = menuList.stream()
|
||||
.filter(menu -> T.StrUtil.equalsIgnoreCase(menu.getType(), "menu"))
|
||||
.collect(Collectors.groupingBy(SysMenuEntity::getPid));
|
||||
menuList.forEach(menu -> {
|
||||
menu.setChildren(groupMap.get(menu.getId()));
|
||||
});
|
||||
List<SysMenuEntity> collect = menuList.stream().filter(menu -> T.StrUtil.isBlank(menu.getPid()))
|
||||
.collect(Collectors.toList());
|
||||
result.put("menus", collect);
|
||||
@Autowired
|
||||
private IWorkspaceMemberService workspaceMemberService;
|
||||
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public SysUserEntity login(String userName, String pwd) {
|
||||
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
|
||||
public void logout() {
|
||||
StpUtil.logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户权限
|
||||
*/
|
||||
@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"),
|
||||
SIGNATURE("signature"),
|
||||
JOB("job"),
|
||||
PCAP("pcap"),
|
||||
DECODE_RECORD("decode_record");
|
||||
PCAP("pcap");
|
||||
|
||||
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;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
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 org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface WorkspaceMemberDao extends BaseMapper<WorkspaceMemberEntity> {
|
||||
|
||||
List<WorkspaceMemberEntity> queryList(String workspaceId);
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
package net.geedge.asw.module.workspace.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.SysRoleEntity;
|
||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@TableName("workspace")
|
||||
@@ -21,6 +26,13 @@ public class WorkspaceEntity {
|
||||
private String createUserId;
|
||||
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;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import net.geedge.asw.module.sys.entity.SysRoleEntity;
|
||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@TableName("workspace_member")
|
||||
@@ -14,4 +19,13 @@ public class WorkspaceMemberEntity {
|
||||
private Long createTimestamp;
|
||||
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 net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
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;
|
||||
|
||||
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.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.entity.WorkspaceMemberEntity;
|
||||
import net.geedge.asw.module.workspace.service.IWorkspaceMemberService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
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;
|
||||
|
||||
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 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.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.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,19 @@ spring:
|
||||
main:
|
||||
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:
|
||||
# port: 2023
|
||||
servlet:
|
||||
|
||||
114
src/main/resources/db/mapper/app/ApplicationMapper.xml
Normal file
114
src/main/resources/db/mapper/app/ApplicationMapper.xml
Normal file
@@ -0,0 +1,114 @@
|
||||
<?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="longName" column="long_name"/>
|
||||
<result property="properties" column="properties"/>
|
||||
<result property="description" column="description"/>
|
||||
<result property="surrogates" column="surrogates"/>
|
||||
<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.id != null and params.id != ''">
|
||||
AND app.id = #{params.id}
|
||||
</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>
|
||||
<if test="workspaceId != null and workspaceId != ''">
|
||||
AND app.workspace_id = #{workspaceId}
|
||||
</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>
|
||||
<if test="params.workspaceId != null and params.workspaceId != ''">
|
||||
AND app.workspace_id = #{params.workspaceId}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -6,16 +6,10 @@
|
||||
<resultMap type="net.geedge.asw.module.runner.entity.PcapEntity" id="pcapResultMap">
|
||||
<id property="id" column="id"/>
|
||||
<result property="name" column="name"/>
|
||||
<result property="tags" column="tags"/>
|
||||
<result property="description" column="description"/>
|
||||
<result property="path" column="path"/>
|
||||
<result property="size" column="size"/>
|
||||
<result property="connections" column="connections"/>
|
||||
<result property="hosts" column="hosts"/>
|
||||
<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="createTimestamp" column="create_timestamp"/>
|
||||
<result property="createUserId" column="create_user_id"/>
|
||||
@@ -81,6 +75,10 @@
|
||||
<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}, pcap.name) OR locate(#{params.q}, pcap.description) )
|
||||
</if>
|
||||
|
||||
<if test="params.jobIds != null and params.jobIds != ''">
|
||||
AND job.id in
|
||||
<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,44 @@ 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 (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 (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);
|
||||
|
||||
|
||||
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,
|
||||
`user_name` varchar(255) NOT NULL,
|
||||
`pwd` varchar(255) NOT NULL,
|
||||
`access_level` varchar(255) NOT NULL,
|
||||
`create_timestamp` bigint(20) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_user_name` (`user_name`) USING BTREE,
|
||||
KEY `idx_name` (`name`) USING BTREE
|
||||
) 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 表
|
||||
@@ -35,6 +36,10 @@ CREATE TABLE `sys_role` (
|
||||
KEY `idx_name` (`name`) USING BTREE
|
||||
) 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`;
|
||||
CREATE TABLE `sys_menu` (
|
||||
@@ -59,14 +64,14 @@ CREATE TABLE `sys_user_role` (
|
||||
`role_id` varchar(64) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO `sys_user_role`(`user_id`, `role_id`) VALUES ('admin', 'admin');
|
||||
|
||||
DROP TABLE IF EXISTS `sys_role_menu`;
|
||||
CREATE TABLE `sys_role_menu` (
|
||||
`menu_id` varchar(64) NOT NULL,
|
||||
`role_id` varchar(64) NOT NULL
|
||||
) 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 表
|
||||
@@ -217,16 +222,10 @@ DROP TABLE IF EXISTS `pcap`;
|
||||
CREATE TABLE `pcap` (
|
||||
`id` varchar(64) NOT NULL COMMENT '主键',
|
||||
`name` varchar(256) NOT NULL DEFAULT '' COMMENT '文件名称',
|
||||
`tags` varchar(256) NOT NULL DEFAULT '' COMMENT '标签',
|
||||
`description` text NOT NULL DEFAULT '' COMMENT '描述信息',
|
||||
`path` varchar(64) NOT NULL DEFAULT '' COMMENT 'PCAP文件路径',
|
||||
`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',
|
||||
`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',
|
||||
`create_timestamp` bigint(20) NOT NULL COMMENT '创建时间戳',
|
||||
`create_user_id` varchar(64) NOT NULL COMMENT '创建人',
|
||||
@@ -234,23 +233,6 @@ CREATE TABLE `pcap` (
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `idx_name` (`name`) 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
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -271,12 +253,34 @@ CREATE TABLE `application` (
|
||||
`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 '版本号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `idx_name` (`name`) USING BTREE,
|
||||
KEY `idx_long_name` (`long_name`) USING BTREE,
|
||||
KEY `idx_workspace_id` (`workspace_id`) USING BTREE
|
||||
) 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 '应用名称',
|
||||
`long_name` varchar(256) NOT NULL DEFAULT '' COMMENT '应用全称',
|
||||
`properties` text NOT NULL DEFAULT '' COMMENT '应用数据',
|
||||
`description` text NOT NULL DEFAULT '' COMMENT '描述信息',
|
||||
`surrogates` 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;
|
||||
|
||||
/**
|
||||
* 新增 package 表
|
||||
*/
|
||||
@@ -359,7 +363,7 @@ DROP TABLE IF EXISTS `workbook_resource`;
|
||||
CREATE TABLE `workbook_resource` (
|
||||
`id` varchar(64) NOT NULL COMMENT '主键',
|
||||
`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',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -383,6 +387,8 @@ CREATE TABLE `workspace` (
|
||||
KEY `idx_name` (`name`) USING BTREE
|
||||
) 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`;
|
||||
CREATE TABLE `workspace_member` (
|
||||
`workspace_id` varchar(64) NOT NULL,
|
||||
|
||||
Reference in New Issue
Block a user