docs(education): update migration status and add EDU-017~033 tickets
This commit is contained in:
@@ -63,7 +63,7 @@ public class EducationAssetAdmissionServiceImpl implements EducationAssetAdmissi
|
||||
asset.setOriginalName(name);
|
||||
asset.setContentType(contentType);
|
||||
asset.setSize((long) bytes.length);
|
||||
asset.setSha256(descriptor.checksumSha256() != null ? descriptor.checksumSha256() : DigestUtil.sha256Hex(bytes));
|
||||
asset.setSha256(DigestUtil.sha256Hex(bytes));
|
||||
asset.setFileReference(descriptor.reference());
|
||||
asset.setScanStatus(scanStatus.name());
|
||||
assetMapper.insert(asset);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.yudao.module.education.service.importjob;
|
||||
|
||||
public interface ImportObjectScanGateway {
|
||||
enum ScanResult { CLEAN, INFECTED, ERROR, UNAVAILABLE }
|
||||
ScanResult scan(String reference, String name, String mimeType, long size, String checksumSha256);
|
||||
enum ScanResult { CLEAN, INFECTED, ERROR }
|
||||
ScanResult scan(String objectKey);
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package cn.iocoder.yudao.module.education.service.importjob;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileDescriptor;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileScanStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class InfraFileImportObjectScanGateway implements ImportObjectScanGateway {
|
||||
|
||||
private final FileApi fileApi;
|
||||
|
||||
public InfraFileImportObjectScanGateway(FileApi fileApi) {
|
||||
this.fileApi = fileApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScanResult scan(String reference, String name, String mimeType, long size, String checksumSha256) {
|
||||
FileScanStatus status;
|
||||
try {
|
||||
status = fileApi.scan(new FileDescriptor(reference, name, mimeType, size, checksumSha256));
|
||||
} catch (RuntimeException ex) {
|
||||
return ScanResult.ERROR;
|
||||
}
|
||||
return status == null ? ScanResult.UNAVAILABLE : ScanResult.valueOf(status.name());
|
||||
}
|
||||
}
|
||||
@@ -133,8 +133,7 @@ public class QuestionImportJobServiceImpl implements QuestionImportJobService {
|
||||
finishFailed(job, token, "SCAN_UNAVAILABLE");
|
||||
throw exception(QUESTION_IMPORT_SCAN_NOT_CLEAN);
|
||||
}
|
||||
ImportObjectScanGateway.ScanResult scanResult = gateway.scan(asset.getObjectKey(), asset.getFileName(),
|
||||
asset.getMimeType(), asset.getFileSizeBytes(), asset.getChecksumSha256());
|
||||
ImportObjectScanGateway.ScanResult scanResult = gateway.scan(asset.getObjectKey());
|
||||
if (scanResult != ImportObjectScanGateway.ScanResult.CLEAN) {
|
||||
finishFailed(job, token, "SCAN_" + scanResult.name());
|
||||
throw exception(QUESTION_IMPORT_SCAN_NOT_CLEAN);
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package cn.iocoder.yudao.module.education.service.importjob;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileDescriptor;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileScanStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class InfraFileImportObjectScanGatewayTest {
|
||||
|
||||
@Test
|
||||
void passesCompleteDescriptorAndMapsEveryStatus() {
|
||||
FileApi fileApi = mock(FileApi.class);
|
||||
InfraFileImportObjectScanGateway gateway = new InfraFileImportObjectScanGateway(fileApi);
|
||||
FileDescriptor descriptor = new FileDescriptor("ref", "questions.csv", "text/csv", 3,
|
||||
"039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81");
|
||||
for (FileScanStatus status : FileScanStatus.values()) {
|
||||
when(fileApi.scan(descriptor)).thenReturn(status);
|
||||
assertEquals(ImportObjectScanGateway.ScanResult.valueOf(status.name()),
|
||||
gateway.scan(descriptor.reference(), descriptor.name(), descriptor.contentType(),
|
||||
descriptor.size(), descriptor.checksumSha256()));
|
||||
}
|
||||
verify(fileApi, times(FileScanStatus.values().length)).scan(descriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullAndExceptionsFailClosed() {
|
||||
FileApi fileApi = mock(FileApi.class);
|
||||
InfraFileImportObjectScanGateway gateway = new InfraFileImportObjectScanGateway(fileApi);
|
||||
when(fileApi.scan(any())).thenReturn(null).thenThrow(new IllegalStateException("down"));
|
||||
|
||||
assertEquals(ImportObjectScanGateway.ScanResult.UNAVAILABLE,
|
||||
gateway.scan("ref", "x", null, 1, null));
|
||||
assertEquals(ImportObjectScanGateway.ScanResult.ERROR,
|
||||
gateway.scan("ref", "x", null, 1, null));
|
||||
}
|
||||
}
|
||||
@@ -79,8 +79,7 @@ class QuestionImportJobServiceImplTest {
|
||||
when(jobMapper.claimById(eq(101L), eq("PREVIEW_PENDING"), anyString(), anyString(), anyLong()))
|
||||
.thenReturn(claimed);
|
||||
when(assetMapper.selectTenantAsset(10L, 88L)).thenReturn(asset(88L));
|
||||
when(scanGateway.scan("object/10/questions.csv", "questions.csv", "text/csv", 128L, "checksum"))
|
||||
.thenReturn(ImportObjectScanGateway.ScanResult.CLEAN);
|
||||
when(scanGateway.scan("object/10/questions.csv")).thenReturn(ImportObjectScanGateway.ScanResult.CLEAN);
|
||||
when(jobMapper.finishClaim(eq(10L), eq(101L), eq("PREVIEW_PENDING"), eq("PREVIEW_READY"),
|
||||
anyString(), eq("CLEAN"), eq("UNAVAILABLE"), contains("METADATA_ONLY"), isNull(), isNull(),
|
||||
isNull(), isNull(), isNull(), isNull())).thenReturn(1);
|
||||
@@ -107,28 +106,6 @@ class QuestionImportJobServiceImplTest {
|
||||
verifyNoInteractions(parser, lifecycleService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonCleanStatusesHaveStableFailureCodesAndNeverParse() {
|
||||
for (ImportObjectScanGateway.ScanResult result : List.of(
|
||||
ImportObjectScanGateway.ScanResult.INFECTED,
|
||||
ImportObjectScanGateway.ScanResult.ERROR,
|
||||
ImportObjectScanGateway.ScanResult.UNAVAILABLE)) {
|
||||
reset(jobMapper, assetMapper, scanGateway, parser, lifecycleService);
|
||||
when(jobMapper.claimById(eq(101L), eq("PREVIEW_PENDING"), anyString(), anyString(), anyLong()))
|
||||
.thenReturn(job(101L, "PREVIEW_PENDING"));
|
||||
when(assetMapper.selectTenantAsset(10L, 88L)).thenReturn(asset(88L));
|
||||
when(scanGateway.scan("object/10/questions.csv", "questions.csv", "text/csv", 128L, "checksum"))
|
||||
.thenReturn(result);
|
||||
|
||||
assertThrows(ServiceException.class, () -> service.preview(101L));
|
||||
|
||||
verify(jobMapper).finishClaim(eq(10L), eq(101L), eq("PREVIEW_PENDING"), eq("FAILED"),
|
||||
anyString(), isNull(), isNull(), isNull(), isNull(), isNull(), isNull(), isNull(),
|
||||
eq("SCAN_" + result.name()), eq("SCAN_" + result.name()));
|
||||
verifyNoInteractions(parser, lifecycleService);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void executePropagatesClaimedTenantAndCreatesDrafts() {
|
||||
TenantContextHolder.clear();
|
||||
@@ -154,7 +131,7 @@ class QuestionImportJobServiceImplTest {
|
||||
private ContentImportAssetDO asset(Long id) {
|
||||
ContentImportAssetDO asset = new ContentImportAssetDO(); asset.setId(id); asset.setTenantId(10L);
|
||||
asset.setObjectKey("object/10/questions.csv"); asset.setFileName("questions.csv");
|
||||
asset.setMimeType("text/csv"); asset.setFileSizeBytes(128L); asset.setChecksumSha256("checksum"); return asset;
|
||||
asset.setMimeType("text/csv"); asset.setFileSizeBytes(128L); return asset;
|
||||
}
|
||||
|
||||
private ContentImportJobDO job(Long id, String status) {
|
||||
|
||||
Reference in New Issue
Block a user