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

Ea 3923 fix thumbnail urls #72

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ nbdist/

### JEnv ###
.java-version
/pom-local-depcheck.xml
29 changes: 28 additions & 1 deletion owasp-suppress.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,32 @@
<packageUrl regex="true">^pkg:maven/org\.apache\.tomcat\.embed/tomcat\-embed\-core@.*$</packageUrl>
<cve>CVE-2022-45143</cve>
</suppress>

<suppress>
<notes><![CDATA[
file name: spring-web-5.3.27.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework/spring-web@.*$</packageUrl>
<vulnerabilityName>CVE-2024-22262</vulnerabilityName>
</suppress>
<suppress>
<notes><![CDATA[
file name: spring-web-5.3.27.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework/spring-web@.*$</packageUrl>
<vulnerabilityName>CVE-2024-22243</vulnerabilityName>
</suppress>
<suppress>
<notes><![CDATA[
file name: spring-web-5.3.27.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework/spring-web@.*$</packageUrl>
<vulnerabilityName>CVE-2024-38809</vulnerabilityName>
</suppress>
<suppress>
<notes><![CDATA[
file name: swagger-ui-5.11.8.jar: swagger-ui-bundle.js
]]></notes>
<packageUrl regex="true">^pkg:javascript/DOMPurify@.*$</packageUrl>
<vulnerabilityName>CVE-2024-45801</vulnerabilityName>
</suppress>
</suppressions>
38 changes: 22 additions & 16 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
<maven.compiler.target>${java.version}</maven.compiler.target>
<sonar.organization>europeana</sonar.organization>

<fulltext-common.version>0.9.1</fulltext-common.version>
<fulltext-common.version>0.9.7</fulltext-common.version>
<apicommons.version>0.3.20</apicommons.version>
<!-- 3rd party -->
<spring-boot.version>2.7.11</spring-boot.version>
<springdoc.version>1.6.13</springdoc.version>
<springdoc.version>1.8.0</springdoc.version>
<jackson-core.version>2.14.1</jackson-core.version>
<jsonpath.version>2.9.0</jsonpath.version>
<jaxb-api.version>2.4.0-b180830.0359</jaxb-api.version>
Expand All @@ -40,6 +40,11 @@
<mockito.version>3.7.0</mockito.version>
<wiremock.version>2.35.1</wiremock.version>

<dependency-check-maven.version>10.0.4</dependency-check-maven.version>
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
<spring-security.version>6.3.3</spring-security.version>
<spring-security-crypto.version>6.3.3</spring-security-crypto.version>

</properties>

<dependencyManagement>
Expand Down Expand Up @@ -144,12 +149,13 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.7.8</version>
<version>${spring-security.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>5.7.8</version>
<version>${spring-security-crypto.version}</version>
</dependency>

<!-- for serializing -->
Expand Down Expand Up @@ -230,7 +236,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!-- JUnit 5 requires Surefire version 2.22.0 or higher -->
<version>2.22.2</version>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
Expand All @@ -244,18 +250,18 @@
</execution>
</executions>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>depcheck</id>
<build>
<plugins>
<!-- </plugins>-->
<!-- </build>-->
<!-- -->
<!-- <profiles>-->
<!-- <profile>-->
<!-- <id>depcheck</id>-->
<!-- <build>-->
<!-- <plugins>-->
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.2.0</version>
<version>${dependency-check-maven.version}</version>
<configuration>
<nvdApiKeyEnvironmentVariable>NVD_APIKEY</nvdApiKeyEnvironmentVariable>
<!-- see EA-3505 why we host the known exploited vulnerabilties file ourselves -->
Expand All @@ -276,7 +282,7 @@
</plugin>
</plugins>
</build>
</profile>
</profiles>
<!-- </profile>-->
<!-- </profiles>-->

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import eu.europeana.iiif.model.WebResource;
import eu.europeana.iiif.model.v2.*;
import eu.europeana.iiif.model.v3.LanguageMap;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -202,12 +204,12 @@ static eu.europeana.iiif.model.v2.Image getThumbnailImageV2(String europeanaId,
* @param webresourceId hasview image ID
* @return Image object, or null if either provided String was null
*/
static eu.europeana.iiif.model.v2.Image getCanvasThumbnailImageV2(String webresourceId) {
if (StringUtils.isAnyEmpty(THUMBNAIL_API_URL, webresourceId)) {
static eu.europeana.iiif.model.v2.Image getCanvasThumbnailImageV2(String webresourceId, String ThumbnailApiUrl) {
if (StringUtils.isAnyEmpty(ThumbnailApiUrl, webresourceId)) {
return null;
}
return new eu.europeana.iiif.model.v2.Image(
THUMBNAIL_API_URL + webresourceId + CANVAS_THUMBNAIL_POSTFIX,
ThumbnailApiUrl + webresourceId + CANVAS_THUMBNAIL_POSTFIX,
null,
null);
}
Expand Down Expand Up @@ -349,7 +351,7 @@ private static eu.europeana.iiif.model.v2.Canvas getCanvasV2(ManifestSettings se

//EA-3325: check if the webResource has a "svcsHasService"; if not, add a thumbnail
if (Objects.isNull(webResource.get(EdmManifestUtils.SVCS_HAS_SERVICE))){
c.setThumbnail(getCanvasThumbnailImageV2(webResource.getId()));
c.setThumbnail(getCanvasThumbnailImageV2(URLEncoder.encode(webResource.getId(), StandardCharsets.UTF_8), settings.getThumbnailApiUrl()));
}

LinkedHashMap<String, ArrayList<String>> license = (LinkedHashMap<String, ArrayList<String>>) webResource.get(EdmManifestUtils.WEB_RESOURCE_EDM_RIGHTS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import eu.europeana.iiif.model.WebResourceSorter;
import eu.europeana.iiif.model.v3.Collection;
import eu.europeana.iiif.model.v3.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -478,7 +480,7 @@ private static eu.europeana.iiif.model.v3.Canvas getCanvasV3(ManifestSettings se

//EA-3325: check if the webResource has a "svcsHasService"; if not, add a thumbnail
if (Objects.isNull(webResource.get(EdmManifestUtils.SVCS_HAS_SERVICE))){
c.setThumbnail(getCanvasThumbnailImageV3(webResource.getId()));
c.setThumbnail(getCanvasThumbnailImageV3(URLEncoder.encode(webResource.getId(), StandardCharsets.UTF_8)));
}

// a canvas has 1 annotation page by default (an extra annotation page is added later if there is a full text available)
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/eu/europeana/iiif/service/EdmManifestData.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class EdmManifestData {

public static final String TEST_THUMBNAIL_ID = "https://www.europeana.eu/api/v2/thumbnail-by-url.json?uri=test&size=LARGE&type=IMAGE";
public static final String TEST_THUMBNAIL = "{\"object\": {\"europeanaAggregation\" :{ \"edmPreview\":\""+TEST_THUMBNAIL_ID+"\"}}}";

public static final String TEST_CANVAS_THUMBNAIL_ID = "https://www.museumap.hu/media-provider-webapp/rest/file/preview/solr/oai-aggregated-bib9568907?mediaId=323995&size=masterview&tenant_id=Museumap&defaultImage=true";

public static final String TEST_NAVDATE = "{\"object\": {\"proxies\":[{}, {\"dctermsIssued\":{\"en\":[\"NOT A REAL DATE\"]}}, {\"dctermsIssued\":{\"def\":[\"1922-03-15\"]}} ]}}";

Expand Down Expand Up @@ -62,6 +64,17 @@ public class EdmManifestData {
"{\"def\":[\"wr3License\"]}, \"ebucoreHasMimeType\": \"image/webp\", \"svcsHasService\": [\"service3Id\"], \"ebucoreDuration\": \"98765\" }"+
"] } ], \"services\": [{\"about\": \"service3Id\", \"doapImplements\": [\"serviceProfile\"]}] } }";

public static final String TEST_SEQUENCE_1CANVAS_THUMB = "{\"object\": { \"proxies\":[{\"about\":\"/proxy/provider/testing\",\"proxyIn\":[\"/aggregation/provider/testing\"]}]," +
"\"aggregations\": [ {\"about\":\"/aggregation/provider/testing\",\"edmIsShownBy\": \"wr2Id\", " +
"\"hasView\": [\"" + TEST_CANVAS_THUMBNAIL_ID + "\"], " +
"\"webResources\": [ "+
"{\"about\": \"" + TEST_CANVAS_THUMBNAIL_ID + "\", " +
"\"textAttributionSnippet\": \"wr1Attribution\" , \"webResourceEdmRights\":"+
"{\"def\":[\"wr1License\"]}, \"ebucoreHasMimeType\": \"image/jpeg\" },"+
"{\"about\": \"wr2Id\", \"textAttributionSnippet\": \"wr2Attribution\", \"htmlAttributionSnippet\": \"<span>wr2Attribution</span>\", \"webResourceEdmRights\":"+
"{\"def\":[\"wr2License\"]}, \"ebucoreHasMimeType\": \"image/webp\", \"svcsHasService\": [\"service2Id\"], \"ebucoreDuration\": \"98765\" }"+
"] } ], \"services\": [{\"about\": \"service2Id\", \"doapImplements\": [\"serviceProfile\"]}] } }";


public static final String TEST_SEQUENCE_MULTIPLE_PROXY_AGG = "{ \"object\" : { \"aggregations\": [" +
"{\"about\": \"/aggregation/provider/1/\", \"edmIsShownBy\": \"provider_edmIsShownBy\", \"hasView\": [\"wr2Id\"]," +
Expand Down Expand Up @@ -94,5 +107,9 @@ public class EdmManifestData {
"{\"about\": \"wr2Id\", \"textAttributionSnippet\": \"wr2Attribution\", \"webResourceEdmRights\":"+
"{\"def\":[\"wr2License\"]}, \"ebucoreHasMimeType\": \"image/jpeg\", \"svcsHasService\": [\"service2Id\"] }"+
"] } ], \"services\": [{\"about\": \"service1Id\", \"doapImplements\": [\"serviceProfile\"]}] } }";

public static final String CANVAS_THUMBNAIL_ENCODED_URL = "https%3A%2F%2Fwww.museumap.hu%2Fmedia-provider-webapp%2Frest%2Ffile%2Fpreview%2Fsolr%2Foai-aggregated-bib9568907%3FmediaId%3D323995%26size%3Dmasterview%26tenant_id%3DMuseumap%26defaultImage%3Dtrue";

public static final String CANVAS_THUMBNAIL_DECODED_URL = "https://www.museumap.hu/media-provider-webapp/rest/file/preview/solr/oai-aggregated-bib9568907?mediaId=323992&size=masterview&tenant_id=Museumap&defaultImage=true";
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package eu.europeana.iiif.service;

import static eu.europeana.iiif.model.ManifestDefinitions.CANVAS_THUMBNAIL_POSTFIX;
import static eu.europeana.iiif.service.EdmManifestData.CANVAS_THUMBNAIL_DECODED_URL;
import static eu.europeana.iiif.service.EdmManifestData.CANVAS_THUMBNAIL_ENCODED_URL;

import com.jayway.jsonpath.Configuration;
import eu.europeana.iiif.config.AppConfig;
import eu.europeana.iiif.config.ManifestSettings;
Expand Down Expand Up @@ -339,6 +343,32 @@ public void checkCanvas(ExpectedCanvasValues ecv, Canvas c) {
}
}

/**
* Test if canvas thumbnails are URLencoded properly
*/
@Test
public void testCanvasWithThumbnail() {
Object document = Configuration.defaultConfiguration().jsonProvider().parse(EdmManifestData.TEST_SEQUENCE_1CANVAS_THUMB);
String edmIsShownBy = EdmManifestUtils.getValueFromDataProviderAggregation(document, null, "edmIsShownBy");
Sequence[] sequence = EdmManifestMappingV2.getSequencesV2(settings, mediaTypes,"/test-id", edmIsShownBy, document);
Assertions.assertNotNull(sequence);
Assertions.assertEquals(1, sequence.length); // one sequence

// test canvas part
Assertions.assertTrue(sequence[0].getStartCanvas().endsWith("/test-id" + "/canvas/p1"));
Assertions.assertNotNull(sequence[0].getCanvases());
Assertions.assertEquals(2, sequence[0].getCanvases().length); // with two canvasii

// only the second canvas contains the canvas thumbnail and needs checking
ExpectedCanvasValues ecv = new ExpectedCanvasValues();
ecv.id = sequence[0].getCanvases()[1].getId();
String ThumbnailUrl = settings.getThumbnailApiUrl() + CANVAS_THUMBNAIL_ENCODED_URL + CANVAS_THUMBNAIL_POSTFIX;
ecv.thumbNail = new eu.europeana.iiif.model.v2.Image(ThumbnailUrl, null, null);

Assertions.assertEquals(ecv.thumbNail.getId(), sequence[0].getCanvases()[1].getThumbnail().getId());
}


/**
* Test if we generate an annotation and annotation body object (and containing service object) properly
*/
Expand Down Expand Up @@ -371,6 +401,7 @@ private static class ExpectedCanvasValues {
String attribution;
String license;
ExpectedAnnotationAndBodyValues annotationAndBody;
Image thumbNail;
}

private static class ExpectedAnnotationAndBodyValues {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package eu.europeana.iiif.service;

import static eu.europeana.iiif.model.ManifestDefinitions.ATTRIBUTION_STRING;
import static eu.europeana.iiif.model.ManifestDefinitions.CANVAS_THUMBNAIL_POSTFIX;
import static eu.europeana.iiif.service.EdmManifestData.CANVAS_THUMBNAIL_ENCODED_URL;

import com.jayway.jsonpath.Configuration;
import eu.europeana.iiif.config.AppConfig;
import eu.europeana.iiif.config.ManifestSettings;
import eu.europeana.iiif.config.MediaTypes;
import eu.europeana.iiif.config.SerializationConfig;
import eu.europeana.iiif.model.v2.Sequence;
import eu.europeana.iiif.model.v3.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -457,6 +460,33 @@ private void checkCanvas(ExpectedCanvasAndAnnotationPageValues expected, Canvas
}
}

/**
* Test if canvas thumbnails are URLencoded properly
*/
@Test
public void testCanvasWithThumbnail() {
Object document = Configuration.defaultConfiguration().jsonProvider().parse(EdmManifestData.TEST_SEQUENCE_1CANVAS_THUMB);
String edmIsShownBy = EdmManifestUtils.getValueFromDataProviderAggregation(document, null, "edmIsShownBy");
Sequence[] sequence = EdmManifestMappingV2.getSequencesV2(settings, mediaTypes, "/test-id", edmIsShownBy, document);
Assertions.assertNotNull(sequence);
Assertions.assertEquals(1, sequence.length); // one sequence

// test canvas part
Assertions.assertTrue(sequence[0].getStartCanvas().endsWith("/test-id" + "/canvas/p1"));
Assertions.assertNotNull(sequence[0].getCanvases());
Assertions.assertEquals(2, sequence[0].getCanvases().length); // with two canvasii

// only the second canvas contains the canvas thumbnail and needs checking
String thumbnailUrl = settings.getThumbnailApiUrl() + CANVAS_THUMBNAIL_ENCODED_URL + CANVAS_THUMBNAIL_POSTFIX;
ExpectedCanvasAndAnnotationPageValues ecapv = new ExpectedCanvasAndAnnotationPageValues();
eu.europeana.iiif.model.v3.Image[] Thumbnails = {
new eu.europeana.iiif.model.v3.Image(thumbnailUrl)
};
ecapv.thumbnails = Thumbnails;

Assertions.assertEquals(ecapv.thumbnails[0].getId(), sequence[0].getCanvases()[1].getThumbnail().getId());
}

private void checkAnnotationAndBodyAndServiceValues(ExpectedAnnotationAndBodyValues[] expectedAnnotations, Annotation[] annotations) {
Assertions.assertNotNull(annotations);
Assertions.assertNotNull(expectedAnnotations);
Expand Down Expand Up @@ -497,6 +527,7 @@ private static class ExpectedCanvasAndAnnotationPageValues {
// in these tests there can be only 1 annotationPage (because full-text availability check is done elsewhere)
String annoPageid;
String annoPageType;
Image[] thumbnails;
ExpectedAnnotationAndBodyValues[] annoPageAnnotationAndBody;
}

Expand Down