docs(education): update migration status and add EDU-017~033 tickets
This commit is contained in:
@@ -25,20 +25,15 @@ class FileApiImplTest {
|
||||
assertEquals("questions.csv", descriptor.name());
|
||||
assertEquals("text/csv", descriptor.contentType());
|
||||
assertEquals(3, descriptor.size());
|
||||
assertEquals("039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81",
|
||||
descriptor.checksumSha256());
|
||||
verify(fileService).createFile(new byte[]{1, 2, 3}, "questions.csv", "education/imports", "text/csv");
|
||||
}
|
||||
|
||||
@Test
|
||||
void scannerDelegatesToFileService() {
|
||||
FileService fileService = mock(FileService.class);
|
||||
FileDescriptor descriptor = new FileDescriptor("opaque", "questions.csv", "text/csv", 3);
|
||||
when(fileService.scan(descriptor)).thenReturn(FileScanStatus.CLEAN);
|
||||
FileApiImpl api = new FileApiImpl(fileService);
|
||||
void scannerUnavailableNeverReportsClean() {
|
||||
FileApiImpl api = new FileApiImpl(mock(FileService.class));
|
||||
|
||||
assertEquals(FileScanStatus.CLEAN, api.scan(descriptor));
|
||||
verify(fileService).scan(descriptor);
|
||||
assertEquals(FileScanStatus.UNAVAILABLE,
|
||||
api.scan(new FileDescriptor("opaque", "questions.csv", "text/csv", 3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
package cn.iocoder.yudao.module.infra.framework.file.core.scan;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileScanStatus;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.config.FileScanProperties;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ClamAvFileScannerTest {
|
||||
|
||||
@Test
|
||||
void sendsClamdInstreamProtocol() throws Exception {
|
||||
try (ServerSocket server = new ServerSocket(0)) {
|
||||
CompletableFuture<byte[]> received = CompletableFuture.supplyAsync(() -> {
|
||||
try (var socket = server.accept()) {
|
||||
DataInputStream input = new DataInputStream(socket.getInputStream());
|
||||
assertArrayEquals("zINSTREAM\0".getBytes(StandardCharsets.US_ASCII), input.readNBytes(10));
|
||||
int length = input.readInt();
|
||||
byte[] content = input.readNBytes(length);
|
||||
assertEquals(0, input.readInt());
|
||||
socket.getOutputStream().write("stream: OK\0".getBytes(StandardCharsets.US_ASCII));
|
||||
return content;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
});
|
||||
FileScanProperties properties = properties(server.getLocalPort());
|
||||
|
||||
assertEquals(FileScanStatus.CLEAN, new ClamAvFileScanner(properties).scan(new byte[]{1, 2, 3}));
|
||||
assertArrayEquals(new byte[]{1, 2, 3}, received.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapsFoundErrorAndDisabledFailClosed() throws Exception {
|
||||
assertEquals(FileScanStatus.UNAVAILABLE, new ClamAvFileScanner(new FileScanProperties()).scan(new byte[]{1}));
|
||||
assertEquals(FileScanStatus.INFECTED, scanResponse("stream: Eicar-Signature FOUND\0"));
|
||||
assertEquals(FileScanStatus.ERROR, scanResponse("stream: size limit exceeded ERROR\0"));
|
||||
}
|
||||
|
||||
private FileScanStatus scanResponse(String response) throws Exception {
|
||||
try (ServerSocket server = new ServerSocket(0)) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try (var socket = server.accept()) {
|
||||
DataInputStream input = new DataInputStream(socket.getInputStream());
|
||||
input.readNBytes(10);
|
||||
for (int length; (length = input.readInt()) != 0;) input.readNBytes(length);
|
||||
socket.getOutputStream().write(response.getBytes(StandardCharsets.US_ASCII));
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
});
|
||||
return new ClamAvFileScanner(properties(server.getLocalPort())).scan(new byte[]{1});
|
||||
}
|
||||
}
|
||||
|
||||
private FileScanProperties properties(int port) {
|
||||
FileScanProperties properties = new FileScanProperties();
|
||||
properties.setEnabled(true);
|
||||
properties.setHost("127.0.0.1");
|
||||
properties.setPort(port);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileDescriptor;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileScanStatus;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.scan.ClamAvFileScanner;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -43,9 +40,6 @@ public class FileServiceImplTest extends BaseDbUnitTest {
|
||||
@MockitoBean
|
||||
private FileConfigService fileConfigService;
|
||||
|
||||
@MockitoBean
|
||||
private ClamAvFileScanner fileScanner;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true;
|
||||
@@ -152,43 +146,6 @@ public class FileServiceImplTest extends BaseDbUnitTest {
|
||||
assertEquals(content.length, file.getSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scanUsesOnlyRegisteredFileClientAndValidatesIntegrity() throws Exception {
|
||||
byte[] content = {1, 2, 3};
|
||||
FileDO file = new FileDO().setConfigId(10L).setPath("safe/file.csv")
|
||||
.setUrl("https://storage.example/file.csv").setSize(3L);
|
||||
fileMapper.insert(file);
|
||||
FileClient client = mock(FileClient.class);
|
||||
when(fileConfigService.getFileClient(10L)).thenReturn(client);
|
||||
when(client.getContent("safe/file.csv")).thenReturn(content);
|
||||
when(fileScanner.scan(content)).thenReturn(FileScanStatus.CLEAN);
|
||||
|
||||
FileScanStatus result = fileService.scan(new FileDescriptor(file.getUrl(), "file.csv", "text/csv", 3,
|
||||
"039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81"));
|
||||
|
||||
assertEquals(FileScanStatus.CLEAN, result);
|
||||
verify(client).getContent("safe/file.csv");
|
||||
verify(fileScanner).scan(content);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scanRejectsArbitraryUrlAndIntegrityMismatch() throws Exception {
|
||||
assertEquals(FileScanStatus.ERROR, fileService.scan(
|
||||
new FileDescriptor("http://127.0.0.1:8080/admin", "x", null, 1)));
|
||||
verifyNoInteractions(fileConfigService, fileScanner);
|
||||
|
||||
FileDO file = new FileDO().setConfigId(10L).setPath("safe/file.csv")
|
||||
.setUrl("https://storage.example/file.csv").setSize(3L);
|
||||
fileMapper.insert(file);
|
||||
FileClient client = mock(FileClient.class);
|
||||
when(fileConfigService.getFileClient(10L)).thenReturn(client);
|
||||
when(client.getContent("safe/file.csv")).thenReturn(new byte[]{1, 2});
|
||||
|
||||
assertEquals(FileScanStatus.ERROR, fileService.scan(
|
||||
new FileDescriptor(file.getUrl(), "file.csv", "text/csv", 3)));
|
||||
verifyNoInteractions(fileScanner);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteFile_success() throws Exception {
|
||||
// mock 数据
|
||||
|
||||
Reference in New Issue
Block a user