package jnpf.dmsService;
|
|
import jnpf.base.UserInfo;
|
import jnpf.dmsEntity.permission.model.DmsSubjectSet;
|
import jnpf.dmsEntity.permission.enums.DmsPermissionAction;
|
import jnpf.dmsEntity.permission.enums.DmsResourceType;
|
import jnpf.dmsEntity.permission.vo.DmsCursorPageVO;
|
import jnpf.dmsEntity.permission.vo.DmsFileCenterItemVO;
|
import jnpf.dmsEntity.permission.vo.DmsFolderTreeNodeVO;
|
import jnpf.dmsMapper.DmsFileCenterMapper;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.dmsPermission.DmsFileCenterCursorCodec;
|
import jnpf.dmsPermission.DmsFileCenterQuery;
|
import jnpf.dmsPermission.DmsPermissionException;
|
import jnpf.dmsPermission.DmsPermissionGroupMembershipResolver;
|
import jnpf.dmsPermission.DmsPermissionProperties;
|
import jnpf.dmsPermission.DmsSubjectResolver;
|
import org.junit.jupiter.api.Test;
|
import org.mockito.ArgumentCaptor;
|
|
import java.util.Arrays;
|
import java.util.Collections;
|
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.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.when;
|
|
class DmsFileCenterServiceTest {
|
|
@Test
|
void folderTreeReturnsOnlyOnePageWithPermissionFilteredExpansionState() {
|
Fixture fixture = new Fixture(false);
|
when(fixture.subjectResolver.resolve(fixture.user)).thenReturn(new DmsSubjectSet());
|
DmsFileCenterItemVO first = folder("A", fixture.firstId);
|
first.setParentId(fixture.folderId);
|
first.setHasChildren(true);
|
DmsFileCenterItemVO second = folder("B", fixture.secondId);
|
second.setHasChildren(false);
|
when(fixture.mapper.selectFolders(any())).thenReturn(Arrays.asList(first, second));
|
|
DmsCursorPageVO<DmsFolderTreeNodeVO> result = fixture.service.folderTree(fixture.folderId, null, 1);
|
|
assertEquals(1, result.getList().size());
|
assertEquals(first.getId(), result.getList().get(0).getId());
|
assertEquals(first.getParentId(), result.getList().get(0).getParentId());
|
assertEquals(first.getName(), result.getList().get(0).getName());
|
assertTrue(result.getList().get(0).isHasChildren());
|
assertTrue(result.isHasMore());
|
DmsFileCenterCursorCodec.Cursor decoded = fixture.cursorCodec.decode(result.getNextCursor(), "FOLDER", "tenant-1",
|
"user-1", fixture.folderId, fixture.cursorCodec.fingerprint(null));
|
assertEquals(first.getId(), decoded.getId());
|
assertEquals(first.getSortCode(), decoded.getSortCode());
|
ArgumentCaptor<DmsFileCenterQuery> captor = ArgumentCaptor.forClass(DmsFileCenterQuery.class);
|
verify(fixture.mapper).selectFolders(captor.capture());
|
assertTrue(captor.getValue().isIncludeFolderChildren());
|
assertFalse(captor.getValue().isAdministrator());
|
assertEquals(fixture.folderId, captor.getValue().getParentId());
|
assertEquals("tenant-1", captor.getValue().getTenantId());
|
assertEquals("user-1", captor.getValue().getUserId());
|
}
|
|
@Test
|
void folderTreeSupportsRootLeafAndEmptyResults() {
|
Fixture fixture = new Fixture(true);
|
DmsFileCenterItemVO leaf = folder("A", fixture.firstId);
|
leaf.setHasChildren(false);
|
when(fixture.mapper.selectFolders(any())).thenReturn(Collections.singletonList(leaf),
|
Collections.emptyList());
|
|
DmsCursorPageVO<DmsFolderTreeNodeVO> root = fixture.service.folderTree(null, null, 20);
|
assertFalse(root.getList().get(0).isHasChildren());
|
assertFalse(root.isHasMore());
|
assertTrue(fixture.service.folderTree(fixture.firstId, null, 20).getList().isEmpty());
|
}
|
|
@Test
|
void folderTreeRejectsInvalidPageSizeAndCursorFromAnotherParentOrUser() {
|
Fixture fixture = new Fixture(true);
|
String cursor = fixture.cursorCodec.encode("FOLDER", "tenant-1", "user-1", fixture.folderId,
|
fixture.cursorCodec.fingerprint(null), new DmsFileCenterCursorCodec.Cursor(
|
"A", null, null, 1024L, fixture.firstId));
|
assertThrows(DmsPermissionException.class, () -> fixture.service.folderTree(null, null, 0));
|
assertThrows(DmsPermissionException.class, () -> fixture.service.folderTree(null, null, 101));
|
assertThrows(DmsPermissionException.class, () -> fixture.service.folderTree(null, cursor, 20));
|
fixture.user.setUserId("user-2");
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.folderTree(fixture.folderId, cursor, 20));
|
verify(fixture.mapper, never()).selectFolders(any());
|
}
|
|
@Test
|
void folderTreeRequiresAuthenticatedUser() {
|
Fixture fixture = new Fixture(false);
|
when(fixture.currentIdentity.requireUser()).thenThrow(new IllegalStateException("not logged in"));
|
assertThrows(IllegalStateException.class, () -> fixture.service.folderTree(null, null, 20));
|
verify(fixture.mapper, never()).selectFolders(any());
|
}
|
|
@Test
|
void resolvesOrdinaryUserSubjectsBeforeFolderQueryAndReturnsKeysetCursor() {
|
Fixture fixture = new Fixture(false);
|
DmsSubjectSet subjects = new DmsSubjectSet();
|
subjects.getDirectOrgIds().add("org-direct");
|
subjects.getAncestorOrgIds().add("org-parent");
|
subjects.getPositionIds().add("position-1");
|
subjects.getRoleIds().add("role-1");
|
subjects.getPermissionGroupIds().add("group-1");
|
when(fixture.subjectResolver.resolve(fixture.user)).thenReturn(subjects);
|
|
DmsFileCenterItemVO first = folder("A", fixture.firstId);
|
DmsFileCenterItemVO second = folder("B", fixture.secondId);
|
DmsFileCenterItemVO overflow = folder("C", fixture.thirdId);
|
when(fixture.mapper.selectFolders(any())).thenReturn(Arrays.asList(first, second, overflow));
|
|
DmsCursorPageVO<DmsFileCenterItemVO> result = fixture.service.rootFolders(null, 2);
|
|
assertEquals(Arrays.asList(first, second), result.getList());
|
assertTrue(result.isHasMore());
|
assertNotNull(result.getNextCursor());
|
verify(fixture.groupResolver).resolveAll(subjects, 1000);
|
|
ArgumentCaptor<DmsFileCenterQuery> queryCaptor = ArgumentCaptor.forClass(DmsFileCenterQuery.class);
|
verify(fixture.mapper).selectFolders(queryCaptor.capture());
|
DmsFileCenterQuery query = queryCaptor.getValue();
|
assertFalse(query.isAdministrator());
|
assertEquals(3, query.getLimit());
|
assertEquals(Collections.singletonList("org-direct"), query.getDirectOrgIds());
|
assertEquals(Collections.singletonList("org-parent"), query.getAncestorOrgIds());
|
assertEquals(Collections.singletonList("position-1"), query.getPositionIds());
|
assertEquals(Collections.singletonList("role-1"), query.getRoleIds());
|
assertEquals(Collections.singletonList("group-1"), query.getPermissionGroupIds());
|
}
|
|
@Test
|
void administratorSkipsSubjectAndPermissionGroupResolution() {
|
Fixture fixture = new Fixture(true);
|
when(fixture.mapper.selectCurrentFiles(any())).thenReturn(Collections.emptyList());
|
|
DmsCursorPageVO<DmsFileCenterItemVO> result = fixture.service.currentDocuments(
|
fixture.folderId, null, null, " report ");
|
|
assertFalse(result.isHasMore());
|
assertEquals(Collections.emptyList(), result.getList());
|
verify(fixture.subjectResolver, never()).resolve(any());
|
verify(fixture.groupResolver, never()).resolveAll(any(DmsSubjectSet.class), any(Integer.class));
|
|
ArgumentCaptor<DmsFileCenterQuery> queryCaptor = ArgumentCaptor.forClass(DmsFileCenterQuery.class);
|
verify(fixture.mapper).selectCurrentFiles(queryCaptor.capture());
|
verify(fixture.mapper, never()).selectCurrentDocuments(any());
|
assertTrue(queryCaptor.getValue().isAdministrator());
|
assertEquals("report", queryCaptor.getValue().getKeyword());
|
assertEquals(21, queryCaptor.getValue().getLimit());
|
}
|
|
@Test
|
void fileNameExistenceChecksExactNameWithoutUsingVersion() {
|
Fixture fixture = new Fixture(true);
|
when(fixture.mapper.fileNameExists("tenant-1", fixture.folderId, "report.pdf"))
|
.thenReturn(true);
|
|
assertTrue(fixture.service.fileNameExists(fixture.folderId, " report.pdf ", "V1"));
|
assertTrue(fixture.service.fileNameExists(fixture.folderId, " report.pdf ", "V2"));
|
|
verify(fixture.mapper, times(2)).fileNameExists("tenant-1", fixture.folderId, "report.pdf");
|
}
|
|
@Test
|
void fileNameExistenceRejectsMissingInputs() {
|
Fixture fixture = new Fixture(true);
|
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.fileNameExists(null, "report.pdf", "V1"));
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.fileNameExists(fixture.folderId, " ", "V1"));
|
verify(fixture.mapper, never()).fileNameExists(any(), any(), any());
|
}
|
|
@Test
|
void fileNameExistenceRequiresFolderCreatePermission() {
|
Fixture fixture = new Fixture(false);
|
|
fixture.service.fileNameExists(fixture.folderId, "report.pdf", "V1");
|
|
verify(fixture.decisionService).requireAllowed(
|
DmsResourceType.FOLDER, fixture.folderId, DmsPermissionAction.CREATE);
|
verify(fixture.mapper).fileNameExists("tenant-1", fixture.folderId, "report.pdf");
|
}
|
|
@Test
|
void folderBrowsingWithoutKeywordKeepsDocumentContainerQuery() {
|
Fixture fixture = new Fixture(true);
|
when(fixture.mapper.selectHistoricalVersions(any())).thenReturn(Collections.emptyList());
|
|
fixture.service.historicalVersions(fixture.folderId, null, 20, " ");
|
|
verify(fixture.mapper).selectHistoricalVersions(any());
|
verify(fixture.mapper, never()).selectHistoricalFiles(any());
|
}
|
|
@Test
|
void historicalSearchUsesActualFileVersionQuery() {
|
Fixture fixture = new Fixture(true);
|
when(fixture.mapper.selectHistoricalFiles(any())).thenReturn(Collections.emptyList());
|
|
fixture.service.historicalVersions(fixture.folderId, null, 20, " report ");
|
|
ArgumentCaptor<DmsFileCenterQuery> queryCaptor = ArgumentCaptor.forClass(DmsFileCenterQuery.class);
|
verify(fixture.mapper).selectHistoricalFiles(queryCaptor.capture());
|
verify(fixture.mapper, never()).selectHistoricalVersions(any());
|
assertEquals("report", queryCaptor.getValue().getKeyword());
|
}
|
|
@Test
|
void rejectsUnknownSharedCenterBeforeCallingMapper() {
|
Fixture fixture = new Fixture(true);
|
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.sharedDocuments("ARCHIVE", null, 20));
|
|
verify(fixture.mapper, never()).selectSharedDocuments(any());
|
verify(fixture.mapper, never()).selectSharedHistoricalVersions(any());
|
}
|
|
@Test
|
void currentDocumentDirectoryUsesCurrentVersionQuery() {
|
Fixture fixture = new Fixture(true);
|
when(fixture.mapper.selectCurrentDocumentVersions(any())).thenReturn(Collections.emptyList());
|
|
fixture.service.documentVersions(fixture.firstId, "CURRENT", null, 20, " report ");
|
|
ArgumentCaptor<DmsFileCenterQuery> queryCaptor = ArgumentCaptor.forClass(DmsFileCenterQuery.class);
|
verify(fixture.mapper).selectCurrentDocumentVersions(queryCaptor.capture());
|
verify(fixture.mapper, never()).selectDocumentVersions(any());
|
assertEquals(fixture.firstId, queryCaptor.getValue().getDocumentId());
|
assertEquals("report", queryCaptor.getValue().getKeyword());
|
}
|
|
@Test
|
void historicalDocumentDirectoryUsesTerminalVersionQuery() {
|
Fixture fixture = new Fixture(true);
|
when(fixture.mapper.selectDocumentVersions(any())).thenReturn(Collections.emptyList());
|
|
fixture.service.documentVersions(fixture.firstId, "HISTORICAL", null, 20, null);
|
|
verify(fixture.mapper).selectDocumentVersions(any());
|
verify(fixture.mapper, never()).selectCurrentDocumentVersions(any());
|
}
|
|
private static DmsFileCenterItemVO folder(String name, UUID id) {
|
DmsFileCenterItemVO value = new DmsFileCenterItemVO();
|
value.setId(id);
|
value.setName(name);
|
value.setResourceType("Folder");
|
value.setSortCode((long) name.charAt(0) * 1024);
|
return value;
|
}
|
|
private static class Fixture {
|
private final UUID folderId = UUID.fromString("018f0000-0000-7000-8000-000000000201");
|
private final UUID firstId = UUID.fromString("018f0000-0000-7000-8000-000000000202");
|
private final UUID secondId = UUID.fromString("018f0000-0000-7000-8000-000000000203");
|
private final UUID thirdId = UUID.fromString("018f0000-0000-7000-8000-000000000204");
|
private final UserInfo user = new UserInfo();
|
private final DmsCurrentIdentity currentIdentity = mock(DmsCurrentIdentity.class);
|
private final DmsSubjectResolver subjectResolver = mock(DmsSubjectResolver.class);
|
private final DmsPermissionGroupMembershipResolver groupResolver =
|
mock(DmsPermissionGroupMembershipResolver.class);
|
private final DmsPermissionProperties properties = properties();
|
private final DmsFileCenterCursorCodec cursorCodec = new DmsFileCenterCursorCodec(properties);
|
private final DmsFileCenterMapper mapper = mock(DmsFileCenterMapper.class);
|
private final DmsPermissionDecisionService decisionService = mock(DmsPermissionDecisionService.class);
|
private final DmsFileCenterService service = new DmsFileCenterService(
|
currentIdentity, subjectResolver, groupResolver, properties, cursorCodec, mapper,
|
decisionService);
|
|
private Fixture(boolean administrator) {
|
user.setUserId("user-1");
|
user.setTenantId("tenant-1");
|
when(currentIdentity.requireUser()).thenReturn(user);
|
when(currentIdentity.tenantId(user)).thenReturn("tenant-1");
|
when(currentIdentity.isPermissionAdministrator()).thenReturn(administrator);
|
}
|
|
private static DmsPermissionProperties properties() {
|
DmsPermissionProperties value = new DmsPermissionProperties();
|
value.setDefaultPageSize(20);
|
value.setMaxPageSize(100);
|
value.setMaxPermissionGroupScan(1000);
|
value.setCursorSigningSecret("0123456789abcdef0123456789abcdef");
|
return value;
|
}
|
}
|
}
|