Skip to content

Commit

Permalink
[Accelerator 4] Adding event notification endpoint implementation (#169)
Browse files Browse the repository at this point in the history
Add event notification endpoint implementation
  • Loading branch information
Ashi1993 authored Dec 12, 2024
1 parent 94bd467 commit 2980a40
Show file tree
Hide file tree
Showing 15 changed files with 1,258 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ context = "(.*)/fs/authenticationendpoint/(.*)"
http_method = "all"
secure = "false"

[[resource.access_control]]
allowed_auth_handlers = ["BasicAuthentication"]
context = "(.*)/api/fs/event-notifications/(.*)"
http_method = "all"
permissions = ["/permission/admin"]
secure = "true"

[[resource.access_control]]
context="(.*)/scim2/Me"
secure=true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
~ Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
~
~ WSO2 LLC. licenses this file to you 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.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>financial-services-accelerator</artifactId>
<groupId>org.wso2.financial.services.accelerator</groupId>
<version>4.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

<artifactId>org.wso2.financial.services.accelerator.event.notifications.endpoint</artifactId>
<packaging>war</packaging>
<name>WSO2 Financial Services - Event Notification Endpoint</name>

<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.inbound.auth.oauth2</groupId>
<artifactId>org.wso2.carbon.identity.oauth</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.financial.services.accelerator</groupId>
<artifactId>org.wso2.financial.services.accelerator.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.financial.services.accelerator</groupId>
<artifactId>org.wso2.financial.services.accelerator.consent.mgt.service</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.financial.services.accelerator</groupId>
<artifactId>org.wso2.financial.services.accelerator.consent.mgt.dao</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.wso2.financial.services.accelerator</groupId>
<artifactId>org.wso2.financial.services.accelerator.event.notifications.service</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>src/main/webapp</directory>
</resource>
</webResources>
<warName>api#fs#event-notifications</warName>
<packagingExcludes>WEB-INF/lib/slf4j-api-*.jar</packagingExcludes>
</configuration>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
<xmlOutput>true</xmlOutput>
<failOnError>true</failOnError>
<spotbugsXmlOutputDirectory>${project.build.directory}/spotbugs</spotbugsXmlOutputDirectory>
<excludeFilterFile>${project.basedir}/src/main/resources/findbugs-exclude.xml</excludeFilterFile>
<includeFilterFile>${project.basedir}/src/main/resources/findbugs-include.xml</includeFilterFile>
<plugins>
<plugin>
<groupId>com.h3xstream.findsecbugs</groupId>
<artifactId>findsecbugs-plugin</artifactId>
<version>${com.h3xstream.findsecbugs.version}</version>
</plugin>
</plugins>
</configuration>
<executions>
<execution>
<id>analyze-compile</id>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/**
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
* <p>
* WSO2 LLC. licenses this file to you 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.wso2.financial.services.accelerator.event.notifications.endpoint.api;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.financial.services.accelerator.event.notifications.endpoint.constants.EventNotificationEndPointConstants;
import org.wso2.financial.services.accelerator.event.notifications.endpoint.util.EventNotificationUtils;
import org.wso2.financial.services.accelerator.event.notifications.service.constants.EventNotificationConstants;
import org.wso2.financial.services.accelerator.event.notifications.service.dto.NotificationCreationDTO;
import org.wso2.financial.services.accelerator.event.notifications.service.exception.FSEventNotificationException;
import org.wso2.financial.services.accelerator.event.notifications.service.handler.EventCreationServiceHandler;
import org.wso2.financial.services.accelerator.event.notifications.service.model.EventCreationResponse;
import org.wso2.financial.services.accelerator.event.notifications.service.util.EventNotificationServiceUtil;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

/**
* Events creation API.
*/
@Path("/")
public class EventCreationEndpoint {

private static final Log log = LogFactory.getLog(EventCreationEndpoint.class);
private final EventCreationServiceHandler eventCreationServiceHandler;
private static final String specialChars = "!@#$%&*()'+,./:;<=>?[]^_`{|}";
private static final String illegalChars = "\\\\r|\\\\n|\\r|\\n|\\[|]| ";

public EventCreationEndpoint() {

eventCreationServiceHandler = EventNotificationUtils.getEventNotificationCreationServiceHandler();
}

public EventCreationEndpoint(EventCreationServiceHandler handler) {

eventCreationServiceHandler = handler;
}

/**
* This API will be used to create events.
*/
@SuppressFBWarnings({"JAXRS_ENDPOINT", "SERVLET_HEADER"})
// Suppressed content - Endpoint
// Suppression reason - False Positive : This endpoint is secured with access control lists in the configuration
// Suppressed content - request.getHeader()
// Suppression reason - False Positive : Header is properly validated to ensure no special characters are passed
// Suppressed warning count - 4
@POST
@Path("/create-events")
@Consumes({"application/x-www-form-urlencoded"})
@Produces({"application/json; charset=utf-8"})
public Response createEvents(@Context HttpServletRequest request, @Context HttpServletResponse response,
MultivaluedMap parameterMap) {


NotificationCreationDTO notificationCreationDTO = new NotificationCreationDTO();
String requestData = StringUtils.EMPTY;
JSONObject notificationEvents;

try {
//Check if the request pay load is empty
if (!parameterMap.isEmpty() && parameterMap.containsKey(EventNotificationEndPointConstants.REQUEST)) {

requestData = parameterMap.get(EventNotificationEndPointConstants.REQUEST).
toString().replaceAll(illegalChars, StringUtils.EMPTY);

byte[] decodedBytes = Base64.getDecoder().decode(requestData);
String decodedString = new String(decodedBytes, StandardCharsets.UTF_8);
notificationEvents = new JSONObject(decodedString);
log.debug("Decoded payload string : " + decodedString.replaceAll("[\r\n]", ""));

} else {
log.error(EventNotificationEndPointConstants.MISSING_REQUEST_PAYLOAD);
return Response.status(Response.Status.BAD_REQUEST).entity(EventNotificationServiceUtil
.getErrorDTO(EventNotificationEndPointConstants.MISSING_REQUEST_PAYLOAD,
EventNotificationConstants.MISSING_REQ_PAYLOAD)).build();
}

//check if the client id is present in the header
String clientId = request.getHeader(EventNotificationEndPointConstants.X_WSO2_CLIENT_ID);
if (!StringUtils.isBlank(clientId)) {
notificationCreationDTO.setClientId(request.getHeader(
EventNotificationEndPointConstants.X_WSO2_CLIENT_ID));
} else {
return Response.status(Response.Status.BAD_REQUEST).entity(EventNotificationServiceUtil
.getErrorDTO(EventNotificationEndPointConstants.MISSING_REQUEST_HEADER,
EventNotificationConstants.MISSING_HEADER_PARAM_CLIENT_ID)).build();
}

//check if the resource id is present in the header
String resourceId = request.getHeader(EventNotificationEndPointConstants.X_WSO2_RESOURCE_ID);
if (!StringUtils.isBlank(resourceId)) {
if (StringUtils.containsAny(resourceId, specialChars)) {
return Response.status(Response.Status.BAD_REQUEST).entity(EventNotificationServiceUtil.
getErrorDTO(EventNotificationEndPointConstants.INVALID_REQUEST_HEADER,
EventNotificationConstants.INVALID_CHARS_IN_HEADER_ERROR)).build();
}
notificationCreationDTO.setResourceId(request.getHeader(
EventNotificationEndPointConstants.X_WSO2_RESOURCE_ID));;
} else {
return Response.status(Response.Status.BAD_REQUEST).entity(EventNotificationServiceUtil.
getErrorDTO(EventNotificationEndPointConstants.MISSING_REQUEST_HEADER,
EventNotificationConstants.MISSING_HEADER_PARAM_RESOURCE_ID)).build();
}

//set events to notificationCreationDTO
notificationEvents.keySet().forEach(eventName -> {
JSONObject eventInformation = notificationEvents.getJSONObject(eventName);
notificationCreationDTO.setEventPayload(eventName, eventInformation);
});


EventCreationResponse eventCreationResponse = eventCreationServiceHandler.
publishEvent(notificationCreationDTO);

return EventNotificationUtils.mapEventCreationServiceResponse(eventCreationResponse);

} catch (ClassCastException e) {
log.error(EventNotificationEndPointConstants.REQUEST_PAYLOAD_ERROR, e);
return Response.status(Response.Status.BAD_REQUEST).entity(EventNotificationServiceUtil
.getErrorDTO(EventNotificationEndPointConstants.INVALID_REQUEST_PAYLOAD,
EventNotificationEndPointConstants.REQUEST_PAYLOAD_ERROR)).build();
} catch (FSEventNotificationException e) {
log.error(EventNotificationEndPointConstants.EVENT_CREATION_ERROR_RESPONSE, e);
return Response.status(e.getStatus()).entity(EventNotificationServiceUtil
.getErrorDTO(EventNotificationEndPointConstants.INVALID_REQUEST,
e.getMessage())).build();
}

}

}
Loading

0 comments on commit 2980a40

Please sign in to comment.