ACS-2148: Adding get StorageObjectProps to ContentService (#773)

* ACS-2148: Adding get StorageObjectProps to ContentService and implementation.

* ACS-2148: Adding propertyQName param to get storage property method.

* ACS-2148: Security config for added method.

* ACS-2148: Renaming getObjectStorageProperties to getStorageProperties

* ACS-2148: Javadoc fix

* ACS-2148: Fixing security context after method renaming.
This commit is contained in:
mpichura
2021-10-26 13:48:53 +02:00
committed by GitHub
parent 5041249f03
commit e515dacab1
4 changed files with 102 additions and 2 deletions

View File

@@ -45,6 +45,7 @@ import org.alfresco.repo.policy.ClassPolicyDelegate;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
@@ -649,6 +650,23 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
return directAccessUrl;
}
/**
* {@inheritDoc}
*/
@Override
@Experimental
public Map<String, String> getStorageProperties(NodeRef nodeRef, QName propertyQName)
{
final ContentData contentData = getContentData(nodeRef, propertyQName);
if (contentData == null || contentData.getContentUrl() == null)
{
throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " and property name: " + propertyQName + " has no content.");
}
return store.getObjectStorageProperties(contentData.getContentUrl());
}
protected String getFileName(NodeRef nodeRef)
{
String fileName = null;
@@ -672,4 +690,4 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
}
return validFor;
}
}
}

View File

@@ -28,9 +28,13 @@ package org.alfresco.service.cmr.repository;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.Auditable;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.namespace.QName;
import java.util.Collections;
import java.util.Map;
/**
* Provides methods for accessing and transforming content.
* <p>
@@ -194,4 +198,22 @@ public interface ContentService
*/
@Auditable(parameters = {"nodeRef", "validFor"})
DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment, Long validFor);
/**
* Gets a key-value (String-String) collection of storage headers/properties with their respective values for a specific node reference.
* A particular Cloud Connector will fill in that data with Cloud Storage Provider generic data.
* Map may be also filled in with entries consisting of pre-defined Alfresco keys of {@code ObjectStorageProps} and their values.
* If empty Map is returned - no connector is present or connector is not supporting retrieval of the properties
* or cannot determine the properties.
*
* @param nodeRef a reference to a node having a content property
* @param propertyQName the name of the property, which must be of type <b>content</b>
* @return Returns a key-value (String-String) collection of storage headers/properties with their respective values for a given {@link NodeRef}.
*/
@Auditable
@Experimental
default Map<String, String> getStorageProperties(NodeRef nodeRef, QName propertyQName)
{
return Collections.emptyMap();
}
}

View File

@@ -497,6 +497,7 @@
org.alfresco.service.cmr.repository.ContentService.getTempWriter=ACL_ALLOW
org.alfresco.service.cmr.repository.ContentService.requestContentDirectUrl=ACL_NODE.0.sys:base.ReadContent
org.alfresco.service.cmr.repository.ContentService.isContentDirectUrlEnabled=ACL_ALLOW
org.alfresco.service.cmr.repository.ContentService.getStorageProperties=ACL_NODE.0.sys:base.ReadContent
org.alfresco.service.cmr.repository.ContentService.*=ACL_DENY
</value>
</property>

View File

@@ -25,8 +25,10 @@
*/
package org.alfresco.repo.content;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -41,6 +43,7 @@ import static org.mockito.MockitoAnnotations.openMocks;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.directurl.DirectAccessUrlDisabledException;
import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.DirectAccessUrl;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -50,6 +53,9 @@ import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.Collections;
import java.util.Map;
/**
* Unit tests for content service implementation.
*
@@ -64,6 +70,13 @@ public class ContentServiceImplUnitTest
private static final Long SYS_MAX_EXPIRY_TIME_IN_SECS = 300L;
private static final NodeRef NODE_REF = new NodeRef("content://Node/Ref");
public static final String SOME_CONTENT_URL = "someContentUrl";
private static final NodeRef NODE_REF_2 = new NodeRef("content://Node/Ref2");;
private static final String X_AMZ_HEADER_1 = "x-amz-header1";
private static final String VALUE_1 = "value1";
private static final String X_AMZ_HEADER_2 = "x-amz-header-2";
private static final String VALUE_2 = "value2";
@InjectMocks
private ContentServiceImpl contentService;
@@ -77,12 +90,15 @@ public class ContentServiceImplUnitTest
@Mock
private ContentData mockContentData;
@Mock
private DictionaryService mockDictionaryService;
@Before
public void setup()
{
openMocks(this);
when(mockNodeService.getProperty(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentData);
when(mockContentData.getContentUrl()).thenReturn("someContentUrl");
when(mockContentData.getContentUrl()).thenReturn(SOME_CONTENT_URL);
when(mockContentData.getMimetype()).thenReturn("someMimetype");
when(mockNodeService.getProperty(NODE_REF, ContentModel.PROP_NAME)).thenReturn("someFilename");
}
@@ -148,6 +164,49 @@ public class ContentServiceImplUnitTest
verify(mockContentStore, times(1)).requestContentDirectUrl(anyString(), eq(true), anyString(), anyString(), anyLong());
}
@Test
public void shouldReturnStoragePropertiesWhenTheyExist()
{
final Map<String, String> storageObjectPropsMap = Map.of(X_AMZ_HEADER_1, VALUE_1, X_AMZ_HEADER_2, VALUE_2);
when(mockContentStore.getObjectStorageProperties(SOME_CONTENT_URL)).thenReturn(storageObjectPropsMap);
final Map<String, String> objectStorageProperties = contentService.getStorageProperties(NODE_REF, ContentModel.PROP_CONTENT);
assertFalse(objectStorageProperties.isEmpty());
assertEquals(storageObjectPropsMap, objectStorageProperties);
}
@Test
public void shouldReturnEmptyStoragePropertiesWhenTheyDontExist()
{
when(mockContentStore.getObjectStorageProperties(SOME_CONTENT_URL)).thenReturn(Collections.emptyMap());
final Map<String, String> objectStorageProperties = contentService.getStorageProperties(NODE_REF, ContentModel.PROP_CONTENT);
assertTrue(objectStorageProperties.isEmpty());
}
@Test
public void getStoragePropertiesThrowsExceptionWhenNoContentFound()
{
final String dummyContentProperty = "dummy";
when(mockNodeService.getProperty(NODE_REF_2, ContentModel.PROP_CONTENT)).thenReturn(dummyContentProperty);
when(mockDictionaryService.getProperty(ContentModel.PROP_CONTENT)).thenReturn(null);
assertThrows(IllegalArgumentException.class, () -> {
contentService.getStorageProperties(NODE_REF_2, ContentModel.PROP_CONTENT);
});
}
@Test
public void getStoragePropertiesThrowsExceptionWhenNoContentUrlFound()
{
final ContentData contentWithoutUrl = new ContentData(null, null, 0, null);
when(mockNodeService.getProperty(NODE_REF_2, ContentModel.PROP_CONTENT)).thenReturn(contentWithoutUrl);
assertThrows(IllegalArgumentException.class, () -> {
contentService.getStorageProperties(NODE_REF_2, ContentModel.PROP_CONTENT);
});
}
/* Helper method to set system-wide direct access url configuration settings */
private void setupSystemWideDirectAccessConfig(Boolean isEnabled)
{