diff --git a/set-definitions/src/main/java/eu/europeana/set/definitions/model/UserSet.java b/set-definitions/src/main/java/eu/europeana/set/definitions/model/UserSet.java index e64da92c..fa81fd11 100644 --- a/set-definitions/src/main/java/eu/europeana/set/definitions/model/UserSet.java +++ b/set-definitions/src/main/java/eu/europeana/set/definitions/model/UserSet.java @@ -3,7 +3,6 @@ import java.util.Date; import java.util.List; import java.util.Map; - import eu.europeana.set.definitions.model.agent.Agent; import eu.europeana.set.definitions.model.impl.Provider; @@ -49,6 +48,10 @@ public interface UserSet extends PageInfo { void setModified(Date modified); + Date getIssued(); + + void setIssued(Date issued); + List getItems(); void setItems(List items); diff --git a/set-definitions/src/main/java/eu/europeana/set/definitions/model/impl/BaseUserSet.java b/set-definitions/src/main/java/eu/europeana/set/definitions/model/impl/BaseUserSet.java index ad351863..b24a70e6 100644 --- a/set-definitions/src/main/java/eu/europeana/set/definitions/model/impl/BaseUserSet.java +++ b/set-definitions/src/main/java/eu/europeana/set/definitions/model/impl/BaseUserSet.java @@ -3,7 +3,6 @@ import java.util.Date; import java.util.List; import java.util.Map; - import eu.europeana.set.definitions.model.UserSet; import eu.europeana.set.definitions.model.agent.Agent; import eu.europeana.set.definitions.model.vocabulary.UserSetTypes; @@ -79,6 +78,12 @@ public abstract class BaseUserSet extends BasePageInfo implements UserSet { * literal expressed as xsd:dateTime with the UTC timezone expressed as "Z". */ private Date modified; + + /** + * The time at which the Set was published, after creation. The value must be a + * literal expressed as xsd:dateTime with the UTC timezone expressed as "Z". + */ + private Date issued; /** * Ordered Collections from Activity Streams For EDM Collection class @@ -198,6 +203,16 @@ public void setModified(Date modified) { this.modified = modified; } + @Override + public Date getIssued() { + return issued; + } + + @Override + public void setIssued(Date issued) { + this.issued = issued; + } + @Override public List getItems() { return items; diff --git a/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetFields.java b/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetFields.java index 107b0d61..234c0d18 100644 --- a/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetFields.java +++ b/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetFields.java @@ -25,6 +25,7 @@ public class WebUserSetFields extends WebUserSetModelFields { public static final String PATH_PARAM_CREATOR_ID = "creator"; public static final String PATH_PARAM_LOCAL_ID = "localId"; public static final String PATH_PARAM_POSITION = "position"; + public static final String REQUEST_PARAM_ISSUED = "issued"; /** * sort order should be included in the sort param @@ -67,8 +68,6 @@ public class WebUserSetFields extends WebUserSetModelFields { // Serialization Constants public static final String SEPARATOR_SEMICOLON = ":"; - public static final String SET_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; -// public static final String DEFAULT_USER_BASE_URL = "http://data.europeana.eu/user/"; // Entity user set and Elevation Constants public static final String ELEVATION_FILENAME = "elevate.xml"; diff --git a/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetModelFields.java b/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetModelFields.java index aac17cfe..8b95a665 100644 --- a/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetModelFields.java +++ b/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetModelFields.java @@ -22,6 +22,7 @@ public class WebUserSetModelFields { public static final String CONTRIBUTOR = "contributor"; public static final String CREATED = "created"; public static final String MODIFIED = "modified"; + public static final String ISSUED = "issued"; public static final String IS_DEFINED_BY = "isDefinedBy"; public static final String SUBJECT = "subject"; public static final String ITEMS = "items"; diff --git a/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/BaseUserSetTestUtils.java b/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/BaseUserSetTestUtils.java index 919f80f2..a2ca2640 100644 --- a/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/BaseUserSetTestUtils.java +++ b/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/BaseUserSetTestUtils.java @@ -5,6 +5,7 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -316,4 +317,17 @@ protected void addToCreatedSets(String identifier) { userSet.setIdentifier(identifier); createdUserSets.add(userSet); } + + protected String getStringValue(String jsonBody, String fieldName) throws JSONException { + JSONObject json = new JSONObject(jsonBody); + return json.getString(fieldName); + } + + protected List getStringListValues(String jsonBody, String fieldName) throws JSONException { + assertNotNull(jsonBody); + JSONObject json = new JSONObject(jsonBody); + return Collections.singletonList(json.getString(fieldName)); + } + + } diff --git a/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/web/EntityBestItemsSetIT.java b/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/web/EntityBestItemsSetIT.java index 2dd5d9a8..adc46a8e 100644 --- a/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/web/EntityBestItemsSetIT.java +++ b/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/web/EntityBestItemsSetIT.java @@ -8,11 +8,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import java.util.Collections; -import java.util.List; import org.apache.commons.lang3.StringUtils; -import org.codehaus.jettison.json.JSONException; -import org.codehaus.jettison.json.JSONObject; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -105,10 +101,10 @@ void createSetSuccessfully() throws Exception { createdUserSets.add(createdSet); assertNotNull(identifier); - String creator = getCreator(result); + String creator = getStringValue(result, WebUserSetModelFields.CREATOR); assertNotNull(creator); assertTrue(StringUtils.contains(creator, getConfiguration().getEntityUserSetUserId())); - String provider = getProvider(result); + String provider = getStringValue(result, WebUserSetModelFields.PROVIDER); assertNotNull(provider); // check name assertTrue(containsKeyOrValue(provider, "Europeana XX")); @@ -117,7 +113,7 @@ void createSetSuccessfully() throws Exception { containsKeyOrValue(provider, "https:\\/\\/pro.europeana.eu\\/project\\/europeana-xx")); // check subject assertEquals("http://data.europeana.eu/concept/114", createdSet.getSubject().get(0)); - assertNotNull(getSetContributors(result)); + assertNotNull(getStringListValues(result, WebUserSetModelFields.CONTRIBUTOR)); } @@ -140,10 +136,10 @@ void createSetWithProviderId() throws Exception { createdUserSets.add(createdSet); assertNotNull(identifier); - String creator = getCreator(result); + String creator = getStringValue(result, WebUserSetModelFields.CREATOR); assertNotNull(creator); assertTrue(StringUtils.contains(creator, getConfiguration().getEntityUserSetUserId())); - String provider = getProvider(result); + String provider = getStringValue(result, WebUserSetModelFields.PROVIDER); assertNotNull(provider); // check name - must not be present assertFalse(containsKeyOrValue(provider, "Europeana XX")); @@ -151,7 +147,7 @@ void createSetWithProviderId() throws Exception { assertTrue( containsKeyOrValue(provider, "https:\\/\\/pro.europeana.eu\\/project\\/europeana-xx")); - assertNotNull(getSetContributors(result)); + assertNotNull(getStringListValues(result, WebUserSetModelFields.CONTRIBUTOR)); } @Test @@ -684,26 +680,6 @@ void deletePinnedItems_EntityUserSets_withEditorUser() throws Exception { } - private String getCreator(String result) throws JSONException { - assertNotNull(result); - JSONObject json = new JSONObject(result); - String creator = json.getString(WebUserSetModelFields.CREATOR); - return creator; - } - - private String getProvider(String result) throws JSONException { - assertNotNull(result); - JSONObject json = new JSONObject(result); - String provider = json.getString(WebUserSetModelFields.PROVIDER); - return provider; - } - - private List getSetContributors(String result) throws JSONException { - assertNotNull(result); - JSONObject json = new JSONObject(result); - return Collections.singletonList(json.getString(WebUserSetModelFields.CONTRIBUTOR)); - } - private void checkItemCountAndPosition(UserSet existingUserSet, String newItem, int expectedTotalItems, int expectedPinnedItems, int expectedPositionOfItem) { assertEquals(expectedPinnedItems, existingUserSet.getPinned()); diff --git a/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/web/WebUserSetPublishingIT.java b/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/web/WebUserSetPublishingIT.java index 31e68a3a..5ad8ad3f 100644 --- a/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/web/WebUserSetPublishingIT.java +++ b/set-integration-testing/src/integration-test/java/eu/europeana/api/set/integration/web/WebUserSetPublishingIT.java @@ -9,6 +9,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.UnsupportedEncodingException; +import java.util.Date; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -19,10 +20,13 @@ import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import eu.europeana.api.commons.definitions.utils.DateUtils; import eu.europeana.api.commons.definitions.vocabulary.CommonApiConstants; import eu.europeana.api.set.integration.BaseUserSetTestUtils; import eu.europeana.set.definitions.model.utils.UserSetUtils; import eu.europeana.set.definitions.model.vocabulary.LdProfiles; +import eu.europeana.set.definitions.model.vocabulary.WebUserSetFields; +import eu.europeana.set.definitions.model.vocabulary.WebUserSetModelFields; import eu.europeana.set.web.model.WebUserSetImpl; /** @@ -43,7 +47,7 @@ public class WebUserSetPublishingIT extends BaseUserSetTestUtils { @BeforeAll public static void initTokens() { - if(DISABLE_AUTH) { + if (DISABLE_AUTH) { return; } initRegularUserToken(); @@ -62,20 +66,61 @@ protected void deleteCreatedSets() { super.deleteCreatedSets(); } - // publish/unpublish user set tests + // publish and validate user set tests @Test - public void publishUnpublishUserSet_Success() throws Exception { + void publishUserSet_Success() throws Exception { // create set by publisher WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, publisherUserToken); // publish set by publisher // expected change of ownership to editorial team - publishUserSet(userSet, getConfiguration().getEuropeanaPublisherNickname()); + String issued = DateUtils.convertDateToStr(new Date()); + MockHttpServletResponse response = + publishUserSet(userSet, issued, getConfiguration().getEuropeanaPublisherNickname()); + assertNotNull(response); + } + + @Test + void publishPreviouslyPublishedUserSet() throws Exception { + + WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, regularUserToken); + + // publish published user set + publishUserSet(userSet, null, USERNAME_REGULAR); + //Date is set in seconds, ensure 1 second before method execution + final int oneSecondInMilis = 1000; + Date beforeCallDate = new Date(System.currentTimeMillis() - oneSecondInMilis); + + MockHttpServletResponse response = mockMvc + .perform(MockMvcRequestBuilders.put(BASE_URL + userSet.getIdentifier() + "/publish") + .header(HttpHeaders.AUTHORIZATION, publisherUserToken) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .param(CommonApiConstants.QUERY_PARAM_PROFILE, LdProfiles.STANDARD.name())).andReturn().getResponse(); + + assertEquals(HttpStatus.OK.value(), response.getStatus()); + String result = response.getContentAsString(); + + Date issued = DateUtils.parseToDate(getStringValue(result, WebUserSetModelFields.ISSUED)); + Date modified = DateUtils.parseToDate(getStringValue(result, WebUserSetModelFields.MODIFIED)); + assertEquals(issued, modified); + //issued should be after the call date + assertTrue(issued.compareTo(beforeCallDate)>=0); + } + + // unpublish user set tests + @Test + void unpublishUserSet_Success() throws Exception { + // create set by publisher + WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, publisherUserToken); + + // publish set by publisher + // expected change of ownership to editorial team + String issued = DateUtils.convertDateToStr(new Date()); + publishUserSet(userSet, issued, getConfiguration().getEuropeanaPublisherNickname()); MockHttpServletResponse response; String result; - - // depublish set + // unpublish set response = mockMvc .perform(MockMvcRequestBuilders.put(BASE_URL + userSet.getIdentifier() + "/unpublish") .header(HttpHeaders.AUTHORIZATION, publisherUserToken) @@ -88,20 +133,70 @@ public void publishUnpublishUserSet_Success() throws Exception { assertTrue(containsKeyOrValue(result, UserSetUtils .buildUserSetId(getConfiguration().getSetDataEndpoint(), userSet.getIdentifier()))); assertTrue(containsKeyOrValue(result, "public")); + assertFalse(containsKeyOrValue(result, WebUserSetModelFields.ISSUED)); // unpublished set, the ownership is changed back to current user assertFalse(containsKeyOrValue(result, getConfiguration().getEuropeanaPublisherNickname())); assertTrue(containsKeyOrValue(result, USERNAME_PUBLISHER)); assertEquals(HttpStatus.OK.value(), response.getStatus()); } + + // unpublish user set tests + @Test + void unpublishUserSet_NoOwnerTransfer() throws Exception { + // create set by publisher + WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, regularUserToken); + + // publish set by publisher + // expected change of ownership to editorial team + String issued = DateUtils.convertDateToStr(new Date()); + MockHttpServletResponse response = publishUserSet(userSet, issued, USERNAME_REGULAR); + + String result; + // unpublish set + response = mockMvc + .perform(MockMvcRequestBuilders.put(BASE_URL + userSet.getIdentifier() + "/unpublish") + .header(HttpHeaders.AUTHORIZATION, publisherUserToken) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .param(CommonApiConstants.QUERY_PARAM_PROFILE, LdProfiles.STANDARD.name())) + .andReturn().getResponse(); + + result = response.getContentAsString(); + assertEquals(HttpStatus.OK.value(), response.getStatus()); + //assert user name not changed + assertTrue(containsKeyOrValue(result, USERNAME_REGULAR)); + + assertTrue(containsKeyOrValue(result, UserSetUtils + .buildUserSetId(getConfiguration().getSetDataEndpoint(), userSet.getIdentifier()))); + assertTrue(containsKeyOrValue(result, "public")); + assertFalse(containsKeyOrValue(result, WebUserSetModelFields.ISSUED)); + // unpublished set, the ownership is changed back to current user + assertFalse(containsKeyOrValue(result, getConfiguration().getEuropeanaPublisherNickname())); + + } @Test - public void updatePublishedUserSet_Success() throws Exception { + void unpublishNotPublishedUserSet() throws Exception { + // create set by publisher + WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, publisherUserToken); + + // unpublish unpublished user set + // must return 400 + mockMvc + .perform(MockMvcRequestBuilders.put(BASE_URL + userSet.getIdentifier() + "/unpublish") + .header(HttpHeaders.AUTHORIZATION, publisherUserToken) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .param(CommonApiConstants.QUERY_PARAM_PROFILE, LdProfiles.STANDARD.name())) + .andExpect(status().is(HttpStatus.BAD_REQUEST.value())); + } + + + @Test + void updatePublishedUserSet_Success() throws Exception { // create userset WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, regularUserToken); // publish userset by other user, the ownership stays with the creator - publishUserSet(userSet, USERNAME_REGULAR); - + publishUserSet(userSet, null, USERNAME_REGULAR); // update userset String updatedRequestJson = getJsonStringInput(USER_SET_REGULAR_UPDATED); @@ -130,12 +225,12 @@ public void updatePublishedUserSet_Success() throws Exception { } @Test - public void updatePublishedUserSetWithVisibility_Success() throws Exception { + void updatePublishedUserSetWithVisibility_Success() throws Exception { // create userset WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, regularUserToken); // publish userset by other user, the ownership stays with the creator - publishUserSet(userSet, USERNAME_REGULAR); + publishUserSet(userSet, null, USERNAME_REGULAR); // update userset @@ -165,12 +260,12 @@ public void updatePublishedUserSetWithVisibility_Success() throws Exception { } @Test - public void addItemToPublishedSet() throws Exception { + void addItemToPublishedSet() throws Exception { // create userset WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, regularUserToken); // publish userset by other user, the ownership stays with the creator - publishUserSet(userSet, USERNAME_REGULAR); + publishUserSet(userSet, null, USERNAME_REGULAR); // add item to userset as publisher @@ -198,12 +293,12 @@ public void addItemToPublishedSet() throws Exception { } @Test - public void removeItemFromPublishedSet() throws Exception { + void removeItemFromPublishedSet() throws Exception { // create userset WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, regularUserToken); // publish userset by other user, the ownership stays with the creator - publishUserSet(userSet, USERNAME_REGULAR); + publishUserSet(userSet, null, USERNAME_REGULAR); // add item to userset as publisher MockHttpServletResponse response = mockMvc @@ -230,12 +325,12 @@ public void removeItemFromPublishedSet() throws Exception { @Test - public void checkItemInSetFromPublishedSet() throws Exception { + void checkItemInSetFromPublishedSet() throws Exception { // create userset WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, regularUserToken); // publish userset by other user, the ownership stays with the creator - publishUserSet(userSet, USERNAME_REGULAR); + publishUserSet(userSet, null, USERNAME_REGULAR); // add item to userset as publisher MockHttpServletResponse response = mockMvc @@ -246,56 +341,67 @@ public void checkItemInSetFromPublishedSet() throws Exception { assertEquals(HttpStatus.NO_CONTENT.value(), response.getStatus()); } - private void publishUserSet(WebUserSetImpl userSet, String expectedOwner) - throws Exception, UnsupportedEncodingException { + private MockHttpServletResponse publishUserSet(WebUserSetImpl userSet, String issued, + String expectedOwner) throws Exception, UnsupportedEncodingException { - MockHttpServletResponse response = mockMvc - .perform(MockMvcRequestBuilders.put(BASE_URL + userSet.getIdentifier() + "/publish") + MockHttpServletResponse response = + mockMvc.perform(MockMvcRequestBuilders.put(BASE_URL + userSet.getIdentifier() + "/publish") .header(HttpHeaders.AUTHORIZATION, publisherUserToken) .contentType(MediaType.APPLICATION_JSON_VALUE) - .param(CommonApiConstants.QUERY_PARAM_PROFILE, LdProfiles.STANDARD.name())) - .andReturn().getResponse(); + .param(CommonApiConstants.QUERY_PARAM_PROFILE, LdProfiles.STANDARD.name()) + .param(WebUserSetFields.REQUEST_PARAM_ISSUED, issued)).andReturn().getResponse(); String result = response.getContentAsString(); assertNotNull(result); assertTrue(containsKeyOrValue(result, UserSetUtils .buildUserSetId(getConfiguration().getSetDataEndpoint(), userSet.getIdentifier()))); assertTrue(containsKeyOrValue(result, "published")); + assertTrue(containsKeyOrValue(result, WebUserSetModelFields.ISSUED)); + if (issued != null) { + assertTrue(containsKeyOrValue(result, issued)); + } if (expectedOwner != null) { assertTrue(containsKeyOrValue(result, expectedOwner)); } assertEquals(HttpStatus.OK.value(), response.getStatus()); + return response; } - + @Test - public void publishUnpublishUserSet_Exceptions() throws Exception { - - WebUserSetImpl userSet = createTestUserSet(USER_SET_REGULAR, regularUserToken); - + void publishNonExistingUserSet() throws Exception { mockMvc .perform(MockMvcRequestBuilders.put(BASE_URL + "test-dummy" + "/publish") .header(HttpHeaders.AUTHORIZATION, publisherUserToken) .contentType(MediaType.APPLICATION_JSON_VALUE) .param(CommonApiConstants.QUERY_PARAM_PROFILE, LdProfiles.STANDARD.name())) .andExpect(status().is(HttpStatus.NOT_FOUND.value())); - + } + + @Test + void publishWrongSetType() throws Exception { + // wrong user set type (bookmark folder) + WebUserSetImpl userSet2 = createTestUserSet(USER_SET_BOOKMARK_FOLDER, regularUserToken); mockMvc - .perform(MockMvcRequestBuilders.put(BASE_URL + userSet.getIdentifier() + "/publish") - .header(HttpHeaders.AUTHORIZATION, regularUserToken) + .perform(MockMvcRequestBuilders.put(BASE_URL + userSet2.getIdentifier() + "/publish") + .header(HttpHeaders.AUTHORIZATION, publisherUserToken) .contentType(MediaType.APPLICATION_JSON_VALUE) .param(CommonApiConstants.QUERY_PARAM_PROFILE, LdProfiles.STANDARD.name())) - .andExpect(status().is(HttpStatus.FORBIDDEN.value())); - - getUserSetService().deleteUserSet(userSet.getIdentifier()); - - userSet = createTestUserSet(USER_SET_BOOKMARK_FOLDER, regularUserToken); + .andExpect(status().is(HttpStatus.BAD_REQUEST.value())); + } + + @Test + void publishWithoutPermission() throws Exception { + // wrong user set identifier + WebUserSetImpl userSet1 = createTestUserSet(USER_SET_REGULAR, regularUserToken); + //publish without publish permission mockMvc - .perform(MockMvcRequestBuilders.put(BASE_URL + userSet.getIdentifier() + "/publish") - .header(HttpHeaders.AUTHORIZATION, publisherUserToken) + .perform(MockMvcRequestBuilders.put(BASE_URL + userSet1.getIdentifier() + "/publish") + .header(HttpHeaders.AUTHORIZATION, regularUserToken) .contentType(MediaType.APPLICATION_JSON_VALUE) .param(CommonApiConstants.QUERY_PARAM_PROFILE, LdProfiles.STANDARD.name())) - .andExpect(status().is(HttpStatus.BAD_REQUEST.value())); + .andExpect(status().is(HttpStatus.FORBIDDEN.value())); } + } diff --git a/set-web/src/main/java/eu/europeana/set/web/search/UserSetLdSerializer.java b/set-web/src/main/java/eu/europeana/set/web/search/UserSetLdSerializer.java index 23584094..e270f00f 100644 --- a/set-web/src/main/java/eu/europeana/set/web/search/UserSetLdSerializer.java +++ b/set-web/src/main/java/eu/europeana/set/web/search/UserSetLdSerializer.java @@ -3,10 +3,9 @@ import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Locale; - import com.fasterxml.jackson.databind.ObjectMapper; - import eu.europeana.api.commons.definitions.statistics.set.SetMetric; +import eu.europeana.api.commons.definitions.utils.DateUtils; import eu.europeana.set.definitions.model.UserSet; import eu.europeana.set.definitions.model.utils.UserSetUtils; import eu.europeana.set.definitions.model.vocabulary.WebUserSetFields; @@ -19,106 +18,106 @@ public class UserSetLdSerializer { - UserSetUtils userSetUtils = new UserSetUtils(); - ObjectMapper mapper = new ObjectMapper(); - JsonldResourceBuilder userSetResourceBuilder; - JsonldResourceBuilder> resultPageResourceBuilder; - JsonldResourceBuilder collectionPageResourceBuilder; - - public UserSetUtils getUserSetUtils() { - return userSetUtils; - } - - public UserSetLdSerializer() { - SimpleDateFormat df = new SimpleDateFormat(WebUserSetFields.SET_DATE_FORMAT, Locale.ENGLISH); - mapper.setDateFormat(df); - } - - /** - * This method provides full serialization of a user set - * - * @param userSet - * @return full user set view - * @throws IOException - */ - public String serialize(UserSet userSet) throws IOException { - - mapper.registerModule(new JsonldModule()); - return mapper.writer().writeValueAsString(getUserSetResourceBuilder().build(userSet)); - } - - /** - * This method provides full serialization of a result page (search results) - * - * @param resultsPage - * @return full user set view - * @throws IOException - */ - public String serialize(BaseUserSetResultPage resultsPage) throws IOException { - - mapper.registerModule(new JsonldModule()); - return mapper.writer().writeValueAsString(getResultPageResourceBuilder().build(resultsPage)); - } - - /** - * This method provides full serialization of a Metric View (Usage stats results) - * - * @param metricData - * @return full metric view - * @throws IOException - */ - public String serialize(SetMetric metricData) throws IOException { - mapper.registerModule(new JsonldModule()); - return mapper.writer().writeValueAsString(metricData); - } - - /** - * This method provides full serialization of a searchApiRequest - * - * @param searchApiRequest - * @return json String of searchApiRequest - * @throws IOException - */ - public String serialize(SearchApiRequest searchApiRequest) throws IOException { - mapper.registerModule(new JsonldModule()); - return mapper.writer().writeValueAsString(searchApiRequest); - } - - /** - * This method provides full serialization of a CollectionPage - * - * @param itemPage - * @return full user set view - * @throws IOException - */ - public String serialize(CollectionPage itemPage) throws IOException { - - mapper.registerModule(new JsonldModule()); - return mapper.writer().writeValueAsString(getCollectionPageResourceBuilder().build(itemPage)); - } - - private JsonldResourceBuilder getCollectionPageResourceBuilder() { - if (collectionPageResourceBuilder == null) { - collectionPageResourceBuilder = JsonldResource.Builder.create(); - collectionPageResourceBuilder.context(WebUserSetFields.CONTEXT); - } - return collectionPageResourceBuilder; + UserSetUtils userSetUtils = new UserSetUtils(); + ObjectMapper mapper = new ObjectMapper(); + JsonldResourceBuilder userSetResourceBuilder; + JsonldResourceBuilder> resultPageResourceBuilder; + JsonldResourceBuilder collectionPageResourceBuilder; + + public UserSetUtils getUserSetUtils() { + return userSetUtils; + } + + public UserSetLdSerializer() { + SimpleDateFormat df = new SimpleDateFormat(DateUtils.DATE_FORMAT, Locale.ENGLISH); + mapper.setDateFormat(df); + } + + /** + * This method provides full serialization of a user set + * + * @param userSet + * @return full user set view + * @throws IOException + */ + public String serialize(UserSet userSet) throws IOException { + + mapper.registerModule(new JsonldModule()); + return mapper.writer().writeValueAsString(getUserSetResourceBuilder().build(userSet)); + } + + /** + * This method provides full serialization of a result page (search results) + * + * @param resultsPage + * @return full user set view + * @throws IOException + */ + public String serialize(BaseUserSetResultPage resultsPage) throws IOException { + + mapper.registerModule(new JsonldModule()); + return mapper.writer().writeValueAsString(getResultPageResourceBuilder().build(resultsPage)); + } + + /** + * This method provides full serialization of a Metric View (Usage stats results) + * + * @param metricData + * @return full metric view + * @throws IOException + */ + public String serialize(SetMetric metricData) throws IOException { + mapper.registerModule(new JsonldModule()); + return mapper.writer().writeValueAsString(metricData); + } + + /** + * This method provides full serialization of a searchApiRequest + * + * @param searchApiRequest + * @return json String of searchApiRequest + * @throws IOException + */ + public String serialize(SearchApiRequest searchApiRequest) throws IOException { + mapper.registerModule(new JsonldModule()); + return mapper.writer().writeValueAsString(searchApiRequest); + } + + /** + * This method provides full serialization of a CollectionPage + * + * @param itemPage + * @return full user set view + * @throws IOException + */ + public String serialize(CollectionPage itemPage) throws IOException { + + mapper.registerModule(new JsonldModule()); + return mapper.writer().writeValueAsString(getCollectionPageResourceBuilder().build(itemPage)); + } + + private JsonldResourceBuilder getCollectionPageResourceBuilder() { + if (collectionPageResourceBuilder == null) { + collectionPageResourceBuilder = JsonldResource.Builder.create(); + collectionPageResourceBuilder.context(WebUserSetFields.CONTEXT); } + return collectionPageResourceBuilder; + } - public JsonldResourceBuilder getUserSetResourceBuilder() { - if (userSetResourceBuilder == null) { - userSetResourceBuilder = JsonldResource.Builder.create(); - userSetResourceBuilder.context(WebUserSetFields.CONTEXT); - } - return userSetResourceBuilder; + public JsonldResourceBuilder getUserSetResourceBuilder() { + if (userSetResourceBuilder == null) { + userSetResourceBuilder = JsonldResource.Builder.create(); + userSetResourceBuilder.context(WebUserSetFields.CONTEXT); } + return userSetResourceBuilder; + } - public JsonldResourceBuilder> getResultPageResourceBuilder() { - if (resultPageResourceBuilder == null) { - resultPageResourceBuilder = JsonldResource.Builder.create(); - resultPageResourceBuilder.context(WebUserSetFields.CONTEXT); - } - return resultPageResourceBuilder; + public JsonldResourceBuilder> getResultPageResourceBuilder() { + if (resultPageResourceBuilder == null) { + resultPageResourceBuilder = JsonldResource.Builder.create(); + resultPageResourceBuilder.context(WebUserSetFields.CONTEXT); } + return resultPageResourceBuilder; + } } diff --git a/set-web/src/main/java/eu/europeana/set/web/service/UserSetService.java b/set-web/src/main/java/eu/europeana/set/web/service/UserSetService.java index 5ca23547..5e54c99b 100644 --- a/set-web/src/main/java/eu/europeana/set/web/service/UserSetService.java +++ b/set-web/src/main/java/eu/europeana/set/web/service/UserSetService.java @@ -1,6 +1,7 @@ package eu.europeana.set.web.service; import java.io.IOException; +import java.util.Date; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.codehaus.jettison.json.JSONException; @@ -244,6 +245,6 @@ ItemIdsResultPage buildItemIdsResultsPage(String setId, List itemIds, in * @return * @throws HttpException */ - UserSet publishUnpublishUserSet(String userSetId, Authentication authentication, boolean publish) throws HttpException; + UserSet publishUnpublishUserSet(String userSetId, Date issued, Authentication authentication, boolean publish) throws HttpException; } \ No newline at end of file diff --git a/set-web/src/main/java/eu/europeana/set/web/service/controller/BaseRest.java b/set-web/src/main/java/eu/europeana/set/web/service/controller/BaseRest.java index 8329ecdd..4dac7678 100644 --- a/set-web/src/main/java/eu/europeana/set/web/service/controller/BaseRest.java +++ b/set-web/src/main/java/eu/europeana/set/web/service/controller/BaseRest.java @@ -15,6 +15,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TimeZone; +import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; @@ -62,6 +64,11 @@ public class BaseRest extends BaseRestController { @Resource UsageStatsService usageStatsService; + + @PostConstruct + void started() { + TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC")); + } Logger logger = LogManager.getLogger(getClass()); diff --git a/set-web/src/main/java/eu/europeana/set/web/service/controller/jsonld/WebUserSetRest.java b/set-web/src/main/java/eu/europeana/set/web/service/controller/jsonld/WebUserSetRest.java index 943b7360..1596a0f4 100644 --- a/set-web/src/main/java/eu/europeana/set/web/service/controller/jsonld/WebUserSetRest.java +++ b/set-web/src/main/java/eu/europeana/set/web/service/controller/jsonld/WebUserSetRest.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.util.Collections; +import java.util.Date; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.validation.constraints.Pattern; @@ -25,6 +26,8 @@ import com.fasterxml.jackson.core.JsonParseException; import eu.europeana.api.common.config.swagger.SwaggerSelect; import eu.europeana.api.commons.definitions.config.i18n.I18nConstants; +import eu.europeana.api.commons.definitions.exception.DateParsingException; +import eu.europeana.api.commons.definitions.utils.DateUtils; import eu.europeana.api.commons.definitions.vocabulary.CommonApiConstants; import eu.europeana.api.commons.web.definitions.WebFields; import eu.europeana.api.commons.web.exception.ApplicationAuthenticationException; @@ -370,11 +373,22 @@ public ResponseEntity publishUserSet( @PathVariable(value = WebUserSetFields.PATH_PARAM_SET_ID) String identifier, @RequestParam(value = CommonApiConstants.QUERY_PARAM_PROFILE, required = false, defaultValue = CommonApiConstants.PROFILE_MINIMAL) String profileStr, + @RequestParam(value = WebUserSetFields.REQUEST_PARAM_ISSUED, required = false) String issued, HttpServletRequest request) throws HttpException { // check user credentials, if invalid respond with HTTP 401, // or if unauthorized respond with HTTP 403 Authentication authentication = verifyWriteAccess(SetOperations.PUBLISH, request); - return publishUnpublishUserSet(identifier, authentication, true, profileStr, request); + Date issuedDate=null; + if(issued!=null) { + try { + issuedDate = DateUtils.parseToDate(issued); + } catch (DateParsingException e) { + throw new ParamValidationException(I18nConstants.INVALID_PARAM_VALUE, + I18nConstants.INVALID_PARAM_VALUE, new String[] {WebUserSetFields.REQUEST_PARAM_ISSUED, issued}, e); + } + } + + return publishUnpublishUserSet(identifier, authentication, true, profileStr, issuedDate, request); } @PutMapping(value = {"/set/{identifier}/unpublish"}, @@ -389,15 +403,15 @@ public ResponseEntity unpublishUserSet( // check user credentials, if invalid respond with HTTP 401, // or if unauthorized respond with HTTP 403 Authentication authentication = verifyWriteAccess(SetOperations.PUBLISH, request); - return publishUnpublishUserSet(identifier, authentication, false, profileStr, request); + return publishUnpublishUserSet(identifier, authentication, false, profileStr, null, request); } protected ResponseEntity publishUnpublishUserSet(String identifier, - Authentication authentication, boolean publish, String profileStr, HttpServletRequest request) + Authentication authentication, boolean publish, String profileStr, Date issued, HttpServletRequest request) throws HttpException { try { UserSet updatedUserSet = - getUserSetService().publishUnpublishUserSet(identifier, authentication, publish); + getUserSetService().publishUnpublishUserSet(identifier, issued, authentication, publish); // serialize to JsonLd LdProfiles profile = getProfile(profileStr, request); diff --git a/set-web/src/main/java/eu/europeana/set/web/service/impl/BaseUserSetServiceImpl.java b/set-web/src/main/java/eu/europeana/set/web/service/impl/BaseUserSetServiceImpl.java index 77b5e8cc..438f2ecd 100644 --- a/set-web/src/main/java/eu/europeana/set/web/service/impl/BaseUserSetServiceImpl.java +++ b/set-web/src/main/java/eu/europeana/set/web/service/impl/BaseUserSetServiceImpl.java @@ -854,12 +854,7 @@ void updateTotal(UserSet existingUserSet) { } } - PersistentUserSet updateUserSetForPublish(PersistentUserSet userSet, - Authentication authentication) { - if (userSet.isPublished()) { - // just a second check to prevent updates for allready published sets - return userSet; - } + PersistentUserSet updateUserSetForPublish(PersistentUserSet userSet, Date issued, Authentication authentication){ // update the visibility to publish if (isOwner(userSet, authentication)) { // if the requesting user is the owner of the gallery, the ownership is reassigned to @@ -868,7 +863,12 @@ PersistentUserSet updateUserSetForPublish(PersistentUserSet userSet, userSet.setCreator(creator); } userSet.setVisibility(VisibilityTypes.PUBLISHED.getJsonValue()); - userSet.setModified(new Date()); + Date now = new Date(); + if(issued==null) { + issued=now; + } + userSet.setIssued(issued); + userSet.setModified(now); return getMongoPersistence().update(userSet); } @@ -882,11 +882,6 @@ private Agent buildEuropeanaPublisherUser() { PersistentUserSet updateUserSetForUnpublish(PersistentUserSet userSet, Authentication authentication) { - - if(!userSet.isPublished()){ - // just a second check to prevent updates for not published sets - return userSet; - } // update the visibility to public if (hasPublisherAsOwner(userSet)) { // if the owner is @europeana, then the ownership is reassigned to the requesting user @@ -895,6 +890,7 @@ PersistentUserSet updateUserSetForUnpublish(PersistentUserSet userSet, } userSet.setVisibility(VisibilityTypes.PUBLIC.getJsonValue()); + userSet.setIssued(null); userSet.setModified(new Date()); return getMongoPersistence().update(userSet); } diff --git a/set-web/src/main/java/eu/europeana/set/web/service/impl/UserSetServiceImpl.java b/set-web/src/main/java/eu/europeana/set/web/service/impl/UserSetServiceImpl.java index 30f67229..61fdd2d1 100644 --- a/set-web/src/main/java/eu/europeana/set/web/service/impl/UserSetServiceImpl.java +++ b/set-web/src/main/java/eu/europeana/set/web/service/impl/UserSetServiceImpl.java @@ -898,7 +898,7 @@ private void setSerializedItemIds(UserSet userSet) { } @Override - public UserSet publishUnpublishUserSet(String userSetId, Authentication authentication, + public UserSet publishUnpublishUserSet(String userSetId, Date issued, Authentication authentication, boolean publish) throws HttpException { PersistentUserSet userSet = getMongoPersistence().getByIdentifier(userSetId); // if the user set does not exist, return 404 @@ -908,7 +908,7 @@ public UserSet publishUnpublishUserSet(String userSetId, Authentication authenti } validateUserSetForPublishUnPublish(userSet, publish); if (publish) { - return updateUserSetForPublish(userSet, authentication); + return updateUserSetForPublish(userSet, issued, authentication); } else { return updateUserSetForUnpublish(userSet, authentication); } @@ -929,11 +929,7 @@ private void validateUserSetForPublishUnPublish(PersistentUserSet userSet, boole new String[] {"Publish/Unpublish user set ", userSet.getType()}); } // verify the state of the object - if (publish && userSet.isPublished()) { - // if publishing - throw new RequestValidationException(UserSetI18nConstants.USER_SET_OPERATION_NOT_ALLOWED, - new String[] {"Publish", "allready published"}); - } else if (!publish && !userSet.isPublished()) { + if (!publish && !userSet.isPublished()) { // if depublishing throw new RequestValidationException(UserSetI18nConstants.USER_SET_OPERATION_NOT_ALLOWED, new String[] {"Unpublish", "not published"});