refactor: 新增Common包的单元测试
This commit is contained in:
@@ -47,6 +47,18 @@
|
||||
<artifactId>agileboot-domain</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.agileboot.common.exception.ApiException;
|
||||
import com.agileboot.common.exception.error.ErrorCode;
|
||||
import com.agileboot.common.utils.ServletHolderUtil;
|
||||
import com.agileboot.common.utils.file.FileUploadUtils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -50,7 +51,7 @@ public class FileController {
|
||||
}
|
||||
|
||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
||||
String filePath = AgileBootConfig.getDownloadPath() + fileName;
|
||||
String filePath = AgileBootConfig.getDownloadPath() + File.separator + fileName;
|
||||
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.agileboot.admin.config;
|
||||
|
||||
|
||||
import com.agileboot.admin.AgileBooAdminApplication;
|
||||
import com.agileboot.common.config.AgileBootConfig;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@SpringBootTest(classes = AgileBooAdminApplication.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
public class AgileBootConfigTest {
|
||||
|
||||
@Autowired
|
||||
private AgileBootConfig config;
|
||||
|
||||
@Test
|
||||
public void testConfig() {
|
||||
|
||||
String fileBaseDir = "D:\\agileboot\\uploadPath";
|
||||
|
||||
Assertions.assertEquals("AgileBoot", config.getName());
|
||||
Assertions.assertEquals("1.0.0", config.getVersion());
|
||||
Assertions.assertEquals("2022", config.getCopyrightYear());
|
||||
Assertions.assertEquals(true, config.isDemoEnabled());
|
||||
Assertions.assertEquals(fileBaseDir, AgileBootConfig.getFileBaseDir());
|
||||
Assertions.assertEquals(false, AgileBootConfig.isAddressEnabled());
|
||||
Assertions.assertEquals("math", AgileBootConfig.getCaptchaType());
|
||||
Assertions.assertEquals("math", AgileBootConfig.getCaptchaType());
|
||||
Assertions.assertEquals(fileBaseDir + "\\import", AgileBootConfig.getImportPath());
|
||||
Assertions.assertEquals(fileBaseDir + "\\avatar", AgileBootConfig.getAvatarPath());
|
||||
Assertions.assertEquals(fileBaseDir + "\\download", AgileBootConfig.getDownloadPath());
|
||||
Assertions.assertEquals(fileBaseDir + "\\upload", AgileBootConfig.getUploadPath());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -161,6 +161,12 @@
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
package com.agileboot.common.config;
|
||||
|
||||
import com.agileboot.common.constant.Constants.UploadDir;
|
||||
import java.io.File;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 读取项目相关配置
|
||||
*
|
||||
* @author ruoyi
|
||||
* @author valarchie
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "agileboot")
|
||||
@Data
|
||||
public class AgileBootConfig {
|
||||
|
||||
/**
|
||||
@@ -35,7 +39,7 @@ public class AgileBootConfig {
|
||||
/**
|
||||
* 上传路径
|
||||
*/
|
||||
private static String profile;
|
||||
private static String fileBaseDir;
|
||||
|
||||
/**
|
||||
* 获取地址开关
|
||||
@@ -52,44 +56,12 @@ public class AgileBootConfig {
|
||||
*/
|
||||
private static String rsaPrivateKey;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
public static String getFileBaseDir() {
|
||||
return fileBaseDir;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getCopyrightYear() {
|
||||
return copyrightYear;
|
||||
}
|
||||
|
||||
public void setCopyrightYear(String copyrightYear) {
|
||||
this.copyrightYear = copyrightYear;
|
||||
}
|
||||
|
||||
public boolean isDemoEnabled() {
|
||||
return demoEnabled;
|
||||
}
|
||||
|
||||
public void setDemoEnabled(boolean demoEnabled) {
|
||||
this.demoEnabled = demoEnabled;
|
||||
}
|
||||
|
||||
public static String getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
public void setProfile(String profile) {
|
||||
AgileBootConfig.profile = profile;
|
||||
public void setFileBaseDir(String fileBaseDir) {
|
||||
AgileBootConfig.fileBaseDir = fileBaseDir;
|
||||
}
|
||||
|
||||
public static boolean isAddressEnabled() {
|
||||
@@ -120,27 +92,27 @@ public class AgileBootConfig {
|
||||
* 获取导入上传路径
|
||||
*/
|
||||
public static String getImportPath() {
|
||||
return getProfile() + "/import";
|
||||
return getFileBaseDir() + File.separator + UploadDir.IMPORT_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取头像上传路径
|
||||
*/
|
||||
public static String getAvatarPath() {
|
||||
return getProfile() + "/avatar";
|
||||
return getFileBaseDir() + File.separator + UploadDir.AVATAR_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载路径
|
||||
*/
|
||||
public static String getDownloadPath() {
|
||||
return getProfile() + "/download/";
|
||||
return getFileBaseDir() + File.separator + UploadDir.DOWNLOAD_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传路径
|
||||
*/
|
||||
public static String getUploadPath() {
|
||||
return getProfile() + "/upload";
|
||||
return getFileBaseDir() + File.separator + UploadDir.UPLOAD_PATH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,18 @@ public class Constants {
|
||||
|
||||
}
|
||||
|
||||
public static class UploadDir {
|
||||
|
||||
public static final String IMPORT_PATH = "import";
|
||||
|
||||
public static final String AVATAR_PATH = "avatar";
|
||||
|
||||
public static final String DOWNLOAD_PATH = "download";
|
||||
|
||||
public static final String UPLOAD_PATH = "upload";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ import com.agileboot.common.utils.i18n.MessageUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 统一异常类
|
||||
* @author valarchie
|
||||
*/
|
||||
@Slf4j
|
||||
public class ApiException extends RuntimeException{
|
||||
|
||||
|
||||
protected ErrorCodeInterface errorCode;
|
||||
|
||||
protected String message;
|
||||
@@ -26,11 +26,6 @@ public class ApiException extends RuntimeException{
|
||||
fillErrorCode(errorCode, args);
|
||||
}
|
||||
|
||||
public ApiException(Throwable e, ErrorCodeInterface errorCode) {
|
||||
super(e);
|
||||
fillErrorCode(errorCode);
|
||||
}
|
||||
|
||||
public ApiException(ErrorCodeInterface errorCode, Object... args) {
|
||||
fillErrorCode(errorCode, args);
|
||||
}
|
||||
@@ -46,7 +41,6 @@ public class ApiException extends RuntimeException{
|
||||
|
||||
this.formattedMessage = StrUtil.format(this.message, args);
|
||||
|
||||
// TODO 错误码的 i18n 信息 应该做成缓存
|
||||
try {
|
||||
this.i18nFormattedMessage = MessageUtils.message(errorCode.i18nKey(), args);
|
||||
} catch (Exception e) {
|
||||
@@ -55,7 +49,6 @@ public class ApiException extends RuntimeException{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ErrorCodeInterface getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
/**
|
||||
* 文件上传工具类
|
||||
*
|
||||
* @author ruoyi 待改进
|
||||
* @author valarchie
|
||||
*/
|
||||
public class FileUploadUtils {
|
||||
|
||||
@@ -35,9 +35,9 @@ public class FileUploadUtils {
|
||||
public static final long MAX_FILE_SIZE = 50 * Constants.MB;
|
||||
|
||||
/**
|
||||
* 默认的文件名最大长度 100
|
||||
* 默认的文件名最大长度 127
|
||||
*/
|
||||
public static final int MAX_FILE_NAME_LENGTH = 100;
|
||||
public static final int MAX_FILE_NAME_LENGTH = 127;
|
||||
|
||||
public static final String[] ALLOWED_DOWNLOAD_EXTENSIONS = {
|
||||
// 图片
|
||||
@@ -51,29 +51,6 @@ public class FileUploadUtils {
|
||||
// pdf
|
||||
"pdf"};
|
||||
|
||||
/**
|
||||
* 默认上传的地址
|
||||
*/
|
||||
private static String defaultBaseDir = AgileBootConfig.getProfile();
|
||||
|
||||
|
||||
public static String getDefaultBaseDir() {
|
||||
return defaultBaseDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* 以默认配置进行文件上传
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @return 文件名称
|
||||
*/
|
||||
public static String upload(MultipartFile file) throws IOException {
|
||||
try {
|
||||
return upload(getDefaultBaseDir(), file, ALLOWED_DOWNLOAD_EXTENSIONS);
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件路径上传
|
||||
@@ -101,17 +78,11 @@ public class FileUploadUtils {
|
||||
*/
|
||||
public static String upload(String baseDir, MultipartFile file, String[] allowedExtension)
|
||||
throws IOException {
|
||||
|
||||
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
|
||||
if (fileNameLength > FileUploadUtils.MAX_FILE_NAME_LENGTH) {
|
||||
throw new ApiException(ErrorCode.Business.UPLOAD_FILE_NAME_EXCEED_MAX_LENGTH, MAX_FILE_NAME_LENGTH);
|
||||
}
|
||||
|
||||
assertAllowed(file, allowedExtension);
|
||||
|
||||
String fileName = generateFilename(file);
|
||||
|
||||
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
|
||||
String absPath = getAbsoluteFilePath(baseDir, fileName).getAbsolutePath();
|
||||
file.transferTo(Paths.get(absPath));
|
||||
return getPathFileName(baseDir, fileName);
|
||||
}
|
||||
@@ -120,11 +91,20 @@ public class FileUploadUtils {
|
||||
* 编码文件名
|
||||
*/
|
||||
public static String generateFilename(MultipartFile file) {
|
||||
return StrUtil.format("{}_{}_{}.{}", DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN),
|
||||
FilenameUtils.getBaseName(file.getOriginalFilename()), IdUtil.simpleUUID(), getExtension(file));
|
||||
return StrUtil.format("{}_{}_{}.{}",
|
||||
DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN),
|
||||
FilenameUtils.getBaseName(file.getOriginalFilename()),
|
||||
IdUtil.simpleUUID(),
|
||||
getExtension(file));
|
||||
}
|
||||
|
||||
public static File getAbsoluteFile(String uploadDir, String fileName) {
|
||||
/**
|
||||
* 获取上传文件的路径
|
||||
* @param uploadDir 长传的文件夹
|
||||
* @param fileName
|
||||
* @return
|
||||
*/
|
||||
public static File getAbsoluteFilePath(String uploadDir, String fileName) {
|
||||
File desc = new File(uploadDir + File.separator + fileName);
|
||||
if (!desc.exists()) {
|
||||
if (!desc.getParentFile().exists()) {
|
||||
@@ -135,8 +115,8 @@ public class FileUploadUtils {
|
||||
}
|
||||
|
||||
public static String getPathFileName(String uploadDir, String fileName) {
|
||||
String currentDir = StrUtil.strip(uploadDir, AgileBootConfig.getProfile() + "/");
|
||||
return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
|
||||
String currentDir = StrUtil.strip(uploadDir, AgileBootConfig.getFileBaseDir() + File.separator);
|
||||
return Constants.RESOURCE_PREFIX + File.separator + currentDir + File.separator + fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,6 +125,12 @@ public class FileUploadUtils {
|
||||
* @param file 上传的文件
|
||||
*/
|
||||
public static void assertAllowed(MultipartFile file, String[] allowedExtension) {
|
||||
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
|
||||
|
||||
if (fileNameLength > FileUploadUtils.MAX_FILE_NAME_LENGTH) {
|
||||
throw new ApiException(ErrorCode.Business.UPLOAD_FILE_NAME_EXCEED_MAX_LENGTH, MAX_FILE_NAME_LENGTH);
|
||||
}
|
||||
|
||||
long size = file.getSize();
|
||||
if (size > MAX_FILE_SIZE) {
|
||||
throw new ApiException(ErrorCode.Business.UPLOAD_FILE_SIZE_EXCEED_MAX_SIZE, MAX_FILE_SIZE / Constants.MB);
|
||||
@@ -155,7 +141,6 @@ public class FileUploadUtils {
|
||||
throw new ApiException(ErrorCode.Business.UPLOAD_FILE_TYPE_NOT_ALLOWED,
|
||||
StrUtil.join(",", (Object[]) allowedExtension));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,10 +35,12 @@ public class OfflineIpRegionUtil {
|
||||
public static IpRegion getIpRegion(String ip) {
|
||||
try {
|
||||
|
||||
if (StrUtil.isBlank(ip) || IPAddressUtil.isIPv6LiteralAddress(ip)) {
|
||||
if (StrUtil.isBlank(ip) || IPAddressUtil.isIPv6LiteralAddress(ip)
|
||||
|| !IPAddressUtil.isIPv4LiteralAddress(ip)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
String rawRegion = searcher.search(ip);
|
||||
|
||||
if (StrUtil.isEmpty(rawRegion)) {
|
||||
|
||||
@@ -24,7 +24,7 @@ public class OnlineIpRegionUtil {
|
||||
|
||||
|
||||
public static IpRegion getIpRegion(String ip) {
|
||||
if(StrUtil.isBlank(ip) || IPAddressUtil.isIPv6LiteralAddress(ip)) {
|
||||
if(StrUtil.isBlank(ip) || IPAddressUtil.isIPv6LiteralAddress(ip) || !IPAddressUtil.isIPv4LiteralAddress(ip)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,12 @@ import com.agileboot.common.annotation.ExcelSheet;
|
||||
import com.agileboot.common.exception.ApiException;
|
||||
import com.agileboot.common.exception.error.ErrorCode.Internal;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
@@ -20,12 +23,30 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
public class CustomExcelUtil {
|
||||
|
||||
|
||||
public static void writeToResponse(List<?> list, Class clazz, HttpServletResponse response) {
|
||||
public static void writeToResponse(List<?> list, Class<?> clazz, HttpServletResponse response) {
|
||||
try {
|
||||
writeToOutputStream(list, clazz, response.getOutputStream());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new ApiException(Internal.UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<?> readFromRequest(Class<?> clazz, MultipartFile file) {
|
||||
try {
|
||||
return readFromInputStream(clazz, file.getInputStream());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new ApiException(Internal.UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeToOutputStream(List<?> list, Class<?> clazz, OutputStream outputStream) {
|
||||
|
||||
// 通过工具类创建writer
|
||||
ExcelWriter writer = ExcelUtil.getWriter();
|
||||
|
||||
ExcelSheet sheetAnno = (ExcelSheet)clazz.getAnnotation(ExcelSheet.class);
|
||||
ExcelSheet sheetAnno = clazz.getAnnotation(ExcelSheet.class);
|
||||
|
||||
if (sheetAnno != null) {
|
||||
// 默认的sheetName是 sheet1
|
||||
@@ -46,30 +67,17 @@ public class CustomExcelUtil {
|
||||
writer.setOnlyAlias(true);
|
||||
|
||||
// 合并单元格后的标题行,使用默认标题样式
|
||||
// writer.merge(4, "一班成绩单");
|
||||
// 一次性写出内容,使用默认样式,强制输出标题
|
||||
// writer.merge(4, "一班成绩单"); 一次性写出内容,使用默认样式,强制输出标题
|
||||
writer.write(list, true);
|
||||
|
||||
try {
|
||||
writer.flush(response.getOutputStream(), true);
|
||||
} catch (IOException e) {
|
||||
writer.close();
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
writer.flush(outputStream, true);
|
||||
}
|
||||
|
||||
public static List<?> readFromRequest(Class clazz, MultipartFile file) {
|
||||
ExcelReader reader;
|
||||
|
||||
try {
|
||||
reader = ExcelUtil.getReader(file.getInputStream());
|
||||
// 去除掉excel中的html标签语言 避免xss攻击
|
||||
reader.setCellEditor(new TrimXssEditor());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new ApiException(Internal.UNKNOWN_ERROR);
|
||||
}
|
||||
|
||||
public static List<?> readFromInputStream(Class<?> clazz, InputStream inputStream) {
|
||||
ExcelReader reader = ExcelUtil.getReader(inputStream);
|
||||
// 去除掉excel中的html标签语言 避免xss攻击
|
||||
reader.setCellEditor(new TrimXssEditor());
|
||||
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.agileboot.common.exception.error;
|
||||
|
||||
import com.agileboot.common.exception.error.ErrorCode.Client;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ErrorCodeInterfaceTest {
|
||||
|
||||
@Test
|
||||
void testI18nKey() {
|
||||
String i18nKey = Client.COMMON_FORBIDDEN_TO_CALL.i18nKey();
|
||||
Assertions.assertEquals("20001_COMMON_FORBIDDEN_TO_CALL", i18nKey);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import org.junit.Test;
|
||||
public class FileUploadUtilsTest {
|
||||
|
||||
@Test
|
||||
public void isAllowedExtension() {
|
||||
public void testIsAllowedExtension() {
|
||||
String[] imageTypes = new String[]{"img", "gif"};
|
||||
boolean isAllow = FileUploadUtils.isAllowedExtension("img", imageTypes);
|
||||
boolean isNotAllow = FileUploadUtils.isAllowedExtension("png", imageTypes);
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.agileboot.common.utils.ip;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class IpRegionUtilTest {
|
||||
|
||||
@Test
|
||||
void testGetIpRegion() {
|
||||
IpRegion ipRegion = IpRegionUtil.getIpRegion("110.81.189.80");
|
||||
|
||||
Assertions.assertEquals("中国", ipRegion.getCountry());
|
||||
Assertions.assertEquals("福建省", ipRegion.getProvince());
|
||||
Assertions.assertEquals("泉州市", ipRegion.getCity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpRegionWithIpv6() {
|
||||
IpRegion ipRegion = IpRegionUtil.getIpRegion("2001:0DB8:0000:0023:0008:0800:200C:417A");
|
||||
|
||||
Assertions.assertNotNull(ipRegion);
|
||||
Assertions.assertNull(ipRegion.getCountry());
|
||||
Assertions.assertEquals("未知 未知", ipRegion.briefLocation());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpRegionWithEmpty() {
|
||||
IpRegion ipRegion = IpRegionUtil.getIpRegion("");
|
||||
|
||||
Assertions.assertNotNull(ipRegion);
|
||||
Assertions.assertNull(ipRegion.getCountry());
|
||||
Assertions.assertEquals("未知 未知", ipRegion.briefLocation());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpRegionWithNull() {
|
||||
IpRegion ipRegion = IpRegionUtil.getIpRegion(null);
|
||||
|
||||
Assertions.assertNotNull(ipRegion);
|
||||
Assertions.assertNull(ipRegion.getCountry());
|
||||
Assertions.assertEquals("未知 未知", ipRegion.briefLocation());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpRegionWithWrongIpString() {
|
||||
IpRegion ipRegion = IpRegionUtil.getIpRegion("xsdfwefsfsd");
|
||||
|
||||
Assertions.assertNotNull(ipRegion);
|
||||
Assertions.assertNull(ipRegion.getCountry());
|
||||
Assertions.assertEquals("未知 未知", ipRegion.briefLocation());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBriefLocationByIp() {
|
||||
String briefLocationByIp = IpRegionUtil.getBriefLocationByIp("110.81.189.80");
|
||||
|
||||
Assertions.assertEquals("福建省 泉州市", briefLocationByIp);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.agileboot.common.utils.ip;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class OfflineIpRegionUtilTest {
|
||||
|
||||
@@ -9,26 +10,43 @@ public class OfflineIpRegionUtilTest {
|
||||
public void testGetIpRegionWhenIpv4() {
|
||||
IpRegion ipRegion = OfflineIpRegionUtil.getIpRegion("110.81.189.80");
|
||||
|
||||
Assert.assertEquals("中国", ipRegion.getCountry());
|
||||
Assert.assertEquals("福建省", ipRegion.getProvince());
|
||||
Assert.assertEquals("泉州市", ipRegion.getCity());
|
||||
Assertions.assertEquals("中国", ipRegion.getCountry());
|
||||
Assertions.assertEquals("福建省", ipRegion.getProvince());
|
||||
Assertions.assertEquals("泉州市", ipRegion.getCity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpRegionWithIpv6() {
|
||||
IpRegion ipRegion = OfflineIpRegionUtil.getIpRegion("2001:0DB8:0000:0023:0008:0800:200C:417A");
|
||||
Assert.assertNull(ipRegion);
|
||||
IpRegion region = Assertions.assertDoesNotThrow(() ->
|
||||
OfflineIpRegionUtil.getIpRegion("2001:0DB8:0000:0023:0008:0800:200C:417A")
|
||||
);
|
||||
|
||||
Assertions.assertNull(region);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpRegionWithEmpty() {
|
||||
IpRegion ipRegion = OfflineIpRegionUtil.getIpRegion("");
|
||||
Assert.assertNull(ipRegion);
|
||||
IpRegion region = Assertions.assertDoesNotThrow(() ->
|
||||
OfflineIpRegionUtil.getIpRegion("")
|
||||
);
|
||||
|
||||
Assertions.assertNull(region);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpRegionWithNull() {
|
||||
IpRegion ipRegion = OfflineIpRegionUtil.getIpRegion(null);
|
||||
Assert.assertNull(ipRegion);
|
||||
IpRegion region = Assertions.assertDoesNotThrow(() ->
|
||||
OfflineIpRegionUtil.getIpRegion(null)
|
||||
);
|
||||
|
||||
Assertions.assertNull(region);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpRegionWithWrongIpString() {
|
||||
IpRegion region = Assertions.assertDoesNotThrow(() ->
|
||||
OfflineIpRegionUtil.getIpRegion("asfdsfdsff")
|
||||
);
|
||||
Assertions.assertNull(region);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@ package com.agileboot.common.utils.ip;
|
||||
|
||||
import com.agileboot.common.config.AgileBootConfig;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class OnlineIpRegionUtilTest {
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void enableOnlineAddressQuery(){
|
||||
AgileBootConfig agileBootConfig = new AgileBootConfig();
|
||||
agileBootConfig.setAddressEnabled(true);
|
||||
@@ -16,8 +17,10 @@ public class OnlineIpRegionUtilTest {
|
||||
|
||||
@Test
|
||||
public void getIpRegionWithIpv6() {
|
||||
IpRegion ipRegion = OnlineIpRegionUtil.getIpRegion("ABCD:EF01:2345:6789:ABCD:EF01:2345:6789");
|
||||
Assert.assertNull(ipRegion);
|
||||
IpRegion region = Assertions.assertDoesNotThrow(() ->
|
||||
OnlineIpRegionUtil.getIpRegion("ABCD:EF01:2345:6789:ABCD:EF01:2345:6789")
|
||||
);
|
||||
Assert.assertNull(region);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -30,17 +33,30 @@ public class OnlineIpRegionUtilTest {
|
||||
|
||||
@Test
|
||||
public void getIpRegionWithEmpty() {
|
||||
IpRegion ipRegion = OnlineIpRegionUtil.getIpRegion("");
|
||||
IpRegion region = Assertions.assertDoesNotThrow(() ->
|
||||
OnlineIpRegionUtil.getIpRegion("")
|
||||
);
|
||||
|
||||
Assert.assertNull(ipRegion);
|
||||
Assert.assertNull(region);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getIpRegionWithNull() {
|
||||
IpRegion ipRegion = OnlineIpRegionUtil.getIpRegion(null);
|
||||
IpRegion region = Assertions.assertDoesNotThrow(() ->
|
||||
OnlineIpRegionUtil.getIpRegion(null)
|
||||
);
|
||||
|
||||
Assert.assertNull(ipRegion);
|
||||
Assert.assertNull(region);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIpRegionWithWrongIpString() {
|
||||
IpRegion region = Assertions.assertDoesNotThrow(() ->
|
||||
OnlineIpRegionUtil.getIpRegion("seffsdfsdf")
|
||||
);
|
||||
|
||||
Assert.assertNull(region);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.agileboot.common.utils.poi;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.http.HtmlUtil;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CustomExcelUtilTest {
|
||||
|
||||
@Test
|
||||
void testImportAndExport() {
|
||||
PostDTO post1 = new PostDTO(1L, "admin1", "管理员1", "1", "无备注", "1", "正常");
|
||||
PostDTO post2 = new PostDTO(2L, "admin2", "管理员2<script>alert(1)</script>", "2", "无备注", "1", "正常");
|
||||
|
||||
List<PostDTO> postDTOList = new ArrayList<>();
|
||||
postDTOList.add(post1);
|
||||
postDTOList.add(post2);
|
||||
|
||||
File file = FileUtil.createTempFile();
|
||||
|
||||
CustomExcelUtil.writeToOutputStream(postDTOList, PostDTO.class, FileUtil.getOutputStream(file));
|
||||
|
||||
List<PostDTO> postListFromExcel = (List<PostDTO>) CustomExcelUtil.readFromInputStream(PostDTO.class, FileUtil.getInputStream(file));
|
||||
|
||||
PostDTO post1fromExcel = postListFromExcel.get(0);
|
||||
PostDTO post2fromExcel = postListFromExcel.get(1);
|
||||
|
||||
Assertions.assertEquals(post1.getPostId(), post1fromExcel.getPostId());
|
||||
Assertions.assertEquals(post1.getPostCode(), post1fromExcel.getPostCode());
|
||||
Assertions.assertEquals(post2.getPostId(), post2fromExcel.getPostId());
|
||||
Assertions.assertEquals(post2.getPostCode(), post2fromExcel.getPostCode());
|
||||
// 检查脚本注入的字符串是否被去除
|
||||
Assertions.assertNotEquals(post2.getPostName(), post2fromExcel.getPostName());
|
||||
Assertions.assertEquals(HtmlUtil.cleanHtmlTag(post2.getPostName()), post2fromExcel.getPostName());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.agileboot.common.utils.poi;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.agileboot.common.annotation.ExcelColumn;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
@EqualsAndHashCode
|
||||
public class PostDTO {
|
||||
|
||||
@ExcelColumn(name = "岗位ID")
|
||||
private Long postId;
|
||||
|
||||
|
||||
@ExcelColumn(name = "岗位编码")
|
||||
private String postCode;
|
||||
|
||||
@ExcelColumn(name = "岗位名称")
|
||||
private String postName;
|
||||
|
||||
|
||||
@ExcelColumn(name = "岗位排序")
|
||||
private String postSort;
|
||||
|
||||
@ExcelColumn(name = "备注")
|
||||
private String remark;
|
||||
|
||||
private String status;
|
||||
|
||||
@ExcelColumn(name = "状态")
|
||||
private String statusStr;
|
||||
|
||||
}
|
||||
@@ -129,7 +129,7 @@ public class MenuApplicationService {
|
||||
|
||||
public List<Tree<Long>> buildMenuEntityTree(Long userId) {
|
||||
|
||||
List<SysMenuEntity> menus = null;
|
||||
List<SysMenuEntity> menus;
|
||||
if (AuthenticationUtils.isAdmin(userId)) {
|
||||
menus = menuService.listMenuListWithoutButton();
|
||||
} else {
|
||||
@@ -191,7 +191,4 @@ public class MenuApplicationService {
|
||||
return buildRouterTree(trees);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,12 @@ import com.agileboot.common.annotation.ExcelColumn;
|
||||
import com.agileboot.orm.entity.SysPostEntity;
|
||||
import com.agileboot.orm.enums.dictionary.CommonStatusEnum;
|
||||
import com.agileboot.orm.enums.interfaces.BasicEnumUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class PostDTO {
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DBExceptionAspect {
|
||||
public class DbExceptionAspect {
|
||||
|
||||
|
||||
@Pointcut("within(com.agileboot.orm..*)")
|
||||
@@ -28,7 +28,7 @@ public class ResourcesConfig implements WebMvcConfigurer {
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
/* 本地文件上传路径 */
|
||||
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
|
||||
.addResourceLocations("file:" + AgileBootConfig.getProfile() + "/");
|
||||
.addResourceLocations("file:" + AgileBootConfig.getFileBaseDir() + "/");
|
||||
|
||||
/* swagger配置 */
|
||||
registry.addResourceHandler("/swagger-ui/**")
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.web.filter.CorsFilter;
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class SecurityConfiguration {
|
||||
public class SecurityConfig {
|
||||
|
||||
/**
|
||||
* 认证失败处理类
|
||||
@@ -47,30 +47,30 @@ public class DruidProperties {
|
||||
private boolean testOnReturn;
|
||||
|
||||
public DruidDataSource dataSource(DruidDataSource datasource) {
|
||||
/** 配置初始化大小、最小、最大 */
|
||||
// 配置初始化大小、最小、最大
|
||||
datasource.setInitialSize(initialSize);
|
||||
datasource.setMaxActive(maxActive);
|
||||
datasource.setMinIdle(minIdle);
|
||||
|
||||
/** 配置获取连接等待超时的时间 */
|
||||
// 配置获取连接等待超时的时间
|
||||
datasource.setMaxWait(maxWait);
|
||||
|
||||
/** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
|
||||
// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
||||
|
||||
/** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */
|
||||
// 配置一个连接在池中最小、最大生存的时间,单位是毫秒
|
||||
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
|
||||
datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
|
||||
|
||||
/**
|
||||
* 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
|
||||
*/
|
||||
//用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,
|
||||
// testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
|
||||
datasource.setValidationQuery(validationQuery);
|
||||
/** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */
|
||||
// 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,
|
||||
// 执行validationQuery检测连接是否有效。
|
||||
datasource.setTestWhileIdle(testWhileIdle);
|
||||
/** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
|
||||
// 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
|
||||
datasource.setTestOnBorrow(testOnBorrow);
|
||||
/** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
|
||||
// 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
|
||||
datasource.setTestOnReturn(testOnReturn);
|
||||
return datasource;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class MessageI18nCheckerRunner implements ApplicationRunner {
|
||||
for (Object errorCode : allErrorCodes) {
|
||||
ErrorCodeInterface errorInterface = (ErrorCodeInterface)errorCode;
|
||||
try {
|
||||
String message = MessageUtils.message(errorInterface.i18nKey());
|
||||
MessageUtils.message(errorInterface.i18nKey());
|
||||
} catch (Exception e) {
|
||||
log.warn(" in the file /resources/i18n/messages.properties, could not find i18n message for:"
|
||||
+ errorInterface.i18nKey());
|
||||
|
||||
@@ -3,9 +3,12 @@ package com.agileboot.infrastructure.security;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.RSA;
|
||||
|
||||
/**
|
||||
* Rsa key生成
|
||||
*/
|
||||
public class RsaKeyPairGenerator {
|
||||
public static void main(String[] args) {
|
||||
|
||||
public static void main(String[] args) {
|
||||
RSA rsa = SecureUtil.rsa();
|
||||
|
||||
String privateKeyBase64 = rsa.getPrivateKeyBase64();
|
||||
|
||||
@@ -143,10 +143,6 @@ public class PermissionService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 判断是否包含权限
|
||||
*
|
||||
@@ -157,4 +153,5 @@ public class PermissionService {
|
||||
private boolean hasPermissions(Set<String> permissions, String permission) {
|
||||
return permissions.contains(ALL_PERMISSION) || permissions.contains(StrUtil.trim(permission));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ agileboot:
|
||||
copyright-year: 2022
|
||||
# 实例演示开关
|
||||
demo-enabled: true
|
||||
# 文件路径 示例( Windows配置D:/agileboot/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||
profile: D:/agileboot/uploadPath
|
||||
# 文件路径 示例( Windows配置D:\agileboot\uploadPath,Linux配置 /home/agileboot/uploadPath)
|
||||
file-base-dir: D:\agileboot\uploadPath
|
||||
# 获取ip地址开关
|
||||
addressEnabled: false
|
||||
# 验证码类型 math 数组计算 char 字符验证
|
||||
|
||||
8
pom.xml
8
pom.xml
@@ -36,6 +36,7 @@
|
||||
<lombok.version>1.18.24</lombok.version>
|
||||
<mybatis-plus.version>3.5.2</mybatis-plus.version>
|
||||
<mybatis-plus-generator.version>3.5.1</mybatis-plus-generator.version>
|
||||
<mockito.version>1.10.19</mockito.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖声明 -->
|
||||
@@ -227,6 +228,13 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user