diff --git a/notification-core/src/main/java/org/opengroup/osdu/notification/pubsub/IPubsubHandshakeHandler.java b/notification-core/src/main/java/org/opengroup/osdu/notification/pubsub/IPubsubHandshakeHandler.java deleted file mode 100644 index a08238247a7744207a8fd920a4e3e6fa2135ea37..0000000000000000000000000000000000000000 --- a/notification-core/src/main/java/org/opengroup/osdu/notification/pubsub/IPubsubHandshakeHandler.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.opengroup.osdu.notification.pubsub; - -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; - -public interface IPubsubHandshakeHandler { - String getHandshakeResponse(); -} diff --git a/notification-core/src/main/java/org/opengroup/osdu/notification/pubsub/IPubsubRequestBodyExtractor.java b/notification-core/src/main/java/org/opengroup/osdu/notification/pubsub/IPubsubRequestBodyExtractor.java deleted file mode 100644 index 1a98f88b36fbc2e3912a39e616abedcb1499012a..0000000000000000000000000000000000000000 --- a/notification-core/src/main/java/org/opengroup/osdu/notification/pubsub/IPubsubRequestBodyExtractor.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.opengroup.osdu.notification.pubsub; - -import org.springframework.stereotype.Component; -import org.springframework.http.ResponseEntity; - -import java.util.Map; - -public interface IPubsubRequestBodyExtractor { - Map<String, String> extractAttributesFromRequestBody() ; - - String extractDataFromRequestBody(); - - String extractNotificationIdFromRequestBody() ; - - boolean isHandshakeRequest(); -} diff --git a/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/pubsub/EventGridHandshakeHandler.java b/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/pubsub/EventGridHandshakeHandler.java index 065ffca5ef72cfd9dd0028b1c74c0c7885ac9c94..b3b2a861f885a62d07699f91e7e028137f85d33b 100644 --- a/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/pubsub/EventGridHandshakeHandler.java +++ b/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/pubsub/EventGridHandshakeHandler.java @@ -16,19 +16,16 @@ package org.opengroup.osdu.notification.provider.azure.pubsub; import com.google.gson.JsonObject; import org.opengroup.osdu.core.common.model.http.AppException; -import org.opengroup.osdu.notification.provider.azure.util.RequestAttributesDispatcher; -import org.opengroup.osdu.notification.pubsub.IPubsubHandshakeHandler; +import org.opengroup.osdu.notification.provider.interfaces.IPubsubHandshakeHandler; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; @Component -@Lazy public class EventGridHandshakeHandler implements IPubsubHandshakeHandler { @Autowired - private RequestAttributesDispatcher requestDispatcher; + private EventGridRequestBodyExtractor eventGridRequestBodyExtractor; /** * Extract Handshake response string form Handshake request. @@ -38,17 +35,16 @@ public class EventGridHandshakeHandler implements IPubsubHandshakeHandler { */ @Override public String getHandshakeResponse() { - String response = null; + String response; try { - JsonObject requestRoot = requestDispatcher.getRequestRoot(); - JsonObject data = (JsonObject) requestRoot.get("data"); - String validationCode = data.get("validationCode").getAsString(); + String validationCode = this.eventGridRequestBodyExtractor.getValidationCodeForHandshake(); JsonObject jsonResponse = new JsonObject(); jsonResponse.addProperty("ValidationResponse", validationCode); + response = jsonResponse.toString(); } catch (Exception exception) { - throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Request payload parsing error", + throw new AppException(HttpStatus.BAD_REQUEST.value(), "Request payload parsing error", "Unable to parse request payload.", exception); } diff --git a/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/pubsub/EventGridRequestBodyExtractor.java b/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/pubsub/EventGridRequestBodyExtractor.java index bd4464efc9e3e79de17833fade4820359f48af10..d81b4ea0ebcd807727e3f452061f7494d997389a 100644 --- a/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/pubsub/EventGridRequestBodyExtractor.java +++ b/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/pubsub/EventGridRequestBodyExtractor.java @@ -14,23 +14,29 @@ package org.opengroup.osdu.notification.provider.azure.pubsub; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.gson.Gson; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; import org.opengroup.osdu.core.common.model.http.AppException; -import org.opengroup.osdu.notification.models.MessageContent; -import org.opengroup.osdu.notification.provider.azure.util.RequestAttributesDispatcher; -import org.opengroup.osdu.notification.pubsub.IPubsubRequestBodyExtractor; +import org.opengroup.osdu.notification.provider.azure.models.HandshakeRequestData; +import org.opengroup.osdu.notification.provider.azure.models.NotificationData; +import org.opengroup.osdu.notification.provider.azure.models.NotificationRequest; +import org.opengroup.osdu.notification.provider.interfaces.IPubsubRequestBodyExtractor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.RequestScope; +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; import java.util.Base64; -import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; // TODO : Make error messages as constants. // TODO : Add TracePoints to exception logs so that monitoring is done well. @@ -39,16 +45,25 @@ import java.util.Map; @RequestScope public class EventGridRequestBodyExtractor implements IPubsubRequestBodyExtractor { private static final String INVALID_EVENTGRID_MESSAGE = "Invalid Event Grid Message"; + private static final String SUBSCRIPTION_ID = "Aeg-Subscription-Name"; private static final String EVENTGRID_VALIDATION_EVENT = "Microsoft.EventGrid.SubscriptionValidationEvent"; private static final Gson GSON = new Gson(); - private MessageContent messageContent; + private static final ObjectMapper objectMapper = new ObjectMapper(); + private JsonObject root = null; + private HttpServletRequest httpServletRequest; + private JaxRsDpsLog log; - @Autowired - private RequestAttributesDispatcher requestDispatcher; + private NotificationRequest notificationRequest; + private NotificationData notificationData; + private HandshakeRequestData handshakeRequestData; + private boolean isHandshakeRequest; - @Autowired - private JaxRsDpsLog log; + public EventGridRequestBodyExtractor(@Autowired HttpServletRequest httpServletRequest, @Autowired JaxRsDpsLog log) { + this.httpServletRequest = httpServletRequest; + this.log = log; + this.notificationRequest = extractNotificationRequestFromHttpRequest(); + } /** * Extracts the attributes from the request that are filled in by publisher of the message. @@ -57,10 +72,10 @@ public class EventGridRequestBodyExtractor implements IPubsubRequestBodyExtracto * @return Request Attributes Map */ public Map<String, String> extractAttributesFromRequestBody() { - if (this.messageContent == null) { - this.messageContent = this.extractPubsubMessageFromRequestBody(); + if(isHandshakeRequest) { + return null; } - return this.messageContent.getAttributes(); + return this.notificationData.getAttributes(); } /** @@ -70,10 +85,10 @@ public class EventGridRequestBodyExtractor implements IPubsubRequestBodyExtracto * @return Request Data String */ public String extractDataFromRequestBody() { - if (this.messageContent == null) { - this.messageContent = this.extractPubsubMessageFromRequestBody(); + if(isHandshakeRequest) { + return null; } - return this.messageContent.getData(); + return new String(Base64.getDecoder().decode(notificationData.getData())); } /** @@ -83,7 +98,11 @@ public class EventGridRequestBodyExtractor implements IPubsubRequestBodyExtracto * @return Request NotificationId String. */ public String extractNotificationIdFromRequestBody() { - return this.requestDispatcher.getRequestSubscriptionId(); + String subscriptionId = httpServletRequest.getHeader(SUBSCRIPTION_ID); + if (Strings.isNullOrEmpty(subscriptionId)) { + throw new AppException(HttpStatus.BAD_REQUEST.value(), "Invalid Event Grid Message", "Subscription ID not found"); + } + return subscriptionId; } /** @@ -93,62 +112,77 @@ public class EventGridRequestBodyExtractor implements IPubsubRequestBodyExtracto * @return Request Type Boolean */ public boolean isHandshakeRequest() { - if (this.root == null) { - this.root = this.requestDispatcher.getRequestRoot(); - } - JsonElement data = this.root.get("eventType"); - if (EVENTGRID_VALIDATION_EVENT.equals(data.getAsString())) { - return true; - } - - return false; + return this.isHandshakeRequest ; } /** - * Utility method that wxtracts the core content in the request. - * This is what the publisher will publish. + * Return ValidationCode * * @throws AppException - * @return Message Content Object + * @return Request Type Boolean */ - private MessageContent extractPubsubMessageFromRequestBody() { - if (this.root == null) { - this.root = this.requestDispatcher.getRequestRoot(); - } - JsonElement message = this.root.get("data"); - if (message == null) { - throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_EVENTGRID_MESSAGE, "message object not found"); - } - - MessageContent content = GSON.fromJson(message.toString(), MessageContent.class); - String eventTime = this.root.getAsJsonObject().get("eventTime").getAsString(); - if (Strings.isNullOrEmpty(eventTime)) { - throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_EVENTGRID_MESSAGE, "Event time not found"); + public String getValidationCodeForHandshake() { + if(!isHandshakeRequest) { + return null; } - content.setPublishTime(eventTime); + return this.handshakeRequestData.getValidationCode(); + } - Map<String, String> attributes = content.getAttributes(); - if (attributes == null || attributes.isEmpty()) { - log.error("Incorrect Message: " + message.toString() ); - throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_EVENTGRID_MESSAGE, "attribute map not found"); - } - String data = content.getData(); - if (Strings.isNullOrEmpty(data)) { - throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_EVENTGRID_MESSAGE, "data field not found"); - } - Map<String, String> lowerCase = new HashMap<>(); - attributes.forEach((key, value) -> lowerCase.put(key.toLowerCase(), value)); - if (Strings.isNullOrEmpty(attributes.get("data-partition-id"))) { - throw new AppException(HttpStatus.BAD_REQUEST.value(), INVALID_EVENTGRID_MESSAGE, - "No tenant information from pubsub message."); + /** + * Utility method that extracts the core content in the request. + * This is what the publisher will publish. + * + * The attributes are validated. + * + * @throws AppException + * @return NotificationRequest Object + */ + private NotificationRequest extractNotificationRequestFromHttpRequest() { + NotificationRequest notificationRequest = null; + if (this.notificationRequest == null) { + try { + BufferedReader reader = httpServletRequest.getReader(); + Stream<String> lines = reader.lines(); + String requestBody = lines.collect(Collectors.joining("\n")); + NotificationRequest[] notificationRequestArray = GSON.fromJson(requestBody, NotificationRequest[].class); + notificationRequest = notificationRequestArray[0]; + + this.isHandshakeRequest = notificationRequest.getEventType().equals(EVENTGRID_VALIDATION_EVENT); + if (isHandshakeRequest) { + extractHandshakeData(notificationRequest); + } else { + extractNotificationData(notificationRequest); + } + } catch (Exception e) { + throw new AppException(HttpStatus.BAD_REQUEST.value(), "Request payload parsing error", + "Unable to parse request payload.", "Request contents are null or empty"); + } } - content.setAttributes(lowerCase); - - String decoded = new String(Base64.getDecoder().decode(data)); - content.setData(decoded); + return notificationRequest; + } - return content; + private void extractHandshakeData(NotificationRequest notificationRequest) { + this.handshakeRequestData = GSON.fromJson(notificationRequest.getData(), HandshakeRequestData.class); + Preconditions.checkNotNull(this.handshakeRequestData.getValidationCode(), "Request payload parsing error" ); } + private void extractNotificationData(NotificationRequest notificationRequest) { + NotificationData notificationData = GSON.fromJson(notificationRequest.getData(), NotificationData.class); + verifyNotificationData(notificationData); + this.notificationData = notificationData; + } -} + // TODO: Clean up for using @NonNull Lombok. + // The Gson deserialisation happens through constructor made out of reflection, + // The unsafe initialisation inspires us to use Jackson + // + // Making Gson use a custom constructor, involves boilerplating, hence adding precondition checks. https://github.com/google/gson/blob/master/UserGuide.md#TOC-Writing-a-Deserializer + // The required condition is not operation as of now.https://github.com/google/gson/issues/61 + private void verifyNotificationData(NotificationData notificationData) { + Preconditions.checkNotNull(notificationData, "Request payload parsing error" ); + Preconditions.checkNotNull(notificationData.getData(), "Request payload parsing error" ); + Preconditions.checkNotNull(notificationData.getMessageId(), "Request payload parsing error" ); + Preconditions.checkNotNull(notificationData.getAttributes().get("correlation-id") , "Request payload parsing error" ); + Preconditions.checkNotNull(notificationData.getAttributes().get("data-partition-id") , "Request payload parsing error" ); + } +} \ No newline at end of file diff --git a/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/util/RequestAttributesDispatcher.java b/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/util/RequestAttributesDispatcher.java deleted file mode 100644 index 68f0e1d93b7705a07c3ae293c10380a4a1a0f677..0000000000000000000000000000000000000000 --- a/provider/notification-azure/src/main/java/org/opengroup/osdu/notification/provider/azure/util/RequestAttributesDispatcher.java +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright © Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package org.opengroup.osdu.notification.provider.azure.util; - -import com.google.common.base.Strings; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import org.opengroup.osdu.core.common.model.http.AppException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Component; -import org.springframework.web.context.annotation.RequestScope; - -import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Component -@RequestScope -public class RequestAttributesDispatcher { - - private JsonObject requestRoot; - - @Autowired - private HttpServletRequest request; - - /** - * Extracts Request's root. - * - * @throws AppException - * @throws IOException - * @return Request Root JsonObject - */ - public JsonObject getRequestRoot(){ - if(requestRoot == null) { - try { - JsonArray requestArray = getRequest(); - JsonElement rootElement = requestArray.get(0); - if (!(rootElement instanceof JsonObject)) { - throw new AppException(HttpStatus.BAD_REQUEST.value(), "RequestBody is not JsonObject.", - "Request Body should be JsonObject to be processed."); - } - this.requestRoot = rootElement.getAsJsonObject(); - - } catch (Exception e) { - throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Request payload parsing error", - "Unable to parse request payload.", e); - } - } - - return requestRoot; - } - - /** - * Extracts Subscription Name from the header. - * - * @throws AppException - * @throws IOException - * @return Sunscription Name String - */ - public String getRequestSubscriptionId(){ - String subscriptionId = request.getHeader("Aeg-Subscription-Name"); - if (Strings.isNullOrEmpty(subscriptionId)) { - throw new AppException(HttpStatus.BAD_REQUEST.value(), "Invalid Event Grid Message", "Subscription ID not found"); - } - return subscriptionId; - } - - /** - * Utility method to read the request's body as stream and - * convert it into JsonArray - * @throws AppException - * @throws IOException - * @return Request JsonArray - */ - private JsonArray getRequest() throws IOException { - JsonParser jsonParser = new JsonParser(); - JsonArray requestArray; - try { - BufferedReader reader = request.getReader(); - Stream<String> lines = reader.lines(); - String requestBody = lines.collect(Collectors.joining("\n")); - requestArray = (JsonArray) jsonParser.parse(requestBody); - } catch (Exception e){ - throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Request payload parsing error", - "Unable to read from the request.", e); - } - return requestArray; - } -} diff --git a/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/pubsub/EventGridHandshakeHandlerTest.java b/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/pubsub/EventGridHandshakeHandlerTest.java index abb2df02cbeee2b641a750e1025a242c4628fa18..3006ae111dc0455f620e1d64f1865a3707dd60ab 100644 --- a/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/pubsub/EventGridHandshakeHandlerTest.java +++ b/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/pubsub/EventGridHandshakeHandlerTest.java @@ -1,3 +1,4 @@ + // Copyright © Microsoft Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,8 +15,6 @@ package org.opengroup.osdu.notification.pubsub; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -25,41 +24,27 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.notification.provider.azure.pubsub.EventGridHandshakeHandler; -import org.opengroup.osdu.notification.provider.azure.util.RequestAttributesDispatcher; +import org.opengroup.osdu.notification.provider.azure.pubsub.EventGridRequestBodyExtractor; import org.springframework.http.HttpStatus; +import java.io.IOException; + import static org.junit.Assert.fail; import static org.mockito.Mockito.when; - @RunWith(MockitoJUnitRunner.class) public class EventGridHandshakeHandlerTest { @Mock - RequestAttributesDispatcher requestAttributesDispatcherMock; + EventGridRequestBodyExtractor eventGridRequestBodyExtractor; @InjectMocks @Spy private EventGridHandshakeHandler sut; @Test - public void should_returnValidResponse_getHandshakeResponse() { + public void should_returnValidResponse_getHandshakeResponse() throws IOException { // Set up - String validHandshakeRequestRoot = - " {\n" + - " \"id\": \"testId\",\n" + - " \"topic\": \"testTopic\",\n" + - " \"subject\": \"\",\n" + - " \"data\": {\n" + - " \"validationCode\": \"testValidationCode\",\n" + - " \"validationUrl\": \"testURL\"\n" + - " },\n" + - " \"eventType\": \"Microsoft.EventGrid.SubscriptionValidationEvent\",\n" + - " \"eventTime\": \"2020-08-14T11:18:55.9278057Z\",\n" + - " \"metadataVersion\": \"1\",\n" + - " \"dataVersion\": \"2\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(validHandshakeRequestRoot).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); + when(sut.getHandshakeResponse()).thenReturn("testValidationCode"); String expectedResponse = "{\"ValidationResponse\":\"testValidationCode\"}"; // Act @@ -70,33 +55,22 @@ public class EventGridHandshakeHandlerTest { } @Test - public void should_throwWhenDataIsMissing_getHandshakeResponse() { + public void should_throw_getHandshakeResponse() throws IOException { // Set up - String validHandshakeRequestRoot = - " {\n" + - " \"id\": \"testId\",\n" + - " \"topic\": \"testTopic\",\n" + - " \"subject\": \"\",\n" + - " \"eventType\": \"Microsoft.EventGrid.SubscriptionValidationEvent\",\n" + - " \"eventTime\": \"2020-08-14T11:18:55.9278057Z\",\n" + - " \"metadataVersion\": \"1\",\n" + - " \"dataVersion\": \"2\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(validHandshakeRequestRoot).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); - - try { + when(sut.getHandshakeResponse()) + .thenThrow(new AppException(HttpStatus.BAD_REQUEST.value(), "Request payload parsing error", "" )); + try{ // Act - this.sut.getHandshakeResponse(); + String observedResponse = this.sut.getHandshakeResponse(); - // Asset + // Assert fail("Should Throw Exception"); - } catch ( - AppException appException){ - Assert.assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), appException.getError().getCode()); - Assert.assertEquals("Unable to parse request payload." , appException.getError().getMessage()); + } catch (AppException appException){ + Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), appException.getError().getCode()); + Assert.assertEquals("Unable to parse request payload.", appException.getError().getMessage()); } catch (Exception exception) { fail("Should Throw AppException"); } } } + diff --git a/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/pubsub/EventGridRequestBodyExtractorTest.java b/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/pubsub/EventGridRequestBodyExtractorTest.java index c84e57c3b2201e3d67c20019fd11c3458431dbbf..ad875413152efab0d5431ee334aa940bc926f36b 100644 --- a/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/pubsub/EventGridRequestBodyExtractorTest.java +++ b/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/pubsub/EventGridRequestBodyExtractorTest.java @@ -14,20 +14,20 @@ package org.opengroup.osdu.notification.pubsub; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; +import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.notification.provider.azure.pubsub.EventGridRequestBodyExtractor; -import org.opengroup.osdu.notification.provider.azure.util.RequestAttributesDispatcher; import org.springframework.http.HttpStatus; +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; import java.util.Map; import static org.junit.Assert.fail; @@ -35,20 +35,20 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class EventGridRequestBodyExtractorTest { - private static final String INVALID_EVENTGRID_MESSAGE = "Invalid Event Grid Message"; + + private EventGridRequestBodyExtractor sut; @Mock - RequestAttributesDispatcher requestAttributesDispatcherMock; + private HttpServletRequest httpServletRequest; - @InjectMocks - @Spy - private EventGridRequestBodyExtractor sut; + @Mock + private JaxRsDpsLog log; @Test - public void should_returntrue_isHandshakeRequest() { + public void should_returnTrue_isHandshakeRequest() throws IOException { // Set up String validHandshakeRequestRoot = - " {\n" + + " [{\n" + " \"id\": \"testId\",\n" + " \"topic\": \"testTopic\",\n" + " \"subject\": \"\",\n" + @@ -60,9 +60,10 @@ public class EventGridRequestBodyExtractorTest { " \"eventTime\": \"2020-08-14T11:18:55.9278057Z\",\n" + " \"metadataVersion\": \"1\",\n" + " \"dataVersion\": \"2\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(validHandshakeRequestRoot).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); + " }]"; + BufferedReader reader = new BufferedReader(new StringReader(validHandshakeRequestRoot)); + when(this.httpServletRequest.getReader()).thenReturn(reader); + sut = new EventGridRequestBodyExtractor(httpServletRequest, log); // Act boolean response = this.sut.isHandshakeRequest(); @@ -72,63 +73,42 @@ public class EventGridRequestBodyExtractorTest { } @Test - public void should_returnfalse_isHandshakeRequest() { + public void shouldThrow_whenRequestTypeIsNotright_isHandshakeRequest() throws IOException { //SetUp String invalidHandshakeRequestRoot = - " {\n" + + " [{\n" + " \"id\": \"testId\",\n" + " \"topic\": \"testTopic\",\n" + " \"subject\": \"\",\n" + " \"data\": {\n" + + " \"validationCode\": \"testValidationCode\",\n" + " \"validationUrl\": \"testURL\"\n" + " },\n" + " \"eventType\": \"SubscriptionValidationEvent\",\n" + " \"eventTime\": \"2020-08-14T11:18:55.9278057Z\",\n" + " \"metadataVersion\": \"1\",\n" + " \"dataVersion\": \"2\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(invalidHandshakeRequestRoot).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); - - // Act - boolean response = this.sut.isHandshakeRequest(); - - // Assert - Assert.assertFalse(response); - } - - @Test - public void should_throwWhenMessageIsMissing_extractDataFromRequestBody() { - // SetUp - String requestRootWithoutData = "{\n" + - " \"id\": \"2425\",\n" + - " \"eventType\": \"recordInserted\",\n" + - " \"subject\": \"myapp/vehicles/motorcycles\",\n" + - " \"dataVersion\": \"1.0\",\n" + - " \"metadataVersion\": \"1\",\n" + - " \"eventTime\": \"2020-08-14T18:04:12+00:00\",\n" + - " \"topic\": \"testTopic\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(requestRootWithoutData).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); + " }]"; + BufferedReader reader = new BufferedReader(new StringReader(invalidHandshakeRequestRoot)); + when(this.httpServletRequest.getReader()).thenReturn(reader); try{ // Act - this.sut.extractDataFromRequestBody(); + sut = new EventGridRequestBodyExtractor(httpServletRequest, log); - // Asset + // Assert fail("Should Throw Exception"); } catch (AppException appException){ Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), appException.getError().getCode()); - Assert.assertEquals("message object not found", appException.getError().getMessage()); + Assert.assertEquals("Unable to parse request payload.", appException.getError().getMessage()); } catch (Exception exception) { fail("Should Throw AppException"); } } @Test - public void should_throwWhenAttributesAreMissing_extractDataFromRequestBody() { - String requestRootWithoutAttributes = "{\n" + + public void should_throwWhenAttributesAreMissing_extractDataFromRequestBody() throws IOException { + String requestRootWithoutAttributes = "[{\n" + " \"id\": \"2425\",\n" + " \"eventType\": \"recordInserted\",\n" + " \"subject\": \"myapp/vehicles/motorcycles\",\n" + @@ -140,27 +120,27 @@ public class EventGridRequestBodyExtractorTest { " \"metadataVersion\": \"1\",\n" + " \"eventTime\": \"2020-08-14T18:04:12+00:00\",\n" + " \"topic\": \"/subscriptions/c99e2bf3-1777-412b-baba-d823676589c2/resourceGroups/komakkar-OSDU-RG/providers/Microsoft.EventGrid/topics/recordChanged\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(requestRootWithoutAttributes).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); + " }]"; + BufferedReader reader = new BufferedReader(new StringReader(requestRootWithoutAttributes)); + when(this.httpServletRequest.getReader()).thenReturn(reader); try{ // Act - this.sut.extractDataFromRequestBody(); + sut = new EventGridRequestBodyExtractor(httpServletRequest, log); // Asset fail("Should Throw Exception"); } catch (AppException appException){ Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), appException.getError().getCode()); - Assert.assertEquals("attribute map not found", appException.getError().getMessage()); + Assert.assertEquals("Unable to parse request payload.", appException.getError().getMessage()); } catch (Exception exception) { - //fail("Should Throw AppException"); + fail("Should Throw AppException"); } } @Test - public void should_throwWhenDataFiledIsMissing_extractDataFromRequestBody() { - String requestRootWithoutData = "{\n" + + public void should_throwWhenDataFiledIsMissing_extractDataFromRequestBody() throws IOException { + String requestRootWithoutData = "[{\n" + " \"id\": \"2425\",\n" + " \"eventType\": \"recordInserted\",\n" + " \"subject\": \"myapp/vehicles/motorcycles\",\n" + @@ -169,34 +149,33 @@ public class EventGridRequestBodyExtractorTest { " \"correlation-id\": \"39137f49-67d6-4001-a6aa-15521ef4f49e\",\n" + " \"data-partition-id\": \"opendes \"\n" + " },\n" + - " \"messageId\": \"136969346945\"\n" + " },\n" + " \"dataVersion\": \"1.0\",\n" + " \"metadataVersion\": \"1\",\n" + " \"eventTime\": \"2020-08-14T18:04:12+00:00\",\n" + " \"topic\": \"/subscriptions/c99e2bf3-1777-412b-baba-d823676589c2/resourceGroups/komakkar-OSDU-RG/providers/Microsoft.EventGrid/topics/recordChanged\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(requestRootWithoutData).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); + " }]"; + BufferedReader reader = new BufferedReader(new StringReader(requestRootWithoutData)); + when(this.httpServletRequest.getReader()).thenReturn(reader); try{ // Act - this.sut.extractDataFromRequestBody(); + sut = new EventGridRequestBodyExtractor(httpServletRequest, log); // Asset fail("Should Throw Exception"); } catch (AppException appException){ Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), appException.getError().getCode()); - Assert.assertEquals("data field not found", appException.getError().getMessage()); + Assert.assertEquals("Unable to parse request payload.", appException.getError().getMessage()); } catch (Exception exception) { fail("Should Throw AppException"); } } @Test - public void should_throwWhenPartitionIdIsMissing_extractDataFromRequestBody() { - String requestRootWithoutDataPartitionId = "{\n" + + public void should_throwWhenPartitionIdIsMissing_extractDataFromRequestBody() throws IOException { + String requestRootWithoutDataPartitionId = "[{\n" + " \"id\": \"2425\",\n" + " \"eventType\": \"recordInserted\",\n" + " \"subject\": \"myapp/vehicles/motorcycles\",\n" + @@ -211,27 +190,27 @@ public class EventGridRequestBodyExtractorTest { " \"metadataVersion\": \"1\",\n" + " \"eventTime\": \"2020-08-14T18:04:12+00:00\",\n" + " \"topic\": \"/subscriptions/c99e2bf3-1777-412b-baba-d823676589c2/resourceGroups/komakkar-OSDU-RG/providers/Microsoft.EventGrid/topics/recordChanged\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(requestRootWithoutDataPartitionId).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); + " }]"; + BufferedReader reader = new BufferedReader(new StringReader(requestRootWithoutDataPartitionId)); + when(this.httpServletRequest.getReader()).thenReturn(reader); try{ // Act - this.sut.extractDataFromRequestBody(); + sut = new EventGridRequestBodyExtractor(httpServletRequest, log); // Asset fail("Should Throw Exception"); } catch (AppException appException){ Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), appException.getError().getCode()); - //Assert.assertEquals("No tenant information from pubsub message.", appException.getError().getMessage()); + Assert.assertEquals("Unable to parse request payload.", appException.getError().getMessage()); } catch (Exception exception) { fail("Should Throw AppException"); } } @Test - public void should_returnValidData_extractDataFromRequestBody() { - String vaidRequestRoot = "{\n" + + public void should_returnValidData_extractDataFromRequestBody() throws IOException { + String vaidRequestRoot = "[{\n" + " \"id\": \"2425\",\n" + " \"eventType\": \"recordInserted\",\n" + " \"subject\": \"myapp/vehicles/motorcycles\",\n" + @@ -247,23 +226,25 @@ public class EventGridRequestBodyExtractorTest { " \"metadataVersion\": \"1\",\n" + " \"eventTime\": \"2020-08-14T18:04:12+00:00\",\n" + " \"topic\": \"/subscriptions/c99e2bf3-1777-412b-baba-d823676589c2/resourceGroups/komakkar-OSDU-RG/providers/Microsoft.EventGrid/topics/recordChanged\"\n" + - " }"; + " }]"; String expectedData = "[{\"kind\":\"testkind\",\"id\":\"testid\",\"operationtype\":\"create\"},{\"kind\":\"testkind2\",\"id\":\"testid2\",\"operationtype\":\"update\"}]"; - JsonObject requestRoot = new JsonParser().parse(vaidRequestRoot).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); + BufferedReader reader = new BufferedReader(new StringReader(vaidRequestRoot)); + when(this.httpServletRequest.getReader()).thenReturn(reader); + + sut = new EventGridRequestBodyExtractor(httpServletRequest, log); // Act - String recievedData = this.sut.extractDataFromRequestBody(); + String receivedData = this.sut.extractDataFromRequestBody(); // Asset - Assert.assertEquals(expectedData,recievedData); + Assert.assertEquals(expectedData,receivedData); } @Test - public void should_returnValidAttributes_extractDataFromRequestBody() { - String vaidRequestRoot = "{\n" + + public void should_returnValidAttributes_extractDataFromRequestBody() throws IOException { + String vaidRequestRoot = "[{\n" + " \"id\": \"2425\",\n" + " \"eventType\": \"recordInserted\",\n" + " \"subject\": \"myapp/vehicles/motorcycles\",\n" + @@ -279,9 +260,10 @@ public class EventGridRequestBodyExtractorTest { " \"metadataVersion\": \"1\",\n" + " \"eventTime\": \"2020-08-14T18:04:12+00:00\",\n" + " \"topic\": \"/subscriptions/c99e2bf3-1777-412b-baba-d823676589c2/resourceGroups/komakkar-OSDU-RG/providers/Microsoft.EventGrid/topics/recordChanged\"\n" + - " }"; - JsonObject requestRoot = new JsonParser().parse(vaidRequestRoot).getAsJsonObject(); - when(this.requestAttributesDispatcherMock.getRequestRoot()).thenReturn(requestRoot); + " }]"; + BufferedReader reader = new BufferedReader(new StringReader(vaidRequestRoot)); + when(this.httpServletRequest.getReader()).thenReturn(reader); + sut = new EventGridRequestBodyExtractor(httpServletRequest, log); // Act Map<String, String> observedAttributes = this.sut.extractAttributesFromRequestBody(); @@ -291,4 +273,32 @@ public class EventGridRequestBodyExtractorTest { Assert.assertEquals(observedAttributes.get("data-partition-id"),"opendes"); } + @Test + public void should_returnValidResponse_getHandshakeResponse() throws IOException { + // Set up + String validHandshakeRequestRoot = + " [{\n" + + " \"id\": \"testId\",\n" + + " \"topic\": \"testTopic\",\n" + + " \"subject\": \"\",\n" + + " \"data\": {\n" + + " \"validationCode\": \"testValidationCode\",\n" + + " \"validationUrl\": \"testURL\"\n" + + " },\n" + + " \"eventType\": \"Microsoft.EventGrid.SubscriptionValidationEvent\",\n" + + " \"eventTime\": \"2020-08-14T11:18:55.9278057Z\",\n" + + " \"metadataVersion\": \"1\",\n" + + " \"dataVersion\": \"2\"\n" + + " }]"; + String expectedResponse = "testValidationCode"; + BufferedReader reader = new BufferedReader(new StringReader(validHandshakeRequestRoot)); + when(this.httpServletRequest.getReader()).thenReturn(reader); + sut = new EventGridRequestBodyExtractor(httpServletRequest, log); + + // Act + String observedResponse = this.sut.getValidationCodeForHandshake(); + + // Assert + Assert.assertEquals(observedResponse, expectedResponse); + } } diff --git a/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/util/RequestAttributesDispatcherTest.java b/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/util/RequestAttributesDispatcherTest.java deleted file mode 100644 index 1e9d8c4851de15397985da24a0c0340ed8f3f459..0000000000000000000000000000000000000000 --- a/provider/notification-azure/src/test/java/org/opengroup/osdu/notification/util/RequestAttributesDispatcherTest.java +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright © Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package org.opengroup.osdu.notification.util; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.MockitoJUnitRunner; -import org.opengroup.osdu.core.common.model.http.AppException; -import org.opengroup.osdu.notification.provider.azure.util.RequestAttributesDispatcher; -import org.springframework.http.HttpStatus; - -import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -@RunWith(MockitoJUnitRunner.class) -public class RequestAttributesDispatcherTest { - - @Mock - private HttpServletRequest requestMock; - - @InjectMocks - @Spy - private RequestAttributesDispatcher sut; - - @Before - public void setup() { - initMocks(this); - } - - @Test - public void should_throwWhenSubscriptionIdMissing_getRequestSubscriptionId() { - when(this.requestMock.getHeader("Aeg-Subscription-Name")).thenReturn(null); - - try{ - this.sut.getRequestSubscriptionId(); - fail("Should Throw Exception"); - } catch (AppException appException){ - Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), appException.getError().getCode()); - Assert.assertEquals("Subscription ID not found", appException.getError().getMessage()); - } catch (Exception exception) { - fail("Should Throw AppException"); - } - } - - @Test - public void should_throwWhenRequestRoot_getRequestRoot() throws IOException { - String invalidRequest = "{\n" + - " \"id\": \"e094dffa-9c15-4491-8312-98c73b699908\",\n" + - " \"topic\": \"/subscriptions/c99e2bf3-1777-412b-baba-d823676589c2/resourceGroups/komakkar-OSDU-RG/providers/Microsoft.EventGrid/topics/recordChanged\",\n" + - " \"subject\": \"\",\n" + - " \"data\": {\n" + - " \"validationCode\": \"6ECAD1AE-3451-4618-9D5D-EC3DD968885D\",\n" + - " \"validationUrl\": \"https://rp-westus2.eventgrid.azure.net:553/eventsubscriptions/eventgridtest/validate?id=6ECAD1AE-3451-4618-9D5D-EC3DD968885D&t=2020-08-14T11:31:24.7804184Z&apiVersion=2020-04-01-preview&token=YX71OvPJuWTTOVnhqaThLXU8gWqx6FkTkJSwoyK9%2fBE%3d\"\n" + - " },\n" + - " \"eventType\": \"Microsoft.EventGrid.SubscriptionValidationEvent\",\n" + - " \"eventTime\": \"2020-08-14T11:31:24.7804184Z\",\n" + - " \"metadataVersion\": \"1\",\n" + - " \"dataVersion\": \"2\"\n" + - "}"; - when(this.requestMock.getReader()).thenReturn( - new BufferedReader(new StringReader(invalidRequest))); - try { - this.sut.getRequestRoot(); - - // Assert - fail("Should Throw Exception"); - } catch (AppException appException) { - Assert.assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), appException.getError().getCode()); - Assert.assertEquals("Unable to parse request payload.", appException.getError().getMessage()); - } catch (Exception exception) { - fail("Should Throw AppException"); - } - } - - @Test - public void should_throwWhenArrayNotFound_getRequestRoot() throws IOException { - String invalidRequest = "[]"; - when(this.requestMock.getReader()).thenReturn( - new BufferedReader(new StringReader(invalidRequest))); - try { - this.sut.getRequestRoot(); - - // Assert - fail("Should Throw Exception"); - } catch (AppException appException) { - Assert.assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), appException.getError().getCode()); - Assert.assertEquals("Unable to parse request payload.", appException.getError().getMessage()); - } catch (Exception exception) { - fail("Should Throw AppException"); - } - } - -} - diff --git a/provider/notification-gcp/src/main/java/org/opengroup/osdu/notification/provider/gcp/pubsub/PubsubRequestBodyExtractor.java b/provider/notification-gcp/src/main/java/org/opengroup/osdu/notification/provider/gcp/pubsub/PubsubRequestBodyExtractor.java index 8e3e86a3887e4ae599079b66b9027ebcff7288ec..485edb527e5bd9c2c924e85cb50634b9c45fb0f8 100644 --- a/provider/notification-gcp/src/main/java/org/opengroup/osdu/notification/provider/gcp/pubsub/PubsubRequestBodyExtractor.java +++ b/provider/notification-gcp/src/main/java/org/opengroup/osdu/notification/provider/gcp/pubsub/PubsubRequestBodyExtractor.java @@ -18,7 +18,7 @@ package org.opengroup.osdu.notification.provider.gcp.pubsub; import com.google.common.base.Strings; import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; -import org.opengroup.osdu.notification.models.MessageContent; +import org.opengroup.osdu.core.common.model.storage.MessageContent; import org.opengroup.osdu.core.common.model.http.AppException; import com.google.gson.Gson;