Skip to content

Commit

Permalink
Fix merge conflicts with "main"
Browse files Browse the repository at this point in the history
  • Loading branch information
lfarrell committed Jan 2, 2024
2 parents 96113ec + 2aaa757 commit 4da2b5d
Show file tree
Hide file tree
Showing 41 changed files with 1,051 additions and 761 deletions.
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 @@ -42,6 +42,7 @@ public class VirusScanJob extends AbstractConcurrentDepositJob {
.getLogger(VirusScanJob.class);

private static final int MAX_RETRIES = 5;
private long maxStreamSize;

private ClamAVClient clamClient;

Expand Down Expand Up @@ -97,18 +98,20 @@ public void runJob() {
Path file = Paths.get(fileURI);

ScanResult result;
// Clamd is unable to find files with unicode characters in their path
if (charactersInBoundsForClam(file)) {
result = clamClient.scanWithResult(file);
} else {
// Scan files with unicode in their paths via streaming
try {
try {
if (shouldScanByPath(file)) {
// Scan entire file by path
log.debug("Scanning file {} by path", file);
result = clamClient.scanWithResult(file);
} else {
// Scanning via InputStream up to the max number of bytes
log.debug("Scanning file {} by stream", file);
result = clamClient.scanWithResult(Files.newInputStream(file));
} catch (IOException e) {
failures.put(fileURI.toString(), "Failed to scan file");
log.error("Unable to scan file {}", file, e);
return;
}
} catch (IOException e) {
failures.put(fileURI.toString(), "Failed to scan file");
log.error("Unable to scan file {}", file, e);
return;
}

switch (result.getStatus()) {
Expand Down Expand Up @@ -180,8 +183,23 @@ private boolean charactersInBoundsForClam(Path path) {
return CharMatcher.ascii().matchesAllOf(path.toString());
}

/**
* Determines if we should scan a file by its file path or use streaming. Files larger than the scanning
* limit or with characters in their path that clamd can't handle will return false.
* @param path
* @return
* @throws IOException
*/
private boolean shouldScanByPath(Path path) throws IOException {
return Files.size(path) < this.maxStreamSize && charactersInBoundsForClam(path);
}

// unused, no results to flush
@Override
protected void registrationAction() {
}
}

public void setMaxStreamSize(long maxStreamSize) {
this.maxStreamSize = maxStreamSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
<property name="clamClient" ref="clamClient" />
<property name="maxQueuedJobs" value="${job.fileValidation.maxQueuedJobs:5}" />
<property name="executorService" ref="fileValidationExecutor" />
<property name="maxStreamSize" value="${clamd.maxStreamSize:64000000}" />
</bean>

<bean id="FixityCheckJob" class="edu.unc.lib.boxc.deposit.validate.FixityCheckJob"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,10 @@
package edu.unc.lib.boxc.deposit.validate;

import static edu.unc.lib.boxc.common.test.TestHelpers.setField;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.UUID;
import java.util.concurrent.ExecutorService;

import org.apache.commons.io.FileUtils;
import org.apache.jena.rdf.model.Bag;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.RDF;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import com.google.common.util.concurrent.MoreExecutors;

import edu.unc.lib.boxc.common.util.URIUtil;
import edu.unc.lib.boxc.deposit.api.RedisWorkerConstants.DepositState;
import edu.unc.lib.boxc.deposit.fcrepo4.AbstractDepositJobTest;
import edu.unc.lib.boxc.deposit.impl.model.DepositModelHelpers;
import edu.unc.lib.boxc.deposit.validate.VirusScanJob;
import edu.unc.lib.boxc.deposit.work.JobFailedException;
import edu.unc.lib.boxc.deposit.work.JobInterruptedException;
import edu.unc.lib.boxc.model.api.exceptions.RepositoryException;
Expand All @@ -51,6 +17,37 @@
import fi.solita.clamav.ClamAVClient;
import fi.solita.clamav.ScanResult;
import fi.solita.clamav.ScanResult.Status;
import org.apache.commons.io.FileUtils;
import org.apache.jena.rdf.model.Bag;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.RDF;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.UUID;
import java.util.concurrent.ExecutorService;

import static edu.unc.lib.boxc.common.test.TestHelpers.setField;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
*
Expand Down Expand Up @@ -92,6 +89,7 @@ public PID answer(InvocationOnMock invocation) throws Throwable {
});

when(clamClient.scanWithResult(any(Path.class))).thenReturn(scanResult);
when(clamClient.scanWithResult(any(InputStream.class))).thenReturn(scanResult);

File examplesFile = new File("src/test/resources/examples");
FileUtils.copyDirectory(examplesFile, depositDir);
Expand All @@ -104,6 +102,7 @@ private void initializeJob() {
job.setJobUUID(jobUUID);
job.setDepositUUID(depositUUID);
job.setDepositDirectory(depositDir);
job.setMaxStreamSize(300l);
setField(job, "pidMinter", pidMinter);
job.setClamClient(clamClient);
job.setPremisLoggerFactory(premisLoggerFactory);
Expand Down Expand Up @@ -142,7 +141,8 @@ public void passScanTest() throws Exception {

job.run();

verify(clamClient, times(3)).scanWithResult(any(Path.class));
verify(clamClient, times(1)).scanWithResult(any(InputStream.class));
verify(clamClient, times(2)).scanWithResult(any(Path.class));

verify(jobStatusFactory).setTotalCompletion(eq(jobUUID), eq(3));
verify(jobStatusFactory, times(3)).incrCompletion(eq(jobUUID), eq(1));
Expand Down Expand Up @@ -189,9 +189,8 @@ public void failOneScanTest() throws Exception {
when(result2.getStatus()).thenReturn(Status.FOUND);
File pdfFile = new File(depositDir, "pdf.pdf");
File textFile = new File(depositDir, "text.txt");
when(clamClient.scanWithResult(any(Path.class)))
.thenReturn(scanResult)
.thenReturn(result2);
when(clamClient.scanWithResult(any(InputStream.class))).thenReturn(scanResult);
when(clamClient.scanWithResult(any(Path.class))).thenReturn(result2);

Model model = job.getWritableModel();
Bag depBag = model.createBag(depositPid.getRepositoryPath());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private List<String> determineContentStatus(DocumentIndexingPackage dip)
status.add(FacetConstants.IS_PRIMARY_OBJECT);
}
if (parentResc.hasProperty(Cdr.useAsThumbnail, resc)) {
status.add(FacetConstants.IS_ASSIGNED_THUMBNAIL);
status.add(FacetConstants.ASSIGNED_AS_THUMBNAIL);
}
}

Expand All @@ -75,7 +75,7 @@ private void addWorkObjectStatuses(List<String> status, Resource resource) {
}

if (resource.hasProperty(Cdr.useAsThumbnail)) {
status.add(FacetConstants.THUMBNAIL_ASSIGNED);
status.add(FacetConstants.HAS_THUMBNAIL_ASSIGNED);
} else {
status.add(FacetConstants.NO_THUMBNAIL_ASSIGNED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public void testWorkWithAssignedThumbnail() throws Exception {
filter.filter(dip);

verify(idb).setContentStatus(listCaptor.capture());
assertTrue(listCaptor.getValue().contains(FacetConstants.THUMBNAIL_ASSIGNED));
assertTrue(listCaptor.getValue().contains(FacetConstants.HAS_THUMBNAIL_ASSIGNED));
assertFalse(listCaptor.getValue().contains(FacetConstants.NO_THUMBNAIL_ASSIGNED));
}

Expand All @@ -216,6 +216,6 @@ public void testIsAssignedThumbnail() throws Exception {
filter.filter(dip);

verify(idb).setContentStatus(listCaptor.capture());
assertTrue(listCaptor.getValue().contains(FacetConstants.IS_ASSIGNED_THUMBNAIL));
assertTrue(listCaptor.getValue().contains(FacetConstants.ASSIGNED_AS_THUMBNAIL));
}
}
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@
<commons-fileupload.version>1.5</commons-fileupload.version>
<abdera.version>1.1.3</abdera.version>

<activemq.version>5.16.3</activemq.version>
<activemq.version>5.17.6</activemq.version>
<activemq-camel.version>5.16.7</activemq-camel.version>
<activemq-protobuf.version>1.1</activemq-protobuf.version>

<slf4j.version>1.7.25</slf4j.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public abstract class FacetConstants {
public static final String STAFF_ONLY_ACCESS = "Staff-Only Access";
public static final String MEMBERS_ARE_ORDERED = "Members Are Ordered";
public static final String MEMBERS_ARE_UNORDERED = "Members Are Unordered";
public static final String THUMBNAIL_ASSIGNED = "Has Assigned Thumbnail";
public static final String HAS_THUMBNAIL_ASSIGNED = "Has Assigned Thumbnail";
public static final String NO_THUMBNAIL_ASSIGNED = "No Assigned Thumbnail";
public static final String IS_ASSIGNED_THUMBNAIL = "Is Assigned Thumbnail";
public static final String ASSIGNED_AS_THUMBNAIL = "Assigned As Thumbnail";

}
2 changes: 1 addition & 1 deletion services-camel-app/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-camel</artifactId>
<version>${activemq.version}</version>
<version>${activemq-camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import edu.unc.lib.boxc.auth.api.Permission;
import edu.unc.lib.boxc.auth.api.services.AccessControlService;
import edu.unc.lib.boxc.model.api.objects.RepositoryObjectLoader;
import edu.unc.lib.boxc.model.api.objects.WorkObject;
import edu.unc.lib.boxc.model.api.rdf.Cdr;
import edu.unc.lib.boxc.model.api.services.RepositoryObjectFactory;
import edu.unc.lib.boxc.model.fcrepo.ids.PIDs;
Expand Down Expand Up @@ -39,17 +40,26 @@ public void process(Exchange exchange) throws IOException {
pid, agent.getPrincipals(), Permission.editDescription);

var file = repositoryObjectLoader.getFileObject(pid);
var work = file.getParent();
var work = (WorkObject) file.getParent();

if (Objects.equals(action, ThumbnailRequest.ASSIGN)) {
// Capture the old thumbnail id before it gets cleared
var oldThumbnailFile = work.getThumbnailObject();
repositoryObjectFactory.createExclusiveRelationship(work, Cdr.useAsThumbnail, file.getResource());
// reindex old thumbnail object
if (oldThumbnailFile != null) {
indexingMessageSender.sendIndexingOperation(
agent.getUsername(), oldThumbnailFile.getPid(), IndexingActionType.UPDATE_DATASTREAMS);
}
} else if ( Objects.equals(action, ThumbnailRequest.DELETE)) {
repositoryObjectFactory.deleteProperty(work, Cdr.useAsThumbnail);
}

// send message to update solr
indexingMessageSender.sendIndexingOperation(
agent.getUsername(), work.getPid(), IndexingActionType.UPDATE_DATASTREAMS);
indexingMessageSender.sendIndexingOperation(
agent.getUsername(), file.getPid(), IndexingActionType.UPDATE_DATASTREAMS);
}

public void setRepositoryObjectLoader(RepositoryObjectLoader repositoryObjectLoader) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,37 @@ void closeService() throws Exception {
}

@Test
public void testUpdateThumbnail() throws Exception {
public void testAssignThumbnail() throws Exception {
var exchange = createRequestExchange(ThumbnailRequest.ASSIGN);

processor.process(exchange);
verify(repositoryObjectFactory).createExclusiveRelationship(eq(parentWork), eq(Cdr.useAsThumbnail), fileResourceCaptor.capture());
// check to see the right file was related to the work
assertEquals(resource, fileResourceCaptor.getValue());
assertIndexingMessageSent();
assertIndexingMessageSent(workPid);
assertIndexingMessageSent(filePid);
}

// test for when the work already has an assigned thumbnail and a new one is chosen
@Test
public void testAssignNewThumbnail() throws Exception {
// set up pre-existing assigned thumbnail
var oldThumbnailPid = ProcessorTestHelper.makePid();
var oldThumbnailFile = mock(FileObject.class);
var oldResource = mock(Resource.class);
when(oldThumbnailFile.getResource()).thenReturn(oldResource);
when(oldThumbnailFile.getPid()).thenReturn(oldThumbnailPid);
when(parentWork.getThumbnailObject()).thenReturn(oldThumbnailFile);

var exchange = createRequestExchange(ThumbnailRequest.ASSIGN);

processor.process(exchange);
verify(repositoryObjectFactory).createExclusiveRelationship(eq(parentWork), eq(Cdr.useAsThumbnail), fileResourceCaptor.capture());
// check to see the right file was related to the work
assertEquals(resource, fileResourceCaptor.getValue());
assertIndexingMessageSent(workPid);
assertIndexingMessageSent(filePid);
assertIndexingMessageSent(oldThumbnailPid);
}

@Test
Expand All @@ -114,11 +137,11 @@ public void testDeleteAssignedThumbnail() throws IOException {

processor.process(exchange);
verify(repositoryObjectFactory).deleteProperty(eq(parentWork), eq(Cdr.useAsThumbnail));
assertIndexingMessageSent();
assertIndexingMessageSent(workPid);
}

private void assertIndexingMessageSent() {
verify(indexingMessageSender).sendIndexingOperation(agent.getUsername(), workPid,
private void assertIndexingMessageSent(PID pid) {
verify(indexingMessageSender).sendIndexingOperation(agent.getUsername(), pid,
IndexingActionType.UPDATE_DATASTREAMS);
}

Expand Down
7 changes: 5 additions & 2 deletions static/js/admin/src/ResultObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ define('ResultObject', [ 'jquery', 'jquery-ui', 'underscore', 'ModalLoadingOverl

if (tags.length > 0) {
this.metadata.tags = tags.filter(function(d) {
return !/^(has|not|no.primary|public.access|members.are.unordered)/i.test(d);
return !/^(has|not|no.primary|public.access|members.are.unordered|no.assigned.thumbnail)/i.test(d);
}).map(function(d) {
var tagValue;

Expand Down Expand Up @@ -85,7 +85,7 @@ define('ResultObject', [ 'jquery', 'jquery-ui', 'underscore', 'ModalLoadingOverl
case 'patron-settings':
helpText = 'Patron access settings for this object have been added';
break;
case 'primary-object':
case 'is-primary-object':
helpText = 'This file is the representative object for the work which contains it';
break;
case 'staff-only':
Expand All @@ -94,6 +94,9 @@ define('ResultObject', [ 'jquery', 'jquery-ui', 'underscore', 'ModalLoadingOverl
case 'inherited-settings':
helpText = 'Object is inheriting patron access settings which have been modified (typically they are more restrictive)';
break;
case 'assigned-as-thumbnail':
helpText = 'This file is the assigned thumbnail for the work which contains it';
break;
default:
helpText = '';
}
Expand Down
Loading

0 comments on commit 4da2b5d

Please sign in to comment.