package jnpf.dmsService; import jnpf.base.UserInfo; import jnpf.dmsEntity.permission.entity.DmsFolderEntity; import jnpf.dmsEntity.permission.entity.DmsPermissionResourceEntity; import jnpf.dmsEntity.permission.enums.DmsPermissionAction; import jnpf.dmsEntity.permission.enums.DmsResourceType; import jnpf.dmsEntity.permission.form.FolderCreateUserForm; import jnpf.dmsEntity.permission.vo.DmsPermissionResourceVO; import jnpf.dmsIntegration.audit.DmsAuditAdapter; import jnpf.dmsMapper.DmsDocumentMapper; import jnpf.dmsMapper.DmsFileVersionMapper; import jnpf.dmsMapper.DmsFolderMapper; import jnpf.dmsMapper.DmsPermissionResourceMapper; import jnpf.dmsPermission.DmsCurrentIdentity; import jnpf.dmsPermission.DmsPermissionError; import jnpf.dmsPermission.DmsPermissionException; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; 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.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class DmsResourceServiceTest { @Test void createsChildFolderAfterCheckingParentPermission() { Fixture fixture = new Fixture(); FolderCreateUserForm form = fixture.form(); DmsPermissionResourceVO created = new DmsPermissionResourceVO(); created.setId(fixture.folderId); when(fixture.resourceMapper.nextUuidV7()).thenReturn(fixture.folderId); when(fixture.resourceMapper.selectView("tenant-1", fixture.folderId)).thenReturn(created); DmsPermissionResourceVO result = fixture.service.createFolder(form); assertSame(created, result); verify(fixture.decisionService).requireAllowed( DmsResourceType.FOLDER, fixture.parentId, DmsPermissionAction.CREATE); verify(fixture.resourceMapper).lockSource( "tenant-1", "SYSTEM", "web-folder:request-1"); ArgumentCaptor folderCaptor = ArgumentCaptor.forClass(DmsFolderEntity.class); verify(fixture.folderMapper).insert(folderCaptor.capture()); DmsFolderEntity folder = folderCaptor.getValue(); assertEquals(fixture.folderId, folder.getId()); assertEquals(fixture.parentId, folder.getParentId()); assertEquals("Child Folder", folder.getName()); assertEquals("tenant-1", folder.getTenantId()); assertEquals("user-1", folder.getCreatedBy()); ArgumentCaptor registryCaptor = ArgumentCaptor.forClass(DmsPermissionResourceEntity.class); verify(fixture.resourceMapper).insert(registryCaptor.capture()); DmsPermissionResourceEntity registry = registryCaptor.getValue(); assertEquals(fixture.folderId, registry.getId()); assertEquals("FOLDER", registry.getResourceType()); assertEquals("SYSTEM", registry.getSourceType()); assertEquals("web-folder:request-1", registry.getSourceId()); assertEquals("jnpf-dms-web", registry.getRegisteredBy()); verify(fixture.permissionGrantService).ensureFolderCreatorCreatePermission( "tenant-1", fixture.folderId, "user-1"); } @Test void returnsSameFolderForIdempotentRetry() { Fixture fixture = new Fixture(); FolderCreateUserForm form = fixture.form(); DmsPermissionResourceEntity registry = new DmsPermissionResourceEntity(); registry.setId(fixture.folderId); registry.setResourceType("FOLDER"); registry.setSourceType("SYSTEM"); registry.setSourceId("web-folder:request-1"); registry.setRegisteredBy("jnpf-dms-web"); DmsFolderEntity folder = new DmsFolderEntity(); folder.setId(fixture.folderId); folder.setTenantId("tenant-1"); folder.setParentId(fixture.parentId); folder.setName("Child Folder"); folder.setCreatedBy("user-1"); DmsPermissionResourceVO existing = new DmsPermissionResourceVO(); existing.setId(fixture.folderId); when(fixture.resourceMapper.selectBySource( "tenant-1", "SYSTEM", "web-folder:request-1")).thenReturn(registry); when(fixture.folderMapper.selectByTenantAndId("tenant-1", fixture.folderId)).thenReturn(folder); when(fixture.resourceMapper.selectView("tenant-1", fixture.folderId)).thenReturn(existing); DmsPermissionResourceVO result = fixture.service.createFolder(form); assertSame(existing, result); verify(fixture.resourceMapper, never()).nextUuidV7(); verify(fixture.folderMapper, never()).insert(any(DmsFolderEntity.class)); verify(fixture.resourceMapper, never()).insert(any(DmsPermissionResourceEntity.class)); verify(fixture.permissionGrantService).ensureFolderCreatorCreatePermission( "tenant-1", fixture.folderId, "user-1"); } @Test void rejectsRootFolderCreationFromWebApi() { Fixture fixture = new Fixture(); FolderCreateUserForm form = fixture.form(); form.setParentId(null); DmsPermissionException exception = assertThrows( DmsPermissionException.class, () -> fixture.service.createFolder(form)); assertEquals(DmsPermissionError.INVALID_RESOURCE_PARENT, exception.getError()); verify(fixture.decisionService, never()).requireAllowed(any(), any(), any()); verify(fixture.folderMapper, never()).insert(any(DmsFolderEntity.class)); verify(fixture.permissionGrantService, never()).ensureFolderCreatorCreatePermission(any(), any(), any()); } private static class Fixture { private final UUID parentId = UUID.fromString("018f0000-0000-7000-8000-000000000401"); private final UUID folderId = UUID.fromString("018f0000-0000-7000-8000-000000000402"); private final DmsCurrentIdentity currentIdentity = mock(DmsCurrentIdentity.class); private final DmsPermissionDecisionService decisionService = mock(DmsPermissionDecisionService.class); private final DmsFolderMapper folderMapper = mock(DmsFolderMapper.class); private final DmsDocumentMapper documentMapper = mock(DmsDocumentMapper.class); private final DmsFileVersionMapper fileVersionMapper = mock(DmsFileVersionMapper.class); private final DmsPermissionResourceMapper resourceMapper = mock(DmsPermissionResourceMapper.class); private final DmsPermissionGrantService permissionGrantService = mock(DmsPermissionGrantService.class); private final DmsAuditAdapter auditAdapter = mock(DmsAuditAdapter.class); private final DmsResourceService service = new DmsResourceService( currentIdentity, decisionService, folderMapper, documentMapper, fileVersionMapper, resourceMapper, permissionGrantService, auditAdapter); private Fixture() { UserInfo user = new UserInfo(); user.setUserId("user-1"); user.setTenantId("tenant-1"); when(currentIdentity.requireUser()).thenReturn(user); when(currentIdentity.tenantId(user)).thenReturn("tenant-1"); } private FolderCreateUserForm form() { FolderCreateUserForm form = new FolderCreateUserForm(); form.setParentId(parentId); form.setName(" Child Folder "); form.setSourceId("request-1"); return form; } } }