package jnpf.dmsService.search;
|
|
import jnpf.dmsEntity.permission.vo.DmsPermissionDecisionVO;
|
import jnpf.dmsEntity.search.form.DmsFullTextSearchForm;
|
import jnpf.dmsEntity.search.vo.DmsFullTextSearchPageVO;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.dmsService.DmsPermissionDecisionService;
|
import jnpf.dmsService.search.meili.DmsMeilisearchClient;
|
import jnpf.dmsService.search.meili.DmsMeilisearchSearchHit;
|
import jnpf.dmsService.search.meili.DmsMeilisearchSearchPage;
|
import jnpf.dmsService.search.meili.DmsSearchIndexDocument;
|
import org.junit.jupiter.api.Test;
|
|
import java.util.Arrays;
|
import java.util.UUID;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.mockito.ArgumentMatchers.anyList;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.when;
|
|
class DmsFullTextSearchServiceTest {
|
private final jnpf.dmsMapper.DmsSearchIndexSourceMapper sources = mock(jnpf.dmsMapper.DmsSearchIndexSourceMapper.class);
|
|
@org.junit.jupiter.api.BeforeEach
|
void currentVersions() {
|
when(sources.currentVersionIds(org.mockito.ArgumentMatchers.anyString(), anyList()))
|
.thenAnswer(call -> call.getArgument(1));
|
}
|
|
@Test
|
void returnsOnlyReadableResultsAndEscapesHighlightedText() throws Exception {
|
DmsCurrentIdentity identity = mock(DmsCurrentIdentity.class);
|
DmsPermissionDecisionService permissions = mock(DmsPermissionDecisionService.class);
|
DmsMeilisearchClient meilisearch = mock(DmsMeilisearchClient.class);
|
DmsFullTextSearchService service = new DmsFullTextSearchService(
|
identity, permissions, meilisearch, sources);
|
DmsMeilisearchSearchHit denied = hit("无权限文件", "正文");
|
DmsMeilisearchSearchHit allowed = hit("<script>alert(1)</script>"
|
+ DmsMeilisearchClient.HIGHLIGHT_START + "规程"
|
+ DmsMeilisearchClient.HIGHLIGHT_END, "命中正文");
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(meilisearch.search("tenant-1", "规程", 0, 100))
|
.thenReturn(new DmsMeilisearchSearchPage(Arrays.asList(denied, allowed), 2));
|
when(permissions.evaluate(anyList())).thenReturn(Arrays.asList(decision(false), decision(true)));
|
|
DmsFullTextSearchForm form = new DmsFullTextSearchForm();
|
form.setKeyword("规程");
|
DmsFullTextSearchPageVO result = service.search(form);
|
|
assertEquals(1, result.getList().size());
|
assertEquals("<script>alert(1)</script><mark>规程</mark>",
|
result.getList().get(0).getHighlightedTitle());
|
assertFalse(result.isHasMore());
|
}
|
|
@Test
|
void returnsCursorForNextReadableResult() throws Exception {
|
DmsCurrentIdentity identity = mock(DmsCurrentIdentity.class);
|
DmsPermissionDecisionService permissions = mock(DmsPermissionDecisionService.class);
|
DmsMeilisearchClient meilisearch = mock(DmsMeilisearchClient.class);
|
DmsFullTextSearchService service = new DmsFullTextSearchService(
|
identity, permissions, meilisearch, sources);
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(meilisearch.search("tenant-1", "文件", 0, 100))
|
.thenReturn(new DmsMeilisearchSearchPage(
|
Arrays.asList(hit("文件一", ""), hit("文件二", "")), 2));
|
when(permissions.evaluate(anyList()))
|
.thenReturn(Arrays.asList(decision(true), decision(true)));
|
DmsFullTextSearchForm form = new DmsFullTextSearchForm();
|
form.setKeyword("文件");
|
form.setPageSize(1);
|
|
DmsFullTextSearchPageVO result = service.search(form);
|
|
assertEquals(1, result.getList().size());
|
assertTrue(result.isHasMore());
|
assertEquals("1", result.getNextCursor());
|
}
|
|
private DmsMeilisearchSearchHit hit(String formattedTitle, String formattedContent) {
|
DmsSearchIndexDocument document = new DmsSearchIndexDocument();
|
UUID versionId = UUID.randomUUID();
|
document.setId(versionId.toString());
|
document.setTenantId("tenant-1");
|
document.setDocumentId(UUID.randomUUID().toString());
|
document.setFileVersionId(versionId.toString());
|
document.setTitle("文件");
|
document.setFileName("file.docx");
|
return new DmsMeilisearchSearchHit(document, formattedTitle, formattedContent);
|
}
|
|
@Test
|
void suppressesExpiredIndexHitEvenWhenHistoricalReadIsAllowed() throws Exception {
|
DmsCurrentIdentity identity = mock(DmsCurrentIdentity.class);
|
DmsPermissionDecisionService permissions = mock(DmsPermissionDecisionService.class);
|
DmsMeilisearchClient client = mock(DmsMeilisearchClient.class);
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(client.search("tenant-1", "文件", 0, 100)).thenReturn(
|
new DmsMeilisearchSearchPage(java.util.List.of(hit("已过期", "历史正文")), 1));
|
when(permissions.evaluate(anyList())).thenReturn(java.util.List.of(decision(true)));
|
when(sources.currentVersionIds(org.mockito.ArgumentMatchers.anyString(), anyList())).thenReturn(java.util.List.of());
|
DmsFullTextSearchForm form = new DmsFullTextSearchForm();
|
form.setKeyword("文件");
|
assertTrue(new DmsFullTextSearchService(identity, permissions, client, sources).search(form).getList().isEmpty());
|
}
|
|
private DmsPermissionDecisionVO decision(boolean allowed) {
|
DmsPermissionDecisionVO decision = new DmsPermissionDecisionVO();
|
decision.setAllowed(allowed);
|
return decision;
|
}
|
}
|