package jnpf.dmsService; import jnpf.base.UserInfo; import jnpf.dmsEntity.permission.entity.DmsFolderEntity; import jnpf.dmsEntity.permission.enums.DmsFolderReorderDirection; import jnpf.dmsEntity.permission.form.FolderCopyForm; import jnpf.dmsEntity.permission.form.FolderMoveForm; import jnpf.dmsEntity.permission.form.FolderReorderForm; import jnpf.dmsEntity.permission.vo.DmsPermissionResourceVO; import jnpf.dmsIntegration.audit.DmsAuditAdapter; import jnpf.dmsIntegration.audit.DmsFolderAuditEvent; import jnpf.dmsMapper.DmsFolderMapper; import jnpf.dmsMapper.DmsPermissionResourceMapper; import jnpf.dmsMapper.DmsPermissionRevisionMapper; import jnpf.dmsPermission.DmsCurrentIdentity; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import java.util.Arrays; 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.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class DmsFolderManagementServiceTest { @Test void reorderSwapsOnlySiblingSortCodesWithoutChangingPermissions() { Fixture fixture = new Fixture(); DmsFolderEntity folder = fixture.folder(fixture.folderId, fixture.parentId, 2048L, 4L); DmsFolderEntity previous = fixture.folder(fixture.previousId, fixture.parentId, 1024L, 7L); DmsPermissionResourceVO view = new DmsPermissionResourceVO(); view.setId(fixture.folderId); when(fixture.folderMapper.selectByTenantAndId("tenant-1", fixture.folderId)).thenReturn(folder); when(fixture.folderMapper.selectByTenantAndIdForUpdate("tenant-1", fixture.folderId)).thenReturn(folder); when(fixture.folderMapper.selectPreviousForUpdate( "tenant-1", fixture.parentId, 2048L, fixture.folderId)).thenReturn(previous); when(fixture.folderMapper.reorder( "tenant-1", fixture.folderId, 1024L, 4L, "user-1")).thenReturn(1); when(fixture.folderMapper.reorder( "tenant-1", fixture.previousId, 2048L, 7L, "user-1")).thenReturn(1); when(fixture.resourceMapper.selectView("tenant-1", fixture.folderId)).thenReturn(view); FolderReorderForm form = new FolderReorderForm(); form.setDirection(DmsFolderReorderDirection.UP); form.setRevision(4L); DmsPermissionResourceVO result = fixture.service.reorder(fixture.folderId, form); assertSame(view, result); verify(fixture.folderMapper).reorder( "tenant-1", fixture.folderId, 1024L, 4L, "user-1"); verify(fixture.folderMapper).reorder( "tenant-1", fixture.previousId, 2048L, 7L, "user-1"); verify(fixture.permissionRevisionMapper, never()).bump(anyString()); verify(fixture.permissionGrantService, never()) .ensureFolderCreatorCreatePermission(anyString(), org.mockito.ArgumentMatchers.any(), anyString()); } @Test void cutPasteKeepsFolderIdentityAndBumpsPermissionRevision() { Fixture fixture = new Fixture(); DmsFolderEntity folder = fixture.folder(fixture.folderId, fixture.parentId, 2048L, 4L); DmsFolderEntity target = fixture.folder(fixture.targetId, null, 1024L, 2L); DmsPermissionResourceVO view = new DmsPermissionResourceVO(); view.setId(fixture.folderId); when(fixture.folderMapper.selectByTenantAndId("tenant-1", fixture.folderId)).thenReturn(folder); when(fixture.folderMapper.selectByTenantAndId("tenant-1", fixture.targetId)).thenReturn(target); when(fixture.folderMapper.selectByTenantAndIdForUpdate("tenant-1", fixture.folderId)).thenReturn(folder); when(fixture.folderMapper.selectByTenantAndIdForUpdate("tenant-1", fixture.targetId)).thenReturn(target); when(fixture.folderMapper.nextSortCode("tenant-1", fixture.targetId)).thenReturn(4096L); when(fixture.folderMapper.move( "tenant-1", fixture.folderId, fixture.targetId, 4096L, 4L, "user-1")).thenReturn(1); when(fixture.resourceMapper.selectView("tenant-1", fixture.folderId)).thenReturn(view); FolderMoveForm form = new FolderMoveForm(); form.setParentId(fixture.targetId); form.setRevision(4L); DmsPermissionResourceVO result = fixture.service.move(fixture.folderId, form); assertSame(view, result); verify(fixture.folderMapper).move( "tenant-1", fixture.folderId, fixture.targetId, 4096L, 4L, "user-1"); verify(fixture.permissionRevisionMapper).bump("tenant-1"); ArgumentCaptor auditCaptor = ArgumentCaptor.forClass(DmsFolderAuditEvent.class); verify(fixture.auditAdapter).folderChange(auditCaptor.capture()); assertEquals("UPDATE", auditCaptor.getValue().getActionCode()); assertEquals(fixture.parentId, auditCaptor.getValue().getBefore().getParentId()); assertEquals(fixture.targetId, auditCaptor.getValue().getAfter().getParentId()); verify(fixture.resourceMapper, never()).nextUuidV7(); verify(fixture.permissionGrantService, never()) .ensureFolderCreatorCreatePermission(anyString(), org.mockito.ArgumentMatchers.any(), anyString()); } @Test void copyCreatesFreshFolderStructureWithOnlyCreatorDefaults() { Fixture fixture = new Fixture(); DmsFolderEntity source = fixture.folder(fixture.folderId, fixture.parentId, 1024L, 4L); source.setName("Source"); DmsFolderEntity child = fixture.folder(fixture.childId, fixture.folderId, 2048L, 1L); child.setName("Child"); DmsFolderEntity target = fixture.folder(fixture.targetId, null, 1024L, 2L); DmsPermissionResourceVO view = new DmsPermissionResourceVO(); view.setId(fixture.copyRootId); when(fixture.folderMapper.selectByTenantAndId("tenant-1", fixture.folderId)).thenReturn(source); when(fixture.folderMapper.selectByTenantAndId("tenant-1", fixture.targetId)).thenReturn(target); when(fixture.folderMapper.selectSubtree("tenant-1", fixture.folderId)) .thenReturn(Arrays.asList(source, child)); when(fixture.folderMapper.nextSortCode("tenant-1", fixture.targetId)).thenReturn(4096L); when(fixture.resourceMapper.nextUuidV7()).thenReturn(fixture.copyRootId, fixture.copyChildId); when(fixture.resourceMapper.selectView("tenant-1", fixture.copyRootId)).thenReturn(view); FolderCopyForm form = new FolderCopyForm(); form.setParentId(fixture.targetId); form.setRequestId("copy-request-1"); DmsPermissionResourceVO result = fixture.service.copy(fixture.folderId, form); assertSame(view, result); ArgumentCaptor folderCaptor = ArgumentCaptor.forClass(DmsFolderEntity.class); verify(fixture.folderMapper, times(2)).insert(folderCaptor.capture()); List copies = folderCaptor.getAllValues(); assertEquals(fixture.copyRootId, copies.get(0).getId()); assertEquals(fixture.targetId, copies.get(0).getParentId()); assertEquals("Source - 副本", copies.get(0).getName()); assertEquals(fixture.copyChildId, copies.get(1).getId()); assertEquals(fixture.copyRootId, copies.get(1).getParentId()); assertEquals("Child", copies.get(1).getName()); verify(fixture.permissionGrantService).ensureFolderCreatorCreatePermission( "tenant-1", fixture.copyRootId, "user-1"); verify(fixture.permissionGrantService).ensureFolderCreatorCreatePermission( "tenant-1", fixture.copyChildId, "user-1"); } @Test void deleteSoftDeletesOnlyAnEmptyNonRootFolderAndBumpsPermissionRevision() { Fixture fixture = new Fixture(); DmsFolderEntity folder = fixture.folder(fixture.folderId, fixture.parentId, 1024L, 4L); when(fixture.folderMapper.selectByTenantAndId("tenant-1", fixture.folderId)).thenReturn(folder); when(fixture.folderMapper.selectByTenantAndIdForUpdate("tenant-1", fixture.folderId)).thenReturn(folder); when(fixture.folderMapper.softDelete( "tenant-1", fixture.folderId, 4L, "user-1")).thenReturn(1); fixture.service.delete(fixture.folderId, 4L); verify(fixture.folderMapper).hasContents("tenant-1", fixture.folderId); verify(fixture.folderMapper).softDelete( "tenant-1", fixture.folderId, 4L, "user-1"); verify(fixture.permissionRevisionMapper).bump("tenant-1"); ArgumentCaptor auditCaptor = ArgumentCaptor.forClass(DmsFolderAuditEvent.class); verify(fixture.auditAdapter).folderChange(auditCaptor.capture()); assertEquals("DELETE", auditCaptor.getValue().getActionCode()); assertEquals(fixture.folderId, auditCaptor.getValue().getBefore().getId()); assertEquals(null, auditCaptor.getValue().getAfter()); } private static class Fixture { private final UUID parentId = UUID.fromString("018f0000-0000-7000-8000-000000000501"); private final UUID folderId = UUID.fromString("018f0000-0000-7000-8000-000000000502"); private final UUID previousId = UUID.fromString("018f0000-0000-7000-8000-000000000503"); private final UUID targetId = UUID.fromString("018f0000-0000-7000-8000-000000000504"); private final UUID childId = UUID.fromString("018f0000-0000-7000-8000-000000000505"); private final UUID copyRootId = UUID.fromString("018f0000-0000-7000-8000-000000000506"); private final UUID copyChildId = UUID.fromString("018f0000-0000-7000-8000-000000000507"); private final DmsCurrentIdentity currentIdentity = mock(DmsCurrentIdentity.class); private final DmsFolderMapper folderMapper = mock(DmsFolderMapper.class); private final DmsPermissionResourceMapper resourceMapper = mock(DmsPermissionResourceMapper.class); private final DmsPermissionRevisionMapper permissionRevisionMapper = mock(DmsPermissionRevisionMapper.class); private final DmsPermissionGrantService permissionGrantService = mock(DmsPermissionGrantService.class); private final DmsAuditAdapter auditAdapter = mock(DmsAuditAdapter.class); private final DmsFolderManagementService service = new DmsFolderManagementService( currentIdentity, folderMapper, resourceMapper, permissionRevisionMapper, permissionGrantService, auditAdapter); private Fixture() { UserInfo user = new UserInfo(); user.setTenantId("tenant-1"); user.setUserId("user-1"); when(currentIdentity.requireUser()).thenReturn(user); when(currentIdentity.tenantId(user)).thenReturn("tenant-1"); } private DmsFolderEntity folder(UUID id, UUID parentId, long sortCode, long revision) { DmsFolderEntity folder = new DmsFolderEntity(); folder.setId(id); folder.setTenantId("tenant-1"); folder.setParentId(parentId); folder.setName("Folder-" + id); folder.setCreatedBy("user-1"); folder.setSortCode(sortCode); folder.setRevision(revision); folder.setDeleteMark(null); return folder; } } }