Commit 7b139871 authored by Komal Makkar's avatar Komal Makkar
Browse files

merged mastercd ..

parents 20950a67 72a6dc6b
// 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.models;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class HandshakeRequestData {
private String validationCode;
private String validationUrl;
}
// 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.models;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
@Data
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NotificationData {
private String data;
private Map<String,String> attributes;
private String messageId;
}
// 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.models;
import com.google.gson.JsonObject;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NotificationRequest {
private String id;
private String eventType;
private String subject;
private JsonObject data;
private String eventTime;
}
// 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.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.JsonObject;
import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
import org.opengroup.osdu.core.common.model.http.AppException;
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.util.Base64;
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.
@Component
@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 static final ObjectMapper objectMapper = new ObjectMapper();
private JsonObject root = null;
private HttpServletRequest httpServletRequest;
private JaxRsDpsLog log;
private NotificationRequest notificationRequest;
private NotificationData notificationData;
private HandshakeRequestData handshakeRequestData;
private boolean isHandshakeRequest;
@Autowired
public EventGridRequestBodyExtractor(HttpServletRequest httpServletRequest, 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.
*
* @throws AppException
* @return Request Attributes Map
*/
public Map<String, String> extractAttributesFromRequestBody() {
if(isHandshakeRequest) {
return null;
}
return this.notificationData.getAttributes();
}
/**
* Extracts the data from the request that are filled in by publisher of the message,
*
* @throws AppException
* @return Request Data String
*/
public String extractDataFromRequestBody() {
if(isHandshakeRequest) {
return null;
}
return new String(Base64.getDecoder().decode(notificationData.getData()));
}
/**
* Extracts the notificationId from the request that are filled in by EventGrid.
*
* @throws AppException
* @return Request NotificationId String.
*/
public String extractNotificationIdFromRequestBody() {
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;
}
/**
* Checks if the request is for handshake.
*
* @throws AppException
* @return Request Type Boolean
*/
public boolean isHandshakeRequest() {
return this.isHandshakeRequest ;
}
/**
* Return ValidationCode
*
* @throws AppException
* @return Request Type Boolean
*/
public String getValidationCodeForHandshake() {
if(!isHandshakeRequest) {
return null;
}
return this.handshakeRequestData.getValidationCode();
}
/**
* 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");
}
}
return notificationRequest;
}
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
......@@ -15,10 +15,8 @@
package org.opengroup.osdu.notification.provider.azure.util;
import com.azure.cosmos.CosmosClient;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
import org.opengroup.osdu.azure.KeyVaultFacade;
import org.opengroup.osdu.notification.provider.interfaces.IAppProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment