Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only show thumbnails if user has viewAccessCopies permissions #1630

Merged
merged 5 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public class DatastreamPermissionUtil {
DS_PERMISSION_MAP.put(DatastreamType.ORIGINAL_FILE, Permission.viewOriginal);
DS_PERMISSION_MAP.put(DatastreamType.TECHNICAL_METADATA, Permission.viewHidden);
DS_PERMISSION_MAP.put(DatastreamType.TECHNICAL_METADATA_HISTORY, Permission.viewHidden);
DS_PERMISSION_MAP.put(DatastreamType.THUMBNAIL_SMALL, Permission.viewMetadata);
DS_PERMISSION_MAP.put(DatastreamType.THUMBNAIL_LARGE, Permission.viewMetadata);
DS_PERMISSION_MAP.put(DatastreamType.THUMBNAIL_SMALL, Permission.viewAccessCopies);
DS_PERMISSION_MAP.put(DatastreamType.THUMBNAIL_LARGE, Permission.viewAccessCopies);
}

private DatastreamPermissionUtil() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export default {
render: (data, type, row) => {
let img;

if ('thumbnail_url' in row) {
if ('thumbnail_url' in row && this.hasPermission(row,'viewAccessCopies')) {
const thumbnail_title = this.$t('full_record.thumbnail_title', { title: row.title })
img = `<img class="data-thumb" loading="lazy" src="${row.thumbnail_url}"` +
` alt="${thumbnail_title}">`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default {
},

src() {
if (this.objectData.thumbnail_url !== undefined) {
if (this.objectData.thumbnail_url !== undefined && this.hasPermission(this.objectData, 'viewAccessCopies')) {
return this.objectData.thumbnail_url;
}

Expand Down
11 changes: 10 additions & 1 deletion static/js/vue-cdr-access/tests/unit/thumbnail.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,21 @@ describe('thumbnail.vue', () => {
});
});

it('displays a thumbnail, if present', () => {
it('displays a thumbnail, if present and user has viewAccessCopies permissions', () => {
expect(wrapper.find('.thumbnail .thumbnail-viewer').exists()).toBe(true);
expect(wrapper.find('i.placeholder').exists()).toBe(false);
expect(wrapper.find('a').attributes('class'))
.toEqual('thumbnail thumbnail-size-large has_tooltip')
});

it('does not display a thumbnail if user does not have viewAccessCopies permissions', async () => {
let updatedRecordData = cloneDeep(recordData);
updatedRecordData.briefObject.permissions = ['viewMetadata'];
await wrapper.setProps({ thumbnailData: updatedRecordData });
expect(wrapper.find('i.placeholder').exists()).toBe(true);
expect(wrapper.find('.thumbnail .thumbnail-viewer').exists()).toBe(false);
});

it('displays a placeholder, if no thumbnail', async () => {
let updatedRecordData = cloneDeep(recordData);
updatedRecordData.briefObject.thumbnail_url = undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public String getThumbnailId(ContentObjectRecord contentObjectRecord, AccessGrou
log.debug("Found thumbnail object directly assigned to object {}", thumbId);
return thumbId;
}

// Don't need to check any further if object isn't a work or doesn't contain files with thumbnails
if (!ResourceType.Work.name().equals(contentObjectRecord.getResourceType())
|| contentObjectRecord.getFileFormatCategory() == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,6 @@ public boolean hasOriginalAccess(AccessGroupSet principals, ContentObjectRecord
return hasDatastreamAccess(principals, ORIGINAL_FILE, metadata);
}

/**
* Returns true if the principals can access thumbnails belonging to
* the requested object, if present.
*
* @param principals
* @param metadata
* @return
*/
public boolean hasThumbnailAccess(AccessGroupSet principals, ContentObjectRecord metadata) {
return hasDatastreamAccess(principals, THUMBNAIL_SMALL, metadata);
}

/**
* Returns true if the principals can access the image preview belonging to
* the requested object, if present.
Expand All @@ -75,7 +63,7 @@ public boolean hasImagePreviewAccess(AccessGroupSet principals, ContentObjectRec
/**
* Returns true if the principals can access the MODS description belonging to
* the requested object, if present.
*
*
* @param metadata
* @return
*/
Expand All @@ -93,7 +81,7 @@ public boolean hasDescriptionAccess(AccessGroupSet principals, ContentObjectReco
* @return
*/
public boolean hasDatastreamAccess(AccessGroupSet principals, DatastreamType datastream,
ContentObjectRecord metadata) {
ContentObjectRecord metadata) {
notNull(principals, "Requires agent principals");
notNull(datastream, "Requires datastream type");
notNull(metadata, "Requires metadata object");
Expand Down Expand Up @@ -168,4 +156,4 @@ public AccessControlService getAccessControlService() {
public void setAccessControlService(AccessControlService accessControlService) {
this.accessControlService = accessControlService;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -371,4 +371,4 @@ private void hasPermissions(ContentObjectSolrRecord contentObject, boolean hasAc
private void populateResultList(ContentObjectRecord... objects) {
when(searchResultResponse.getResultList()).thenReturn(Arrays.asList(objects));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,4 @@ public void testDoesNotHaveEnhancedIfLoggedIn() {
private void assignPermission(Permission permission, boolean value) {
when(accessControlService.hasAccess(any(PID.class), eq(principals), eq(permission))).thenReturn(value);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package edu.unc.lib.boxc.web.services.rest;

import static edu.unc.lib.boxc.auth.api.Permission.viewAccessCopies;
import static edu.unc.lib.boxc.auth.api.Permission.viewHidden;
import static edu.unc.lib.boxc.auth.api.Permission.viewMetadata;
import static edu.unc.lib.boxc.model.api.DatastreamType.MD_EVENTS;
import static edu.unc.lib.boxc.model.api.DatastreamType.TECHNICAL_METADATA;
import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_SMALL;
Expand Down Expand Up @@ -66,10 +66,10 @@
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextHierarchy({
@ContextConfiguration("/spring-test/test-fedora-container.xml"),
@ContextConfiguration("/spring-test/cdr-client-container.xml"),
@ContextConfiguration("/spring-test/solr-indexing-context.xml"),
@ContextConfiguration("/datastream-content-it-servlet.xml")
@ContextConfiguration("/spring-test/test-fedora-container.xml"),
@ContextConfiguration("/spring-test/cdr-client-container.xml"),
@ContextConfiguration("/spring-test/solr-indexing-context.xml"),
@ContextConfiguration("/datastream-content-it-servlet.xml")
})
public class DatastreamRestControllerIT extends AbstractAPIIT {

Expand Down Expand Up @@ -225,7 +225,7 @@ public void testGetThumbnailNoPermission() throws Exception {
createDerivative(id, THUMBNAIL_SMALL, BINARY_CONTENT.getBytes());

doThrow(new AccessRestrictionException()).when(accessControlService)
.assertHasAccess(anyString(), eq(filePid), any(AccessGroupSetImpl.class), eq(viewMetadata));
.assertHasAccess(anyString(), eq(filePid), any(AccessGroupSetImpl.class), eq(viewAccessCopies));

MvcResult result = mvc.perform(get("/thumb/" + filePid.getId()))
.andExpect(status().isForbidden())
Expand Down Expand Up @@ -277,9 +277,9 @@ public void testGetEventLog() throws Exception {

FolderObject folderObj = repositoryObjectFactory.createFolderObject(folderPid, null);
premisLoggerFactory.createPremisLogger(folderObj)
.buildEvent(Premis.Creation)
.addAuthorizingAgent(AgentPids.forPerson("some_user"))
.writeAndClose();
.buildEvent(Premis.Creation)
.addAuthorizingAgent(AgentPids.forPerson("some_user"))
.writeAndClose();

MvcResult result = mvc.perform(get("/file/" + id + "/" + MD_EVENTS.getId()))
.andExpect(status().is2xxSuccessful())
Expand Down Expand Up @@ -321,9 +321,9 @@ public void testGetEventLogNoPermissions() throws Exception {

FolderObject folderObj = repositoryObjectFactory.createFolderObject(folderPid, null);
premisLoggerFactory.createPremisLogger(folderObj)
.buildEvent(Premis.Creation)
.addAuthorizingAgent(AgentPids.forPerson("some_user"))
.writeAndClose();
.buildEvent(Premis.Creation)
.addAuthorizingAgent(AgentPids.forPerson("some_user"))
.writeAndClose();

doThrow(new AccessRestrictionException()).when(accessControlService)
.assertHasAccess(anyString(), eq(folderPid), any(AccessGroupSetImpl.class), eq(viewHidden));
Expand All @@ -347,4 +347,4 @@ private File createDerivative(String id, DatastreamType dsType, byte[] content)

return derivFile;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<mvc:annotation-driven/>

<context:component-scan resource-pattern="**/DatastreamController*" base-package="edu.unc.lib.boxc.web.services.rest"/>

<bean id="fedoraContentService" class="edu.unc.lib.boxc.web.common.services.FedoraContentService">
<property name="accessControlService" ref="aclService" />
<property name="repositoryObjectLoader" ref="repositoryObjectLoader" />
</bean>

<bean id="derivativeContentService" class="edu.unc.lib.boxc.web.common.services.DerivativeContentService">
<property name="accessControlService" ref="aclService" />
</bean>

<bean id="aclService" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="edu.unc.lib.boxc.auth.fcrepo.services.AccessControlServiceImpl" />
</bean>

<bean id="analyticsTracker" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="edu.unc.lib.boxc.web.common.utils.AnalyticsTrackerUtil" />
</bean>
Expand All @@ -41,4 +41,4 @@
<property name="globalPermissionEvaluator" ref="globalPermissionEvaluator" />
<property name="solrSearchService" ref="solrSearchService" />
</bean>
</beans>
</beans>
Loading