package jnpf.dmsService;
|
|
import jnpf.base.UserInfo;
|
import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity;
|
import jnpf.dmsEntity.permission.form.DmsPersonalFolderBorrowForm;
|
import jnpf.dmsEntity.permission.form.DmsPersonalFolderDownloadForm;
|
import jnpf.dmsEntity.permission.form.DmsPersonalFolderFavoriteForm;
|
import jnpf.dmsEntity.permission.enums.DmsPermissionAction;
|
import jnpf.dmsEntity.permission.enums.DmsResourceType;
|
import jnpf.dmsEntity.permission.vo.DmsPersonalFolderAddResultVO;
|
import jnpf.dmsEntity.permission.vo.DmsPersonalFolderFileVO;
|
import jnpf.dmsEntity.permission.vo.DmsPersonalFolderVO;
|
import jnpf.dmsEntity.print.form.DmsWorkflowPrintFilesGrantForm;
|
import jnpf.dmsEntity.print.vo.DmsWorkflowPrintFilesGrantResultVO;
|
import jnpf.dmsMapper.DmsPersonalFolderMapper;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.dmsPermission.DmsPermissionError;
|
import jnpf.dmsPermission.DmsPermissionException;
|
import jnpf.dmsPermission.DmsPermissionExecutionContext;
|
import jnpf.dmsPermission.DmsPermissionGuard;
|
import jnpf.dmsPermission.DmsPermissionOperation;
|
import jnpf.dmsPermission.DmsPermissionProperties;
|
import org.junit.jupiter.api.Test;
|
import org.mockito.InOrder;
|
import org.mockito.ArgumentCaptor;
|
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.UUID;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.startsWith;
|
import static org.mockito.Mockito.inOrder;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verifyNoInteractions;
|
import static org.mockito.Mockito.when;
|
|
class DmsPersonalFolderServiceTest {
|
private static final UUID DOCUMENT_ID =
|
UUID.fromString("018f0000-0000-7000-8000-000000000701");
|
private static final UUID FILE_VERSION_ID =
|
UUID.fromString("018f0000-0000-7000-8000-000000000702");
|
private static final Date VALID_TO = new Date(4102444800000L);
|
private static final Date LATER_VALID_TO = new Date(4102531200000L);
|
|
@Test
|
void exposesExactlyThreeImmutableFolderDefinitions() {
|
Fixture fixture = new Fixture();
|
|
List<DmsPersonalFolderVO> folders = fixture.service.folders();
|
|
assertEquals(3, folders.size());
|
assertEquals("BORROW", folders.get(0).getCode());
|
assertEquals("借阅", folders.get(0).getName());
|
assertEquals("DOWNLOAD", folders.get(1).getCode());
|
assertEquals("下载", folders.get(1).getName());
|
assertEquals("FAVORITE", folders.get(2).getCode());
|
assertEquals("收藏", folders.get(2).getName());
|
verify(fixture.currentIdentity).requireUser();
|
}
|
|
@Test
|
void loadsFilesOnlyForTheAuthenticatedTenantAndUser() {
|
Fixture fixture = new Fixture();
|
List<DmsPersonalFolderFileVO> expected =
|
Collections.singletonList(new DmsPersonalFolderFileVO());
|
when(fixture.mapper.selectFiles("tenant-1", "user-1", "FAVORITE", "report", 80))
|
.thenReturn(expected);
|
|
List<DmsPersonalFolderFileVO> result = fixture.service.files(
|
" favorite ", " report ", 80);
|
|
assertSame(expected, result);
|
verify(fixture.mapper).selectFiles("tenant-1", "user-1", "FAVORITE", "report", 80);
|
}
|
|
@Test
|
void rejectsFoldersOutsideTheFixedSet() {
|
Fixture fixture = new Fixture();
|
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.files("custom", null, null));
|
}
|
|
@Test
|
void favoritesTheCurrentVersionAfterReadPermissionValidation() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderFavoriteForm form = new DmsPersonalFolderFavoriteForm();
|
form.setDocumentId(DOCUMENT_ID);
|
form.setFileVersionId(FILE_VERSION_ID);
|
form.setOperationId(UUID.fromString("018f0000-0000-7000-8000-000000000703"));
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version(DOCUMENT_ID, FILE_VERSION_ID)));
|
when(fixture.mapper.insertFavoriteSnapshot(
|
"tenant-1", "user-1", DOCUMENT_ID, FILE_VERSION_ID)).thenReturn(1);
|
when(fixture.permissionGuard.execute(any(), any())).thenAnswer(invocation -> {
|
DmsPermissionOperation<Integer> operation = invocation.getArgument(1);
|
return operation.execute();
|
});
|
|
DmsPersonalFolderAddResultVO result = fixture.service.addFavoriteSnapshot(form);
|
|
assertEquals(1, result.getRequestedCount());
|
assertEquals(1, result.getAddedCount());
|
ArgumentCaptor<DmsPermissionExecutionContext> contextCaptor =
|
ArgumentCaptor.forClass(DmsPermissionExecutionContext.class);
|
verify(fixture.permissionGuard).execute(contextCaptor.capture(), any());
|
DmsPermissionExecutionContext context = contextCaptor.getValue();
|
assertEquals(DmsResourceType.FILE_VERSION, context.getResourceType());
|
assertEquals(FILE_VERSION_ID, context.getResourceId());
|
assertEquals(DmsPermissionAction.READ, context.getActionCode());
|
assertEquals(form.getOperationId(), context.getOperationId());
|
verify(fixture.mapper).insertFavoriteSnapshot(
|
"tenant-1", "user-1", DOCUMENT_ID, FILE_VERSION_ID);
|
}
|
|
@Test
|
void doesNotFavoriteTheFileWhenReadPermissionIsDenied() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderFavoriteForm form = new DmsPersonalFolderFavoriteForm();
|
form.setDocumentId(DOCUMENT_ID);
|
form.setFileVersionId(FILE_VERSION_ID);
|
form.setOperationId(UUID.fromString("018f0000-0000-7000-8000-000000000703"));
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version(DOCUMENT_ID, FILE_VERSION_ID)));
|
when(fixture.permissionGuard.execute(any(), any())).thenThrow(
|
DmsPermissionException.of(DmsPermissionError.PERMISSION_DENIED,
|
"当前用户没有所需的 READ 权限"));
|
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.addFavoriteSnapshot(form));
|
|
verify(fixture.mapper, never()).insertFavoriteSnapshot(
|
"tenant-1", "user-1", DOCUMENT_ID, FILE_VERSION_ID);
|
}
|
|
@Test
|
void addsTheApprovedBorrowVersionSnapshotToTheTargetUsersFolder() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderBorrowForm form = borrowForm(DOCUMENT_ID, FILE_VERSION_ID);
|
DmsFileVersionEntity version = version(DOCUMENT_ID, FILE_VERSION_ID);
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version));
|
when(fixture.mapper.insertBorrowSnapshots(
|
"tenant-1", "borrower-1", form.getFiles())).thenReturn(1);
|
|
DmsPersonalFolderAddResultVO result = fixture.service.addBorrowSnapshots(
|
form, "jnpf-flowable");
|
|
assertEquals(1, result.getRequestedCount());
|
assertEquals(1, result.getAddedCount());
|
verify(fixture.mapper).insertBorrowSnapshots(
|
"tenant-1", "borrower-1", form.getFiles());
|
verify(fixture.permissionGrantService).ensureWorkflowBorrowReadPermissions(
|
eq("tenant-1"), startsWith("personal-folder-borrow:"), eq("borrower-1"),
|
eq(Collections.singletonList(FILE_VERSION_ID)), eq(VALID_TO),
|
eq("jnpf-flowable"), eq(Collections.emptyList()));
|
}
|
|
@Test
|
void addsDownloadSnapshotAndGrantsTimeLimitedDownloadPermission() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderDownloadForm form = new DmsPersonalFolderDownloadForm();
|
form.setUserId(" downloader-1 ");
|
DmsPersonalFolderDownloadForm.FileRelation file =
|
new DmsPersonalFolderDownloadForm.FileRelation();
|
file.setDocumentId(DOCUMENT_ID);
|
file.setFileVersionId(FILE_VERSION_ID);
|
file.setValidTo(VALID_TO);
|
form.setFiles(Collections.singletonList(file));
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version(DOCUMENT_ID, FILE_VERSION_ID)));
|
when(fixture.mapper.insertDownloadSnapshots(
|
"tenant-1", "downloader-1", form.getFiles())).thenReturn(1);
|
|
DmsPersonalFolderAddResultVO result = fixture.service.addDownloadSnapshots(
|
form, "jnpf-flowable");
|
|
assertEquals(1, result.getRequestedCount());
|
assertEquals(1, result.getAddedCount());
|
verify(fixture.permissionGrantService).ensureWorkflowDownloadPermissions(
|
eq("tenant-1"), startsWith("personal-folder-download:"), eq("downloader-1"),
|
eq(Collections.singletonList(FILE_VERSION_ID)), eq(VALID_TO),
|
eq("jnpf-flowable"), eq(Collections.emptyList()));
|
verify(fixture.mapper).insertDownloadSnapshots(
|
"tenant-1", "downloader-1", form.getFiles());
|
}
|
|
@Test
|
void downloadApplicationsHaveIndependentSourcesButRetriesReuseSource() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderDownloadForm form = new DmsPersonalFolderDownloadForm();
|
form.setUserId("downloader-1");
|
DmsPersonalFolderDownloadForm.FileRelation file =
|
new DmsPersonalFolderDownloadForm.FileRelation();
|
file.setDocumentId(DOCUMENT_ID);
|
file.setFileVersionId(FILE_VERSION_ID);
|
file.setValidTo(VALID_TO);
|
form.setFiles(Collections.singletonList(file));
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version(DOCUMENT_ID, FILE_VERSION_ID)));
|
form.setRequestId("application-1");
|
fixture.service.addDownloadSnapshots(form, "jnpf-flowable");
|
fixture.service.addDownloadSnapshots(form, "jnpf-flowable");
|
form.setRequestId("application-2");
|
fixture.service.addDownloadSnapshots(form, "jnpf-flowable");
|
ArgumentCaptor<String> sources = ArgumentCaptor.forClass(String.class);
|
org.mockito.Mockito.verify(fixture.permissionGrantService, org.mockito.Mockito.times(3))
|
.ensureWorkflowDownloadPermissions(eq("tenant-1"), sources.capture(),
|
eq("downloader-1"), eq(Collections.singletonList(FILE_VERSION_ID)),
|
eq(VALID_TO), eq("jnpf-flowable"), eq(Collections.emptyList()));
|
assertEquals(sources.getAllValues().get(0), sources.getAllValues().get(1));
|
org.junit.jupiter.api.Assertions.assertNotEquals(
|
sources.getAllValues().get(0), sources.getAllValues().get(2));
|
}
|
|
@Test
|
void grantsPrintPermissionWithoutAddingAPersonalFolderItem() {
|
Fixture fixture = new Fixture();
|
DmsWorkflowPrintFilesGrantForm form = new DmsWorkflowPrintFilesGrantForm();
|
form.setUserId(" printer-1 ");
|
DmsWorkflowPrintFilesGrantForm.FileRelation file =
|
new DmsWorkflowPrintFilesGrantForm.FileRelation();
|
file.setDocumentId(DOCUMENT_ID);
|
file.setFileVersionId(FILE_VERSION_ID);
|
file.setValidTo(VALID_TO);
|
form.setFiles(Collections.singletonList(file));
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version(DOCUMENT_ID, FILE_VERSION_ID)));
|
|
DmsWorkflowPrintFilesGrantResultVO result = fixture.service.grantPrintPermissions(
|
form, "jnpf-flowable");
|
|
assertEquals(1, result.getRequestedCount());
|
assertEquals(1, result.getAuthorizedCount());
|
verify(fixture.permissionGrantService).ensureWorkflowPrintPermissions(
|
eq("tenant-1"), startsWith("workflow-print-files:"), eq("printer-1"),
|
eq(Collections.singletonList(FILE_VERSION_ID)), eq(VALID_TO),
|
eq("jnpf-flowable"), eq(Collections.emptyList()));
|
verify(fixture.mapper, never()).insertDownloadSnapshots(
|
eq("tenant-1"), eq("printer-1"), eq(form.getFiles()));
|
}
|
|
@Test
|
void collapsesExactDuplicatesButReportsTheOriginalRequestCount() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderBorrowForm form = borrowForm(DOCUMENT_ID, FILE_VERSION_ID);
|
DmsPersonalFolderBorrowForm.FileRelation duplicate =
|
relation(DOCUMENT_ID, FILE_VERSION_ID);
|
form.setFiles(Arrays.asList(form.getFiles().get(0), duplicate));
|
DmsFileVersionEntity version = version(DOCUMENT_ID, FILE_VERSION_ID);
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version));
|
when(fixture.mapper.insertBorrowSnapshots(
|
"tenant-1", "borrower-1",
|
Collections.singletonList(form.getFiles().get(0))))
|
.thenReturn(1);
|
|
DmsPersonalFolderAddResultVO result = fixture.service.addBorrowSnapshots(
|
form, "jnpf-flowable");
|
|
assertEquals(2, result.getRequestedCount());
|
assertEquals(1, result.getAddedCount());
|
verify(fixture.mapper).insertBorrowSnapshots(
|
"tenant-1", "borrower-1",
|
Collections.singletonList(form.getFiles().get(0)));
|
}
|
|
@Test
|
void rejectsAFileVersionThatDoesNotBelongToTheSuppliedDocument() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderBorrowForm form = borrowForm(DOCUMENT_ID, FILE_VERSION_ID);
|
UUID otherDocumentId = UUID.fromString("018f0000-0000-7000-8000-000000000703");
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version(otherDocumentId, FILE_VERSION_ID)));
|
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.addBorrowSnapshots(form, "jnpf-flowable"));
|
|
verify(fixture.mapper, never()).insertBorrowSnapshots(
|
"tenant-1", "borrower-1", form.getFiles());
|
}
|
|
@Test
|
void rejectsMultipleVersionsOfTheSameDocument() {
|
Fixture fixture = new Fixture();
|
UUID secondVersionId = UUID.fromString("018f0000-0000-7000-8000-000000000704");
|
DmsPersonalFolderBorrowForm form = borrowForm(DOCUMENT_ID, FILE_VERSION_ID);
|
form.setFiles(Arrays.asList(
|
form.getFiles().get(0), relation(DOCUMENT_ID, secondVersionId)));
|
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.addBorrowSnapshots(form, "jnpf-flowable"));
|
|
verify(fixture.mapper, never()).selectReadableVersions(
|
"tenant-1", Arrays.asList(FILE_VERSION_ID, secondVersionId));
|
}
|
|
@Test
|
void rejectsAnExpiredBorrowValidityBeforeGrantingPermission() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderBorrowForm form = borrowForm(DOCUMENT_ID, FILE_VERSION_ID);
|
form.getFiles().get(0).setValidTo(new Date(0));
|
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.addBorrowSnapshots(form, "jnpf-flowable"));
|
|
verifyNoInteractions(fixture.permissionGrantService);
|
}
|
|
@Test
|
void grantsPermanentReadPermissionWhenFileValidityIsNull() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderBorrowForm form = borrowForm(DOCUMENT_ID, FILE_VERSION_ID);
|
form.getFiles().get(0).setValidTo(null);
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID)))
|
.thenReturn(Collections.singletonList(version(DOCUMENT_ID, FILE_VERSION_ID)));
|
when(fixture.mapper.insertBorrowSnapshots(
|
"tenant-1", "borrower-1", form.getFiles())).thenReturn(1);
|
|
DmsPersonalFolderAddResultVO result = fixture.service.addBorrowSnapshots(
|
form, "jnpf-flowable");
|
|
assertEquals(1, result.getAddedCount());
|
verify(fixture.permissionGrantService).ensureWorkflowBorrowReadPermissions(
|
eq("tenant-1"), startsWith("personal-folder-borrow:"), eq("borrower-1"),
|
eq(Collections.singletonList(FILE_VERSION_ID)), eq(null),
|
eq("jnpf-flowable"), eq(Collections.emptyList()));
|
verify(fixture.mapper).insertBorrowSnapshots(
|
"tenant-1", "borrower-1", form.getFiles());
|
}
|
|
@Test
|
void grantsEachFileUsingItsOwnValidityInDeterministicOrder() {
|
Fixture fixture = new Fixture();
|
UUID secondDocumentId = UUID.fromString("018f0000-0000-7000-8000-000000000705");
|
UUID secondVersionId = UUID.fromString("018f0000-0000-7000-8000-000000000706");
|
DmsPersonalFolderBorrowForm form = new DmsPersonalFolderBorrowForm();
|
form.setUserId("borrower-1");
|
form.setFiles(Arrays.asList(
|
relation(secondDocumentId, secondVersionId, LATER_VALID_TO),
|
relation(DOCUMENT_ID, FILE_VERSION_ID, VALID_TO)));
|
when(fixture.mapper.selectReadableVersions(
|
"tenant-1", Arrays.asList(secondVersionId, FILE_VERSION_ID)))
|
.thenReturn(Arrays.asList(
|
version(secondDocumentId, secondVersionId),
|
version(DOCUMENT_ID, FILE_VERSION_ID)));
|
when(fixture.mapper.insertBorrowSnapshots(
|
"tenant-1", "borrower-1", form.getFiles())).thenReturn(2);
|
|
DmsPersonalFolderAddResultVO result = fixture.service.addBorrowSnapshots(
|
form, "jnpf-flowable");
|
|
assertEquals(2, result.getAddedCount());
|
InOrder grants = inOrder(fixture.permissionGrantService);
|
grants.verify(fixture.permissionGrantService).ensureWorkflowBorrowReadPermissions(
|
eq("tenant-1"), startsWith("personal-folder-borrow:"), eq("borrower-1"),
|
eq(Collections.singletonList(FILE_VERSION_ID)), eq(VALID_TO),
|
eq("jnpf-flowable"), eq(Collections.emptyList()));
|
grants.verify(fixture.permissionGrantService).ensureWorkflowBorrowReadPermissions(
|
eq("tenant-1"), startsWith("personal-folder-borrow:"), eq("borrower-1"),
|
eq(Collections.singletonList(secondVersionId)), eq(LATER_VALID_TO),
|
eq("jnpf-flowable"), eq(Collections.emptyList()));
|
}
|
|
@Test
|
void rejectsDifferentValiditiesForTheSameFileVersion() {
|
Fixture fixture = new Fixture();
|
DmsPersonalFolderBorrowForm form = borrowForm(DOCUMENT_ID, FILE_VERSION_ID);
|
form.setFiles(Arrays.asList(
|
form.getFiles().get(0), relation(DOCUMENT_ID, FILE_VERSION_ID, LATER_VALID_TO)));
|
|
assertThrows(DmsPermissionException.class,
|
() -> fixture.service.addBorrowSnapshots(form, "jnpf-flowable"));
|
|
verify(fixture.mapper, never()).selectReadableVersions(
|
"tenant-1", Collections.singletonList(FILE_VERSION_ID));
|
verifyNoInteractions(fixture.permissionGrantService);
|
}
|
|
private static DmsPersonalFolderBorrowForm borrowForm(
|
UUID documentId, UUID fileVersionId) {
|
DmsPersonalFolderBorrowForm form = new DmsPersonalFolderBorrowForm();
|
form.setUserId(" borrower-1 ");
|
form.setFiles(Collections.singletonList(relation(documentId, fileVersionId)));
|
return form;
|
}
|
|
private static DmsPersonalFolderBorrowForm.FileRelation relation(
|
UUID documentId, UUID fileVersionId) {
|
return relation(documentId, fileVersionId, VALID_TO);
|
}
|
|
private static DmsPersonalFolderBorrowForm.FileRelation relation(
|
UUID documentId, UUID fileVersionId, Date validTo) {
|
DmsPersonalFolderBorrowForm.FileRelation relation =
|
new DmsPersonalFolderBorrowForm.FileRelation();
|
relation.setDocumentId(documentId);
|
relation.setFileVersionId(fileVersionId);
|
relation.setValidTo(validTo);
|
return relation;
|
}
|
|
private static DmsFileVersionEntity version(UUID documentId, UUID fileVersionId) {
|
DmsFileVersionEntity version = new DmsFileVersionEntity();
|
version.setId(fileVersionId);
|
version.setDocumentId(documentId);
|
return version;
|
}
|
|
private static class Fixture {
|
private final DmsCurrentIdentity currentIdentity = mock(DmsCurrentIdentity.class);
|
private final DmsPermissionProperties properties = mock(DmsPermissionProperties.class);
|
private final DmsPersonalFolderMapper mapper = mock(DmsPersonalFolderMapper.class);
|
private final DmsPermissionGrantService permissionGrantService =
|
mock(DmsPermissionGrantService.class);
|
private final DmsPermissionGuard permissionGuard = mock(DmsPermissionGuard.class);
|
private final UserInfo user = new UserInfo();
|
private final DmsPersonalFolderService service =
|
new DmsPersonalFolderService(currentIdentity, properties, mapper,
|
permissionGrantService, permissionGuard);
|
|
private Fixture() {
|
user.setUserId("user-1");
|
when(currentIdentity.requireUser()).thenReturn(user);
|
when(currentIdentity.tenantId(user)).thenReturn("tenant-1");
|
when(properties.getDefaultPageSize()).thenReturn(50);
|
when(properties.getMaxPageSize()).thenReturn(100);
|
}
|
}
|
}
|