Compare commits

...

104 Commits
ww ... master

Author SHA1 Message Date
weishao 00c214a473 rm \ 2023-03-09 19:13:18 +08:00
youys 45a2f5be9b 添加注释 2023-03-09 18:10:53 +08:00
youys c657b31416 缺陷>代码详情接口v2版本 2023-03-09 17:35:00 +08:00
youys 7e387eb37a 缺陷>代码详情接口v2版本 2023-03-09 17:34:12 +08:00
weishao 69d126b2f6 扫描文件路径 2023-03-09 16:43:08 +08:00
weishao bd0c90a496 静态扫描扫描逻辑 2023-03-09 16:14:29 +08:00
weishao 0421776f81 静态扫描扫描逻辑 2023-03-09 15:32:02 +08:00
jshixiong 5099a0a90a 组件漏洞 2023-03-09 15:04:34 +08:00
jshixiong 38d1a432a7 fix 2023-03-08 15:08:41 +08:00
jshixiong dd5f1f7fc3 概览 漏洞指标 2023-03-08 15:08:40 +08:00
jshixiong 2f368a2a44 fix:漏洞和组件 2023-03-07 16:01:48 +08:00
jshixiong a40dfb387a 漏洞和组件 2023-03-07 15:45:42 +08:00
weishao d72dba7f01 组件漏洞 2023-03-02 18:09:59 +08:00
weishao 88b3b4cd91 漏洞分页 2023-03-02 15:47:22 +08:00
weishao a0b77d21d6 漏洞详情 2023-03-02 15:09:32 +08:00
weishao 172def1186 漏洞 2023-03-02 14:44:08 +08:00
weishao 53428dc4ac 漏洞 2023-03-02 14:13:13 +08:00
weishao f968d9c668 漏洞 2023-03-02 10:39:18 +08:00
youys dd684dd6ef fix 2023-03-01 09:57:51 +08:00
youys 88ec9b0197 组件分险等级统计 2023-02-28 18:08:17 +08:00
youys 50c14fb136 随机分险等级 2023-02-28 18:00:23 +08:00
youys 611948c914 随机分险等级 2023-02-28 17:58:33 +08:00
youys 4041e767e8 组件名称取值问题 2023-02-28 17:45:32 +08:00
youys a70ac2cb64 fix 异步线程池mdc值传递 2023-02-27 15:54:42 +08:00
youys 3c98a12b58 失败了也去查询结果 2023-02-22 19:20:01 +08:00
youys ee7523dd5e fix 2023-02-22 19:15:02 +08:00
youys 09161eff8f .net 扫描分支 2023-02-22 19:03:27 +08:00
youys bfc61bfc79 异步解析组件 2023-02-15 14:45:18 +08:00
jshixiong 917632e8a8 fix 2023-02-14 14:12:00 +08:00
jshixiong 51a2a47748 注释 2023-02-14 10:38:57 +08:00
jshixiong 00e797b7a6 导出pdf报告 2023-02-13 18:25:17 +08:00
youys 24c7240c2b 项目在检测中不能再次检测 2023-02-07 09:41:30 +08:00
youys c002010512 获取文件目录大小命令更新 2023-02-06 18:05:54 +08:00
youys 9100963f74 分页问题 2023-02-06 17:02:25 +08:00
youys 20079ce5cd Merge branch 'component' into merge 2023-02-06 16:50:27 +08:00
youys c4eaae0ae3 code_license 删除了full_name字段 2023-02-06 16:50:12 +08:00
youys f432c69247 Merge branch 'component' into merge 2023-02-06 11:52:27 +08:00
youys a8fb88fcce 依赖路径关系箭头 2023-02-06 11:52:14 +08:00
youys 1889819871 空转换数值问题 2023-02-03 18:11:04 +08:00
youys f4e915fad9 添加字段 2023-02-03 14:09:06 +08:00
youys 4161413a2c Merge branch 'component' into merge 2023-02-03 13:49:29 +08:00
youys b0a9bb6498 组件找不到给默认数据 2023-02-03 13:49:14 +08:00
youys 62878d96b7 更新模板 2023-02-03 11:16:58 +08:00
youys 1a1dd97dc3 add log 2023-02-03 10:49:32 +08:00
youys 4e53d32e08 Merge branch 'component' into merge 2023-02-03 10:39:34 +08:00
youys a52babb07c 移除写死数据 2023-02-03 10:39:22 +08:00
youys 6922d0f08a Merge branch 'component' into merge 2023-02-03 10:38:02 +08:00
youys 68f5eeb2bb 移除写死数据 2023-02-03 10:37:53 +08:00
youys 1586cb84e5 合并代码 2023-02-03 10:29:41 +08:00
youys 3ed1d3237f 移除todo 2023-02-03 10:27:57 +08:00
jshixiong dcbf3265f3 fill delete 2023-02-02 18:20:28 +08:00
weishao 409a655207 检测冗余参数 2023-02-02 18:14:42 +08:00
weishao eff035728c Merge branch 'merge' of https://gitlink.org.cn/youys/quality_analysis into merge 2023-02-02 17:51:11 +08:00
weishao 8b5afadb78 无组件情况 2023-02-02 17:50:55 +08:00
jshixiong 86777e7a7b 模板列表不关联项目 2023-02-02 17:43:07 +08:00
weishao 931552ecab Merge branch 'merge' of https://gitlink.org.cn/youys/quality_analysis into merge 2023-02-02 17:18:22 +08:00
weishao 31b7863dd8 组件分析 2023-02-02 17:17:56 +08:00
jshixiong 7cfce85563 缺陷列表导出 2023-02-02 10:22:31 +08:00
weishao fe829ca081 展示非本人创建的分析任务 2023-02-01 10:24:31 +08:00
weishao 68730a7f50 算法修正 2023-01-29 20:59:06 +08:00
weishao 32032ceb45 算法修正 2023-01-29 20:48:31 +08:00
weishao 18c43a7a0b 算法修正 2023-01-29 20:32:15 +08:00
weishao 84ecd6bd01 nil默认语言 2023-01-29 19:21:53 +08:00
weishao d97d33011b nil jar 配置 2023-01-29 19:13:01 +08:00
weishao bcf3ebf44b nil配置 2023-01-29 19:01:02 +08:00
weishao 3d4ad762f0 Merge branch 'clone_detection' into merge 2023-01-29 18:51:36 +08:00
weishao 315062ff48 nil 2023-01-29 18:03:34 +08:00
weishao a799a70f9a 增加语言 2023-01-29 18:01:14 +08:00
weishao d410460795 克隆检测调整 2023-01-29 16:50:33 +08:00
jshixiong 0dabd940fa Merge branch 'merge_report' into merge
# Conflicts:
#	web/src/main/java/net/educoder/quality/entity/mysql/ComponentParseRecordDetail.java
#	web/src/main/resources/template/report-center-template.docx
2023-01-20 13:09:27 +08:00
jshixiong 6e670317b4 报告批量下载 2023-01-20 12:55:24 +08:00
jshixiong 924b333c0f fix 2023-01-20 12:03:56 +08:00
youys 41655f8156 导出模板格式更新 2023-01-20 10:54:23 +08:00
jshixiong 25564a9e75 质量分析报告 2023-01-20 10:18:40 +08:00
jshixiong c5ed615565 质量分析报告 2023-01-20 10:16:25 +08:00
youys 1d7f22a18e Merge branch 'component' into merge 2023-01-19 12:06:14 +08:00
youys ff8799130b 只取一条许可证 2023-01-19 12:05:53 +08:00
youys 0eee13f0d1 只取一条许可证 2023-01-19 12:05:30 +08:00
youys ec7da92229 Merge branch 'component' into merge 2023-01-19 11:44:25 +08:00
youys 454833c4fe 增加home_url字段 2023-01-19 11:44:14 +08:00
youys 95443d066b Merge branch 'component' into merge 2023-01-19 10:45:31 +08:00
youys 974b623867 增加数据库配置 2023-01-19 10:43:22 +08:00
youys 1a78551d49 Merge branch 'component' into merge 2023-01-18 14:57:44 +08:00
youys b16a83e44c 增加漏洞字段,增加mock数据 2023-01-18 14:57:21 +08:00
weishao ad4462228d Merge branch 'clone_detection' into merge 2023-01-17 17:56:21 +08:00
weishao 3cd1113b17 开源质量分析模板 2023-01-17 17:55:32 +08:00
youys 2af9e0c033 merge clone_detection 2023-01-17 12:34:42 +08:00
youys 5295ea916f Merge branch 'component' into merge 2023-01-17 12:32:54 +08:00
youys 63d9cc1247 组件许可证数据 2023-01-17 12:31:33 +08:00
weishao e4617f7249 jsoup test 2023-01-12 20:16:44 +08:00
weishao d21ed60307 jsoup test 2023-01-12 20:16:23 +08:00
weishao 63816225b0 本地写死地址测试 2023-01-06 17:17:59 +08:00
weishao bfbdc6099b 本地写死地址测试 2023-01-06 17:13:26 +08:00
weishao dba47fee69 本地写死地址测试 2023-01-06 16:21:13 +08:00
weishao 8ae64d86db 本地写死地址测试 2023-01-06 15:46:53 +08:00
weishao fd389367ca 本地写死地址测试 2023-01-06 15:43:09 +08:00
weishao ab589a1ba8 nil 2023-01-06 15:20:47 +08:00
weishao c3bd36abd9 ceshi 2023-01-06 14:25:14 +08:00
weishao 27ec41ae72 克隆检测记录 2023-01-06 14:15:45 +08:00
weishao 3971d7dea2 克隆检测记录 2023-01-06 14:02:04 +08:00
weishao 21731f2983 克隆检测记录 2023-01-06 13:50:00 +08:00
weishao c270bc1650 可运行 2023-01-06 12:31:12 +08:00
weishao 5cbb3ac29b 克隆检测逻辑实现 2023-01-05 23:28:05 +08:00
youys e050cfec84 组件mock数据,以及新增缺失接口 2022-12-27 11:31:16 +08:00
90 changed files with 3506 additions and 628 deletions

View File

@ -25,6 +25,8 @@ public class DynamicDataSourceConfig {
public static final String MASTER = "master";
public static final String READONLY = "readonly";
public static final String GITEA = "gitea";
public static final String SAST = "sast";
private static final List INIT_SQLS = Arrays.asList("SET NAMES utf8mb4");
@ -96,6 +98,77 @@ public class DynamicDataSourceConfig {
@Value("${spring.datasource.readonly.druid.test-while-idle}")
private boolean readonlyTestWhileIdle;
// --------------------------gitea----------------------------------
@Value("${spring.datasource.gitea.driver-class-name}")
private String giteaDriverClass;
@Value("${spring.datasource.gitea.url}")
private String giteaUrl;
@Value("${spring.datasource.gitea.username}")
private String giteaUsername;
@Value("${spring.datasource.gitea.password}")
private String giteaPassword;
@Value("${spring.datasource.gitea.druid.initial-size}")
private Integer giteaInitialSize;
@Value("${spring.datasource.gitea.druid.max-active}")
private Integer giteaMaxActive;
@Value("${spring.datasource.gitea.druid.min-idle}")
private Integer giteaMinIdle;
@Value("${spring.datasource.gitea.druid.validation-query}")
private String giteaValidationQuery;
@Value("${spring.datasource.gitea.druid.test-on-borrow}")
private boolean giteaTestOnBorrow;
@Value("${spring.datasource.gitea.druid.test-on-return}")
private boolean giteaTestOnReturn;
@Value("${spring.datasource.gitea.druid.test-while-idle}")
private boolean giteaTestWhileIdle;
// --------------------------sast----------------------------------
@Value("${spring.datasource.sast.driver-class-name}")
private String sastDriverClass;
@Value("${spring.datasource.sast.url}")
private String sastUrl;
@Value("${spring.datasource.sast.username}")
private String sastUsername;
@Value("${spring.datasource.sast.password}")
private String sastPassword;
@Value("${spring.datasource.sast.druid.initial-size}")
private Integer sastInitialSize;
@Value("${spring.datasource.sast.druid.max-active}")
private Integer sastMaxActive;
@Value("${spring.datasource.sast.druid.min-idle}")
private Integer sastMinIdle;
@Value("${spring.datasource.sast.druid.validation-query}")
private String sastValidationQuery;
@Value("${spring.datasource.sast.druid.test-on-borrow}")
private boolean sastTestOnBorrow;
@Value("${spring.datasource.sast.druid.test-on-return}")
private boolean sastTestOnReturn;
@Value("${spring.datasource.sast.druid.test-while-idle}")
private boolean sastTestWhileIdle;
@Bean("master")
public DataSource masterDataSource() {
DruidDataSource masterDataSource = new DruidDataSource();
@ -142,12 +215,59 @@ public class DynamicDataSourceConfig {
}
@Bean("gitea")
public DataSource giteaDataSource() {
DruidDataSource giteaDataSource = new DruidDataSource();
giteaDataSource.setDriverClassName(giteaDriverClass);
giteaDataSource.setUrl(giteaUrl);
giteaDataSource.setUsername(giteaUsername);
giteaDataSource.setPassword(giteaPassword);
giteaDataSource.setMinIdle(giteaMinIdle);
giteaDataSource.setMaxActive(giteaMaxActive);
giteaDataSource.setMinIdle(giteaMinIdle);
giteaDataSource.setTestOnBorrow(giteaTestOnBorrow);
giteaDataSource.setTestOnReturn(giteaTestOnReturn);
giteaDataSource.setTestWhileIdle(giteaTestWhileIdle);
giteaDataSource.setValidationQuery(giteaValidationQuery);
// 连接失败后中断---重试10次
giteaDataSource.setBreakAfterAcquireFailure(true);
giteaDataSource.setConnectionErrorRetryAttempts(10);
// 快速失败
giteaDataSource.setFailFast(true);
return giteaDataSource;
}
@Bean("sast")
public DataSource sastDataSource() {
DruidDataSource sastDataSource = new DruidDataSource();
sastDataSource.setDriverClassName(sastDriverClass);
sastDataSource.setUrl(sastUrl);
sastDataSource.setUsername(sastUsername);
sastDataSource.setPassword(sastPassword);
sastDataSource.setMinIdle(sastMinIdle);
sastDataSource.setMaxActive(sastMaxActive);
sastDataSource.setMinIdle(sastMinIdle);
sastDataSource.setTestOnBorrow(sastTestOnBorrow);
sastDataSource.setTestOnReturn(sastTestOnReturn);
sastDataSource.setTestWhileIdle(sastTestWhileIdle);
sastDataSource.setValidationQuery(sastValidationQuery);
// 连接失败后中断---重试10次
sastDataSource.setBreakAfterAcquireFailure(true);
sastDataSource.setConnectionErrorRetryAttempts(10);
// 快速失败
sastDataSource.setFailFast(true);
return sastDataSource;
}
@Bean
@Primary
public DataSource dynamicDataSource() {
Map<Object, Object> dataSourceMap = new HashMap<>(2);
dataSourceMap.put(MASTER, masterDataSource());
dataSourceMap.put(READONLY, slaveDataSource());
dataSourceMap.put(GITEA, giteaDataSource());
dataSourceMap.put(SAST, sastDataSource());
//设置动态数据源
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(dataSourceMap);

View File

@ -0,0 +1,46 @@
package net.educoder.quality.common.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import tk.mybatis.spring.annotation.MapperScan;
import javax.sql.DataSource;
/**
* @Author: youys
* @Date: 2022/9/15
* @Description:
*/
@Configuration
@MapperScan(basePackages = "net.educoder.quality.mapper.gitea", sqlSessionFactoryRef = "sqlSessionFactoryGiteaDataSource")
public class GiteaDatasourceConfig {
@Bean(name = "sqlSessionFactoryGiteaDataSource")
public SqlSessionFactory sqlSessionFactoryDdsDataSource(@Qualifier("gitea") DataSource masterDataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(masterDataSource);
//下边两句仅仅用于*.xml文件如果整个持久层操作不需要使用到xml文件的话只用注解就可以搞定则不加
//指定entity和mapperxml的路径
factoryBean.setTypeAliasesPackage("net.educoder.quality.entity.gitea");
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:gitea.mapper/*Mapper.xml"));
return factoryBean.getObject();
}
@Bean(name = "giteaPlatformTransactionManager")
public PlatformTransactionManager platformTransactionManager(@Qualifier("gitea") DataSource giteaDataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(giteaDataSource);
return dataSourceTransactionManager;
}
}

View File

@ -21,4 +21,22 @@ public class PropertiesConfig {
@Value("${openi.gitPassword}")
private String gitPassword;
@Value("${nil.mil}")
private String mil;
@Value("${nil.mit}")
private String mit;
@Value("${nil.filtrationThreshold}")
private String filtrationThreshold;
@Value("${nil.verificationThreshold}")
private String verificationThreshold;
@Value("${nil.jarPath}")
private String nilJarPath;
@Value("${sast.driver}")
private String sastDriver;
}

View File

@ -0,0 +1,35 @@
package net.educoder.quality.common.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import tk.mybatis.spring.annotation.MapperScan;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "net.educoder.quality.mapper.sast", sqlSessionFactoryRef = "sqlSessionFactorySastDataSource")
public class SastDatasourceConfig {
@Bean(name = "sqlSessionFactorySastDataSource")
public SqlSessionFactory sqlSessionFactoryDdsDataSource(@Qualifier("sast") DataSource sastDataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(sastDataSource);
factoryBean.setTypeAliasesPackage("net.educoder.quality.entity.sast");
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:sast.mapper/*Mapper.xml"));
return factoryBean.getObject();
}
@Bean(name = "sastPlatformTransactionManager")
public PlatformTransactionManager platformTransactionManager(@Qualifier("sast") DataSource sastDataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(sastDataSource);
return dataSourceTransactionManager;
}
}

View File

@ -1,9 +1,9 @@
package net.educoder.quality.common.config;
import net.educoder.quality.common.filter.MdcTaskDecorator;
import net.educoder.quality.common.util.mdc.MdcThreadPoolTaskScheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@ -30,6 +30,19 @@ public class ThreadPoolConfig {
return threadPoolExecutor;
}
@Bean("cloneDetectionThreadPool")
public ThreadPoolTaskExecutor cloneDetectionThreadPool() {
ThreadPoolTaskExecutor threadPoolExecutor = new ThreadPoolTaskExecutor();
threadPoolExecutor.setCorePoolSize(100);
threadPoolExecutor.setMaxPoolSize(100);
threadPoolExecutor.setQueueCapacity(5000);
threadPoolExecutor.setThreadNamePrefix("clone-detection-thread-");
threadPoolExecutor.setWaitForTasksToCompleteOnShutdown(true);
threadPoolExecutor.setAwaitTerminationMillis(5);
threadPoolExecutor.setTaskDecorator(new MdcTaskDecorator());
return threadPoolExecutor;
}
@Bean("sonarQueryResultThreadPool")
public ThreadPoolTaskExecutor sonarQueryResultThreadPool() {
@ -66,7 +79,7 @@ public class ThreadPoolConfig {
*/
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
MdcThreadPoolTaskScheduler taskScheduler = new MdcThreadPoolTaskScheduler();
//核心线程池数量方法: 返回可用处理器的Java虚拟机的数量
taskScheduler.setPoolSize(20);
taskScheduler.setThreadNamePrefix("schedule-");

View File

@ -11,6 +11,7 @@ public interface QualityConstants {
String C = "c";
String CXX = "cpp";
String CPP = "c++";
String NET = "c#";
String OTHER = "other";

View File

@ -42,4 +42,16 @@ public enum BugTypeEnum {
}
return null;
}
public static String getDescriptionByDbValue(String dbValue){
if (dbValue==null || "".equals(dbValue)){
return null;
}
for (BugTypeEnum bugTypeEnum : BugTypeEnum.values()) {
if(bugTypeEnum.dbValue.equals(dbValue)){
return bugTypeEnum.description;
}
}
return null;
}
}

View File

@ -28,6 +28,11 @@ public enum ErrorCodeEnum {
AFTERMATH_EXP("000013","评测线程出错,善后处理发生异常"),
GIT_FAIL("000014","获取git凭证失败: "),
GIT_CREDENTIAL_FAIL("000015","设置git凭证失败:"),
GIT_CREDENTIAL_INVALID("000016","git账号密码不匹配"),
GIT_URL_INVALID("000017","非法的git地址"),
COMPONENT_NOT_FOUND("000018","组件未找到"),
LICENSE_NOT_FOUND("000019","许可证未找到"),
UNDER_DETECTION_ERROR("000020","项目正在检测中,请稍后再试"),
;
String value;

View File

@ -1,10 +1,11 @@
package net.educoder.quality.common.util;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.educoder.quality.common.bean.ShellResult;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
/**
* @Author: youys
* @Date: 2022/10/14
@ -13,24 +14,25 @@ import org.apache.commons.lang3.StringUtils;
@Slf4j
public class GitUtil {
/**
* 克隆代码
*
* @param fullWorkspace
* @return
* 克隆代码到指定目录
*/
public static boolean gitClone(String gitUrl, String branch, String username, String password, String fullWorkspace) {
// 拉代码
// TODO 暂时为了测试
int index = gitUrl.replaceAll("localhost:43001", "118.31.13.117:64300").lastIndexOf("//");
// int index = gitUrl.lastIndexOf("//");
String command = StringUtils.join("cd ", fullWorkspace, " && git clone -b ", branch, " ", gitUrl.substring(0, index + 2), username, ":",
password, "@", gitUrl.substring(index + 2));
public static ShellResult gitClone(String gitUrl, String branch, String username, String password, String fullWorkspace) {
File file = new File(fullWorkspace);
if (!file.exists()) {
file.mkdirs();
}
ShellResult shellResult = ShellUtil.executeAndGetExitStatus(command);
log.info("command:{},git克隆代码返回:{}", command, JSONObject.toJSONString(shellResult));
return shellResult.getExitStatus() == 0;
int index = gitUrl.lastIndexOf("//");
String command;
if (StringUtils.isNotBlank(username)) {
command = StringUtils.join("cd ", fullWorkspace, " && git clone -b ", branch, " ", gitUrl.substring(0, index + 2), username, ":",
password, "@", gitUrl.substring(index + 2));
} else {
command = StringUtils.join("cd ", fullWorkspace, " && git clone -b ", branch, " ", gitUrl.substring(0, index + 2), gitUrl.substring(index + 2));
}
return ShellUtil.executeAndGetExitStatus(command);
}
}

View File

@ -94,7 +94,6 @@ public final class ShellUtil {
continue;
}
logger.debug("executeAndGetExitStatus line: {}", line); // TODO 此处稳定后去除
out.append(line);
out.append(System.getProperty("line.separator"));
}

View File

@ -1,10 +1,12 @@
package net.educoder.quality.common.util;
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -52,4 +54,167 @@ public class WordUtil {
return value;
}
/**
* 取得某个表格多行的段落
* @param table XWPFTable
*/
public static List<XWPFParagraph> getTableRowsParagraphs(XWPFTable table,int begain,int end) {
List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>();
// 列表内段落
for (int i = begain;i<=end;i++){
XWPFTableRow row = table.getRow(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
paragraphs.addAll(cell.getParagraphs());
}
}
return paragraphs;
}
/**
* 取得一行的段落
* @param row 一行
*/
public static List<XWPFParagraph> getRowParagraphs(XWPFTableRow row) {
List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>();
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
paragraphs.addAll(cell.getParagraphs());
}
return paragraphs;
}
/**
* insertRow 在word表格中指定位置插入一行并将某一行的样式及内容复制到新增行
* */
public static XWPFTableRow insertRow(XWPFTable table, XWPFTableRow copyRow, int newrowIndex) {
// 在表格中指定的位置新增一行
XWPFTableRow targetRow = table.insertNewTableRow(newrowIndex);
//复制行对象
targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
//或许需要复制的行的列
List<XWPFTableCell> copyCells = copyRow.getTableCells();
//复制列对象
XWPFTableCell targetCell = null;
for (int i = 0; i < copyCells.size(); i++) {
XWPFTableCell copyCell = copyCells.get(i);
targetCell = targetRow.addNewTableCell();
targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());
if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) {
targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());
if (copyCell.getParagraphs().get(0).getRuns() != null
&& copyCell.getParagraphs().get(0).getRuns().size() > 0) {
XWPFRun cellRun = targetCell.getParagraphs().get(0).createRun();
XWPFRun copyRun = copyCell.getParagraphs().get(0).getRuns().get(0);
//字体名称
cellRun.setFontFamily(copyRun.getFontFamily());
//字体颜色
cellRun.setColor(copyRun.getColor());
//字体加粗
cellRun.setBold(copyRun.isBold());
//字体倾斜
cellRun.setItalic(copyRun.isItalic());
cellRun.setText(copyCell.getText());
}
}
}
return targetRow;
}
/**
* 替换全部文本
* @param textMap 替换信息
* @param paragraphs 段落
*/
public static void replaceAllTexts(Map<String, String> textMap, List<XWPFParagraph> paragraphs) {
Set<Map.Entry<String, String>> textEntrySet = textMap.entrySet();
for (Map.Entry<String, String> entry : textEntrySet) {
String key = entry.getKey();
String value = entry.getValue();
// 替换全部文本
replaceAllTexts(key, value, paragraphs);
}
}
/**
* 替换全部文本
* @param key 替换键
* @param value 替换值
* @param paragraphs 段落
*/
public static void replaceAllTexts(String key, String value, List<XWPFParagraph> paragraphs) {
for (XWPFParagraph paragraph : paragraphs) {
// 待替换文本
String text = paragraph.getText();
if (StringUtils.isNotEmpty(text) && text.indexOf(key) != -1) {
List<XWPFRun> runs = paragraph.getRuns();
// 只保留第一个Run
for (int i = (runs.size() - 1); i > 0; i--) {
paragraph.removeRun(i);
}
runs.get(0).setText(text.replace(key, value), 0);
}
}
}
/**
* 保存Word
* @param document Word文档
* @param filePath 保存路径
*/
public static void save(XWPFDocument document, String filePath) throws Exception {
FileOutputStream fos = null;
try {
System.out.println("POI生成Word文件" + filePath);
File file = new File(filePath);
// FileUtil.makeDir(file.getParentFile());
fos = new FileOutputStream(file);
document.write(fos);
} finally {
if (fos != null) {
fos.close();
}
}
}
/**
* 打开Word
* @param filePath 文件全路径
*/
public static XWPFDocument open(String filePath) throws Exception {
InputStream is = null;
try {
System.out.println("POI打开Word文件" + filePath);
is = new FileInputStream(filePath);
return new XWPFDocument(is);
} finally {
if (is != null) {
is.close();
}
}
}
/**
* word转pdf
* 功能依赖于poi 3.17
* linux或win环境下需要相应的中文字体支持宋体微软雅黑...否则中文不显示
* @param document
*/
public static void docToPdf(XWPFDocument document,OutputStream outPDF ){
PdfOptions options = PdfOptions.create();
try {
PdfConverter.getInstance().convert(document, outPDF, options);
}catch (IOException e){
e.printStackTrace();
}finally {
try {
if (outPDF!=null){
outPDF.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,31 @@
package net.educoder.quality.common.util.mdc;
import cn.hutool.core.util.IdUtil;
import org.slf4j.MDC;
import java.util.Map;
/**
* @Author: youys
* @Date: 2023/2/27
* @Description:
*/
public class MdcTaskDecorator {
public static Runnable decorate(Runnable runnable) {
Map<String, String> contextMap = MDC.getCopyOfContextMap();
return () -> {
try {
if (contextMap != null) {
MDC.setContextMap(contextMap);
}
MDC.put("traceId", IdUtil.fastSimpleUUID());
runnable.run();
} finally {
MDC.clear();
}
};
}
}

View File

@ -0,0 +1,25 @@
package net.educoder.quality.common.util.mdc;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
/**
* @Author: youys
* @Date: 2023/2/27
* @Description:
*/
public class MdcThreadPoolTaskScheduler extends ThreadPoolTaskScheduler {
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
return super.scheduleWithFixedDelay(MdcTaskDecorator.decorate(task), startTime, delay);
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
return super.schedule(MdcTaskDecorator.decorate(task), startTime);
}
}

View File

@ -163,7 +163,12 @@
<version>${pagehelper.version}</version>
</dependency>
<!-- word to pdf -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.poi.xwpf.converter.pdf-gae</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>

View File

@ -31,9 +31,30 @@
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.9.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>

View File

@ -55,6 +55,12 @@ public class OperateLogAop {
commonVO.setRepository(request.getParameter("repository"));
}
if (commonVO == null){
commonVO = new CommonVO();
commonVO.setCurrentUser(request.getParameter("currentUser"));
commonVO.setRepoOwner(request.getParameter("repoOwner"));
commonVO.setRepository(request.getParameter("repository"));
}
// 获取IP地址
String ipAddress = IpUtil.getIpAddress(request);

View File

@ -1,12 +1,14 @@
package net.educoder.quality.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageInfo;
import net.educoder.quality.common.util.R;
import net.educoder.quality.dto.ComponentListDTO;
import net.educoder.quality.dto.ComponentStatisticsDTO;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.service.ComponentService;
import net.educoder.quality.vo.PageVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@ -31,7 +33,7 @@ public class ComponentController {
/**
* 组件统计
* 组件解析
*
* @return
*/
@ -55,12 +57,13 @@ public class ComponentController {
@GetMapping("/component/{projectId}/list")
public R list(@PathVariable Long projectId, @Valid PageVO pageVO) {
PageInfo<ComponentParseRecordDetail> componentListDTOPageInfo = componentService.componentList(projectId, pageVO);
PageInfo<ComponentParseRecordDetailDTO> componentListDTOPageInfo = componentService.componentList(projectId, pageVO);
List<ComponentListDTO> resultList = new ArrayList<>(componentListDTOPageInfo.getList().size());
for (ComponentParseRecordDetail componentParseRecordDetail : componentListDTOPageInfo.getList()) {
ComponentListDTO componentListDTO = new ComponentListDTO();
BeanUtils.copyProperties(componentParseRecordDetail, componentListDTO);
componentListDTO.setVulnerabilities(StringUtils.isNotEmpty(componentParseRecordDetail.getVulnerabilities()) ? JSON.parseArray(componentParseRecordDetail.getVulnerabilities()) : new JSONArray());
resultList.add(componentListDTO);
}
PageInfo<ComponentListDTO> pageInfo = new PageInfo<>();
@ -70,4 +73,17 @@ public class ComponentController {
return R.success(pageInfo);
}
@GetMapping("/component/detail/{id}")
public R<ComponentDetailDTO> getComponentDetail(@PathVariable Long id) {
ComponentDetailDTO detailDTO = componentService.getComponentDetail(id);
return R.success(detailDTO);
}
@GetMapping("/component/depend/{id}")
public R<DependComponentDTO> getDependComponent(@PathVariable Long id) {
List<DependComponentDTO> dependComponentList = componentService.getDependComponent(id);
return R.success(dependComponentList);
}
}

View File

@ -5,15 +5,19 @@ import com.github.pagehelper.PageInfo;
import net.educoder.quality.common.annotations.OperateLogAnnotation;
import net.educoder.quality.common.util.R;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -177,6 +181,26 @@ public class ProjectController {
return R.success(projectBugCenterDTOPageInfo);
}
/**
* 缺陷列表导出
*
* @param projectId
*/
@GetMapping("/projects/{projectId}/bug/export")
public void projectBugExport(@PathVariable Long projectId, @Valid ProjectBugCenterVO projectBugCenterVO, HttpServletResponse response) throws Exception {
List<ProjectBugCenterDTO> projectBugCenterDTOList = projectService.projectBugList(projectId, projectBugCenterVO);
Projects projects = projectService.getProjectById(projectId);
response.setCharacterEncoding("utf-8");
String fileName = new String(projects.getProjectName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
response.setHeader("Content-disposition", "attachment;filename=" + fileName + "_bug.xlsx");
response.setContentType("application/vnd.ms-excel");
EasyExcel.write(response.getOutputStream(), ProjectBugCenterDTO.class).sheet().doWrite(projectBugCenterDTOList);
}
/**
* 缺陷中心> 代码详情
*
@ -191,169 +215,16 @@ public class ProjectController {
/**
* 漏洞统计信息
* 缺陷中心> 代码详情
* V2版本
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability")
public R<ProjectVulnerabilityDTO> projectVulnerability(@PathVariable Long projectId) {
// TODO 暂时写死为了调试
projectId = 1L;
ProjectVulnerabilityDTO projectVulnerabilityDTO = projectService.projectVulnerability(projectId);
return R.success(projectVulnerabilityDTO);
@GetMapping("/projects/v2/{projectId}/bug/center/codeDetail")
public R<ProjectBugCenterCodeDetailV2DTO> projectBugCenterCodeDetailV2(@PathVariable Long projectId, @RequestParam("ruleId") Integer id) {
ProjectBugCenterCodeDetailV2DTO codeDetailV2DTO = projectService.projectBugCenterCodeDetailV2(projectId, id);
return R.success(codeDetailV2DTO);
}
/**
* 漏洞列表
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/list")
public R<PageInfo> projectVulnerabilityList(@PathVariable Long projectId, @Valid PageVO pageVO) {
// TODO 暂时写死为了调试
projectId = 1L;
pageVO.setCurrentUser("youys");
pageVO.setRepoOwner("youys");
pageVO.setRepository("demo1");
PageInfo<ProjectVulnerabilityListDTO> projectVulnerabilityListDTOPageInfo = projectService.projectVulnerabilityList(projectId, pageVO);
return R.success(projectVulnerabilityListDTOPageInfo);
}
/**
* 漏洞列表导出
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/export")
public void projectVulnerabilityExport(@PathVariable Long projectId, @Valid CommonVO commonVO, HttpServletResponse response) throws Exception {
// TODO 暂时写死为了调试
projectId = 1L;
commonVO.setCurrentUser("youys");
commonVO.setRepoOwner("youys");
commonVO.setRepository("demo1");
List<ProjectVulnerabilityListDTO> vulnerabilityListDTOS = projectService.projectVulnerabilityExport(projectId, commonVO);
Projects projects = projectService.getProjectById(projectId);
response.setCharacterEncoding("utf-8");
String fileName = new String(projects.getProjectName().getBytes("utf-8"), "ISO8859-1");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
response.setContentType("application/octet-stream");
EasyExcel.write(response.getOutputStream(), ProjectVulnerabilityListDTO.class).sheet().doWrite(vulnerabilityListDTOS);
}
/**
* 漏洞详情
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/detail")
public R<ProjectVulnerabilityDetailDTO> projectVulnerabilityDetail(@PathVariable Long projectId, @RequestParam("uuid") String uuid) {
projectId = 1L;
ProjectVulnerabilityDetailDTO detailDTO = projectService.projectVulnerabilityDetail(projectId, uuid);
return R.success(detailDTO);
}
/**
* 许可证总计
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/licence/overview")
public R<LicenceOverviewDTO> projectLicenceOverview(@PathVariable("projectId") Long projectId) {
return R.success(projectService.projectLicenceOverview(projectId));
}
/**
* 许可证兼容风险总计
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/licence/risk")
public R<LicenceRiskDTO> projectLicenceRiskOverview(@PathVariable("projectId") Long projectId) {
return R.success(projectService.projectLicenceRiskOverview(projectId));
}
/**
* 许可证分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licence/page")
public R<PageInfo<LicenceListDTO>> licencePage(@PathVariable("projectId") Long projectId, ProjectLicencePageVO vo) {
return R.success(projectService.licencePage(projectId, vo));
}
/**
* 许可证文件或组件列表
* vo.fileType : 1文件2组件
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licence/files")
public R<List<LicenceFileDTO>> licenceFileList(@PathVariable("projectId") Long projectId, @Valid LicenceFileVO vo) {
return R.success(projectService.licenceFileList(projectId, vo));
}
/**
* 许可证版权信息分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licenceCopyright/page")
public R<PageInfo<LicenceCopyrightDTO>> licenceCopyrightList(@PathVariable("projectId") Long projectId, PageVO vo) {
return R.success(projectService.licenceCopyrightList(projectId, vo));
}
/**
* 许可证兼容分析分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licenceCompatible/page")
public R<PageInfo<LicenceCompatibleDTO>> licenceCompatibleList(@PathVariable("projectId") Long projectId, PageVO vo) {
return R.success(projectService.licenceCompatibleList(projectId, vo));
}
/**
* 许可证版权信息篡改分析分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licenceCopyrightDistort/page")
public R<PageInfo<LicenceCopyrightDTO>> licenceCopyrightDistortList(@PathVariable("projectId") Long projectId, PageVO vo) {
return R.success(projectService.licenceCopyrightDistortList(projectId, vo));
}
/**
* 许可证篡改分析分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licenceDistort/page")
public R<PageInfo<LicenceDistortDTO>> licenceDistortList(@PathVariable("projectId") Long projectId, PageVO vo) {
return R.success(projectService.licenceDistortList(projectId, vo));
}
}

View File

@ -6,10 +6,12 @@ import cn.hutool.core.util.ZipUtil;
import com.github.pagehelper.PageInfo;
import net.educoder.quality.common.util.R;
import net.educoder.quality.common.util.WordUtil;
import net.educoder.quality.dto.ReportDetailDTO;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.entity.mysql.ReportCenter;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.service.ReportCenterService;
import net.educoder.quality.service.postgres.PgProjectsService;
import net.educoder.quality.vo.ExportReportVO;
import net.educoder.quality.vo.ReportListVO;
import org.apache.commons.lang3.StringUtils;
@ -39,6 +41,9 @@ public class ReportCenterController {
@Autowired
private ProjectService projectService;
@Autowired
private PgProjectsService pgProjectsService;
@Value("${download.tempDir}")
private String downloadTempDir;
@ -84,23 +89,43 @@ public class ReportCenterController {
// 设置文件下载参数
response.setCharacterEncoding("utf-8");
String fileName = new String(reportCenter.getReportName().getBytes("utf-8"), "ISO8859-1");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx");
response.setContentType("application/octet-stream");
// TODO 获取模板填充数据目前写死
// 获取模板填充数据
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("template/report-center-template.docx");
ServletOutputStream outputStream = response.getOutputStream();
ReportDetailDTO reportDetail = pgProjectsService.getReportDetail(projects.getProjectName());
Map<String, String> param = new HashMap<>(4);
Map<String, String> param = new HashMap<>(13);
param.put("projectName", projects.getProjectName());
param.put("createTime", DateUtil.formatDateTime(new Date()));
param.put("issueCount",String.valueOf(reportDetail.getBugCount().getTotal()));
param.put("seriousIssueCount",String.valueOf(reportDetail.getBugCount().getCritical()));
param.put("highRiskIssueCount",String.valueOf(reportDetail.getBugCount().getHigh()));
param.put("midRiskIssueCount",String.valueOf(reportDetail.getBugCount().getMiddle()));
param.put("lowRiskIssueCount",String.valueOf(reportDetail.getBugCount().getLow()));
param.put("componentCount",String.valueOf(reportDetail.getComponents()));
param.put("componentBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getTotal()));
param.put("seriousBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getCritical()));
param.put("highRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getHigh()));
param.put("midRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getMiddle()));
param.put("lowRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getLow()));
XWPFDocument doc = new XWPFDocument(resourceAsStream);
WordUtil.changeText(doc, param);
doc.write(outputStream);
pgProjectsService.fillReportTable(doc,reportDetail);
String format = reportCenter.getFormat();
if ("pdf".equals(format)){
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".pdf");
response.setContentType("application/pdf");
WordUtil.docToPdf(doc,outputStream);
}else {
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx");
response.setContentType("application/octet-stream");
doc.write(outputStream);
}
}
@ -130,16 +155,30 @@ public class ReportCenterController {
ReportCenter reportCenter = reportCenterService.reportCenterDetail(reportId);
Projects projects = projectService.getProjectById(reportCenter.getProjectId());
// TODO 获取模板填充数据目前写死
// 获取模板填充数据
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("template/report-center-template.docx");
Map<String, String> param = new HashMap<>(2);
ReportDetailDTO reportDetail = pgProjectsService.getReportDetail(projects.getProjectName());
Map<String, String> param = new HashMap<>(13);
param.put("projectName", projects.getProjectName());
param.put("createTime", DateUtil.formatDateTime(new Date()));
param.put("issueCount",String.valueOf(reportDetail.getBugCount().getTotal()));
param.put("seriousIssueCount",String.valueOf(reportDetail.getBugCount().getCritical()));
param.put("highRiskIssueCount",String.valueOf(reportDetail.getBugCount().getHigh()));
param.put("midRiskIssueCount",String.valueOf(reportDetail.getBugCount().getMiddle()));
param.put("lowRiskIssueCount",String.valueOf(reportDetail.getBugCount().getLow()));
param.put("componentCount",String.valueOf(reportDetail.getComponents()));
param.put("componentBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getTotal()));
param.put("seriousBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getCritical()));
param.put("highRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getHigh()));
param.put("midRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getMiddle()));
param.put("lowRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getLow()));
XWPFDocument doc = new XWPFDocument(resourceAsStream);
WordUtil.changeText(doc, param);
pgProjectsService.fillReportTable(doc,reportDetail);
String filePath = filePath(reportCenter.getReportName());
doc.write(new FileOutputStream(new File(filePath)));

View File

@ -0,0 +1,63 @@
package net.educoder.quality.controller;
import com.github.pagehelper.PageInfo;
import net.educoder.quality.common.util.R;
import net.educoder.quality.dto.ProjectVulnerabilityDTO;
import net.educoder.quality.dto.ProjectVulnerabilityDetailDTO;
import net.educoder.quality.service.VulnerabilityService;
import net.educoder.quality.vo.PageVO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
/**
* 克隆检测控制器
*/
@RestController
public class VulnerabilityController {
@Resource
private VulnerabilityService vulnerabilityService;
/**
* 漏洞统计信息
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability")
public R<ProjectVulnerabilityDTO> projectVulnerability(@PathVariable Long projectId) {
ProjectVulnerabilityDTO projectVulnerabilityDTO = vulnerabilityService.vulnerabilityStatistics(projectId);
return R.success(projectVulnerabilityDTO);
}
/**
* 漏洞列表
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/list")
public R<PageInfo> projectVulnerabilityList(@PathVariable Long projectId, @Valid PageVO pageVO) {
PageInfo<ProjectVulnerabilityDetailDTO> vulnerabilityList = vulnerabilityService.vulnerabilityList(projectId, pageVO);
return R.success(vulnerabilityList);
}
/**
* 漏洞详情
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/detail")
public R<ProjectVulnerabilityDetailDTO> projectVulnerabilityDetail(@PathVariable Long projectId, @RequestParam("uuid") String uuid) {
ProjectVulnerabilityDetailDTO detailDTO = vulnerabilityService.vulnerabilityDetail(projectId, uuid);
return R.success(detailDTO);
}
}

View File

@ -12,7 +12,7 @@ public class CloneDetectionResultProjectLevelDTO {
/**
* 相似文件比
*/
private Double similarityFilePercent;
private Integer similarityFilePercent;
/**
* 相似文件数

View File

@ -0,0 +1,28 @@
package net.educoder.quality.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class ClonePairDTO {
private String sourceFile;
private int sourceFileStartLine;
private int sourceFileEndLine;
private String targetFile;
private int targetFileStartLine;
private int targetFileEndLine;
private double similarity;
private int similarLines;
public ClonePairDTO(String sourceFile, int sourceFileStartLine, int sourceFileEndLine, String targetFile, int targetFileStartLine, int targetFileEndLine, double similarity) {
this.sourceFile = sourceFile;
this.sourceFileStartLine = sourceFileStartLine;
this.sourceFileEndLine = sourceFileEndLine;
this.targetFile = targetFile;
this.targetFileStartLine = targetFileStartLine;
this.targetFileEndLine = targetFileEndLine;
this.similarity = similarity;
this.similarLines = Math.max(Math.min(sourceFileEndLine - sourceFileStartLine, targetFileEndLine - targetFileStartLine), 0);
}
}

View File

@ -0,0 +1,53 @@
package net.educoder.quality.dto;
import lombok.Data;
import java.util.List;
/**
* @Author: youys
* @Date: 2022/12/27
* @Description: 组件-查看详情
*/
@Data
public class ComponentDetailDTO {
/**
* 组件名称
*/
private String componentName;
/**
* 许可证
*/
private String permit;
/**
* 主业
*/
private String homeUrl;
/**
* 发布日期
*/
private String publishDate;
/**
* 更新日期
*/
private String updateDate;
/**
* 描述
*/
private String description;
/**
* 关键词
*/
private String keysWord;
/**
* 使用版本
*/
private List<String> useVersion;
}

View File

@ -1,5 +1,6 @@
package net.educoder.quality.dto;
import com.alibaba.fastjson.JSONArray;
import lombok.Data;
/**
@ -10,6 +11,8 @@ import lombok.Data;
@Data
public class ComponentListDTO {
private Long id;
/**
* 组件名称
*/
@ -26,6 +29,10 @@ public class ComponentListDTO {
* 漏洞
*/
private String vulnerability;
/**
* 漏洞详情
*/
private JSONArray vulnerabilities;
/**
* 依赖方式
*/
@ -35,5 +42,9 @@ public class ComponentListDTO {
* 依赖路径
*/
private String dependPath;
/**
* 依赖数量
*/
private Integer dependNum;
}

View File

@ -0,0 +1,20 @@
package net.educoder.quality.dto;
import lombok.Data;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
/**
* @Author: youys
* @Date: 2022/12/27
* @Description:
*/
@Data
public class ComponentParseRecordDetailDTO extends ComponentParseRecordDetail {
/**
* 依赖数量
*/
private Integer dependNum;
}

View File

@ -0,0 +1,16 @@
package net.educoder.quality.dto;
import lombok.Data;
/**
* @Author: youys
* @Date: 2022/12/27
* @Description:
*/
@Data
public class DependComponentDTO {
private String componentName;
private String version;
private String dependPath;
}

View File

@ -1,6 +1,8 @@
package net.educoder.quality.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: youys
@ -8,6 +10,8 @@ import lombok.Data;
* @Description:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FileSourceDTO {
private Integer rowNumber;

View File

@ -0,0 +1,44 @@
package net.educoder.quality.dto;
import lombok.Data;
import java.util.List;
/**
* @Author: youys
* @Date: 2023/3/9
* @Description: 缺陷中心>查看详情 v2版本
*/
@Data
public class ProjectBugCenterCodeDetailV2DTO {
private String filePath;
/**
* 代码行号
*/
private Integer line;
/**
* 缺陷名称
*/
private String bugName;
/**
* 缺陷描述
*/
private String description;
/**
* 正确代码示例
*/
private String example;
/**
* 错误代码示例
*/
private String errorExample;
/**
* 代码所属错误分类
*/
private String parentBugCatalog;
/**
* 代码
*/
private List<FileSourceDTO> codes;
}

View File

@ -1,5 +1,7 @@
package net.educoder.quality.dto;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
@ -10,31 +12,38 @@ import java.util.Date;
* @Description:
*/
@Data
@ExcelIgnoreUnannotated
public class ProjectBugCenterDTO {
/**
* 缺陷名称
*/
@ExcelProperty("缺陷名称")
private String bugName;
/**
* 缺陷描述
*/
@ExcelProperty("缺陷描述")
private String bugDescription;
/**
* 文件路径
*/
@ExcelProperty("文件路径")
private String filePath;
/**
* 行号
*/
@ExcelProperty("行号")
private String rowNumber;
/**
* 缺陷级别
*/
@ExcelProperty("缺陷级别")
private String bugLevel;
/**
* 检测时间
*/
@ExcelProperty("检测时间")
private Date detectTime;
/**

View File

@ -11,6 +11,7 @@ import java.util.Date;
*/
@Data
public class ProjectVulnerabilityDetailDTO {
private String uuid;
/**
* 漏洞编号

View File

@ -0,0 +1,29 @@
package net.educoder.quality.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.educoder.quality.entity.postgres.PgIssues;
import java.util.List;
/**
* @Date: 2023/01/19
* @author jshixiong
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReportDetailDTO {
private CompareBaseResultDTO vulnerabilityCount;
private CompareBaseResultDTO bugCount;
private Integer components;
private List<PgIssues> bugIssues;
private List<ComponentParseRecordDetailDTO> parseRecordDetails;
}

View File

@ -0,0 +1,14 @@
package net.educoder.quality.dto;
import lombok.Data;
@Data
public class SastBugDTO {
private Long bugId;
private String bugType;
private int line;
private String filePath;
private String message;
private String methodName;
private String variable;
}

View File

@ -54,4 +54,11 @@ public class SonarScannerParam {
* git密码
*/
private String gitPassword;
/**
* .net代码sonar扫描服务
*/
private String donetSonarServer;
}

View File

@ -1,6 +1,8 @@
package net.educoder.quality.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: youys
@ -9,6 +11,4 @@ import lombok.Data;
*/
@Data
public class VulnerabilityResultDTO extends CompareBaseResultDTO{
}

View File

@ -0,0 +1,24 @@
package net.educoder.quality.entity.gitea;
import lombok.Data;
import java.util.Date;
/**
* @Author: youys
* @Date: 2023/1/17
* @Description: 许可证
*/
@Data
public class PgCodeLicense {
private Long id;
private String name;
private String riskLevel;
private String version;
private Date createTime;
private String content;
private String description;
private String publicUrl;
}

View File

@ -1,13 +1,14 @@
package net.educoder.quality.entity.mysql;
import lombok.Data;
import net.educoder.quality.common.util.AbstractDO;
import java.util.Date;
import javax.persistence.*;
@Data
@Table(name = "clone_detection")
public class CloneDetection {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public class CloneDetection extends AbstractDO {
/**
* 源工程ID
@ -39,155 +40,5 @@ public class CloneDetection {
@Column(name = "target_project_password")
private String targetProjectPassword;
/**
* 创建时间
*/
@Column(name = "create_time")
private Date createTime;
/**
* 更新时间
*/
@Column(name = "update_time")
private Date updateTime;
/**
* @return id
*/
public Integer getId() {
return id;
}
/**
* @param id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取源工程ID
*
* @return project_id - 源工程ID
*/
public Long getProjectId() {
return projectId;
}
/**
* 设置源工程ID
*
* @param projectId 源工程ID
*/
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
/**
* 获取目标工程名
*
* @return target_project_name - 目标工程名
*/
public String getTargetProjectName() {
return targetProjectName;
}
/**
* 设置目标工程名
*
* @param targetProjectName 目标工程名
*/
public void setTargetProjectName(String targetProjectName) {
this.targetProjectName = targetProjectName;
}
/**
* 获取目标工程URL
*
* @return target_project_url - 目标工程URL
*/
public String getTargetProjectUrl() {
return targetProjectUrl;
}
/**
* 设置目标工程URL
*
* @param targetProjectUrl 目标工程URL
*/
public void setTargetProjectUrl(String targetProjectUrl) {
this.targetProjectUrl = targetProjectUrl;
}
/**
* 获取目标工程用户名
*
* @return target_project_username - 目标工程用户名
*/
public String getTargetProjectUsername() {
return targetProjectUsername;
}
/**
* 设置目标工程用户名
*
* @param targetProjectUsername 目标工程用户名
*/
public void setTargetProjectUsername(String targetProjectUsername) {
this.targetProjectUsername = targetProjectUsername;
}
/**
* 获取目标工程密码
*
* @return target_project_password - 目标工程密码
*/
public String getTargetProjectPassword() {
return targetProjectPassword;
}
/**
* 设置目标工程密码
*
* @param targetProjectPassword 目标工程密码
*/
public void setTargetProjectPassword(String targetProjectPassword) {
this.targetProjectPassword = targetProjectPassword;
}
/**
* 获取创建时间
*
* @return create_time - 创建时间
*/
public Date getCreateTime() {
return createTime;
}
/**
* 设置创建时间
*
* @param createTime 创建时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* 获取更新时间
*
* @return update_time - 更新时间
*/
public Date getUpdateTime() {
return updateTime;
}
/**
* 设置更新时间
*
* @param updateTime 更新时间
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View File

@ -57,13 +57,13 @@ public class CloneDetectionResultFileCodeLevel extends AbstractDO {
* 相似比
*/
@Column(name = "common_source_percent")
private String commonSourcePercent;
private Double commonSourcePercent;
/**
* 相似行数
*/
@Column(name = "common_source_line")
private String commonSourceLine;
private Integer commonSourceLine;
/**
* 克隆检测ID

View File

@ -28,6 +28,48 @@ public class CloneDetectionResultProjectLevel extends AbstractDO {
@Column(name = "similarity_file")
private Integer similarityFile;
/**
* 总文件数
*/
@Column(name = "total_file")
private Long totalFile;
/**
* 相似行数
*/
@Column(name = "similarity_line")
private Long similarityLine;
/**
* 相似行数比
*/
@Column(name = "similarity_line_percent")
private Double similarityLinePercent;
/**
* 总行数
*/
@Column(name = "total_line")
private Long totalLine;
/**
* 相似容量
*/
@Column(name = "similarity_capacity")
private Long similarityCapacity;
/**
* 相似容量比
*/
@Column(name = "similarity_capacity_percent")
private Double similarityCapacityPercent;
/**
* 总容量
*/
@Column(name = "total_capacity")
private Long totalCapacity;
/**
* 源工程ID
*/

View File

@ -0,0 +1,23 @@
package net.educoder.quality.entity.mysql;
import lombok.Data;
import java.util.Date;
/**
* @Author: youys
* @Date: 2023/1/17
* @Description: 组件库
*/
@Data
public class ComponentLibrary {
private Long id;
private String language;
private String componentName;
private String shortName;
private String license;
private Date createTime;
private String homeUrl;
}

View File

@ -9,18 +9,50 @@ public class ComponentParseRecordDetail extends AbstractDO {
private Long componentId;
/**
* 组件名称
*/
private String componentName;
/**
* 语言
*/
private String language;
/**
* 风险等级
*/
private String riskLevel;
/**
* 漏洞
*/
private String vulnerability;
/**
* 版本
*/
private String version;
/**
* 依赖方式直接 or 间接
*/
private String dependWay;
/**
* 依赖路径
*/
private String dependPath;
/**
* 父组件
*/
private String parentUuid;
/**
* 唯一标识
*/
private String uuid;
private String vulnerabilities;
}

View File

@ -22,6 +22,11 @@ public class DetectionTemplate extends AbstractDO {
private String securityDetection;
/**
* 依赖函数库
*/
private String dependFunction;
/**
* 仓库所属用户
*/

View File

@ -0,0 +1,91 @@
package net.educoder.quality.entity.mysql;
import lombok.Data;
import net.educoder.quality.common.util.AbstractDO;
import javax.persistence.Table;
import java.util.Objects;
@Data
@Table(name = "project_vulnerability_detail")
public class ProjectVulnerabilityDetail extends AbstractDO {
/**
* 漏洞编号
*/
private String vulnerabilityNumber;
/**
* 漏洞名称
*/
private String vulnerabilityName;
/**
* 风险等级
*/
private Integer riskLevel;
/**
* 发布日期
*/
private String publishDate;
/**
* 利用难度
*/
private Integer difficulty;
/**
* 攻击类型远程
*/
private String attackType;
/**
* 漏洞描述
*/
private String description;
/**
* 修复建议
*/
private String repairSuggestions;
/**
* 组件ID
*/
private Long componentId;
/**
* 工程ID
*/
private Long projectId;
@Override
public boolean equals(Object o) {
if (this == o){
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ProjectVulnerabilityDetail that = (ProjectVulnerabilityDetail) o;
return strEquals(vulnerabilityNumber,that.vulnerabilityNumber) && strEquals(vulnerabilityName,that.vulnerabilityName) && intEquals(riskLevel, that.riskLevel) && strEquals(publishDate, that.publishDate) && intEquals(difficulty, that.difficulty) && strEquals(attackType, that.attackType) && strEquals(description, that.description) && strEquals(repairSuggestions, that.repairSuggestions);
}
private boolean strEquals(String a,String b){
if (a==null || "".equals(a)){
return b == null || "".equals(b);
}
return a.equals(b);
}
private boolean intEquals(Integer a,Integer b){
if (a==null){
return b == null;
}
return a.equals(b);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), vulnerabilityNumber, vulnerabilityName, riskLevel, publishDate, difficulty, attackType, description, repairSuggestions);
}
}

View File

@ -62,4 +62,9 @@ public class Projects extends AbstractDO {
*/
private Date testingTime;
/**
* 项目语言
*/
private String language;
}

View File

@ -0,0 +1,208 @@
package net.educoder.quality.entity.mysql;
import java.util.Date;
import javax.persistence.*;
import lombok.Data;
import net.educoder.quality.common.util.AbstractDO;
@Data
@Table(name = "sast_analysis_detail")
public class SastAnalysisDetail extends AbstractDO {
/**
* bug分类
*/
@Column(name = "bug_catalog")
private String bugCatalog;
/**
* bug大分类
*/
@Column(name = "parent_bug_catalog")
private String parentBugCatalog;
/**
* bug类型编号
*/
@Column(name = "bug_no")
private String bugNo;
/**
* bug名称
*/
@Column(name = "bug_name")
private String bugName;
/**
* bug类型父级编号
*/
@Column(name = "parent_bug_no")
private String parentBugNo;
/**
* bug类型号
*/
@Column(name = "bug_type")
private String bugType;
/**
* bug类型名
*/
@Column(name = "bug_type_name")
private String bugTypeName;
/**
* bug级别
*/
@Column(name = "bug_level")
private String bugLevel;
/**
* 常见后果关键词
*/
@Column(name = "frequent_result_keyword")
private String frequentResultKeyword;
/**
* 创建时间
*/
@Column(name = "create_time")
private Date createTime;
/**
* 更新时间
*/
@Column(name = "update_time")
private Date updateTime;
/**
* 工程id
*/
@Column(name = "project_id")
private Long projectId;
/**
* 任务id
*/
@Column(name = "task_id")
private String taskId;
/**
* 简介
*/
private String synopsis;
/**
* 描述
*/
private String description;
/**
* 常见后果
*/
@Column(name = "frequent_result")
private String frequentResult;
/**
* 修复意见
*/
@Column(name = "repair_opinion")
private String repairOpinion;
/**
* 示例
*/
private String example;
/**
* 错误示例
*/
@Column(name = "error_example")
private String errorExample;
@Column(name = "method_name")
private String methodName;
private String variable;
private Integer line;
@Column(name = "file_path")
private String filePath;
public static final String ID = "id";
public static final String DB_ID = "id";
public static final String BUG_CATALOG = "bugCatalog";
public static final String DB_BUG_CATALOG = "bug_catalog";
public static final String BUG_NO = "bugNo";
public static final String DB_BUG_NO = "bug_no";
public static final String BUG_NAME = "bugName";
public static final String DB_BUG_NAME = "bug_name";
public static final String PARENT_BUG_NO = "parentBugNo";
public static final String DB_PARENT_BUG_NO = "parent_bug_no";
public static final String BUG_TYPE = "bugType";
public static final String DB_BUG_TYPE = "bug_type";
public static final String BUG_TYPE_NAME = "bugTypeName";
public static final String DB_BUG_TYPE_NAME = "bug_type_name";
public static final String BUG_LEVEL = "bugLevel";
public static final String DB_BUG_LEVEL = "bug_level";
public static final String FREQUENT_RESULT_KEYWORD = "frequentResultKeyword";
public static final String DB_FREQUENT_RESULT_KEYWORD = "frequent_result_keyword";
public static final String CREATE_TIME = "createTime";
public static final String DB_CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "updateTime";
public static final String DB_UPDATE_TIME = "update_time";
public static final String PROJECT_ID = "projectId";
public static final String DB_PROJECT_ID = "project_id";
public static final String TASK_ID = "taskId";
public static final String DB_TASK_ID = "task_id";
public static final String SYNOPSIS = "synopsis";
public static final String DB_SYNOPSIS = "synopsis";
public static final String DESCRIPTION = "description";
public static final String DB_DESCRIPTION = "description";
public static final String FREQUENT_RESULT = "frequentResult";
public static final String DB_FREQUENT_RESULT = "frequent_result";
public static final String REPAIR_OPINION = "repairOpinion";
public static final String DB_REPAIR_OPINION = "repair_opinion";
public static final String EXAMPLE = "example";
public static final String DB_EXAMPLE = "example";
public static final String ERROR_EXAMPLE = "errorExample";
public static final String DB_ERROR_EXAMPLE = "error_example";
}

View File

@ -0,0 +1,216 @@
package net.educoder.quality.entity.sast;
import java.util.Date;
import javax.persistence.*;
import lombok.Data;
@Data
@Table(name = "biz_knowledge_bug")
public class BizKnowledgeBug {
/**
* 知识库BUG类型ID
*/
@Id
@Column(name = "OID_KNOWLEDGE_BUG_ID")
private String oidKnowledgeBugId;
/**
* 知识库目录ID
*/
@Column(name = "OID_KNOWLEDGE_CATALOG_ID")
private String oidKnowledgeCatalogId;
/**
* BUG类型编号
*/
@Column(name = "BUG_NO")
private String bugNo;
/**
* BUG名称
*/
@Column(name = "BUG_NAME")
private String bugName;
/**
* BUG类型父级编号
*/
@Column(name = "PARENT_BUG_NO")
private String parentBugNo;
/**
* BUG类型号
*/
@Column(name = "BUG_TYPE")
private String bugType;
/**
* BUG类型名
*/
@Column(name = "BUG_TYPE_NAME")
private String bugTypeName;
/**
* BUG级别
*/
@Column(name = "BUG_LEVEL")
private String bugLevel;
/**
* 常见后果关键词
*/
@Column(name = "FREQUENT_RESULT_KEYWORD")
private String frequentResultKeyword;
/**
* 删除FLG
*/
@Column(name = "DEL_FLG")
private String delFlg;
/**
* 作成者ID
*/
@Column(name = "INS_USER_ID")
private String insUserId;
/**
* 作成日
*/
@Column(name = "INS_DATE")
private Date insDate;
/**
* 更新者ID
*/
@Column(name = "UPD_USER_ID")
private String updUserId;
/**
* 更新日
*/
@Column(name = "UPD_DATE")
private Date updDate;
/**
* 简介
*/
@Column(name = "SYNOPSIS")
private String synopsis;
/**
* 描述
*/
@Column(name = "DESCRIPTION")
private String description;
/**
* 常见后果
*/
@Column(name = "FREQUENT_RESULT")
private String frequentResult;
/**
* 修复意见
*/
@Column(name = "REPAIR_OPINION")
private String repairOpinion;
/**
* 示例
*/
@Column(name = "EXAMPLE")
private String example;
/**
* 错误示例
*/
@Column(name = "ERROR_EXAMPLE")
private String errorExample;
@Transient
private String bugCatalog;
@Transient
private String parentBugCatalog;
public static final String OID_KNOWLEDGE_BUG_ID = "oidKnowledgeBugId";
public static final String DB_OID_KNOWLEDGE_BUG_ID = "OID_KNOWLEDGE_BUG_ID";
public static final String OID_KNOWLEDGE_CATALOG_ID = "oidKnowledgeCatalogId";
public static final String DB_OID_KNOWLEDGE_CATALOG_ID = "OID_KNOWLEDGE_CATALOG_ID";
public static final String BUG_NO = "bugNo";
public static final String DB_BUG_NO = "BUG_NO";
public static final String BUG_NAME = "bugName";
public static final String DB_BUG_NAME = "BUG_NAME";
public static final String PARENT_BUG_NO = "parentBugNo";
public static final String DB_PARENT_BUG_NO = "PARENT_BUG_NO";
public static final String BUG_TYPE = "bugType";
public static final String DB_BUG_TYPE = "BUG_TYPE";
public static final String BUG_TYPE_NAME = "bugTypeName";
public static final String DB_BUG_TYPE_NAME = "BUG_TYPE_NAME";
public static final String BUG_LEVEL = "bugLevel";
public static final String DB_BUG_LEVEL = "BUG_LEVEL";
public static final String FREQUENT_RESULT_KEYWORD = "frequentResultKeyword";
public static final String DB_FREQUENT_RESULT_KEYWORD = "FREQUENT_RESULT_KEYWORD";
public static final String DEL_FLG = "delFlg";
public static final String DB_DEL_FLG = "DEL_FLG";
public static final String INS_USER_ID = "insUserId";
public static final String DB_INS_USER_ID = "INS_USER_ID";
public static final String INS_DATE = "insDate";
public static final String DB_INS_DATE = "INS_DATE";
public static final String UPD_USER_ID = "updUserId";
public static final String DB_UPD_USER_ID = "UPD_USER_ID";
public static final String UPD_DATE = "updDate";
public static final String DB_UPD_DATE = "UPD_DATE";
public static final String SYNOPSIS = "synopsis";
public static final String DB_SYNOPSIS = "SYNOPSIS";
public static final String DESCRIPTION = "description";
public static final String DB_DESCRIPTION = "DESCRIPTION";
public static final String FREQUENT_RESULT = "frequentResult";
public static final String DB_FREQUENT_RESULT = "FREQUENT_RESULT";
public static final String REPAIR_OPINION = "repairOpinion";
public static final String DB_REPAIR_OPINION = "REPAIR_OPINION";
public static final String EXAMPLE = "example";
public static final String DB_EXAMPLE = "EXAMPLE";
public static final String ERROR_EXAMPLE = "errorExample";
public static final String DB_ERROR_EXAMPLE = "ERROR_EXAMPLE";
}

View File

@ -0,0 +1,19 @@
package net.educoder.quality.mapper.gitea;
import net.educoder.quality.entity.gitea.PgCodeLicense;
/**
* @Author: youys
* @Date: 2023/1/17
* @Description:
*/
public interface PgCodeLicenseMapper {
/**
* 根据许可证名称查询
* @param name
* @return
*/
PgCodeLicense selectByName(String name);
}

View File

@ -0,0 +1,19 @@
package net.educoder.quality.mapper.mysql;
import net.educoder.quality.entity.mysql.ComponentLibrary;
/**
* @Author: youys
* @Date: 2023/1/17
* @Description:
*/
public interface ComponentLibraryMapper {
/**
* 查询组件信息
* @param componentName
* @return
*/
ComponentLibrary selectByComponentName(String componentName);
}

View File

@ -2,8 +2,33 @@ package net.educoder.quality.mapper.mysql;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.dto.ComponentParseRecordDetailDTO;
import net.educoder.quality.dto.DependComponentDTO;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import java.util.List;
public interface ComponentParseRecordDetailMapper extends BaseMapper<ComponentParseRecordDetail> {
/**
* 根据componentId查询
* @param componentId
* @return
*/
List<ComponentParseRecordDetailDTO> queryByComponentId(Long componentId);
/**
* 查询依赖的组件
* @param uuid
* @return
*/
List<DependComponentDTO> queryDependComponentList(String uuid);
/**
* 总共依赖的组件
* @param componentId
* @return
*/
Integer countDependComponentsByComponentId(Long componentId);
}

View File

@ -4,6 +4,21 @@ package net.educoder.quality.mapper.mysql;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.entity.mysql.ComponentParseRecord;
import java.util.List;
public interface ComponentParseRecordMapper extends BaseMapper<ComponentParseRecord> {
/**
* 项目最近的一次组件分析记录
* @param projectId
* @return
*/
ComponentParseRecord getByProjectId(Long projectId);
/**
* 项目所有分析记录
* @param projectId
* @return
*/
List<ComponentParseRecord> quaryByProjectId(Long projectId);
}

View File

@ -0,0 +1,7 @@
package net.educoder.quality.mapper.mysql;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.entity.mysql.ProjectVulnerabilityDetail;
public interface ProjectVulnerabilityDetailMapper extends BaseMapper<ProjectVulnerabilityDetail> {
}

View File

@ -6,4 +6,5 @@ import net.educoder.quality.entity.mysql.Projects;
public interface ProjectsMapper extends BaseMapper<Projects> {
Projects getByName(String projectName);
}

View File

@ -0,0 +1,7 @@
package net.educoder.quality.mapper.mysql;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.entity.mysql.SastAnalysisDetail;
public interface SastAnalysisDetailMapper extends BaseMapper<SastAnalysisDetail> {
}

View File

@ -67,8 +67,8 @@ public interface PgProjectMapper {
/**
* 根据issueType查询出现的次数
* issueType2 漏洞
* issueType3 缺陷
* issueType2 缺陷
* issueType3 漏洞
*
* @param projectName
* @param issueType

View File

@ -0,0 +1,10 @@
package net.educoder.quality.mapper.sast;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.entity.sast.BizKnowledgeBug;
import java.util.List;
public interface BizKnowledgeBugMapper {
List<BizKnowledgeBug> selectBugAndCatalogByTypes(List<String> bugTypes);
}

View File

@ -30,6 +30,8 @@ public class ComponentTask {
} catch (Exception e) {
log.error("ComponentTask.timingAnalysisTask is Exception", e);
}
log.info("-----------------ComponentTask.timingAnalysisTask end-------------");
}

View File

@ -1,12 +1,13 @@
package net.educoder.quality.service;
import com.github.pagehelper.PageInfo;
import net.educoder.quality.dto.ComponentListDTO;
import net.educoder.quality.dto.ComponentStatisticsDTO;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.vo.PageVO;
import java.util.List;
/**
* @Author: youys
* @Date: 2022/10/13
@ -39,11 +40,25 @@ public interface ComponentService {
* @param pageVO
* @return
*/
PageInfo<ComponentParseRecordDetail> componentList(Long projectId, PageVO pageVO);
PageInfo<ComponentParseRecordDetailDTO> componentList(Long projectId, PageVO pageVO);
/**
* 定时解析组件
*/
void timingAnalysisTask();
/**
* 组件-查看详情
* @param id
* @return
*/
ComponentDetailDTO getComponentDetail(Long id);
/**
* 组件-依赖
* @param id
* @return
*/
List<DependComponentDTO> getDependComponent(Long id);
}

View File

@ -128,6 +128,14 @@ public interface ProjectService {
*/
PageInfo<ProjectBugCenterDTO> projectBugCenter(Long projectId, ProjectBugCenterVO projectBugCenterVO);
/**
* 缺陷列表
*
* @param projectId
* @param projectBugCenterVO
*/
List<ProjectBugCenterDTO> projectBugList(Long projectId, ProjectBugCenterVO projectBugCenterVO);
/**
* 获取缺陷中心代码详情
@ -138,6 +146,15 @@ public interface ProjectService {
*/
ProjectBugCenterCodeDetailDTO projectBugCenterCodeDetail(Long projectId, ProjectBugCenterCodeDetailVO centerCodeDetailVO);
/**
* 获取缺陷中心代码详情 V2版本
* @param projectId
* @param id
* @return
*/
ProjectBugCenterCodeDetailV2DTO projectBugCenterCodeDetailV2(Long projectId, Integer id);
/**
* 许可证总计
*
@ -224,6 +241,15 @@ public interface ProjectService {
*/
PageInfo<ProjectVulnerabilityListDTO> projectVulnerabilityList(Long projectId, PageVO pageVO);
/**
* 项目漏洞列表
*
* @param projectId
* @param pageVO
* @return
*/
PageInfo<ProjectVulnerabilityListDTO> getProjectVulnerabilityList(Long projectId, PageVO pageVO);
/**
* 项目漏洞详情
*
@ -241,4 +267,5 @@ public interface ProjectService {
* @return
*/
List<ProjectVulnerabilityListDTO> projectVulnerabilityExport(Long projectId, CommonVO commonVO);
}

View File

@ -0,0 +1,12 @@
package net.educoder.quality.service;
import net.educoder.quality.entity.mysql.SastAnalysisDetail;
public interface SastService {
void analysis(Long projectId, String taskId);
SastAnalysisDetail findById(Long id);
}

View File

@ -0,0 +1,26 @@
package net.educoder.quality.service;
import com.github.pagehelper.PageInfo;
import net.educoder.quality.dto.ProjectVulnerabilityDTO;
import net.educoder.quality.dto.ProjectVulnerabilityDetailDTO;
import net.educoder.quality.vo.PageVO;
public interface VulnerabilityService {
/**
* 漏洞列表
*/
PageInfo<ProjectVulnerabilityDetailDTO> vulnerabilityList(Long projectId, PageVO pageVO);
/**
* 漏洞详情
*/
ProjectVulnerabilityDetailDTO vulnerabilityDetail(Long projectId, String uuid);
/**
* 漏洞统计
* @param projectId
* @return
*/
ProjectVulnerabilityDTO vulnerabilityStatistics(Long projectId);
}

View File

@ -1,30 +1,46 @@
package net.educoder.quality.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.MoreObjects;
import lombok.extern.slf4j.Slf4j;
import net.educoder.quality.common.bean.ShellResult;
import net.educoder.quality.common.config.PropertiesConfig;
import net.educoder.quality.common.enums.ErrorCodeEnum;
import net.educoder.quality.common.exception.BusinessException;
import net.educoder.quality.common.util.GitUtil;
import net.educoder.quality.common.util.ShellUtil;
import net.educoder.quality.dto.CloneDetectionResultFileCodeLevelDTO;
import net.educoder.quality.dto.CloneDetectionResultProjectLevelDTO;
import net.educoder.quality.dto.CloneDetectionStatisticsDTO;
import net.educoder.quality.dto.ClonePairDTO;
import net.educoder.quality.entity.mysql.CloneDetection;
import net.educoder.quality.entity.mysql.CloneDetectionResultFileCodeLevel;
import net.educoder.quality.entity.mysql.CloneDetectionResultProjectLevel;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.mapper.mysql.CloneDetectionMapper;
import net.educoder.quality.mapper.mysql.CloneDetectionResultFileCodeLevelMapper;
import net.educoder.quality.mapper.mysql.CloneDetectionResultProjectLevelMapper;
import net.educoder.quality.service.CloneDetectionService;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.vo.AddCloneDetectionVO;
import net.educoder.quality.vo.PageVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.aspectj.util.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.io.File;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
@Service
@ -32,24 +48,165 @@ public class CloneDetectionServiceImpl implements CloneDetectionService {
@Autowired
private ProjectService projectService;
@Autowired
private PropertiesConfig propertiesConfig;
@Resource
private CloneDetectionResultProjectLevelMapper cloneDetectionResultProjectLevelMapper;
@Resource
private CloneDetectionResultFileCodeLevelMapper cloneDetectionResultFileCodeLevelMapper;
@Resource
private CloneDetectionMapper cloneDetectionMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void add(Long projectId, AddCloneDetectionVO addCloneDetectionVO) {
Projects project = projectService.getProjectById(projectId);
if (project == null) {
throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXISTS);
}
// 校验git地址合法性
String regex = "((git|ssh|http(s)?)|(git@[\\w\\.]+))(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)(/)?";
Matcher matcher = Pattern.compile(regex).matcher(addCloneDetectionVO.getTargetRepoURL());
if (!matcher.find()) {
log.error("git url非法projectId: {}, url: {}", projectId, addCloneDetectionVO.getTargetRepoURL());
throw new BusinessException(ErrorCodeEnum.GIT_URL_INVALID.getValue(), ErrorCodeEnum.GIT_URL_INVALID.getDescription());
}
// 存在历史检测记录删除
CloneDetection oldCloneDetection = new CloneDetection();
oldCloneDetection.setProjectId(projectId);
oldCloneDetection.setTargetProjectUrl(addCloneDetectionVO.getTargetRepoURL());
List<CloneDetection> oldResult = cloneDetectionMapper.select(oldCloneDetection);
if (CollectionUtils.isNotEmpty(oldResult)) {
cloneDetectionMapper.deleteByPrimaryKey(oldResult.get(0).getId());
CloneDetectionResultProjectLevel cloneDetectionResultProjectLevel = new CloneDetectionResultProjectLevel();
cloneDetectionResultProjectLevel.setCloneDetectionId(oldResult.get(0).getId());
cloneDetectionResultProjectLevelMapper.delete(cloneDetectionResultProjectLevel);
CloneDetectionResultFileCodeLevel cloneDetectionResultFileCodeLevel = new CloneDetectionResultFileCodeLevel();
cloneDetectionResultFileCodeLevel.setCloneDetectionId(oldResult.get(0).getId());
cloneDetectionResultFileCodeLevelMapper.delete(cloneDetectionResultFileCodeLevel);
}
// 写数据库插入克隆记录
CloneDetection cloneDetection = new CloneDetection();
cloneDetection.setProjectId(projectId);
String targetProjectUrl = addCloneDetectionVO.getTargetRepoURL();
cloneDetection.setTargetProjectUrl(targetProjectUrl);
String targetProjectName = targetProjectUrl.replaceAll(".*/", "").replace(".git", "");
cloneDetection.setTargetProjectName(targetProjectName);
cloneDetection.setCreateTime(DateTime.now());
cloneDetection.setUpdateTime(DateTime.now());
cloneDetectionMapper.insert(cloneDetection);
Long cloneDetectionId = cloneDetection.getId();
// 克隆代码并组织到目录
String fullPath = propertiesConfig.getWorkspace() + "/" + DateUtil.formatDate(new Date()).replace("-", "") + "/" + RandomUtil.randomString(10);
ShellResult sourceRepoCloneResult = GitUtil.gitClone(project.getGitUrl(), project.getBranch(), propertiesConfig.getGitUsername(), propertiesConfig.getGitPassword(), fullPath + "/source");
if (sourceRepoCloneResult.getExitStatus() != 0) {
log.error("clone源仓库失败projectId: {}", projectId);
throw new BusinessException(ErrorCodeEnum.EXCEPTION.getValue(), ErrorCodeEnum.EXCEPTION.getDescription());
}
ShellResult targetRepoCloneResult = GitUtil.gitClone(addCloneDetectionVO.getTargetRepoURL(), MoreObjects.firstNonNull(addCloneDetectionVO.getTargetRepoBranch(), "master"), addCloneDetectionVO.getTargetRepoUsername(), addCloneDetectionVO.getTargetRepoPassword(), fullPath + "/target");
if (targetRepoCloneResult.getExitStatus() != 0 && (
targetRepoCloneResult.getOut().contains("invalid credentials")
|| targetRepoCloneResult.getOut().contains("Username for"))
|| targetRepoCloneResult.getOut().contains("Authentication failed")) {
log.error("clone目标仓库git用户名密码错误projectId: {}, url: {}", projectId, targetProjectUrl);
throw new BusinessException(ErrorCodeEnum.GIT_CREDENTIAL_INVALID.getValue(), ErrorCodeEnum.GIT_CREDENTIAL_INVALID.getDescription());
}
// nil分析
List<ClonePairDTO> cloneDetectionResult = getCloneDetectionResult(fullPath, MoreObjects.firstNonNull(project.getLanguage(), "common").trim().toLowerCase());
// 写数据库
long similarLines = 0;
long similarCapacityCount = 0;
Map<String, Integer> similarSourceLinesMap = new HashMap();
for (ClonePairDTO clonePairDTO : cloneDetectionResult) {
try {
CloneDetectionResultFileCodeLevel cloneDetectionResultFileCodeLevel = new CloneDetectionResultFileCodeLevel();
cloneDetectionResultFileCodeLevel.setCloneDetectionId(cloneDetectionId);
cloneDetectionResultFileCodeLevel.setSourceFileCode(FileUtil.readAsString(new File(fullPath + clonePairDTO.getSourceFile())));
cloneDetectionResultFileCodeLevel.setSourceFilePath(clonePairDTO.getSourceFile().replace("/source/" + project.getProjectName() + "/", ""));
cloneDetectionResultFileCodeLevel.setSourceFileStartLine(clonePairDTO.getSourceFileStartLine());
cloneDetectionResultFileCodeLevel.setSourceFileEndLine(clonePairDTO.getSourceFileEndLine());
cloneDetectionResultFileCodeLevel.setTargetFileCode(FileUtil.readAsString(new File(fullPath + clonePairDTO.getTargetFile())));
cloneDetectionResultFileCodeLevel.setTargetFilePath(clonePairDTO.getTargetFile().replace("/target/" + targetProjectName + "/", ""));
cloneDetectionResultFileCodeLevel.setTargetFileStartLine(clonePairDTO.getTargetFileStartLine());
cloneDetectionResultFileCodeLevel.setTargetFileEndLine(clonePairDTO.getTargetFileEndLine());
cloneDetectionResultFileCodeLevel.setTargetProjectUrl(targetProjectUrl);
cloneDetectionResultFileCodeLevel.setTargetProjectName(targetProjectName);
cloneDetectionResultFileCodeLevel.setProjectId(projectId);
cloneDetectionResultFileCodeLevel.setCommonSourceLine(clonePairDTO.getSimilarLines());
cloneDetectionResultFileCodeLevel.setCommonSourcePercent(clonePairDTO.getSimilarity());
cloneDetectionResultFileCodeLevel.setCreateTime(DateTime.now());
cloneDetectionResultFileCodeLevel.setUpdateTime(DateTime.now());
cloneDetectionResultFileCodeLevelMapper.insert(cloneDetectionResultFileCodeLevel);
if (similarSourceLinesMap.get(clonePairDTO.getSourceFile()) == null || clonePairDTO.getSimilarLines() > similarSourceLinesMap.get(clonePairDTO.getSourceFile())) {
similarSourceLinesMap.put(clonePairDTO.getSourceFile(), clonePairDTO.getSimilarLines());
similarLines += clonePairDTO.getSimilarLines();
similarCapacityCount += cloneDetectionResultFileCodeLevel.getSourceFileCode().getBytes().length;
}
} catch (Exception e) {
log.error("save clone detail to database failed, source: {}, target: {}", fullPath + clonePairDTO.getSourceFile(), fullPath + clonePairDTO.getTargetFile(), e);
}
}
CloneDetectionResultProjectLevel cloneDetectionResultProjectLevel = new CloneDetectionResultProjectLevel();
cloneDetectionResultProjectLevel.setCloneDetectionId(cloneDetectionId);
cloneDetectionResultProjectLevel.setSimilarityFile(similarSourceLinesMap.size());
long totalFile = getFileCount(fullPath + "/source");
cloneDetectionResultProjectLevel.setSimilarityFilePercent(Math.min(((double)similarSourceLinesMap.size()) / totalFile, 1));
cloneDetectionResultProjectLevel.setTotalFile(totalFile);
cloneDetectionResultProjectLevel.setSimilarityLine(similarLines);
long totalLine = getLinesCount(fullPath + "/source/" + project.getProjectName());
cloneDetectionResultProjectLevel.setSimilarityLinePercent(Math.min(((double)similarLines) / totalLine, 1));
cloneDetectionResultProjectLevel.setTotalLine(totalLine);
cloneDetectionResultProjectLevel.setSimilarityCapacity(similarCapacityCount);
long totalCapacity = getCapacityCount(fullPath + "/source/" + project.getProjectName());
cloneDetectionResultProjectLevel.setSimilarityCapacityPercent(Math.min(((double)similarCapacityCount) / totalCapacity, 1));
cloneDetectionResultProjectLevel.setTotalCapacity(totalCapacity);
cloneDetectionResultProjectLevel.setTargetProjectUrl(targetProjectUrl);
cloneDetectionResultProjectLevel.setTargetProjectName(targetProjectName);
cloneDetectionResultProjectLevel.setProjectId(projectId);
cloneDetectionResultProjectLevel.setCreateTime(DateTime.now());
cloneDetectionResultProjectLevel.setUpdateTime(DateTime.now());
cloneDetectionResultProjectLevelMapper.insert(cloneDetectionResultProjectLevel);
}
@Override
public CloneDetectionStatisticsDTO cloneDetectionStatistics(Long projectId) {
return new CloneDetectionStatisticsDTO(18.1, 81.9, 52.2, 47.8, 34.5, 65.5);
CloneDetectionResultProjectLevel cloneDetectionResultProjectLevel = new CloneDetectionResultProjectLevel();
cloneDetectionResultProjectLevel.setProjectId(projectId);
List<CloneDetectionResultProjectLevel> cloneDetectionResultProjectLevelList = cloneDetectionResultProjectLevelMapper.select(cloneDetectionResultProjectLevel);
int similarFiles = 0;
int totalFiles = 0;
int similarLines = 0;
int totalLines = 0;
int similarCapacity = 0;
int totalCapacity = 0;
for (CloneDetectionResultProjectLevel item : cloneDetectionResultProjectLevelList) {
similarFiles += item.getSimilarityFile();
totalFiles += item.getTotalFile();
similarLines += item.getSimilarityLine();
totalLines += item.getTotalLine();
similarCapacity += item.getSimilarityCapacity();
totalCapacity += item.getTotalCapacity();
}
int fileCodeSimilarityPercent = totalFiles == 0 ? 0 : (int)(((double)similarFiles) / totalFiles * 100) ;
int codeLineSimilarityPercent = totalLines == 0 ? 0 : (int)(((double)similarLines) / totalLines * 100) ;
int capacitySimilarityPercent = totalCapacity == 0 ? 0 : (int)(((double)similarCapacity) / totalCapacity * 100) ;
return new CloneDetectionStatisticsDTO(
fileCodeSimilarityPercent, 100 - fileCodeSimilarityPercent,
codeLineSimilarityPercent, 100 - codeLineSimilarityPercent,
capacitySimilarityPercent, 100 - capacitySimilarityPercent);
}
@Override
@ -66,101 +223,22 @@ public class CloneDetectionServiceImpl implements CloneDetectionService {
for (CloneDetectionResultFileCodeLevel c : cloneDetectionResultFileCodeLevelList) {
CloneDetectionResultFileCodeLevelDTO cdto = new CloneDetectionResultFileCodeLevelDTO();
BeanUtil.copyProperties(c, cdto);
cdto.setOriginalSourcePercent(100 - cdto.getCommonSourcePercent());
result.add(cdto);
}
PageInfo<CloneDetectionResultFileCodeLevelDTO> dtoPageInfo = new PageInfo<>();
BeanUtil.copyProperties(doPageInfo, dtoPageInfo);
// 临时数据
CloneDetectionResultFileCodeLevelDTO tmp = new CloneDetectionResultFileCodeLevelDTO();
tmp.setSourceFileCode("package com.educoder.bridge.handler;\n" +
"\n" +
"import com.educoder.bridge.service.JchService;\n" +
"import org.slf4j.Logger;\n" +
"import org.slf4j.LoggerFactory;\n" +
"import org.springframework.beans.factory.annotation.Autowired;\n" +
"import org.springframework.web.socket.CloseStatus;\n" +
"import org.springframework.web.socket.TextMessage;\n" +
"import org.springframework.web.socket.WebSocketSession;\n" +
"import org.springframework.web.socket.handler.TextWebSocketHandler;\n" +
"\n" +
"public class WebsshHandler extends TextWebSocketHandler {\n" +
"\n" +
" @Autowired\n" +
" JchService jchService;\n" +
"\n" +
" @Override\n" +
" public void afterConnectionEstablished(WebSocketSession wsSession) throws Exception {\n" +
" super.afterConnectionEstablished(wsSession);\n" +
" jchService.add(wsSession);\n" +
" }\n" +
"\n" +
" /**\n" +
" * 重写handleTextMessage方法用于处理从websocket接收到的信息\n" +
" */\n" +
" @Override\n" +
" protected void handleTextMessage(WebSocketSession wsSession, TextMessage message) throws Exception {\n" +
" jchService.recv(message.getPayload(), wsSession);\n" +
" super.handleTextMessage(wsSession, message);\n" +
" }\n" +
"\n" +
"\n" +
" @Override\n" +
" public void afterConnectionClosed(WebSocketSession wsSession, CloseStatus status) throws Exception {\n" +
" super.afterConnectionClosed(wsSession, status);\n" +
" jchService.closeByWebSocket(wsSession);\n" +
" }\n" +
"}");
tmp.setTargetProjectUrl("https://openi.pcl.ac.cn/wangwei/jwebssh.git");
tmp.setTargetFileCode("import org.springframework.web.socket.WebSocketSession;\n" +
"import org.springframework.web.socket.handler.TextWebSocketHandler;\n" +
"\n" +
"public class WebsshHandler extends TextWebSocketHandler {\n" +
"\n" +
" @Autowired\n" +
" JchService jchService;\n" +
"\n" +
" @Override\n" +
" public void afterConnectionEstablished(WebSocketSession wsSession) throws Exception {\n" +
" super.aft(wsSession);\n" +
" }\n" +
"\n" +
" /**\n" +
" * 重写handleTextMessage方法用于处理从websocket接收到的信息\n" +
" */\n" +
" @Override\n" +
" protected void handleTextMessage(WebSocketSession wsSession, TextMessage message) throws Exception {\n" +
" jchService.recv(message.getPayload(), wsSession);\n" +
" super.handleTextMessage(wsSession, message);\n" +
" }\n" +
"\n" +
"\n" +
" @Override\n" +
" public voidonnectionClosed(WebSocketSession wsSession, CloseStatus status) throws Exception {\n" +
" super.afterConnectionClosed(wsSession, status);\n" +
" jchService.closeByWebSocket(wsSession);\n" +
" }\n" +
"}");
tmp.setProjectId(1L);
tmp.setTargetProjectName("jwebssh");
tmp.setOriginalSourcePercent(81.9);
tmp.setSourceFileStartLine(18);
tmp.setSourceFileEndLine(28);
tmp.setCommonSourcePercent(12.1);
tmp.setSourceFilePath("src/main/java/com/educoder/bridge/handler/WebsshHandler.java");
tmp.setTargetFilePath("src/main/java/com/educoder/bridge/handler/WebsshHandler.java");
tmp.setTargetFileStartLine(10);
tmp.setTargetFileEndLine(20);
tmp.setCommonSourceLine(11);
result.add(tmp);
dtoPageInfo.setList(result);
return dtoPageInfo;
}
@Override
public PageInfo<CloneDetectionResultProjectLevelDTO> cloneDetectionResultProjectLevelList(Long projectId, PageVO pageVO) {
Projects project = projectService.getProjectById(projectId);
if (project == null) {
throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXISTS);
}
// 数据库查详情记录
PageHelper.startPage(pageVO.getPageNum(), pageVO.getPageSize());
CloneDetectionResultProjectLevel cloneDetectionResultProjectLevel = new CloneDetectionResultProjectLevel();
@ -173,23 +251,89 @@ public class CloneDetectionServiceImpl implements CloneDetectionService {
for (CloneDetectionResultProjectLevel c : cloneDetectionResultProjectLevelList) {
CloneDetectionResultProjectLevelDTO cdto = new CloneDetectionResultProjectLevelDTO();
BeanUtil.copyProperties(c, cdto);
cdto.setSourceProjectName(project.getProjectName());
cdto.setSimilarityFilePercent((int)(c.getSimilarityFilePercent() * 100));
result.add(cdto);
}
PageInfo<CloneDetectionResultProjectLevelDTO> dtoPageInfo = new PageInfo<>();
BeanUtil.copyProperties(doPageInfo, dtoPageInfo);
// 临时数据
CloneDetectionResultProjectLevelDTO tmp = new CloneDetectionResultProjectLevelDTO();
tmp.setCloneDetectionId(1L);
tmp.setSimilarityFile(2);
tmp.setSourceProjectName("jwebssh");
tmp.setTargetProjectUrl("https://openi.pcl.ac.cn/wangwei/jwebssh.git");
tmp.setTargetProjectName("jwebssh");
tmp.setSimilarityFilePercent(12.1);
result.add(tmp);
dtoPageInfo.setList(result);
return dtoPageInfo;
}
private List<ClonePairDTO> getCloneDetectionResult(String sourcePath, String language) {
String jarPath = propertiesConfig.getNilJarPath();
String resultCSVPath = sourcePath + "/result.csv";
// java -jar /Users/weiwang/IdeaProjects/NIL/build/libs/NIL-all.jar -s /Users/weiwang/IdeaProjects/bridge/business-service/game/src/main/java/com/educoder/bridge/game -o /tmp/a.csv
String command = "java -jar " + jarPath + " -o " + resultCSVPath +
" -s " + sourcePath + " -l " + language + " -mil " + propertiesConfig.getMil()
+ " -mit " + propertiesConfig.getMit() + " -f " + propertiesConfig.getFiltrationThreshold()
+ " -v " + propertiesConfig.getVerificationThreshold();
String nilOut = ShellUtil.execute(command);
log.info("nilOut: {}", nilOut);
List<String> nilResult = FileUtil.readAsLines(new File(resultCSVPath));
List<ClonePairDTO> result = new ArrayList<>();
for (String line : nilResult) {
String[] lineEle = line.split(",");
// 过滤自身与自身的对比
lineEle[0] = lineEle[0].replaceFirst(".*" + sourcePath, "");
lineEle[3] = lineEle[3].replaceFirst(".*" + sourcePath, "");
if (!lineEle[0].equals(lineEle[3])
&& lineEle[0].charAt(1) != lineEle[3].charAt(1)) {
if (lineEle[0].startsWith("/source")) {
String sourceFile = lineEle[0];
int sourceFileStartLine = Integer.parseInt(lineEle[1]);
int sourceFileEndLine = Integer.parseInt(lineEle[2]);
String targetFile = lineEle[3];
int targetFileStartLine = Integer.parseInt(lineEle[4]);
int targetFileEndLine = Integer.parseInt(lineEle[5]);
double similarity = Double.parseDouble(lineEle[6]);
result.add(new ClonePairDTO(sourceFile, sourceFileStartLine, sourceFileEndLine, targetFile, targetFileStartLine, targetFileEndLine, similarity));
} else {
String sourceFile = lineEle[3];
int sourceFileStartLine = Integer.parseInt(lineEle[4]);
int sourceFileEndLine = Integer.parseInt(lineEle[5]);
String targetFile = lineEle[0];
int targetFileStartLine = Integer.parseInt(lineEle[1]);
int targetFileEndLine = Integer.parseInt(lineEle[2]);
double similarity = Double.parseDouble(lineEle[6]);
result.add(new ClonePairDTO(sourceFile, sourceFileStartLine, sourceFileEndLine, targetFile, targetFileStartLine, targetFileEndLine, similarity));
}
}
}
return result;
}
/**
* 统计文件夹下文件个数
*/
private int getFileCount(String repoPath) {
String cnt = ShellUtil.execute("ls -lR " + repoPath + "| grep \"^-\" | wc -l");
return NumberUtils.toInt(cnt, 0);
}
/**
* 统计文件夹下文件行数
*/
private int getLinesCount(String repoPath) {
String cntResult = ShellUtil.execute("cd " + repoPath + " && git ls-files | xargs cat | wc -l");
String[] split = cntResult.trim().split("\n");
return NumberUtils.toInt(split[split.length - 1].trim(), Integer.MAX_VALUE);
}
/**
* 统计文件夹大小
* @param repoPath
* @return
*/
private long getCapacityCount(String repoPath) {
// mac上为String cntResult = ShellUtil.execute("cd " + repoPath + " && du -s -k -I \"\\.git\" | awk '{print $1}'");
String cntResult = ShellUtil.execute("cd " + repoPath + " && du -s -k --exclude=\"\\.git\" | awk '{print $1}'");
String[] split = cntResult.trim().split("\n");
return NumberUtils.toInt(split[split.length - 1].trim(), Integer.MAX_VALUE) * 1024L;
}
}

View File

@ -1,8 +1,10 @@
package net.educoder.quality.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
@ -14,27 +16,30 @@ import net.educoder.quality.common.enums.ErrorCodeEnum;
import net.educoder.quality.common.exception.BusinessException;
import net.educoder.quality.common.util.GitUtil;
import net.educoder.quality.common.util.ShellUtil;
import net.educoder.quality.dto.ComponentStatisticsDTO;
import net.educoder.quality.entity.mysql.ComponentParseRecord;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.common.util.mdc.MdcTaskDecorator;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.*;
import net.educoder.quality.entity.gitea.PgCodeLicense;
import net.educoder.quality.mapper.mysql.ComponentLibraryMapper;
import net.educoder.quality.mapper.mysql.ComponentParseRecordDetailMapper;
import net.educoder.quality.mapper.mysql.ComponentParseRecordMapper;
import net.educoder.quality.mapper.gitea.PgCodeLicenseMapper;
import net.educoder.quality.mapper.mysql.ProjectVulnerabilityDetailMapper;
import net.educoder.quality.service.ComponentService;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.task.ComponentParseRunnable;
import net.educoder.quality.vo.PageVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import java.io.File;
import javax.annotation.Resource;
import java.nio.charset.Charset;
import java.util.*;
@ -59,6 +64,15 @@ public class ComponentServiceImpl implements ComponentService {
@Autowired
private ComponentParseRecordDetailMapper componentParseRecordDetailMapper;
@Autowired
private ComponentLibraryMapper componentLibraryMapper;
@Autowired
private PgCodeLicenseMapper pgCodeLicenseMapper;
@Resource
private ProjectVulnerabilityDetailMapper projectVulnerabilityDetailMapper;
@Autowired
@Qualifier("parseComponentThreadPool")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@ -66,6 +80,8 @@ public class ComponentServiceImpl implements ComponentService {
@Value("${opensca-cli.path}")
private String openScaCliPath;
private static final List<String> RISK_LEVEL = Arrays.asList("严重","高危", "中危", "低危");
@Override
@Transactional(rollbackFor = Exception.class)
public void parseComponent(Long projectId) {
@ -83,66 +99,177 @@ public class ComponentServiceImpl implements ComponentService {
Long projectId = projects.getId();
String fullPath = propertiesConfig.getWorkspace() + "/" + DateUtil.formatDate(new Date()) + "/" + RandomUtil.randomString(10);
File file = new File(fullPath);
if (!file.exists()) {
file.mkdirs();
}
boolean flag = GitUtil.gitClone(projects.getGitUrl(), projects.getBranch(), propertiesConfig.getGitUsername(), propertiesConfig.getGitPassword(), fullPath);
if (!flag) {
ShellResult gitCloneResult = GitUtil.gitClone(projects.getGitUrl(), projects.getBranch(), propertiesConfig.getGitUsername(), propertiesConfig.getGitPassword(), fullPath);
if (gitCloneResult.getExitStatus() != 0) {
log.info("projectId:{}克隆代码失败,终止执行", projectId);
return;
}
// 克隆之后执行组件分析
ComponentParseRecord query = new ComponentParseRecord();
query.setProjectId(projectId);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.selectOne(query);
ComponentParseRecord componentParseRecord;
Set<ComponentParseRecordDetail> parseRecordDetailSet = new HashSet<>(200);
// 未解析
if (componentParseRecord == null) {
String outPath = fullPath + "/output.json";
String url = "http://opensca.xmirror.cn:8003";
String token = "6cb2f6fb-cf87-463d-b5a3-d242eb97d7c1";
String command = StringUtils.join(openScaCliPath," -url "
, url, " -token ", token, " -path ", fullPath, " -out ", outPath);
ShellResult shellResult = ShellUtil.executeAndGetExitStatus(command);
log.info("command:{}, result:{}", command, shellResult);
if (shellResult.getExitStatus() == 0) {
String output = FileUtil.readString(outPath, Charset.defaultCharset());
//每次都重新分析
String outPath = fullPath + "/output.json";
String url = "http://opensca.xmirror.cn:8003";
String token = "6cb2f6fb-cf87-463d-b5a3-d242eb97d7c1";
String command = StringUtils.join(openScaCliPath," -url "
, url, " -token ", token, " -path ", fullPath, " -out ", outPath);
ShellResult shellResult = ShellUtil.executeAndGetExitStatus(command);
log.info("command:{}, result:{}", command, shellResult);
componentParseRecord = new ComponentParseRecord();
componentParseRecord.setProjectId(projectId);
componentParseRecord.setCreateTime(new Date());
componentParseRecord.setUpdateTime(new Date());
componentParseRecord = new ComponentParseRecord();
componentParseRecord.setProjectId(projectId);
componentParseRecord.setResult(output);
componentParseRecord.setCreateTime(new Date());
componentParseRecord.setUpdateTime(new Date());
componentParseRecordMapper.insertSelective(componentParseRecord);
if (shellResult.getExitStatus() == 0) {
String output = FileUtil.readString(outPath, Charset.defaultCharset());
parseResult(componentParseRecord.getResult(), componentParseRecord.getId(), parseRecordDetailSet);
componentParseRecord.setResult(output);
componentParseRecordMapper.insertSelective(componentParseRecord);
log.info("if需要插入的组件详情数据有{}条", parseRecordDetailSet.size());
List<ComponentParseRecordDetail> batchList = new ArrayList<>(parseRecordDetailSet);
componentParseRecordDetailMapper.insertList(batchList);
}
} else {
log.info("projectId:{},组件已解析", projectId);
ComponentParseRecordDetail detailQuery = new ComponentParseRecordDetail();
detailQuery.setComponentId(componentParseRecord.getId());
int count = componentParseRecordDetailMapper.selectCount(detailQuery);
if (count > 0) {
log.info("projectId:{},组件已解析,并且已入库", projectId);
return;
}
parseResult(componentParseRecord.getResult(), componentParseRecord.getId(), parseRecordDetailSet);
String result = componentParseRecord.getResult();
parseResult(result, componentParseRecord.getId(), parseRecordDetailSet);
log.info("else需要插入的组件详情数据有{}条", parseRecordDetailSet.size());
log.info("parseComponent需要插入的组件详情数据有{}条", parseRecordDetailSet.size());
if (CollectionUtils.isNotEmpty(parseRecordDetailSet)) {
List<ComponentParseRecordDetail> batchList = new ArrayList<>(parseRecordDetailSet);
componentParseRecordDetailMapper.insertList(batchList);
}
}else {
componentParseRecord.setResult("");
componentParseRecordMapper.insertSelective(componentParseRecord);
}
// } else {
// log.info("projectId:{},组件已解析", projectId);
// ComponentParseRecordDetail detailQuery = new ComponentParseRecordDetail();
// detailQuery.setComponentId(componentParseRecord.getId());
// int count = componentParseRecordDetailMapper.selectCount(detailQuery);
// if (count > 0) {
// log.info("projectId:{},组件已解析,并且已入库", projectId);
// return;
// }
//
// String result = componentParseRecord.getResult();
// parseResult(result, componentParseRecord.getId(), parseRecordDetailSet);
// log.info("else需要插入的组件详情数据有{}条", parseRecordDetailSet.size());
// if (CollectionUtils.isNotEmpty(parseRecordDetailSet)) {
// List<ComponentParseRecordDetail> batchList = new ArrayList<>(parseRecordDetailSet);
// componentParseRecordDetailMapper.insertList(batchList);
// }
// }
// 插入漏洞
log.info("开始插入漏洞");
try{
batchInsertVulnerability(parseRecordDetailSet, projectId,componentParseRecord.getId());
log.info("插入漏洞成功");
}catch (Exception e){
log.info("插入漏洞失败");
e.printStackTrace();
}
}
/**
* 批量插入漏洞增量
*/
private void batchInsertVulnerability(Set<ComponentParseRecordDetail> parseRecordDetailSet, Long projectId, Long componentId) {
List<ProjectVulnerabilityDetail> projectVulnerabilityDetailList = new ArrayList<>();
for (ComponentParseRecordDetail componentParseRecordDetail : parseRecordDetailSet) {
String vulnerabilities = componentParseRecordDetail.getVulnerabilities();
if (StringUtils.isNotEmpty(vulnerabilities)) {
JSONArray vuls = JSON.parseArray(vulnerabilities);
for (int i = 0; i < vuls.size(); i++) {
ProjectVulnerabilityDetail pvd = new ProjectVulnerabilityDetail();
JSONObject vul = vuls.getJSONObject(i);
pvd.setVulnerabilityNumber(StringUtils.firstNonBlank(vul.getString("cwe_id"), vul.getString("id").replaceAll("XMIRROR-", "")));
pvd.setDescription(vul.getString("description"));
pvd.setAttackType(vul.getString("attack_type"));
pvd.setDifficulty(vul.getInteger("exploit_level_id"));
pvd.setRiskLevel(vul.getInteger("security_level_id"));
pvd.setPublishDate(vul.getString("release_date"));
pvd.setRepairSuggestions(vul.getString("suggestion"));
pvd.setVulnerabilityName(vul.getString("name"));
pvd.setComponentId(componentId);
pvd.setProjectId(projectId);
pvd.setCreateTime(DateTime.now());
pvd.setUpdateTime(DateTime.now());
projectVulnerabilityDetailList.add(pvd);
}
}
}
//新漏洞排除已有旧漏洞
List<ComponentParseRecord> parseRecords = componentParseRecordMapper.quaryByProjectId(projectId);
List<ProjectVulnerabilityDetail> oldVulnerabilityList = new ArrayList<>();
if (parseRecords.size()>=2){
Long oldComponentId = parseRecords.get(1).getId();
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setComponentId(oldComponentId);
oldVulnerabilityList = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
}
if (oldVulnerabilityList.size()>0){
Iterator<ProjectVulnerabilityDetail> it = projectVulnerabilityDetailList.iterator();
while (it.hasNext()){
ProjectVulnerabilityDetail newVulnerability = it.next();
for (ProjectVulnerabilityDetail oldVulnerability:oldVulnerabilityList) {
if (newVulnerability.equals(oldVulnerability)){
it.remove();
break;
}
}
}
//新漏洞加上所有旧漏洞
for (ProjectVulnerabilityDetail oldVulnerability:oldVulnerabilityList) {
oldVulnerability.setId(null);
oldVulnerability.setComponentId(componentId);
oldVulnerability.setProjectId(projectId);
oldVulnerability.setCreateTime(new Date());
oldVulnerability.setUpdateTime(new Date());
}
projectVulnerabilityDetailList.addAll(oldVulnerabilityList);
}
log.info("本次漏洞数据有{}条", projectVulnerabilityDetailList.size());
if (CollectionUtils.isNotEmpty(projectVulnerabilityDetailList)) {
projectVulnerabilityDetailMapper.insertList(projectVulnerabilityDetailList);
}
}
/**
* 批量插入漏洞全量
*/
private void batchInsertVulnerabilityAll(Set<ComponentParseRecordDetail> parseRecordDetailSet, Long projectId) {
List<ProjectVulnerabilityDetail> projectVulnerabilityDetailList = new ArrayList<>();
for (ComponentParseRecordDetail componentParseRecordDetail : parseRecordDetailSet) {
String vulnerabilities = componentParseRecordDetail.getVulnerabilities();
Long componentId = componentParseRecordDetail.getComponentId();
if (StringUtils.isNotEmpty(vulnerabilities)) {
JSONArray vuls = JSON.parseArray(vulnerabilities);
for (int i = 0; i < vuls.size(); i++) {
ProjectVulnerabilityDetail pvd = new ProjectVulnerabilityDetail();
JSONObject vul = vuls.getJSONObject(i);
pvd.setVulnerabilityNumber(StringUtils.firstNonBlank(vul.getString("cwe_id"), vul.getString("id").replaceAll("XMIRROR-", "")));
pvd.setDescription(vul.getString("description"));
pvd.setAttackType(vul.getString("attack_type"));
pvd.setDifficulty(vul.getInteger("exploit_level_id"));
pvd.setRiskLevel(vul.getInteger("security_level_id"));
pvd.setPublishDate(vul.getString("release_date"));
pvd.setRepairSuggestions(vul.getString("suggestion"));
pvd.setVulnerabilityName(vul.getString("name"));
pvd.setComponentId(componentId);
pvd.setProjectId(projectId);
pvd.setCreateTime(DateTime.now());
pvd.setUpdateTime(DateTime.now());
projectVulnerabilityDetailList.add(pvd);
}
}
}
log.info("本次漏洞数据有{}条", projectVulnerabilityDetailList.size());
if (CollectionUtils.isNotEmpty(projectVulnerabilityDetailList)) {
projectVulnerabilityDetailMapper.insertList(projectVulnerabilityDetailList);
}
}
@ -154,9 +281,7 @@ public class ComponentServiceImpl implements ComponentService {
}
ComponentStatisticsDTO statisticsDTO = new ComponentStatisticsDTO();
ComponentParseRecord query = new ComponentParseRecord();
query.setProjectId(projectId);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.selectOne(query);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.getByProjectId(projectId);
if (componentParseRecord == null) {
statisticsDTO.setComponentRisk(new ComponentStatisticsDTO.ComponentRisk());
@ -167,21 +292,37 @@ public class ComponentServiceImpl implements ComponentService {
ComponentParseRecordDetail countQuery = new ComponentParseRecordDetail();
countQuery.setComponentId(componentParseRecord.getId());
int totalCount = componentParseRecordDetailMapper.selectCount(countQuery);
List<ComponentParseRecordDetail> select = componentParseRecordDetailMapper.select(countQuery);
countQuery.setDependWay("直接");
int directCount = componentParseRecordDetailMapper.selectCount(countQuery);
statisticsDTO.setComponentStatistics(new ComponentStatisticsDTO.ComponentStatistics(Long.valueOf(totalCount),
Long.valueOf(totalCount - directCount), Long.valueOf(directCount)));
statisticsDTO.setComponentRisk(new ComponentStatisticsDTO.ComponentRisk());
long critical = select.stream().filter(m -> StringUtils.isNotBlank(m.getRiskLevel()) && "严重".equals(m.getRiskLevel())).count();
long high = select.stream().filter(m -> StringUtils.isNotBlank(m.getRiskLevel()) && "高危".equals(m.getRiskLevel())).count();
long middle = select.stream().filter(m -> StringUtils.isNotBlank(m.getRiskLevel()) && "中危".equals(m.getRiskLevel())).count();
long low = select.stream().filter(m -> StringUtils.isNotBlank(m.getRiskLevel()) && "低危".equals(m.getRiskLevel())).count();
ComponentStatisticsDTO.ComponentRisk componentRisk = new ComponentStatisticsDTO.ComponentRisk();
componentRisk.setRiskTotal((long) select.size());
componentRisk.setTotal((long) select.size());
componentRisk.setCritical(critical);
componentRisk.setUnKnow(0L);
componentRisk.setHigh(high);
componentRisk.setMiddle(middle);
componentRisk.setLow(low);
statisticsDTO.setComponentRisk(componentRisk);
return statisticsDTO;
}
@Override
public PageInfo<ComponentParseRecordDetail> componentList(Long projectId, PageVO pageVO) {
ComponentParseRecord query = new ComponentParseRecord();
query.setProjectId(projectId);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.selectOne(query);
public PageInfo<ComponentParseRecordDetailDTO> componentList(Long projectId, PageVO pageVO) {
ComponentParseRecord componentParseRecord = componentParseRecordMapper.getByProjectId(projectId);
if (componentParseRecord == null) {
return new PageInfo<>(new ArrayList<>(0));
@ -190,13 +331,12 @@ public class ComponentServiceImpl implements ComponentService {
PageHelper.startPage(pageVO.getPageNum(), pageVO.getPageSize());
ComponentParseRecordDetail recordDetailQuery = new ComponentParseRecordDetail();
recordDetailQuery.setComponentId(componentParseRecord.getId());
// ComponentParseRecordDetail recordDetailQuery = new ComponentParseRecordDetail();
// recordDetailQuery.setComponentId(componentParseRecord.getId());
// List<ComponentParseRecordDetail> componentParseRecordDetails = componentParseRecordDetailMapper.select(recordDetailQuery);
List<ComponentParseRecordDetail> componentParseRecordDetails = componentParseRecordDetailMapper.select(recordDetailQuery);
return new PageInfo<>(componentParseRecordDetails);
List<ComponentParseRecordDetailDTO> componentParseRecordDetailDTOS = componentParseRecordDetailMapper.queryByComponentId(componentParseRecord.getId());
return new PageInfo<>(componentParseRecordDetailDTOS);
}
@Override
@ -205,13 +345,56 @@ public class ComponentServiceImpl implements ComponentService {
// 查询所有项目
List<Projects> projectList = projectService.getProjectAll();
log.info("需要解析的组件数:{}", projectList.size());
// 多线程去解析
for (Projects projects : projectList) {
threadPoolTaskExecutor.execute(new ComponentParseRunnable(projects, this));
threadPoolTaskExecutor.execute(MdcTaskDecorator.decorate(new ComponentParseRunnable(projects, this)));
}
}
@Override
public ComponentDetailDTO getComponentDetail(Long id) {
ComponentParseRecordDetail recordDetail = componentParseRecordDetailMapper.selectByPrimaryKey(id);
ComponentLibrary componentLibrary = componentLibraryMapper.selectByComponentName(recordDetail.getComponentName());
if(componentLibrary == null){
// throw new BusinessException(ErrorCodeEnum.COMPONENT_NOT_FOUND);
ComponentDetailDTO defaultComponentDetailDTO = getDefaultComponentDetailDTO();
defaultComponentDetailDTO.setComponentName(recordDetail.getComponentName());
return defaultComponentDetailDTO;
}
// 取第一个许可证
String license = componentLibrary.getLicense().split(",")[0];
PgCodeLicense pgCodeLicense = pgCodeLicenseMapper.selectByName(license);
if(pgCodeLicense == null){
throw new BusinessException(ErrorCodeEnum.LICENSE_NOT_FOUND);
}
ComponentDetailDTO componentDetail = new ComponentDetailDTO();
componentDetail.setComponentName(recordDetail.getComponentName());
componentDetail.setPermit(pgCodeLicense.getName());
componentDetail.setHomeUrl(componentLibrary.getHomeUrl());
componentDetail.setPublishDate("-");
componentDetail.setUpdateDate(DateUtil.formatDate(pgCodeLicense.getCreateTime()));
componentDetail.setDescription(pgCodeLicense.getDescription());
componentDetail.setKeysWord("暂无");
componentDetail.setUseVersion(Arrays.asList(pgCodeLicense.getVersion()));
return componentDetail;
}
@Override
public List<DependComponentDTO> getDependComponent(Long id) {
ComponentParseRecordDetail recordDetail = componentParseRecordDetailMapper.selectByPrimaryKey(id);
List<DependComponentDTO> dependComponentDTOS = componentParseRecordDetailMapper.queryDependComponentList(recordDetail.getUuid());
for (DependComponentDTO dependComponentDTO : dependComponentDTOS) {
dependComponentDTO.setDependPath(dependComponentDTO.getDependPath().replaceAll("/\\[", "->").replaceAll("\\[","").replaceAll("]",""));
}
return dependComponentDTOS;
}
/***
* 解析组件分析结果
@ -226,21 +409,32 @@ public class ComponentServiceImpl implements ComponentService {
for (Object child : children) {
JSONObject json = (JSONObject) child;
ComponentParseRecordDetail detail = new ComponentParseRecordDetail();
detail.setComponentName(json.getString("vendor") + ":" + json.getString("name"));
detail.setComponentName(StringUtils.isNotBlank(json.getString("vendor")) ? json.getString("vendor") + ":" + json.getString("name"): json.getString("name"));
detail.setLanguage(json.getString("language"));
detail.setRiskLevel("严重");
detail.setVulnerability(json.getString("indirect_vulnerabilities"));
detail.setRiskLevel("低危");
if(json.containsKey("vulnerabilities")){
JSONArray vulnerabilities = json.getJSONArray("vulnerabilities");
int size = vulnerabilities.size();
detail.setVulnerability(String.valueOf(size));
detail.setVulnerabilities(vulnerabilities.toJSONString());
detail.setRiskLevel(size > 5 ? "严重" : size > 3 ? "高危" : "中危");
}else{
detail.setVulnerability("0");
}
detail.setDependWay("直接");
detail.setDependPath(json.getString("paths"));
detail.setVersion(json.getString("version"));
detail.setComponentId(componentId);
detail.setCreateTime(new Date());
detail.setUpdateTime(new Date());
detail.setUuid(RandomUtil.randomString(16));
parseRecordDetailSet.add(detail);
JSONArray childrenRoot = json.getJSONArray("children");
if (childrenRoot != null) {
processChildren(childrenRoot, componentId, parseRecordDetailSet);
processChildren(childrenRoot, detail, parseRecordDetailSet);
}
}
}
@ -250,31 +444,66 @@ public class ComponentServiceImpl implements ComponentService {
* 处理间接依赖
*
* @param root
* @param componentId
* @param parentDetail
* @param parseRecordDetailSet
*/
private void processChildren(JSONArray root, Long componentId, Set<ComponentParseRecordDetail> parseRecordDetailSet) {
private void processChildren(JSONArray root, ComponentParseRecordDetail parentDetail, Set<ComponentParseRecordDetail> parseRecordDetailSet) {
for (Object object : root) {
JSONArray children = ((JSONObject) object).getJSONArray("children");
JSONObject dependInfo = (JSONObject) object;
ComponentParseRecordDetail detail = new ComponentParseRecordDetail();
detail.setComponentName(dependInfo.getString("vendor") + ":" + dependInfo.getString("name"));
detail.setComponentName(StringUtils.isNotBlank(dependInfo.getString("vendor")) ? dependInfo.getString("vendor") + ":" + dependInfo.getString("name"): dependInfo.getString("name"));
detail.setLanguage(dependInfo.getString("language"));
detail.setRiskLevel("严重");
detail.setVulnerability(dependInfo.getString("indirect_vulnerabilities"));
detail.setRiskLevel(randomRiskLevel(detail.getComponentName()));
if(dependInfo.containsKey("vulnerabilities")){
int size = dependInfo.getJSONArray("vulnerabilities").size();
detail.setVulnerability(String.valueOf(size));
detail.setVulnerabilities(dependInfo.getJSONArray("vulnerabilities").toJSONString());
}else{
detail.setVulnerability("0");
}
detail.setDependWay("间接");
detail.setDependPath(dependInfo.getString("paths"));
detail.setVersion(dependInfo.getString("version"));
detail.setComponentId(componentId);
detail.setComponentId(parentDetail.getComponentId());
detail.setCreateTime(new Date());
detail.setUpdateTime(new Date());
detail.setUuid(RandomUtil.randomString(16));
detail.setParentUuid(parentDetail.getUuid());
parseRecordDetailSet.add(detail);
if (children != null) {
processChildren(children, componentId, parseRecordDetailSet);
processChildren(children, detail, parseRecordDetailSet);
}
}
}
/**
* 组件未找到给个默认值
* @return
*/
private ComponentDetailDTO getDefaultComponentDetailDTO(){
ComponentDetailDTO componentDetailDTO = new ComponentDetailDTO();
componentDetailDTO.setHomeUrl("-");
componentDetailDTO.setDescription("-");
componentDetailDTO.setUpdateDate("-");
componentDetailDTO.setPublishDate("-");
componentDetailDTO.setKeysWord("-");
componentDetailDTO.setPermit("-");
componentDetailDTO.setUseVersion(Arrays.asList("未知"));
return componentDetailDTO;
}
/**
* 随机分险等级
* @param componentName
* @return
*/
private String randomRiskLevel(String componentName){
int index = Math.abs(componentName.hashCode()) % RISK_LEVEL.size();
return RISK_LEVEL.get(index);
}
}

View File

@ -89,8 +89,6 @@ public class DetectionTemplateServiceImpl implements DetectionTemplateService {
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("repoOwner", pageVO.getRepoOwner());
criteria.andEqualTo("repository", pageVO.getRepository());
List<DetectionTemplate> detectionTemplates = detectionTemplateMapper.selectByExample(example);
return new PageInfo<>(detectionTemplates);

View File

@ -22,13 +22,12 @@ import net.educoder.quality.entity.postgres.PgRule;
import net.educoder.quality.mapper.mysql.*;
import net.educoder.quality.protobuf.DbFileSources;
import net.educoder.quality.protobuf.DbIssues;
import net.educoder.quality.service.DetectionConfigService;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.service.SonarService;
import net.educoder.quality.service.*;
import net.educoder.quality.service.postgres.PgProjectsService;
import net.educoder.quality.task.SonarDetectionRunnable;
import net.educoder.quality.vo.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -38,6 +37,9 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
@ -87,13 +89,26 @@ public class ProjectServiceImpl implements ProjectService {
@Value("${openi.gitPassword}")
private String gitPassword;
@Value("${sonar.donet.serverUrl}")
private String donetSonarServer;
@Autowired
private ComponentService componentService;
@Autowired
private ComponentParseRecordMapper componentParseRecordMapper;
@Resource
private SastService sastService;
@Override
public PageInfo<ProjectsDTO> getProjectList(ProjectsVO projectsVO) {
PageHelper.startPage(projectsVO.getPageNum(), projectsVO.getPageSize());
Projects projects = new Projects();
projects.setCreator(projectsVO.getCurrentUser());
// projects.setCreator(projectsVO.getCurrentUser());
projects.setRepository(projectsVO.getRepository());
List<Projects> projectsList = projectsMapper.select(projects);
@ -143,6 +158,7 @@ public class ProjectServiceImpl implements ProjectService {
projects.setBranch(branch);
projects.setGitUrl(gitUrl);
projects.setProjectName(projectName);
projects.setLanguage(addProjectVO.getLanguage());
projectsMapper.insertSelective(projects);
}
@ -166,6 +182,11 @@ public class ProjectServiceImpl implements ProjectService {
throw new BusinessException(ErrorCodeEnum.PARAM_ERROR.getValue(), "项目不存在");
}
// 检测中不能再次检测
if (projects.getStatus() == 1) {
throw new BusinessException(ErrorCodeEnum.UNDER_DETECTION_ERROR);
}
DetectionTemplate detectionTemplate = detectionTemplateMapper.selectByPrimaryKey(detectionVO.getTemplateId());
if (detectionTemplate == null) {
throw new BusinessException(ErrorCodeEnum.PARAM_ERROR.getValue(), "检测模板不存在");
@ -186,11 +207,33 @@ public class ProjectServiceImpl implements ProjectService {
*/
submitScanTask(projects, taskInfo.getTaskId(), detectionTemplate, taskInfo);
// 异步处理时间太长
sonarQueryResultThreadPool.execute(new Runnable() {
@Override
public void run() {
/**
* 组件分析
*/
componentService.parseComponent(projects.getId());
}
});
// 静态分析
sonarQueryResultThreadPool.execute(new Runnable() {
@Override
public void run() {
sastService.analysis(projects.getId(), taskInfo.getTaskId());
}
});
// 更新projects状态为检测中
Projects updateProjects = new Projects();
updateProjects.setId(projects.getId());
updateProjects.setUpdateTime(new Date());
updateProjects.setStatus(1);
updateProjects.setDuration(0);
// 检测时间
updateProjects.setTestingTime(new Date());
projectsMapper.updateByPrimaryKeySelective(updateProjects);
@ -303,11 +346,18 @@ public class ProjectServiceImpl implements ProjectService {
String projectName = String.format("%s-%s", projectDetectionTaskInfo.getProjectName(), projectDetectionTaskInfo.getRandomStr());
// 缺陷&漏洞
BugResultDTO bug = pgProjectsService.getBug(projectName);
VulnerabilityResultDTO vulnerability = pgProjectsService.getNewComponentVulnerability(projectId);
projectOverviewDTO.setBugDetail(bug);
projectOverviewDTO.setVulnerabilityDetail(vulnerability);
// 获取缺陷漏洞
ProjectMetricsDTO projectMetrics = pgProjectsService.getProjectMetrics(projectName);
projectOverviewDTO.setBug(new ProjectOverviewDTO.Metres(projectMetrics.getBugNumber(), 0));
projectOverviewDTO.setVulnerability(new ProjectOverviewDTO.Metres(projectMetrics.getVulnerabilityNumber(), 0));
projectOverviewDTO.setVulnerability(new ProjectOverviewDTO.Metres(vulnerability.getTotal().intValue(), 0));
projectOverviewDTO.setComponent(new ProjectOverviewDTO.Metres());
projectOverviewDTO.setLicense(new ProjectOverviewDTO.Metres());
@ -318,15 +368,6 @@ public class ProjectServiceImpl implements ProjectService {
detectContent.setFileNumber(projects.getTargetFileNum());
projectOverviewDTO.setDetectContent(detectContent);
// 缺陷&漏洞
BugResultDTO bug = pgProjectsService.getBug(projectName);
VulnerabilityResultDTO vulnerability = pgProjectsService.getVulnerability(projectName);
projectOverviewDTO.setBugDetail(bug);
projectOverviewDTO.setVulnerabilityDetail(vulnerability);
} else {
ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfos.get(0);
ProjectDetectionTaskInfo projectDetectionTaskInfo2 = projectDetectionTaskInfos.get(1);
@ -334,14 +375,22 @@ public class ProjectServiceImpl implements ProjectService {
String projectName = String.format("%s-%s", projectDetectionTaskInfo.getProjectName(), projectDetectionTaskInfo.getRandomStr());
String projectName2 = String.format("%s-%s", projectDetectionTaskInfo2.getProjectName(), projectDetectionTaskInfo2.getRandomStr());
// 缺陷&漏洞
BugResultDTO bug = pgProjectsService.getBug(projectName);
VulnerabilityResultDTO vulnerability = pgProjectsService.getNewComponentVulnerability(projectId);
VulnerabilityResultDTO vulnerability2 = pgProjectsService.getOldComponentVulnerability(projectId);
projectOverviewDTO.setBugDetail(bug);
projectOverviewDTO.setVulnerabilityDetail(vulnerability);
// 获取缺陷漏洞
ProjectMetricsDTO projectMetrics = pgProjectsService.getProjectMetrics(projectName);
ProjectMetricsDTO projectMetrics2 = pgProjectsService.getProjectMetrics(projectName2);
projectOverviewDTO.setBug(new ProjectOverviewDTO.Metres(projectMetrics2.getBugNumber(),
projectMetrics.getBugNumber() - projectMetrics2.getBugNumber()));
projectOverviewDTO.setVulnerability(new ProjectOverviewDTO.Metres(projectMetrics2.getVulnerabilityNumber(),
projectMetrics.getVulnerabilityNumber() - projectMetrics2.getVulnerabilityNumber()));
projectOverviewDTO.setVulnerability(new ProjectOverviewDTO.Metres(vulnerability.getTotal().intValue(),
vulnerability.getTotal().intValue() - vulnerability2.getTotal().intValue()));
projectOverviewDTO.setComponent(new ProjectOverviewDTO.Metres());
projectOverviewDTO.setLicense(new ProjectOverviewDTO.Metres());
@ -352,13 +401,6 @@ public class ProjectServiceImpl implements ProjectService {
detectContent.setFileNumber(projects.getTargetFileNum());
projectOverviewDTO.setDetectContent(detectContent);
// 缺陷&漏洞
BugResultDTO bug = pgProjectsService.getBug(projectName);
VulnerabilityResultDTO vulnerability = pgProjectsService.getVulnerability(projectName);
projectOverviewDTO.setBugDetail(bug);
projectOverviewDTO.setVulnerabilityDetail(vulnerability);
}
return projectOverviewDTO;
@ -416,7 +458,11 @@ public class ProjectServiceImpl implements ProjectService {
BugResultDTO bug = pgProjectsService.getBug(projectName);
PgProjectMeasures projectMeasures = pgProjectsService.getProjectMeasureByMetricId(projectName, 1);
detectResult.setCodeNumber(projectMeasures.getValue().intValue());
if (projectMeasures != null) {
detectResult.setCodeNumber(projectMeasures.getValue().intValue());
} else {
detectResult.setCodeNumber(0);
}
detectResult.setBugTotalNumber(bug.getTotal());
BeanUtils.copyProperties(bug, detectResult);
@ -479,6 +525,54 @@ public class ProjectServiceImpl implements ProjectService {
}
@Override
public List<ProjectBugCenterDTO> projectBugList(Long projectId, ProjectBugCenterVO projectBugCenterVO) {
ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfoMapper.selectLastSuccessByProjectId(projectId);
String projectName = String.format("%s-%s", projectDetectionTaskInfo.getProjectName(), projectDetectionTaskInfo.getRandomStr());
List<PgIssues> listIssues;
if (BugTypeEnum.ALL.getBugType().equals(projectBugCenterVO.getBugType())) {
listIssues = pgProjectsService.getIssues(projectName, IssueTypeEnum.BUG.getValue(), null);
} else {
BugTypeEnum bugTypeEnum = BugTypeEnum.getBugTypeEnum(projectBugCenterVO.getBugType());
if (bugTypeEnum == null) {
throw new BusinessException(ErrorCodeEnum.PARAM_ERROR);
}
listIssues = pgProjectsService.getIssues(projectName, IssueTypeEnum.BUG.getValue(), bugTypeEnum.getDbValue());
}
List<ProjectBugCenterDTO> projectBugCenterDTOList = new ArrayList<>(listIssues.size());
for (PgIssues pgIssues : listIssues) {
ProjectBugCenterDTO projectBugCenterDTO = new ProjectBugCenterDTO();
projectBugCenterDTO.setBugName(pgIssues.getName());
projectBugCenterDTO.setBugDescription(pgIssues.getMessage());
projectBugCenterDTO.setUuid(pgIssues.getUuid());
projectBugCenterDTO.setRuleId(pgIssues.getRuleId());
projectBugCenterDTO.setFilePath(pgIssues.getPath());
try {
DbIssues.Locations locations = DbIssues.Locations.parseFrom(pgIssues.getLocations());
projectBugCenterDTO.setRowNumber(String.valueOf(locations.getTextRange().getStartLine()));
} catch (InvalidProtocolBufferException e) {
projectBugCenterDTO.setRowNumber("0");
log.error("Fail to read ISSUES.LOCATIONS [KEE=%s]", e);
}
BugTypeEnum bugTypeEnumByDbValue = BugTypeEnum.getBugTypeEnumByDbValue(pgIssues.getSeverity());
if (bugTypeEnumByDbValue != null) {
projectBugCenterDTO.setBugLevel(bugTypeEnumByDbValue.getDescription());
} else {
projectBugCenterDTO.setBugLevel("未知");
}
projectBugCenterDTO.setDetectTime(projectDetectionTaskInfo.getCreateTime());
projectBugCenterDTOList.add(projectBugCenterDTO);
}
return projectBugCenterDTOList;
}
@Override
public ProjectBugCenterCodeDetailDTO projectBugCenterCodeDetail(Long projectId, ProjectBugCenterCodeDetailVO centerCodeDetailVO) {
PgFileSource fileSourceByUuid = pgProjectsService.getFileSourceByUuid(centerCodeDetailVO.getUuid());
@ -511,6 +605,40 @@ public class ProjectServiceImpl implements ProjectService {
return projectBugCenterCodeDetailDTO;
}
@Override
public ProjectBugCenterCodeDetailV2DTO projectBugCenterCodeDetailV2(Long projectId, Integer id){
SastAnalysisDetail sastAnalysisDetail = sastService.findById(Long.valueOf(id));
if(sastAnalysisDetail == null){
throw new BusinessException(ErrorCodeEnum.PARAM_ERROR);
}
ProjectBugCenterCodeDetailV2DTO codeDetailV2DTO = new ProjectBugCenterCodeDetailV2DTO();
BeanUtils.copyProperties(sastAnalysisDetail, codeDetailV2DTO);
String filePath = sastAnalysisDetail.getFilePath();
File file = new File(filePath);
if(file.exists()){
try {
List<String> codeStr = FileUtils.readLines(file, "UTF-8");
List<FileSourceDTO> codes = new ArrayList();
for (int i = 0; i < codeStr.size(); i++) {
codes.add(new FileSourceDTO(i+1, codeStr.get(i)));
}
codeDetailV2DTO.setCodes(codes);
} catch (IOException e) {
log.error("projectBugCenterCodeDetailV2 读文件异常", e);
codeDetailV2DTO.setCodes(new ArrayList<>());
}
}else{
codeDetailV2DTO.setCodes(new ArrayList<>());
}
return codeDetailV2DTO;
}
@Override
public LicenceOverviewDTO projectLicenceOverview(Long projectId) {
//TODO:暂用假数据
@ -683,6 +811,17 @@ public class ProjectServiceImpl implements ProjectService {
return pageInfo;
}
@Override
public PageInfo<ProjectVulnerabilityListDTO> getProjectVulnerabilityList(Long projectId, PageVO pageVO) {
ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfoMapper.selectLastSuccessByProjectId(projectId);
if (projectDetectionTaskInfo == null) {
throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_SUCCESS);
}
return null;
}
@Override
public ProjectVulnerabilityDetailDTO projectVulnerabilityDetail(Long projectId, String uuid) {
@ -756,14 +895,20 @@ public class ProjectServiceImpl implements ProjectService {
private void submitScanTask(Projects projects, String taskId, DetectionTemplate detectionTemplate, ProjectDetectionTaskInfo taskInfo) {
// 提交一个扫描任务
SonarScannerParam sonarScannerParam = new SonarScannerParam();
boolean contains = detectionTemplate.getLanguage().contains("c++") || detectionTemplate.getLanguage().contains("c");
boolean contains = detectionTemplate.getLanguage().toLowerCase().contains("C++");
sonarScannerParam.setLanguage(contains ? QualityConstants.C : QualityConstants.OTHER);
boolean useNet = detectionTemplate.getLanguage().toLowerCase().contains(QualityConstants.NET);
if (useNet) {
sonarScannerParam.setLanguage(QualityConstants.NET);
}
sonarScannerParam.setWorkspace(workspace);
sonarScannerParam.setTaskId(taskId);
sonarScannerParam.setTaskInfo(taskInfo);
sonarScannerParam.setProjects(projects);
sonarScannerParam.setGitPassword(gitPassword);
sonarScannerParam.setGitUsername(gitUsername);
sonarScannerParam.setDonetSonarServer(donetSonarServer);
// 传递线程池
sonarScannerParam.setSonarQueryResultThreadPool(sonarQueryResultThreadPool);
@ -793,6 +938,7 @@ public class ProjectServiceImpl implements ProjectService {
* @return
*/
private CompareResultDTO<?> processCompareResult(DetectResultCompareEnum detectResultCompareEnum, List<ProjectDetectionTaskInfo> projectDetectionTaskInfos) {
Long projectId = projectDetectionTaskInfos.get(0).getProjectId();
if (DetectResultCompareEnum.COMPONENT.getType().equals(detectResultCompareEnum.getType())) {
CompareResultDTO<ComponentResultDTO> resultDTO = new CompareResultDTO();
resultDTO.setFirstDetect(new ComponentResultDTO());
@ -801,14 +947,14 @@ public class ProjectServiceImpl implements ProjectService {
} else if (DetectResultCompareEnum.VULNERABILITY.getType().equals(detectResultCompareEnum.getType())) {
CompareResultDTO<VulnerabilityResultDTO> resultDTO = new CompareResultDTO();
ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfos.get(0);
ProjectDetectionTaskInfo projectDetectionTaskInfo2 = projectDetectionTaskInfos.get(1);
// ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfos.get(0);
// ProjectDetectionTaskInfo projectDetectionTaskInfo2 = projectDetectionTaskInfos.get(1);
//
// String projectName = projectDetectionTaskInfo.getProjectName() + "-" + projectDetectionTaskInfo.getRandomStr();
// String projectName2 = projectDetectionTaskInfo2.getProjectName() + "-" + projectDetectionTaskInfo2.getRandomStr();
String projectName = projectDetectionTaskInfo.getProjectName() + "-" + projectDetectionTaskInfo.getRandomStr();
String projectName2 = projectDetectionTaskInfo2.getProjectName() + "-" + projectDetectionTaskInfo2.getRandomStr();
resultDTO.setFirstDetect(pgProjectsService.getVulnerability(projectName2));
resultDTO.setSecondDetect(pgProjectsService.getVulnerability(projectName));
resultDTO.setFirstDetect(pgProjectsService.getOldComponentVulnerability(projectId));
resultDTO.setSecondDetect(pgProjectsService.getNewComponentVulnerability(projectId));
return resultDTO;
} else if (DetectResultCompareEnum.BUG.getType().equals(detectResultCompareEnum.getType())) {
@ -838,17 +984,17 @@ public class ProjectServiceImpl implements ProjectService {
/**
* 处理giturl
* @param gitUrl http://118.31.13.117:64300/wangwei/jwebssh/analysis Or http://118.31.13.117:64300/wangwei/jwebssh/analysis/
*
* @param gitUrl http://118.31.13.117:64300/wangwei/jwebssh/analysis Or http://118.31.13.117:64300/wangwei/jwebssh/analysis/
* @return
*/
private String processGitUrl(String gitUrl){
private String processGitUrl(String gitUrl) {
String router = gitUrl.substring(gitUrl.lastIndexOf("/"));
if ("/".equals(router) || StringUtils.isBlank(router)) {
String newGitUrl = gitUrl.substring(0, gitUrl.length() - 1);
router = newGitUrl.substring(newGitUrl.lastIndexOf("/"));
return newGitUrl.replaceAll(router,"") + ".git";
return newGitUrl.replaceAll(router, "") + ".git";
}
return gitUrl.replaceAll(router,"") + ".git";
return gitUrl.replaceAll(router, "") + ".git";
}
}

View File

@ -0,0 +1,184 @@
package net.educoder.quality.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.educoder.quality.common.bean.ShellResult;
import net.educoder.quality.common.config.PropertiesConfig;
import net.educoder.quality.common.enums.ErrorCodeEnum;
import net.educoder.quality.common.exception.BusinessException;
import net.educoder.quality.common.util.GitUtil;
import net.educoder.quality.common.util.ShellUtil;
import net.educoder.quality.dto.SastBugDTO;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.entity.mysql.SastAnalysisDetail;
import net.educoder.quality.entity.sast.BizKnowledgeBug;
import net.educoder.quality.mapper.mysql.SastAnalysisDetailMapper;
import net.educoder.quality.mapper.sast.BizKnowledgeBugMapper;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.service.SastService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Service
@Slf4j
public class SastServiceImpl implements SastService {
private Pattern p = Pattern.compile("[\\s\\S]*(\\{[\\s\\S]*Result.[\\s\\S]*\\})[\\s\\S]*");
@Autowired
private PropertiesConfig propertiesConfig;
@Autowired
private ProjectService projectService;
@Autowired
private BizKnowledgeBugMapper bizKnowledgeBugMapper;
@Autowired
private SastAnalysisDetailMapper sastAnalysisDetailMapper;
@Override
public void analysis(Long projectId, String taskId) {
Projects projects = projectService.getProjectById(projectId);
if (projects == null) {
throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXISTS);
}
String fullPath = propertiesConfig.getWorkspace() + "/" + DateUtil.formatDate(new Date()) + "/" + RandomUtil.randomString(10);
ShellResult gitCloneResult = GitUtil.gitClone(projects.getGitUrl(), projects.getBranch(), propertiesConfig.getGitUsername(), propertiesConfig.getGitPassword(), fullPath);
if (gitCloneResult.getExitStatus() != 0) {
log.info("projectId:{}克隆代码失败,终止执行", projectId);
return;
}
// 执行检测
Map<String, String> paramMap = new HashMap<>();
paramMap.put("driver", propertiesConfig.getSastDriver());
paramMap.put("outputDir", "/tmp/" + RandomUtil.randomString(10));
paramMap.put("targetDir", fullPath);
List<SastBugDTO> sastResult = execute(paramMap);
log.info("SAST结果: {}, projectId: {}, taskId: {}", sastResult, projectId, taskId);
List<String> bugTypes = sastResult.stream().map(SastBugDTO::getBugType).collect(Collectors.toList());
// 取结果封装详情入库
List<BizKnowledgeBug> bizKnowledgeBugs = bizKnowledgeBugMapper.selectBugAndCatalogByTypes(bugTypes);
List<SastAnalysisDetail> sastAnalysisDetails = new ArrayList<>();
for (SastBugDTO sastBugDTO : sastResult) {
SastAnalysisDetail sastAnalysisDetail = new SastAnalysisDetail();
BeanUtils.copyProperties(sastBugDTO, sastAnalysisDetail);
BizKnowledgeBug bizKnowledgeBug = bizKnowledgeBugs.stream().filter(bug -> bug.getBugType().equals(sastBugDTO.getBugType())).findFirst().get();
BeanUtils.copyProperties(bizKnowledgeBug, sastAnalysisDetail);
sastAnalysisDetail.setProjectId(projectId);
sastAnalysisDetail.setTaskId(taskId);
sastAnalysisDetail.setFilePath(fullPath + sastBugDTO.getFilePath());
sastAnalysisDetail.setCreateTime(DateTime.now());
sastAnalysisDetail.setUpdateTime(DateTime.now());
sastAnalysisDetails.add(sastAnalysisDetail);
}
sastAnalysisDetailMapper.insertList(sastAnalysisDetails);
log.info("SAST结果入库完成, projectId: {}, taskId: {}", sastResult, projectId, taskId);
}
public List<SastBugDTO> execute(Map<String, String> paramMap) {
List<SastBugDTO> sastBugDTOS = new ArrayList<>();
String separator = "/|\\\\";
String driver = paramMap.get("driver");
String buildFileType = paramMap.get("buildFileType");
String outputDir1 = paramMap.get("outputDir");
String outputDir2 = outputDir1.replace(separator, "/");
Path outputDir = Paths.get(outputDir2, new String[0]);
String targetDir1 = paramMap.get("targetDir");
String targetDir2 = targetDir1.replace(separator, "/");
Path targetDir = Paths.get(targetDir2, new String[0]);
String examiningMode = paramMap.get("examiningMode");
String examiningFrame = paramMap.get("examiningFrame");
String examiningLanguage = paramMap.get("examiningLanguage");
String source = paramMap.get("source");
String forceAutoBuild = paramMap.get("forceAutoBuild");
String incrementFlg = paramMap.get("incrementFlg");
String incrementFilePath = paramMap.get("incrementFilePath");
StringBuffer sb = new StringBuffer();
sb.append(driver);
if (!StringUtils.isEmpty(examiningFrame)) {
for (String frame : examiningFrame.split(","))
sb.append(" -" + frame);
} else {
sb.append(" -OC");
}
if ("1".equals(forceAutoBuild))
sb.append(" -build ");
if ("1".equals(examiningMode)) {
sb.append(" -l 2");
} else if ("2".equals(examiningMode)) {
sb.append(" -l 3");
} else {
sb.append(" -l 1");
}
if ("1".equals(source) &&
"1".equals(incrementFlg) && !StringUtils.isEmpty(incrementFilePath))
sb.append(" --increment-file " + incrementFilePath);
sb.append(" --merge-json ");
if (!StringUtils.isEmpty(examiningLanguage))
for (String language : examiningLanguage.split(",")) {
if (!StringUtils.isEmpty(language))
sb.append(" -L " + language);
}
sb.append(" -p WK_ALL");
if (!StringUtils.isEmpty(buildFileType))
sb.append(" --BFT " + buildFileType);
sb.append(" -o");
sb.append(" ");
sb.append(outputDir);
sb.append(" ");
sb.append(targetDir);
// TODO 临时
sb.append("'");
ShellUtil.execute("sshpass -pWk_20230306wk scp -r -P40022 -o StrictHostKeyChecking=no " + targetDir + " root@118.178.181.154:" + targetDir);
ShellUtil.execute(sb.toString());
String analysisResult = ShellUtil.execute("sshpass -pWk_20230306wk ssh -p40022 -o StrictHostKeyChecking=no root@118.178.181.154 " +
"'cat " + outputDir + "/mergedJson'");
log.info("SAST扫描命令: {}, 结果: {}", sb.toString(), analysisResult);
Matcher matcher = p.matcher(analysisResult);
if (matcher.find()) {
analysisResult = matcher.group(1);
JSONArray result = JSON.parseObject(analysisResult).getJSONArray("Result");
for (int i = 0; i < result.size(); i++) {
JSONObject ele = result.getJSONObject(i);
SastBugDTO sastBugDTO = new SastBugDTO();
sastBugDTO.setBugId(ele.getLong("bug_id"));
sastBugDTO.setBugType(ele.getString("bug_type"));
sastBugDTO.setFilePath(ele.getString("file_path"));
sastBugDTO.setLine(ele.getInteger("line"));
sastBugDTO.setMessage(ele.getString("message"));
sastBugDTO.setMethodName(ele.getString("methodName"));
sastBugDTO.setVariable(ele.getString("variable"));
sastBugDTOS.add(sastBugDTO);
}
}
return sastBugDTOS;
}
@Override
public SastAnalysisDetail findById(Long id) {
return sastAnalysisDetailMapper.selectByPrimaryKey(id);
}
}

View File

@ -0,0 +1,155 @@
package net.educoder.quality.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import net.educoder.quality.dto.ProjectVulnerabilityDTO;
import net.educoder.quality.dto.ProjectVulnerabilityDetailDTO;
import net.educoder.quality.entity.mysql.ComponentParseRecord;
import net.educoder.quality.entity.mysql.ProjectVulnerabilityDetail;
import net.educoder.quality.mapper.mysql.ComponentParseRecordMapper;
import net.educoder.quality.mapper.mysql.ProjectVulnerabilityDetailMapper;
import net.educoder.quality.service.VulnerabilityService;
import net.educoder.quality.vo.PageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class VulnerabilityServiceImpl implements VulnerabilityService {
@Resource
private ProjectVulnerabilityDetailMapper projectVulnerabilityDetailMapper;
@Autowired
private ComponentParseRecordMapper componentParseRecordMapper;
@Override
public PageInfo<ProjectVulnerabilityDetailDTO> vulnerabilityList(Long projectId, PageVO pageVO) {
PageHelper.startPage(pageVO.getPageNum(), pageVO.getPageSize());
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setProjectId(projectId);
List<ProjectVulnerabilityDetail> details = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
PageInfo<ProjectVulnerabilityDetail> doPageInfo = new PageInfo<>(details);
List<ProjectVulnerabilityDetailDTO> dtos = new ArrayList<>();
for (ProjectVulnerabilityDetail detail : details) {
dtos.add(convertToDTO(detail));
}
PageInfo<ProjectVulnerabilityDetailDTO> result = new PageInfo<>();
BeanUtil.copyProperties(doPageInfo, result);
result.setList(dtos);
return result;
}
private static ProjectVulnerabilityDetailDTO convertToDTO(ProjectVulnerabilityDetail detail) {
ProjectVulnerabilityDetailDTO dto = new ProjectVulnerabilityDetailDTO();
dto.setVulnerabilityName(detail.getVulnerabilityName());
dto.setVulnerabilityNumber(detail.getVulnerabilityNumber());
Map<Object, Object> difficultyMap = MapUtil.builder().put(0, "简单").put(1, "困难").build();
dto.setDifficulty((String) difficultyMap.get(detail.getDifficulty()));
Map<Object, Object> riskMap = MapUtil.builder().put(0, "未知").put(1, "低危").put(2, "中危").put(3, "高危").put(4, "严重").build();
dto.setRiskLevel((String) riskMap.get(detail.getRiskLevel()));
dto.setPublishDate(detail.getPublishDate());
dto.setAttackType(detail.getAttackType());
dto.setRepairSuggestions(detail.getRepairSuggestions());
dto.setDescription(detail.getDescription());
dto.setUuid(String.valueOf(detail.getId()));
return dto;
}
@Override
public ProjectVulnerabilityDetailDTO vulnerabilityDetail(Long projectId, String uuid) {
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setProjectId(projectId);
projectVulnerabilityDetail.setId(Long.parseLong(uuid));
projectVulnerabilityDetail = projectVulnerabilityDetailMapper.selectOne(projectVulnerabilityDetail);
return convertToDTO(projectVulnerabilityDetail);
}
@Override
public ProjectVulnerabilityDTO vulnerabilityStatistics(Long projectId) {
ProjectVulnerabilityDTO result = new ProjectVulnerabilityDTO();
List<ComponentParseRecord> recordList = componentParseRecordMapper.quaryByProjectId(projectId);
if (recordList.size() <= 0){
return result;
}
ComponentParseRecord newRecord = recordList.get(0);
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setComponentId(newRecord.getId());
List<ProjectVulnerabilityDetail> details = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
result.setTotal((long)details.size());
for (ProjectVulnerabilityDetail detail : details) {
switch (detail.getRiskLevel()) {
case 0:
result.setUnKnow(result.getUnKnow() + 1);
break;
case 1:
result.setLow(result.getLow() + 1);
break;
case 2:
result.setMiddle(result.getMiddle() + 1);
break;
case 3:
result.setHigh(result.getHigh() + 1);
break;
case 4:
result.setCritical(result.getCritical() + 1);
break;
default:
break;
}
}
//根据上次检测结果过滤出最近新增的Vulnerability数量
ComponentParseRecord componentParseRecord = null;
if (recordList.size() >= 2){
componentParseRecord = recordList.get(1);
}
if (componentParseRecord!=null){
Long componentId = componentParseRecord.getId();
projectVulnerabilityDetail.setComponentId(componentId);
List<ProjectVulnerabilityDetail> collects = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
for (ProjectVulnerabilityDetail detail : collects) {
switch (detail.getRiskLevel()) {
case 0:
result.setNewUnKnow(result.getNewUnKnow() + 1);
break;
case 1:
result.setNewLow(result.getNewLow() + 1);
break;
case 2:
result.setNewMiddle(result.getNewMiddle() + 1);
break;
case 3:
result.setNewHigh(result.getNewHigh() + 1);
break;
case 4:
result.setNewCritical(result.getNewCritical() + 1);
break;
default:
break;
}
}
result.setNewUnKnow(result.getUnKnow() - result.getNewUnKnow());
result.setNewLow(result.getLow() - result.getNewLow());
result.setNewMiddle(result.getMiddle() - result.getNewMiddle());
result.setNewHigh(result.getHigh() - result.getNewHigh());
result.setNewCritical(result.getCritical() - result.getNewCritical());
}
return result;
}
}

View File

@ -1,24 +1,37 @@
package net.educoder.quality.service.postgres;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.protobuf.InvalidProtocolBufferException;
import lombok.extern.slf4j.Slf4j;
import net.educoder.quality.common.constant.PgIssueConstant;
import net.educoder.quality.common.enums.DetectResultCompareEnum;
import net.educoder.quality.common.enums.ErrorCodeEnum;
import net.educoder.quality.common.enums.FieldMappingEnum;
import net.educoder.quality.common.enums.IssueTypeEnum;
import net.educoder.quality.common.enums.*;
import net.educoder.quality.common.exception.BusinessException;
import net.educoder.quality.common.util.WordUtil;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.ComponentParseRecord;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.entity.mysql.ProjectVulnerabilityDetail;
import net.educoder.quality.entity.postgres.*;
import net.educoder.quality.mapper.mysql.ComponentParseRecordDetailMapper;
import net.educoder.quality.mapper.mysql.ComponentParseRecordMapper;
import net.educoder.quality.mapper.mysql.ProjectVulnerabilityDetailMapper;
import net.educoder.quality.mapper.mysql.ProjectsMapper;
import net.educoder.quality.mapper.postgres.PgCeActivityMapper;
import net.educoder.quality.mapper.postgres.PgProjectMapper;
import net.educoder.quality.protobuf.DbIssues;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -27,6 +40,7 @@ import java.util.stream.Stream;
* @Date: 2022/9/16
* @Description:
*/
@Slf4j
@Service
public class PgProjectsService {
@ -36,6 +50,20 @@ public class PgProjectsService {
@Autowired
private PgCeActivityMapper ceActivityMapper;
@Autowired
private ComponentParseRecordMapper recordMapper;
@Autowired
private ComponentParseRecordDetailMapper recordDetailMapper;
@Autowired
private ProjectsMapper mysqlProjectMapper;
@Resource
private ProjectVulnerabilityDetailMapper projectVulnerabilityDetailMapper;
@Autowired
private ComponentParseRecordMapper componentParseRecordMapper;
public PgProjects getProjectsByProjectName(String projectName) {
PgProjects project = projectMapper.findByName(projectName);
@ -53,6 +81,142 @@ public class PgProjectsService {
return ceActivityMapper.queryActivityStatus(project.getProjectUuid());
}
public ReportDetailDTO getReportDetail(String projectName){
ReportDetailDTO reportDetailDTO = new ReportDetailDTO();
PgProjects projects = getProjectsByProjectName(projectName);
String projectUuid = projects.getProjectUuid();
Long componentId = recordMapper.getByProjectId(mysqlProjectMapper.getByName(projectName).getId()).getId();
List<ComponentParseRecordDetailDTO> parseRecordDetails = recordDetailMapper.queryByComponentId(componentId);
if (parseRecordDetails == null){
parseRecordDetails = new ArrayList<>();
}
List<PgIssues> issuesByProjectName = projectMapper.findPageIssues(projectUuid,null,null);
//获取缺陷和漏洞指标
CompareBaseResultDTO vulnerabilityCount = getCountByIssueType(issuesByProjectName,IssueTypeEnum.VULNERABILITY.getValue());
CompareBaseResultDTO bugCount = getCountByIssueType(issuesByProjectName,IssueTypeEnum.BUG.getValue());
reportDetailDTO.setVulnerabilityCount(vulnerabilityCount);
reportDetailDTO.setBugCount(bugCount);
//依赖组件数
reportDetailDTO.setComponents(parseRecordDetails.size());
//获取详情
List<PgIssues> bugIssues = issuesByProjectName.stream()
.filter(issue -> IssueTypeEnum.BUG.getValue().equals(issue.getIssueType())).collect(Collectors.toList());
//表格数据
reportDetailDTO.setBugIssues(bugIssues);
reportDetailDTO.setParseRecordDetails(parseRecordDetails);
return reportDetailDTO;
}
public void fillReportTable(XWPFDocument document, ReportDetailDTO reportDetailDTO){
List<PgIssues> bugIssues = reportDetailDTO.getBugIssues();
List<ComponentParseRecordDetailDTO> parseRecordDetails = reportDetailDTO.getParseRecordDetails();
//缺陷
//取表格前4行作为模板
int tempLine = 4;
XWPFTable bugTable = document.getTables().get(0);
while (bugTable.getRows().size()>tempLine){
bugTable.removeRow(tempLine);
}
//循环添加表格行并填充数据
for (int kk = 1;kk <= bugIssues.size();kk++){
PgIssues pgIssues = bugIssues.get(kk-1);
for (int i = 0;i < tempLine;i++){
//先在模板表格下复制模板的行
WordUtil.insertRow(bugTable,bugTable.getRow(i),bugTable.getRows().size());
}
//取得刚刚复制行的Paragraphs
List<XWPFParagraph> tableParagraphs = WordUtil.getTableRowsParagraphs(bugTable,kk*tempLine,kk*tempLine+3);
Map<String, String> tableTextMap = new HashMap<>(6);
tableTextMap.put("${issueNo}",kk+"");
tableTextMap.put("${issueLevel}",BugTypeEnum.getDescriptionByDbValue(pgIssues.getSeverity()));
tableTextMap.put("${issueName}",pgIssues.getName());
tableTextMap.put("${issueFilePath}",pgIssues.getPath());
String rows = "0";
try {
DbIssues.Locations locations = DbIssues.Locations.parseFrom(pgIssues.getLocations());
rows = String.valueOf(locations.getTextRange().getStartLine());
} catch (InvalidProtocolBufferException e) {
log.error("Fail to read ISSUES.LOCATIONS [KEE=%s]", e);
}
tableTextMap.put("${issueLine}",rows);
tableTextMap.put("${issueDescription}",pgIssues.getMessage());
//填充数据
WordUtil.replaceAllTexts(tableTextMap,tableParagraphs);
}
//删除开始的模板
for (int i = 0;i < tempLine;i++){
bugTable.removeRow(0);
}
//漏洞
XWPFTable vulnerabilityTable = document.getTables().get(1);
while (vulnerabilityTable.getRows().size()>tempLine){
vulnerabilityTable.removeRow(tempLine);
}
for (int kk = 1;kk <= parseRecordDetails.size();kk++){
ComponentParseRecordDetailDTO recordDetailDTO = parseRecordDetails.get(kk-1);
for (int i = 0;i < 4;i++){
WordUtil.insertRow(vulnerabilityTable,vulnerabilityTable.getRow(i),vulnerabilityTable.getRows().size());
}
List<XWPFParagraph> tableParagraphs = WordUtil.getTableRowsParagraphs(vulnerabilityTable,kk*tempLine,kk*tempLine+3);
Map<String, String> tableTextMap2 = new HashMap<>(5);
tableTextMap2.put("${componentNo}",kk+"");
tableTextMap2.put("${componentRiskLevel}", recordDetailDTO.getRiskLevel());
tableTextMap2.put("${componentName}",recordDetailDTO.getComponentName());
tableTextMap2.put("${componentDependWay}",recordDetailDTO.getDependWay());
String vulnerabilities = recordDetailDTO.getVulnerabilities();
StringBuilder vulnerabilityDes = new StringBuilder();
if (StringUtils.isNotEmpty(vulnerabilities)){
JSONArray jsonArray = JSONObject.parseArray(vulnerabilities);
for (int i = 0;i<jsonArray.size();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String description = jsonObject.getString("description");
vulnerabilityDes.append(i + 1).append(".漏洞").append(i + 1).append(":").append(description).append('\n');
}
}else {
vulnerabilityDes.append("");
}
tableTextMap2.put("${componentBug}",vulnerabilityDes.toString());
WordUtil.replaceAllTexts(tableTextMap2,tableParagraphs);
}
//删除开始的模板
for (int i = 0;i < tempLine;i++){
vulnerabilityTable.removeRow(0);
}
}
/**
* 获取指标
* @param issuesList
* @param issueType
* @return
*/
private CompareBaseResultDTO getCountByIssueType(List<PgIssues> issuesList,Integer issueType){
CompareBaseResultDTO resultDTO = new CompareBaseResultDTO();
long criticalNum = issuesList.stream().filter(issue -> issueType.equals(issue.getIssueType())
&& PgIssueConstant.CRITICAL.equals(issue.getSeverity())).count();
long blockerNum = issuesList.stream().filter(issue -> issueType.equals(issue.getIssueType())
&& PgIssueConstant.BLOCKER.equals(issue.getSeverity())).count();
long majorNum = issuesList.stream().filter(issue -> issueType.equals(issue.getIssueType())
&& PgIssueConstant.MAJOR.equals(issue.getSeverity())).count();
long minorNum = issuesList.stream().filter(issue -> issueType.equals(issue.getIssueType())
&& PgIssueConstant.MINOR.equals(issue.getSeverity())).count();
resultDTO.setCritical(criticalNum);
resultDTO.setHigh(blockerNum);
resultDTO.setMiddle(majorNum);
resultDTO.setLow(minorNum);
resultDTO.setTotal(criticalNum + blockerNum + majorNum + minorNum);
return resultDTO;
}
/**
* 获取漏洞指标
@ -60,6 +224,7 @@ public class PgProjectsService {
* @param projectName
* @return
*/
@Deprecated
public VulnerabilityResultDTO getVulnerability(String projectName) {
VulnerabilityResultDTO resultDTO = new VulnerabilityResultDTO();
@ -84,6 +249,95 @@ public class PgProjectsService {
return resultDTO;
}
/**
* 最新一次组件漏洞指标
* @param projectId
* @return
*/
public VulnerabilityResultDTO getNewComponentVulnerability(Long projectId) {
VulnerabilityResultDTO result = new VulnerabilityResultDTO();
List<ComponentParseRecord> recordList = componentParseRecordMapper.quaryByProjectId(projectId);
if (recordList.size() <= 0){
return result;
}
ComponentParseRecord newRecord = recordList.get(0);
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setComponentId(newRecord.getId());
List<ProjectVulnerabilityDetail> details = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
result.setTotal((long)details.size());
for (ProjectVulnerabilityDetail detail : details) {
switch (detail.getRiskLevel()) {
case 1:
result.setLow(result.getLow() + 1);
break;
case 2:
result.setMiddle(result.getMiddle() + 1);
break;
case 3:
result.setHigh(result.getHigh() + 1);
break;
case 4:
result.setCritical(result.getCritical() + 1);
break;
default:
break;
}
}
return result;
}
/**
* 通过组件检测记录id获取漏洞指标
* @param componentId
* @return
*/
public VulnerabilityResultDTO getVulnerabilityByComponentId(Long componentId) {
VulnerabilityResultDTO result = new VulnerabilityResultDTO();
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setComponentId(componentId);
List<ProjectVulnerabilityDetail> details = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
result.setTotal((long)details.size());
for (ProjectVulnerabilityDetail detail : details) {
switch (detail.getRiskLevel()) {
case 1:
result.setLow(result.getLow() + 1);
break;
case 2:
result.setMiddle(result.getMiddle() + 1);
break;
case 3:
result.setHigh(result.getHigh() + 1);
break;
case 4:
result.setCritical(result.getCritical() + 1);
break;
default:
break;
}
}
return result;
}
/**
* 上一次组件漏洞检测结果
* @param projectId
* @return
*/
public VulnerabilityResultDTO getOldComponentVulnerability(Long projectId) {
List<ComponentParseRecord> recordList = componentParseRecordMapper.quaryByProjectId(projectId);
VulnerabilityResultDTO vulnerability;
if (recordList.size() <= 1){
vulnerability = new VulnerabilityResultDTO();
}else {
Long oldComponentId = recordList.get(1).getId();
vulnerability = getVulnerabilityByComponentId(oldComponentId);
}
return vulnerability;
}
/**
* 获取缺陷指标
*

View File

@ -1,6 +1,7 @@
package net.educoder.quality.task;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.educoder.quality.common.bean.ShellResult;
@ -16,6 +17,8 @@ import org.springframework.util.StopWatch;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: youys
@ -35,7 +38,39 @@ public class SonarDetectionRunnable implements Runnable {
@Override
public void run() {
// 2023-2-22 .net分支
if (sonarScannerParam.getLanguage().equalsIgnoreCase(QualityConstants.NET)) {
log.info("taskId:{},开始执行sonar.net扫描任务", sonarScannerParam.getTaskId());
// 需要调用接口
String donetSonarServer = sonarScannerParam.getDonetSonarServer();
sonarScannerParam.setProjectKey(sonarScannerParam.getTaskInfo().getProjectName() + "-" + sonarScannerParam.getTaskInfo().getRandomStr());
Map<String, Object> requestMap = new HashMap<>(8);
requestMap.put("gitUrl", sonarScannerParam.getProjects().getGitUrl());
requestMap.put("branch", sonarScannerParam.getProjects().getBranch());
requestMap.put("taskId", sonarScannerParam.getTaskId());
requestMap.put("projectKey", sonarScannerParam.getProjectKey());
long start = System.currentTimeMillis();
String response = HttpUtil.post(donetSonarServer, requestMap);
log.info("taskId:{} .net请求sonar服务耗时:{}, 结果:{}", sonarScannerParam.getTaskId(), (System.currentTimeMillis() - start), response);
JSONObject jsonObject = JSONObject.parseObject(response);
if (ErrorCodeEnum.SUCCESS.getValue().equalsIgnoreCase(jsonObject.getString("code"))){
JSONObject results = jsonObject.getJSONObject("results");
SonarDetectionQueryResultRunnable queryResultRunnable = new SonarDetectionQueryResultRunnable(
sonarScannerParam.getProjectKey(), sonarScannerParam.getTaskId(), results.getInteger("fileNum"), results.getString("fileSize"));
sonarScannerParam.getSonarQueryResultThreadPool().execute(queryResultRunnable);
}else{
SonarDetectionQueryResultRunnable queryResultRunnable = new SonarDetectionQueryResultRunnable(
sonarScannerParam.getProjectKey(), sonarScannerParam.getTaskId(), 0, "0k");
sonarScannerParam.getSonarQueryResultThreadPool().execute(queryResultRunnable);
}
return;
}
log.info("taskId:{},开始执行sonar扫描任务", sonarScannerParam.getTaskId());
StopWatch stopWatch = new StopWatch();
stopWatch.start();
@ -64,12 +99,11 @@ public class SonarDetectionRunnable implements Runnable {
// 提交查询结果任务
SonarDetectionQueryResultRunnable queryResultRunnable = new SonarDetectionQueryResultRunnable(
sonarScannerParam.getProjectKey(), sonarScannerParam.getTaskId(), getDirectoryFilesNum(fullWorkspace),
getDirectoryFileSize(fullWorkspace,sonarScannerParam.getProjects().getProjectName()));
getDirectoryFileSize(fullWorkspace, sonarScannerParam.getProjects().getProjectName()));
sonarScannerParam.getSonarQueryResultThreadPool().execute(queryResultRunnable);
// 清空引用
flushAllReference(sonarScannerParam);
}
@ -132,7 +166,7 @@ public class SonarDetectionRunnable implements Runnable {
* @return
*/
private String getDirectoryFileSize(String path, String directoryName) {
String command = StringUtils.join("cd ", path, " && du -sh ", directoryName, " | awk -F ' ' '{print $1}'");
String command = StringUtils.join("cd ", path, "&& cd `ls` && du -sh . | awk -F ' ' '{print $1}'");
ShellResult shellResult = ShellUtil.executeAndGetExitStatus(command);
log.info("获取目录文件大小返回command:{},result:{} ", command, JSONObject.toJSONString(shellResult));
@ -156,9 +190,7 @@ public class SonarDetectionRunnable implements Runnable {
private void gitClone(String fullWorkspace) {
// 拉代码
String gitUrl = sonarScannerParam.getProjects().getGitUrl();
// TODO 暂时为了测试
int index = gitUrl.replaceAll("localhost:43001","118.31.13.117:64300").lastIndexOf("//");
// int index = gitUrl.lastIndexOf("//");
int index = gitUrl.lastIndexOf("//");
String command = StringUtils.join("cd ", fullWorkspace, " && git clone -b ", sonarScannerParam.getProjects().getBranch(), " ", gitUrl.substring(0, index + 2), sonarScannerParam.getGitUsername(), ":",
sonarScannerParam.getGitPassword(), "@", gitUrl.substring(index + 2));
@ -181,4 +213,5 @@ public class SonarDetectionRunnable implements Runnable {
ProjectDetectionTaskInfo taskInfo = sonarScannerParam.getTaskInfo();
sonarScannerParam.setProjectKey(taskInfo.getProjectName() + "-" + taskInfo.getRandomStr());
}
}

View File

@ -12,4 +12,6 @@ public class AddCloneDetectionVO {
private String targetRepoUsername;
private String targetRepoPassword;
private String targetRepoBranch;
}

View File

@ -17,4 +17,6 @@ public class AddProjectVO extends CommonVO {
@NotBlank(message = "gitUrl不能为空")
private String gitUrl;
private String language = "";
}

View File

@ -22,4 +22,9 @@ public class CreateTemplateVO extends CommonVO {
private String codingStandard;
private String securityDetection;
/**
* 依赖函数库
*/
private String dependFunction;
}

View File

@ -23,4 +23,6 @@ public class DetectionVO extends CommonVO {
*/
@NotNull(message = "模板id不能为空")
private Long templateId;
private Integer type;
}

View File

@ -26,4 +26,9 @@ public class UpdateTemplateVO extends CommonVO {
private String codingStandard;
private String securityDetection;
/**
* 依赖函数库
*/
private String dependFunction;
}

View File

@ -1,15 +1,25 @@
# git账号密码
openi:
gitUsername: root
gitPassword: edu_123123
gitUsername: wangwei
gitPassword: zq123456
# sonar相关配置
sonar:
# serverUrl: http://117.50.14.123:9000
serverUrl: http://127.0.0.1:9000
workspace: /opt/workspace
workspace: /tmp/workspace
donet:
serverUrl: http://139.159.227.131:7788/donet/sonar/scan
sast:
driver: sshpass -pWk_20230306wk ssh -p40022 -o StrictHostKeyChecking=no root@118.178.181.154 'source /etc/profile; /home/wukong/docroot/wk/wukong-driver
download:
tempDir: /tmp/quality
# opensca-cli命令路径
opensca-cli:
#path: /data/ww/open-cli/opensca-cli
path: /Users/youyongsheng/Downloads/opensca-cli_v1.0.9_Darwin_x86_64/opensca-cli
nil:
jarPath: /Users/weiwang/IdeaProjects/NIL/build/libs/NIL-all.jar
mil: 6
mit: 50
filtrationThreshold: 10
verificationThreshold: 70

View File

@ -40,6 +40,36 @@ spring:
test-on-borrow: false
test-on-return: false
test-while-idle: true
# gitea数据库
gitea:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://118.31.13.117:55432/opendata
username: postgres
password: Edu_123123pos
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 20
max-active: 40
min-idle: 20
validation-query: select 1
test-on-borrow: false
test-on-return: false
test-while-idle: true
# sast
sast:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://118.178.181.154:43306/zktq_wukong?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
username: root
password: Wk_20230306wk
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 20
max-active: 40
min-idle: 20
validation-query: select 1
test-on-borrow: false
test-on-return: false
test-while-idle: true
# redis配置
redis:
host: 127.0.0.1
@ -72,3 +102,4 @@ pagehelper:
reasonable: true
support-methods-arguments: true
params: count=countSql
auto-runtime-dialect: true

View File

@ -0,0 +1,12 @@
<?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.educoder.quality.mapper.gitea.PgCodeLicenseMapper">
<select id="selectByName" resultType="net.educoder.quality.entity.gitea.PgCodeLicense">
select
id,name, risk_level riskLevel, version, create_time createTime, content, description,public_url publicUrl
from code_license where name like CONCAT(#{name,jdbcType=VARCHAR},'%') limit 1
</select>
</mapper>

View File

@ -1,26 +0,0 @@
<?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.educoder.quality.mapper.mysql.CloneDetectionResultFileCodeLevelMapper" >
<resultMap id="BaseResultMap" type="net.educoder.quality.entity.mysql.CloneDetectionResultFileCodeLevel" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="INTEGER" />
<result column="project_id" property="projectId" jdbcType="BIGINT" />
<result column="source_file_path" property="sourceFilePath" jdbcType="VARCHAR" />
<result column="source_file_start_line" property="sourceFileStartLine" jdbcType="INTEGER" />
<result column="source_file_end_line" property="sourceFileEndLine" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
<result column="target_file_path" property="targetFilePath" jdbcType="VARCHAR" />
<result column="target_file_start_line" property="targetFileStartLine" jdbcType="INTEGER" />
<result column="target_file_end_line" property="targetFileEndLine" jdbcType="INTEGER" />
<result column="common_source_percent" property="commonSourcePercent" jdbcType="VARCHAR" />
<result column="common_source_line" property="commonSourceLine" jdbcType="VARCHAR" />
<result column="clone_detection_id" property="cloneDetectionId" jdbcType="BIGINT" />
<result column="target_project_name" property="targetProjectName" jdbcType="VARCHAR" />
<result column="target_project_url" property="targetProjectUrl" jdbcType="VARCHAR" />
<result column="source_file_code" property="sourceFileCode" jdbcType="LONGVARCHAR" />
<result column="target_file_code" property="targetFileCode" jdbcType="LONGVARCHAR" />
</resultMap>
</mapper>

View File

@ -1,18 +0,0 @@
<?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.educoder.quality.mapper.mysql.CloneDetectionResultProjectLevelMapper" >
<resultMap id="BaseResultMap" type="net.educoder.quality.entity.mysql.CloneDetectionResultProjectLevel" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="INTEGER" />
<result column="clone_detection_id" property="cloneDetectionId" jdbcType="BIGINT" />
<result column="similarity_file_percent" property="similarityFilePercent" jdbcType="DOUBLE" />
<result column="similarity_file" property="similarityFile" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
<result column="project_id" property="projectId" jdbcType="BIGINT" />
<result column="target_project_name" property="targetProjectName" jdbcType="VARCHAR" />
<result column="target_project_url" property="targetProjectUrl" jdbcType="VARCHAR" />
</resultMap>
</mapper>

View File

@ -0,0 +1,11 @@
<?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.educoder.quality.mapper.mysql.ComponentLibraryMapper">
<select id="selectByComponentName" parameterType="java.lang.String" resultType="net.educoder.quality.entity.mysql.ComponentLibrary">
select
id,language,component_name componentName,short_name shortName,license,create_time createTime,home_url homeUrl
from component_library where component_name=#{componentName,jdbcType=VARCHAR}
</select>
</mapper>

View File

@ -0,0 +1,38 @@
<?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.educoder.quality.mapper.mysql.ComponentParseRecordDetailMapper">
<select id="queryByComponentId" resultType="net.educoder.quality.dto.ComponentParseRecordDetailDTO">
select
cprd.id,
cprd.component_id componentId,
cprd.component_name componentName,
cprd.language,
cprd.risk_level riskLevel,
cprd.vulnerability,
cprd.version,
cprd.depend_way dependWay,
cprd.depend_path dependPath,
cprd.create_time createTime,
cprd.update_time updateTime,
cprd.uuid,
cprd.parent_uuid,
cprd.vulnerabilities,
(select count(1) from component_parse_record_detail where parent_uuid= cprd.uuid) dependNum
from component_parse_record_detail cprd where component_id=#{componentId}
</select>
<select id="queryDependComponentList" resultType="net.educoder.quality.dto.DependComponentDTO">
select
component_name componentName,
version,
depend_path dependPath
from component_parse_record_detail where parent_uuid=#{uuid,jdbcType=VARCHAR}
</select>
<select id="countDependComponentsByComponentId" resultType="java.lang.Integer">
select count(1) from component_parse_record_detail where component_id=#{componentId}
</select>
</mapper>

View File

@ -0,0 +1,27 @@
<?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.educoder.quality.mapper.mysql.ComponentParseRecordMapper">
<select id="getByProjectId" resultType="net.educoder.quality.entity.mysql.ComponentParseRecord">
select
id,project_id,result
from
component_parse_record
where
project_id=#{projectId}
order by
create_time desc
limit 1
</select>
<select id="quaryByProjectId" resultType="net.educoder.quality.entity.mysql.ComponentParseRecord">
select
id,project_id,result
from
component_parse_record
where
project_id=#{projectId}
order by
create_time desc
</select>
</mapper>

View File

@ -0,0 +1,4 @@
<?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.educoder.quality.mapper.mysql.ProjectVulnerabilityDetailMapper">
</mapper>

View File

@ -0,0 +1,15 @@
<?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.educoder.quality.mapper.mysql.ProjectsMapper">
<select id="getByName" resultType="net.educoder.quality.entity.mysql.Projects">
select
id,project_name,branch,git_url
from
projects
where
project_name=#{projectName}
order by create_time desc
limit 1
</select>
</mapper>

View File

@ -0,0 +1,33 @@
<?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.educoder.quality.mapper.mysql.SastAnalysisDetailMapper" >
<resultMap id="BaseResultMap" type="net.educoder.quality.entity.mysql.SastAnalysisDetail" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="BIGINT" />
<result column="bug_catalog" property="bugCatalog" jdbcType="VARCHAR" />
<result column="parent_bug_catalog" property="parentBugCatalog" jdbcType="VARCHAR" />
<result column="bug_no" property="bugNo" jdbcType="VARCHAR" />
<result column="bug_name" property="bugName" jdbcType="VARCHAR" />
<result column="parent_bug_no" property="parentBugNo" jdbcType="VARCHAR" />
<result column="bug_type" property="bugType" jdbcType="VARCHAR" />
<result column="bug_type_name" property="bugTypeName" jdbcType="VARCHAR" />
<result column="bug_level" property="bugLevel" jdbcType="CHAR" />
<result column="frequent_result_keyword" property="frequentResultKeyword" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
<result column="project_id" property="projectId" jdbcType="BIGINT" />
<result column="task_id" property="taskId" jdbcType="VARCHAR" />
<result column="synopsis" property="synopsis" jdbcType="LONGVARCHAR" />
<result column="description" property="description" jdbcType="LONGVARCHAR" />
<result column="frequent_result" property="frequentResult" jdbcType="LONGVARCHAR" />
<result column="repair_opinion" property="repairOpinion" jdbcType="LONGVARCHAR" />
<result column="example" property="example" jdbcType="LONGVARCHAR" />
<result column="error_example" property="errorExample" jdbcType="LONGVARCHAR" />
<result column="method_name" property="methodName" jdbcType="VARCHAR" />
<result column="variable" property="variable" jdbcType="VARCHAR" />
<result column="line" property="line" jdbcType="INTEGER" />
<result column="file_path" property="filePath" jdbcType="VARCHAR" />
</resultMap>
</mapper>

Binary file not shown.

View File

@ -5,7 +5,11 @@
<!-- 根据项目名称查询issue列表 -->
<select id="findByName" parameterType="java.lang.String"
resultType="net.educoder.quality.entity.postgres.PgProjects">
select id,enabled,project_uuid projectUuid from projects where name=#{projectName}
select
id,enabled,project_uuid projectUuid
from projects
where name=#{projectName}
limit 1
</select>
<!-- 分页查询 -->

View File

@ -0,0 +1,57 @@
<?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.educoder.quality.mapper.sast.BizKnowledgeBugMapper">
<resultMap id="BaseResultMap" type="net.educoder.quality.entity.sast.BizKnowledgeBug">
<!--
WARNING - @mbg.generated
-->
<id column="OID_KNOWLEDGE_BUG_ID" jdbcType="VARCHAR" property="oidKnowledgeBugId"/>
<result column="OID_KNOWLEDGE_CATALOG_ID" jdbcType="VARCHAR" property="oidKnowledgeCatalogId"/>
<result column="BUG_NO" jdbcType="VARCHAR" property="bugNo"/>
<result column="BUG_NAME" jdbcType="VARCHAR" property="bugName"/>
<result column="PARENT_BUG_NO" jdbcType="VARCHAR" property="parentBugNo"/>
<result column="BUG_TYPE" jdbcType="VARCHAR" property="bugType"/>
<result column="BUG_TYPE_NAME" jdbcType="VARCHAR" property="bugTypeName"/>
<result column="BUG_LEVEL" jdbcType="CHAR" property="bugLevel"/>
<result column="FREQUENT_RESULT_KEYWORD" jdbcType="VARCHAR" property="frequentResultKeyword"/>
<result column="DEL_FLG" jdbcType="CHAR" property="delFlg"/>
<result column="INS_USER_ID" jdbcType="VARCHAR" property="insUserId"/>
<result column="INS_DATE" jdbcType="TIMESTAMP" property="insDate"/>
<result column="UPD_USER_ID" jdbcType="VARCHAR" property="updUserId"/>
<result column="UPD_DATE" jdbcType="TIMESTAMP" property="updDate"/>
<result column="SYNOPSIS" jdbcType="LONGVARCHAR" property="synopsis"/>
<result column="DESCRIPTION" jdbcType="LONGVARCHAR" property="description"/>
<result column="FREQUENT_RESULT" jdbcType="LONGVARCHAR" property="frequentResult"/>
<result column="REPAIR_OPINION" jdbcType="LONGVARCHAR" property="repairOpinion"/>
<result column="EXAMPLE" jdbcType="LONGVARCHAR" property="example"/>
<result column="ERROR_EXAMPLE" jdbcType="LONGVARCHAR" property="errorExample"/>
</resultMap>
<select id="selectBugAndCatalogByTypes" resultType="net.educoder.quality.entity.sast.BizKnowledgeBug"
parameterType="java.util.ArrayList">
select bug.BUG_NO as bugNo,
bug.BUG_NAME as bugName,
bug.BUG_TYPE as bugType,
bug.BUG_TYPE_NAME as bugTypeName,
bug.BUG_LEVEL as bugLevel,
bug.FREQUENT_RESULT_KEYWORD as frequentResultKeyword,
bug.INS_DATE as insDate,
bug.SYNOPSIS as synopsis,
bug.DESCRIPTION as description,
bug.FREQUENT_RESULT as frequentResult,
bug.REPAIR_OPINION as repairOpinion,
bug.EXAMPLE as example,
bug.ERROR_EXAMPLE as errorExample,
cata.FULL_NAME as bugCatalog,
catap.FULL_NAME as parentBugCatalog
from biz_knowledge_bug bug left join biz_knowledge_catalog cata on
bug.OID_KNOWLEDGE_CATALOG_ID = cata.OID_KNOWLEDGE_CATALOG_ID
left join biz_knowledge_catalog catap on cata.PARENT_ID = catap.OID_KNOWLEDGE_CATALOG_ID
<where>
bug.BUG_TYPE in (
<foreach collection="list" item="type" index="index" separator=",">
#{type}
</foreach>
)
</where>
</select>
</mapper>

View File

@ -0,0 +1,48 @@
package net.educoder.quality;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class JSoupTest {
@Test
void test() throws IOException {
String header =
"accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\n" +
"accept-encoding: gzip, deflate, br\n" +
"accept-language: en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7,en-GB;q=0.6\n" +
"cache-control: max-age=0\n" +
"cookie: _ga=GA1.2.1335229334.1671194394; _gid=GA1.2.756675881.1673512957; cf_chl_2=00e3704b29aedc9; cf_clearance=Omt_2Ep1h2..saIgujJFkc3aLFR1b0Zn35Tf2UnwrsY-1673519471-0-160; __cf_bm=TyoiBbX9GXnbnW28253pnebIRbLw.UF10ysjom5WHQU-1673519472-0-AUSXj38lQAt3l83Z3la4yrOVg9emwHeHtT4uFP6EhQIiF8JNEU3R1yIdlmp4UgmkDq8fL6zsMlZgupURpEbnLXbk8ATcHnRlam9EvhSLv06BDRk9Wg41kvhjlm7M0r8VE+wCgreMT/ZoDCLuYU/MqSBYQtSWRrRsc9tV5hINIAMkxtK6mWqpoQGYVMPeFZb7Pw==; MVN_SESSION=eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVpZCI6ImJjZGJhOGYwLTdkM2UtMTFlZC04YzllLTIzY2NhMGMzNWZkZiJ9LCJleHAiOjE3MDUwNTYwMzQsIm5iZiI6MTY3MzUyMDAzNCwiaWF0IjoxNjczNTIwMDM0fQ.J1q2U3-pVVebD8B3L1F2lJ2p1Pw2d74NAadkBr-riUc; _gat=1\n" +
"referer: https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher\n" +
"sec-ch-ua: \"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"\n" +
"sec-ch-ua-mobile: ?0\n" +
"sec-ch-ua-platform: \"macOS\"\n" +
"sec-fetch-dest: document\n" +
"sec-fetch-mode: navigate\n" +
"sec-fetch-site: same-origin\n" +
"sec-fetch-user: ?1\n" +
"upgrade-insecure-requests: 1\n" +
"user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36";
Map<String, String> headerMap = new HashMap<>();
String[] split = header.split("\n");
for (String item : split) {
String[] kv = item.trim().split(": ");
headerMap.put(kv[0].trim(), kv[1].trim());
}
Document post = Jsoup.connect("https://mvnrepository.com/")
.headers(
headerMap
)
.header("Content-Type","application/x-www-form-urlencoded")
.timeout(3000)
.get();
System.out.printf(post.title());
System.out.print(post.html());
}
}

View File

@ -1,12 +1,32 @@
package net.educoder.quality;
import cn.hutool.core.date.DateUtil;
import net.educoder.quality.common.util.WordUtil;
import net.educoder.quality.dto.ReportDetailDTO;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.entity.mysql.ReportCenter;
import net.educoder.quality.entity.postgres.PgIssues;
import net.educoder.quality.entity.postgres.PgProjects;
import net.educoder.quality.mapper.mysql.TestMapper;
import net.educoder.quality.mapper.postgres.PgProjectMapper;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.service.ReportCenterService;
import net.educoder.quality.service.postgres.PgProjectsService;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.ServletOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: youys
* @Date: 2022/9/13
@ -20,6 +40,16 @@ public class MapperTest {
public TestMapper testMapper;
@Autowired
private ReportCenterService reportCenterService;
@Autowired
private ProjectService projectService;
@Autowired
private PgProjectsService pgProjectsService;
@Test
@Transactional
public void testInsert(){
@ -28,4 +58,36 @@ public class MapperTest {
int i=1/0;
}
@Test
public void testS() throws Exception {
Long reportId = 5L;
ReportCenter reportCenter = reportCenterService.reportCenterDetail(reportId);
Projects projects = projectService.getProjectById(reportCenter.getProjectId());
// 获取模板填充数据
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("template/report-center-template.docx");
ReportDetailDTO reportDetail = pgProjectsService.getReportDetail(projects.getProjectName());
Map<String, String> param = new HashMap<>(13);
param.put("projectName", projects.getProjectName());
param.put("createTime", DateUtil.formatDateTime(new Date()));
param.put("issueCount",String.valueOf(reportDetail.getBugCount().getTotal()));
param.put("seriousIssueCount",String.valueOf(reportDetail.getBugCount().getCritical()));
param.put("highRiskIssueCount",String.valueOf(reportDetail.getBugCount().getHigh()));
param.put("midRiskIssueCount",String.valueOf(reportDetail.getBugCount().getMiddle()));
param.put("lowRiskIssueCount",String.valueOf(reportDetail.getBugCount().getLow()));
param.put("componentCount",String.valueOf(reportDetail.getComponents()));
param.put("componentBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getTotal()));
param.put("seriousBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getCritical()));
param.put("highRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getHigh()));
param.put("midRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getMiddle()));
param.put("lowRiskBugCount",String.valueOf(reportDetail.getVulnerabilityCount().getLow()));
XWPFDocument doc = new XWPFDocument(resourceAsStream);
WordUtil.changeText(doc, param);
pgProjectsService.fillReportTable(doc,reportDetail);
WordUtil.save(doc,"C:\\Users\\14666\\Desktop\\res004.docx");
}
}