mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user