package jnpf.dmsService; import jnpf.dmsEntity.permission.entity.DmsFilePermissionEntity; import jnpf.dmsEntity.permission.entity.DmsPermissionResourceEntity; import jnpf.dmsIntegration.audit.DmsAuditAdapter; import jnpf.dmsMapper.DmsFilePermissionMapper; import jnpf.dmsMapper.DmsPermissionResourceMapper; import jnpf.dmsPermission.DmsCurrentIdentity; import jnpf.dmsPermission.DmsPermissionError; import jnpf.dmsPermission.DmsPermissionException; import jnpf.dmsPermission.DmsPermissionProperties; import jnpf.dmsPermission.DmsPrincipalValidator; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import java.util.Collections; import java.util.Date; import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; 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.ArgumentMatchers.eq; 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 DmsPermissionGrantServiceTest { private static final String TENANT_ID = "tenant-1"; private static final String CREATOR_ID = "user-1"; private static final UUID FOLDER_ID = UUID.fromString("018f0000-0000-7000-8000-000000000402"); private static final UUID PERMISSION_ID = UUID.fromString("018f0000-0000-7000-8000-000000000403"); private static final String SOURCE_ID = "folder-creator-create:" + FOLDER_ID; private static final String GRANT_REASON = "目录创建者默认 CREATE 权限"; @Test void grantsSelfCreatePermissionToFolderCreator() { Fixture fixture = new Fixture(); when(fixture.permissionMapper.selectBySource(TENANT_ID, "SYSTEM", SOURCE_ID)) .thenReturn(Collections.emptyList()); when(fixture.permissionMapper.insertReturning(any(DmsFilePermissionEntity.class))) .thenAnswer(invocation -> { DmsFilePermissionEntity entity = invocation.getArgument(0); entity.setId(PERMISSION_ID); return entity; }); DmsFilePermissionEntity result = fixture.service.ensureFolderCreatorCreatePermission( TENANT_ID, FOLDER_ID, CREATOR_ID); assertEquals(PERMISSION_ID, result.getId()); verify(fixture.permissionMapper).lockSource(TENANT_ID, "SYSTEM", SOURCE_ID); ArgumentCaptor captor = ArgumentCaptor.forClass(DmsFilePermissionEntity.class); verify(fixture.permissionMapper).insertReturning(captor.capture()); DmsFilePermissionEntity permission = captor.getValue(); assertEquals(TENANT_ID, permission.getTenantId()); assertEquals("FOLDER", permission.getResourceType()); assertEquals(FOLDER_ID, permission.getResourceId()); assertEquals("SELF", permission.getResourceScope()); assertEquals("USER", permission.getPrincipalType()); assertEquals(CREATOR_ID, permission.getPrincipalId()); assertEquals(Boolean.FALSE, permission.getIncludeChildOrgs()); assertEquals("CREATE", permission.getActionCode()); assertEquals("SYSTEM", permission.getSourceType()); assertEquals(SOURCE_ID, permission.getSourceId()); assertNotNull(permission.getValidFrom()); assertEquals(GRANT_REASON, permission.getGrantReason()); assertEquals("USER", permission.getGrantedByType()); assertEquals(CREATOR_ID, permission.getGrantedById()); verify(fixture.currentIdentity, never()).requirePermissionAdministrator(); verify(fixture.principalValidator, never()).validate(any()); verify(fixture.auditAdapter).permissionChange(eq("PERMISSION_GRANT"), eq("授予 DMS 目录创建者默认权限"), eq(Collections.emptyList()), any(), eq(Collections.emptyList())); } @Test void keepsRevokedPermissionRevokedOnIdempotentRetry() { Fixture fixture = new Fixture(); DmsFilePermissionEntity existing = matchingPermission(); existing.setRevokedAt(new Date()); when(fixture.permissionMapper.selectBySource(TENANT_ID, "SYSTEM", SOURCE_ID)) .thenReturn(Collections.singletonList(existing)); DmsFilePermissionEntity result = fixture.service.ensureFolderCreatorCreatePermission( TENANT_ID, FOLDER_ID, CREATOR_ID); assertSame(existing, result); verify(fixture.permissionMapper, never()).insertReturning(any(DmsFilePermissionEntity.class)); verify(fixture.auditAdapter, never()).permissionChange(any(), any(), any(), any(), any()); } @Test void rejectsMismatchedPermissionUsingSameSource() { Fixture fixture = new Fixture(); DmsFilePermissionEntity existing = matchingPermission(); existing.setActionCode("READ"); when(fixture.permissionMapper.selectBySource(TENANT_ID, "SYSTEM", SOURCE_ID)) .thenReturn(Collections.singletonList(existing)); DmsPermissionException exception = assertThrows(DmsPermissionException.class, () -> fixture.service.ensureFolderCreatorCreatePermission(TENANT_ID, FOLDER_ID, CREATOR_ID)); assertEquals(DmsPermissionError.SOURCE_CONFLICT, exception.getError()); verify(fixture.permissionMapper, never()).insertReturning(any(DmsFilePermissionEntity.class)); } @Test void grantsSingleUseWorkflowDownloadPermissionAsService() { Fixture fixture = new Fixture(); UUID fileVersionId = UUID.fromString("018f0000-0000-7000-8000-000000000404"); String sourceId = "download-request:request-1"; DmsPermissionResourceEntity resource = new DmsPermissionResourceEntity(); resource.setId(fileVersionId); resource.setResourceType("FILE_VERSION"); when(fixture.permissionMapper.selectBySource(TENANT_ID, "WORKFLOW", sourceId)) .thenReturn(Collections.emptyList()); when(fixture.resourceMapper.selectByTenantAndIds(TENANT_ID, Collections.singletonList(fileVersionId))).thenReturn(Collections.singletonList(resource)); when(fixture.permissionMapper.insertReturning(any(DmsFilePermissionEntity.class))) .thenAnswer(invocation -> { DmsFilePermissionEntity permission = invocation.getArgument(0); permission.setId(PERMISSION_ID); return permission; }); DmsFilePermissionEntity result = fixture.service.ensureWorkflowDownloadPermissions( TENANT_ID, sourceId, CREATOR_ID, Collections.singletonList(fileVersionId), "jnpf-file", Collections.emptyList()).get(0); assertEquals("FILE_VERSION", result.getResourceType()); assertEquals(fileVersionId, result.getResourceId()); assertEquals("USER", result.getPrincipalType()); assertEquals(CREATOR_ID, result.getPrincipalId()); assertEquals("DOWNLOAD", result.getActionCode()); assertEquals("WORKFLOW", result.getSourceType()); assertEquals(sourceId, result.getSourceId()); assertEquals(null, result.getValidTo()); assertEquals(Long.valueOf(1L), result.getMaxUseCount()); assertEquals("SERVICE", result.getGrantedByType()); assertEquals("jnpf-file", result.getGrantedById()); verify(fixture.principalValidator).validate(any()); verify(fixture.currentIdentity, never()).requirePermissionAdministrator(); // 审批回调重试不能恢复已消耗的下载次数。 result.setUsedCount(1L); when(fixture.permissionMapper.selectBySource(TENANT_ID, "WORKFLOW", sourceId)) .thenReturn(Collections.singletonList(result)); DmsFilePermissionEntity replay = fixture.service.ensureWorkflowDownloadPermissions( TENANT_ID, sourceId, CREATOR_ID, Collections.singletonList(fileVersionId), "jnpf-file", Collections.emptyList()).get(0); assertSame(result, replay); assertEquals(Long.valueOf(1L), replay.getUsedCount()); verify(fixture.permissionMapper).insertReturning(any(DmsFilePermissionEntity.class)); } @Test void grantsTimeLimitedWorkflowDownloadPermissionAsService() { Fixture fixture = new Fixture(); UUID fileVersionId = UUID.fromString("018f0000-0000-7000-8000-000000000408"); String sourceId = "personal-folder-download:request-1"; Date validTo = new Date(4102444800000L); DmsPermissionResourceEntity resource = new DmsPermissionResourceEntity(); resource.setId(fileVersionId); resource.setResourceType("FILE_VERSION"); when(fixture.permissionMapper.selectBySource(TENANT_ID, "WORKFLOW", sourceId)) .thenReturn(Collections.emptyList()); when(fixture.resourceMapper.selectByTenantAndIds(TENANT_ID, Collections.singletonList(fileVersionId))).thenReturn(Collections.singletonList(resource)); when(fixture.permissionMapper.insertReturning(any(DmsFilePermissionEntity.class))) .thenAnswer(invocation -> invocation.getArgument(0)); DmsFilePermissionEntity result = fixture.service.ensureWorkflowDownloadPermissions( TENANT_ID, sourceId, CREATOR_ID, Collections.singletonList(fileVersionId), validTo, "jnpf-flowable", Collections.emptyList()).get(0); assertEquals("DOWNLOAD", result.getActionCode()); assertEquals(validTo, result.getValidTo()); assertEquals(Long.valueOf(1L), result.getMaxUseCount()); assertEquals("文件下载申请审批通过", result.getGrantReason()); assertEquals("SERVICE", result.getGrantedByType()); assertEquals("jnpf-flowable", result.getGrantedById()); } @Test void grantsPermanentWorkflowPrintPermissionAsService() { Fixture fixture = new Fixture(); UUID fileVersionId = UUID.fromString("018f0000-0000-7000-8000-000000000405"); String sourceId = "print-request:request-1"; DmsPermissionResourceEntity resource = new DmsPermissionResourceEntity(); resource.setId(fileVersionId); resource.setResourceType("FILE_VERSION"); when(fixture.permissionMapper.selectBySource(TENANT_ID, "WORKFLOW", sourceId)) .thenReturn(Collections.emptyList()); when(fixture.resourceMapper.selectByTenantAndIds(TENANT_ID, Collections.singletonList(fileVersionId))).thenReturn(Collections.singletonList(resource)); when(fixture.permissionMapper.insertReturning(any(DmsFilePermissionEntity.class))) .thenAnswer(invocation -> invocation.getArgument(0)); DmsFilePermissionEntity result = fixture.service.ensureWorkflowPrintPermissions( TENANT_ID, sourceId, CREATOR_ID, Collections.singletonList(fileVersionId), "jnpf-file", Collections.emptyList()).get(0); assertEquals("PRINT", result.getActionCode()); assertEquals("WORKFLOW", result.getSourceType()); assertEquals(sourceId, result.getSourceId()); assertEquals(null, result.getValidTo()); assertEquals(null, result.getMaxUseCount()); assertEquals("SERVICE", result.getGrantedByType()); assertEquals("jnpf-file", result.getGrantedById()); } @Test void grantsTimeLimitedWorkflowPrintPermissionAsService() { Fixture fixture = new Fixture(); UUID fileVersionId = UUID.fromString("018f0000-0000-7000-8000-000000000409"); String sourceId = "workflow-print-files:request-1"; Date validTo = new Date(4102444800000L); DmsPermissionResourceEntity resource = new DmsPermissionResourceEntity(); resource.setId(fileVersionId); resource.setResourceType("FILE_VERSION"); when(fixture.permissionMapper.selectBySource(TENANT_ID, "WORKFLOW", sourceId)) .thenReturn(Collections.emptyList()); when(fixture.resourceMapper.selectByTenantAndIds(TENANT_ID, Collections.singletonList(fileVersionId))).thenReturn(Collections.singletonList(resource)); when(fixture.permissionMapper.insertReturning(any(DmsFilePermissionEntity.class))) .thenAnswer(invocation -> invocation.getArgument(0)); DmsFilePermissionEntity result = fixture.service.ensureWorkflowPrintPermissions( TENANT_ID, sourceId, CREATOR_ID, Collections.singletonList(fileVersionId), validTo, "jnpf-flowable", Collections.emptyList()).get(0); assertEquals("PRINT", result.getActionCode()); assertEquals(validTo, result.getValidTo()); assertEquals("文件打印申请审批通过", result.getGrantReason()); assertEquals("jnpf-flowable", result.getGrantedById()); } @Test void grantsTimeLimitedWorkflowBorrowReadPermissionAsService() { Fixture fixture = new Fixture(); UUID fileVersionId = UUID.fromString("018f0000-0000-7000-8000-000000000406"); String sourceId = "personal-folder-borrow:request-1"; Date validTo = new Date(4102444800000L); DmsPermissionResourceEntity resource = new DmsPermissionResourceEntity(); resource.setId(fileVersionId); resource.setResourceType("FILE_VERSION"); when(fixture.permissionMapper.selectBySource(TENANT_ID, "WORKFLOW", sourceId)) .thenReturn(Collections.emptyList()); when(fixture.resourceMapper.selectByTenantAndIds(TENANT_ID, Collections.singletonList(fileVersionId))).thenReturn(Collections.singletonList(resource)); when(fixture.permissionMapper.insertReturning(any(DmsFilePermissionEntity.class))) .thenAnswer(invocation -> invocation.getArgument(0)); DmsFilePermissionEntity result = fixture.service.ensureWorkflowBorrowReadPermissions( TENANT_ID, sourceId, CREATOR_ID, Collections.singletonList(fileVersionId), validTo, "jnpf-flowable", Collections.emptyList()).get(0); assertEquals("FILE_VERSION", result.getResourceType()); assertEquals(fileVersionId, result.getResourceId()); assertEquals("USER", result.getPrincipalType()); assertEquals(CREATOR_ID, result.getPrincipalId()); assertEquals("READ", result.getActionCode()); assertEquals("WORKFLOW", result.getSourceType()); assertEquals(validTo, result.getValidTo()); assertEquals("文件借阅申请审批通过", result.getGrantReason()); assertEquals("SERVICE", result.getGrantedByType()); assertEquals("jnpf-flowable", result.getGrantedById()); } @Test void grantsPermanentWorkflowBorrowReadPermissionWhenValidityIsNull() { Fixture fixture = new Fixture(); UUID fileVersionId = UUID.fromString("018f0000-0000-7000-8000-000000000407"); String sourceId = "personal-folder-borrow:permanent-request"; DmsPermissionResourceEntity resource = new DmsPermissionResourceEntity(); resource.setId(fileVersionId); resource.setResourceType("FILE_VERSION"); when(fixture.permissionMapper.selectBySource(TENANT_ID, "WORKFLOW", sourceId)) .thenReturn(Collections.emptyList()); when(fixture.resourceMapper.selectByTenantAndIds(TENANT_ID, Collections.singletonList(fileVersionId))).thenReturn(Collections.singletonList(resource)); when(fixture.permissionMapper.insertReturning(any(DmsFilePermissionEntity.class))) .thenAnswer(invocation -> invocation.getArgument(0)); DmsFilePermissionEntity result = fixture.service.ensureWorkflowBorrowReadPermissions( TENANT_ID, sourceId, CREATOR_ID, Collections.singletonList(fileVersionId), null, "jnpf-flowable", Collections.emptyList()).get(0); assertEquals("READ", result.getActionCode()); assertNull(result.getValidTo()); assertEquals("文件借阅申请审批通过", result.getGrantReason()); } private static DmsFilePermissionEntity matchingPermission() { DmsFilePermissionEntity permission = new DmsFilePermissionEntity(); permission.setId(PERMISSION_ID); permission.setTenantId(TENANT_ID); permission.setResourceType("FOLDER"); permission.setResourceId(FOLDER_ID); permission.setResourceScope("SELF"); permission.setPrincipalType("USER"); permission.setPrincipalId(CREATOR_ID); permission.setIncludeChildOrgs(false); permission.setActionCode("CREATE"); permission.setSourceType("SYSTEM"); permission.setSourceId(SOURCE_ID); permission.setValidFrom(new Date()); permission.setGrantReason(GRANT_REASON); permission.setGrantedByType("USER"); permission.setGrantedById(CREATOR_ID); return permission; } private static class Fixture { private final DmsCurrentIdentity currentIdentity = mock(DmsCurrentIdentity.class); private final DmsPermissionProperties properties = new DmsPermissionProperties(); private final DmsPrincipalValidator principalValidator = mock(DmsPrincipalValidator.class); private final DmsPermissionResourceMapper resourceMapper = mock(DmsPermissionResourceMapper.class); private final DmsFilePermissionMapper permissionMapper = mock(DmsFilePermissionMapper.class); private final DmsAuditAdapter auditAdapter = mock(DmsAuditAdapter.class); private final DmsPermissionGrantService service = new DmsPermissionGrantService( currentIdentity, properties, principalValidator, resourceMapper, permissionMapper, auditAdapter); } }