refactor(系统设置): 优化文件存储的数据结构,去掉无用参数,文件关联资源增加删除方法

This commit is contained in:
song-tianyang 2023-11-28 13:51:17 +08:00 committed by jianxing
parent 833a9b7d26
commit afd5d29a63
10 changed files with 54 additions and 21 deletions

View File

@ -443,6 +443,7 @@ change.jar.enable=修改了jar文件的启用状态
file.name.exist=文件名已存在 file.name.exist=文件名已存在
file.log.delete_module=模块下的所有数据全部被删除 file.log.delete_module=模块下的所有数据全部被删除
file.module.root=根目录 file.module.root=根目录
file.folder.error=文件夹不合法
file.log.move_to=移动到 file.log.move_to=移动到
file.log.change_file_module=文件进行了移动 file.log.change_file_module=文件进行了移动
file.log.next=之后 file.log.next=之后

View File

@ -479,6 +479,7 @@ change.jar.enable=Change jar file enable
file.name.exist=File name already exists file.name.exist=File name already exists
file.log.delete_module=has be deleted file.log.delete_module=has be deleted
file.module.root=root module file.module.root=root module
file.folder.error=File folder error
file.log.move_to=move to file.log.move_to=move to
file.log.change_file_module=File has be moved file.log.change_file_module=File has be moved
file.log.next=next file.log.next=next

View File

@ -478,6 +478,7 @@ change.jar.enable=修改了jar文件的启用状态
file.name.exist=文件名已存在 file.name.exist=文件名已存在
file.log.delete_module=模块下的所有数据全部被删除 file.log.delete_module=模块下的所有数据全部被删除
file.module.root=根目录 file.module.root=根目录
file.folder.error=文件夹不合法
file.log.move_to=移动到 file.log.move_to=移动到
file.log.change_file_module=文件进行了移动 file.log.change_file_module=文件进行了移动
file.log.next=之后 file.log.next=之后

View File

@ -479,6 +479,7 @@ change.jar.enable=修改了jar文件的啟用狀態
file.name.exist=文件名已存在 file.name.exist=文件名已存在
file.log.delete_module=模塊下的所有數據全部被刪除 file.log.delete_module=模塊下的所有數據全部被刪除
file.module.root=根目錄 file.module.root=根目錄
file.folder.error=文件夾不合法
file.log.move_to=移動到 file.log.move_to=移動到
file.log.change_file_module=文件進行了移動 file.log.change_file_module=文件進行了移動
file.log.next=之後 file.log.next=之後

View File

@ -230,7 +230,7 @@ public class FileAssociationService {
} }
FileAssociationExample example = new FileAssociationExample(); FileAssociationExample example = new FileAssociationExample();
example.createCriteria().andIdIn(idList); example.createCriteria().andIdIn(idList);
return this.deleteAndSelectExample(example, logRecord); return this.deleteAndSaveLog(example, logRecord);
} }
/** /**
@ -246,10 +246,27 @@ public class FileAssociationService {
} }
FileAssociationExample example = new FileAssociationExample(); FileAssociationExample example = new FileAssociationExample();
example.createCriteria().andSourceIdIn(sourceIds); example.createCriteria().andSourceIdIn(sourceIds);
return this.deleteAndSelectExample(example, logRecord); return this.deleteAndSaveLog(example, logRecord);
} }
private int deleteAndSelectExample(FileAssociationExample example, FileLogRecord logRecord) { /**
* 取消关联
*
* @param sourceId 资源ID
* @param fileIds 文件ID
* @param logRecord 日志记录相关
* @return
*/
public int deleteBySourceIdAndFileIds(String sourceId, List<String> fileIds, @Validated FileLogRecord logRecord) {
if (CollectionUtils.isEmpty(fileIds)) {
return 0;
}
FileAssociationExample example = new FileAssociationExample();
example.createCriteria().andSourceIdEqualTo(sourceId).andFileIdIn(fileIds);
return this.deleteAndSaveLog(example, logRecord);
}
private int deleteAndSaveLog(FileAssociationExample example, FileLogRecord logRecord) {
List<FileAssociation> fileAssociationList = fileAssociationMapper.selectByExample(example); List<FileAssociation> fileAssociationList = fileAssociationMapper.selectByExample(example);
Map<String, List<String>> sourceToFileNameMap = this.genSourceNameFileNameMap(fileAssociationList); Map<String, List<String>> sourceToFileNameMap = this.genSourceNameFileNameMap(fileAssociationList);
int deleteCount = fileAssociationMapper.deleteByExample(example); int deleteCount = fileAssociationMapper.deleteByExample(example);

View File

@ -68,7 +68,6 @@ public class FileManagementService {
deleteList.forEach(fileMetadata -> { deleteList.forEach(fileMetadata -> {
FileRequest fileRequest = new FileRequest(); FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(fileMetadata.getId()); fileRequest.setFileName(fileMetadata.getId());
fileRequest.setProjectId(fileMetadata.getProjectId());
fileRequest.setStorage(fileMetadata.getStorage()); fileRequest.setStorage(fileMetadata.getStorage());
try { try {
//删除存储容器中的文件 //删除存储容器中的文件
@ -139,7 +138,6 @@ public class FileManagementService {
deleteList.forEach(fileMetadata -> { deleteList.forEach(fileMetadata -> {
FileRequest fileRequest = new FileRequest(); FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(fileMetadata.getId()); fileRequest.setFileName(fileMetadata.getId());
fileRequest.setProjectId(fileMetadata.getProjectId());
fileRequest.setStorage(fileMetadata.getStorage()); fileRequest.setStorage(fileMetadata.getStorage());
try { try {
fileService.deleteFile(fileRequest); fileService.deleteFile(fileRequest);

View File

@ -11,6 +11,7 @@ import io.metersphere.project.mapper.FileMetadataMapper;
import io.metersphere.project.mapper.FileModuleMapper; import io.metersphere.project.mapper.FileModuleMapper;
import io.metersphere.project.service.FileAssociationService; import io.metersphere.project.service.FileAssociationService;
import io.metersphere.project.service.FileModuleService; import io.metersphere.project.service.FileModuleService;
import io.metersphere.project.service.FileService;
import io.metersphere.project.utils.FileManagementBaseUtils; import io.metersphere.project.utils.FileManagementBaseUtils;
import io.metersphere.project.utils.FileManagementRequestUtils; import io.metersphere.project.utils.FileManagementRequestUtils;
import io.metersphere.project.utils.FileMetadataUtils; import io.metersphere.project.utils.FileMetadataUtils;
@ -23,6 +24,7 @@ import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.AddProjectRequest; import io.metersphere.system.dto.AddProjectRequest;
import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.request.NodeMoveRequest; import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
import io.metersphere.system.file.FileRequest;
import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.service.CommonProjectService; import io.metersphere.system.service.CommonProjectService;
@ -1719,6 +1721,10 @@ public class FileManagementControllerTests extends BaseTest {
//参数测试 //参数测试
Assertions.assertEquals(fileAssociationService.deleteBySourceIds(null, fileLogRecord), 0); Assertions.assertEquals(fileAssociationService.deleteBySourceIds(null, fileLogRecord), 0);
Assertions.assertEquals(fileAssociationService.deleteBySourceIdAndFileIds(null, new ArrayList<>(), fileLogRecord), 0);
Assertions.assertEquals(fileAssociationService.deleteBySourceIdAndFileIds(IDGenerator.nextStr(), new ArrayList<>() {{
this.add(IDGenerator.nextStr());
}}, fileLogRecord), 0);
//重新关联用来测试文件删除是否会级联删除使用bug-3 //重新关联用来测试文件删除是否会级联删除使用bug-3
fileAssociationService.association("sty-file-association-bug-id-3", FileAssociationSourceUtil.SOURCE_TYPE_BUG, bug2IdList, fileLogRecord); fileAssociationService.association("sty-file-association-bug-id-3", FileAssociationSourceUtil.SOURCE_TYPE_BUG, bug2IdList, fileLogRecord);
fileAssociationService.association("sty-file-association-bug-id-2", FileAssociationSourceUtil.SOURCE_TYPE_BUG, bug2IdList, fileLogRecord); fileAssociationService.association("sty-file-association-bug-id-2", FileAssociationSourceUtil.SOURCE_TYPE_BUG, bug2IdList, fileLogRecord);
@ -2326,10 +2332,27 @@ public class FileManagementControllerTests extends BaseTest {
Assertions.assertEquals(fileMetadataMapper.countByExample(example), 0); Assertions.assertEquals(fileMetadataMapper.countByExample(example), 0);
} }
@Resource
private FileService fileService;
@Test @Test
@Order(91) @Order(91)
public void testQuery() throws Exception { public void testQuery() throws Exception {
fileAssociationService.getFiles("TEST", FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE); fileAssociationService.getFiles("TEST", FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
fileAssociationService.getFileAssociations(Collections.singletonList("TEST"), FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE); fileAssociationService.getFileAssociations(Collections.singletonList("TEST"), FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
//测试FileRequest的folder判断
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(IDGenerator.nextStr());
fileRequest.setStorage(StorageType.MINIO.name());
fileRequest.setFolder(IDGenerator.nextStr());
boolean error = false;
try {
fileService.deleteFile(fileRequest);
} catch (Exception e) {
error = true;
}
Assertions.assertTrue(error);
} }
} }

View File

@ -10,21 +10,9 @@ public class FileRequest {
private String folder; private String folder;
/**
* @Deprecated 月底移除
*/
@Deprecated(since="3.x", forRemoval=true)
private String projectId;
// 存储类型 // 存储类型
private String storage; private String storage;
/**
* @Deprecated 月底移除
*/
@Deprecated(since="3.x", forRemoval=true)
private String resourceId;
// 文件名称 // 文件名称
private String fileName; private String fileName;

View File

@ -1,5 +1,6 @@
package io.metersphere.system.file; package io.metersphere.system.file;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.system.config.MinioConfig; import io.metersphere.system.config.MinioConfig;
import io.minio.*; import io.minio.*;
import io.minio.messages.Item; import io.minio.messages.Item;
@ -24,8 +25,10 @@ public class MinioRepository implements FileRepository {
private static final int BUFFER_SIZE = 8192; private static final int BUFFER_SIZE = 8192;
private String getPath(FileRequest request) { private String getPath(FileRequest request) {
String folder = StringUtils.isNotEmpty(request.getFolder()) ? request.getFolder() : request.getProjectId(); String folder = request.getFolder();
//todo 后续要增加对folder起始路径的校验: system / project / organization if (!StringUtils.startsWithAny(folder, "system", "project", "organization")) {
throw new MSException("file.folder.error");
}
return StringUtils.join(folder, "/", request.getFileName()); return StringUtils.join(folder, "/", request.getFileName());
} }

View File

@ -45,7 +45,7 @@ public class FileCenterTests {
private static FileRequest getFileRequest() { private static FileRequest getFileRequest() {
FileRequest request = new FileRequest(); FileRequest request = new FileRequest();
request.setFileName("test.txt"); request.setFileName("test.txt");
request.setFolder("test-project/test-resource-id"); request.setFolder("system/test-project/test-resource-id");
return request; return request;
} }
@ -77,7 +77,7 @@ public class FileCenterTests {
// 创建一个FileRequest对象作为测试用的请求参数 // 创建一个FileRequest对象作为测试用的请求参数
FileRequest request = new FileRequest(); FileRequest request = new FileRequest();
request.setFileName("test.txt"); request.setFileName("test.txt");
request.setFolder("test-project"); request.setFolder("system/test-project");
repository.saveFile(mockFile, request); repository.saveFile(mockFile, request);
Assertions.assertTrue(repository.saveFile(mockFile, request) != null); Assertions.assertTrue(repository.saveFile(mockFile, request) != null);
Assertions.assertTrue(repository.saveFile("Hello, World!".getBytes(), request) != null); Assertions.assertTrue(repository.saveFile("Hello, World!".getBytes(), request) != null);