Skip to content

Commit

Permalink
adds simple REST notification endpoint, fixes #202
Browse files Browse the repository at this point in the history
* to activate the endpoint, credentials for basic authentication have to be defined in PLATO's configuration.properties:
  notification.rest.user, notification.rest.pass
* notifications can be posted if there is a planner with the given email address -
  they are displayed when the planner logs into PLATO as info messages.

Further improvements:
* use of url rewriting solution like http://ocpsoft.com/prettyfaces/
  this would allow to provide links to directly open plans (in the notification, as well as in emails) or revise existing plans.
  • Loading branch information
kraxner committed Sep 3, 2014
1 parent 2092972 commit db309a8
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 31 deletions.
7 changes: 7 additions & 0 deletions plato/pom.xml
Expand Up @@ -171,6 +171,13 @@
<version>2.10.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.3.2.Final</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>jaxen</groupId>
Expand Down
@@ -0,0 +1,61 @@
package eu.scape_project.planning.services;

import java.util.List;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.StringUtils;
import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ResourceMethod;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.UnauthorizedException;
import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.scape_project.planning.utils.ConfigurationLoader;

@Provider
@ServerInterceptor
public class RestSecurityInterceptor implements PreProcessInterceptor {

private static final Logger LOGGER = LoggerFactory.getLogger(RestSecurityInterceptor.class);
@Override
public ServerResponse preProcess(HttpRequest request, ResourceMethod resourceMethod) throws Failure, WebApplicationException {
// Then get the HTTP-Authorization header and base64 decode it
List<String> authHeader = request.getHttpHeaders().getRequestHeader("Authorization");
if (authHeader != null) {


for (String auth : authHeader) {
if (auth.startsWith("Basic ")) {
byte encoded[] = Base64.decodeBase64(auth.substring(6));
String encodedStr = new String(encoded);
String userPwd[] = encodedStr.split(":");
if ((userPwd != null) &&
(userPwd.length == 2) &&
StringUtils.isNotEmpty(userPwd[0]) &&
StringUtils.isNotEmpty(userPwd[1])) {
ConfigurationLoader configurationLoader = new ConfigurationLoader();
Configuration config = configurationLoader.load();
String path = request.getPreprocessedPath().replaceAll("/", ".").substring(1);

String user = config.getString(path + ".rest.user", "");
String passwd = config.getString(path + ".rest.pass", "");

if (user.equals(userPwd[0]) && passwd.equals(userPwd[1])) {
return null;
}
}
}
}
}
throw new UnauthorizedException("Username/Password does not match");
}

}
4 changes: 2 additions & 2 deletions plato/src/main/webapp/WEB-INF/templates/default.xhtml
Expand Up @@ -132,9 +132,9 @@
<h:form id="notificationForm">
<a4j:outputPanel id="notifications" layout="block">
<ui:repeat var="note" value="#{notifications.notifications}">
<div class="alert-box #{note.source == 'Scout'?'scout':'info'}">
<div class="alert-box #{note.source == 'SCOUT'?'scout':'info'}">
<h:outputText value="#{note.message}" escape="false" />
[#{note.source}<h:outputText value="#{note.timestamp}"><f:convertDateTime pattern="dd.MM.yyyy HH:mm" /></h:outputText>]
[#{note.source} <h:outputText value="#{note.timestamp}"><f:convertDateTime pattern=" dd.MM.yyyy HH:mm" /></h:outputText>]

<a4j:commandLink styleClass="close" action="#{notifications.acceptNotification(note)}" render="notifications" value="x"/>
</div>
Expand Down
Expand Up @@ -2,55 +2,54 @@

import java.io.StringWriter;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import javax.ws.rs.core.MediaType;

import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.codehaus.jackson.map.ObjectMapper;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;

import eu.scape_project.planning.annotation.IntegrationTest;

@Category(IntegrationTest.class)
public class NotificationResourceIT {

/**
* adds a test notification.
* - to user scape.pw@gmail.com
* adds a test notification.
* - the server must be running on localhost:8080
*
* - credentials for notification.rest : scout/pass
* - notification is added for user: scape.pw@gmail.com
*
* @throws Exception
*/
@Test
public void addNotificationTest() throws Exception{
DefaultHttpClient httpClient = new DefaultHttpClient();

public void addNotificationTest() throws Exception {
ClientConfig cc = new DefaultClientConfig();
Client client = Client.create(cc);
client.addFilter(new HTTPBasicAuthFilter("scout", "pass"));
WebResource endpoint = client.resource("http://localhost:8080/plato/rest/");

// prepare the json load
WatchNotification n = new WatchNotification(null, "test message", null, null, "scape.pw@gmail.com");

StringWriter writer = new StringWriter();

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(writer, n);

HttpPut putRequest = new HttpPut("http://localhost:8080/plato/rest/notification");
putRequest.addHeader("content-type", "application/json");

putRequest.setEntity(new StringEntity(writer.getBuffer().toString()));

try {
HttpResponse response = httpClient.execute(putRequest);

int statusCode = response.getStatusLine().getStatusCode();

Assert.assertEquals(200, statusCode);

} finally {
httpClient.getConnectionManager().shutdown();
}

}

WebResource fileResource = endpoint.path("notification");
ClientResponse response = fileResource.type(MediaType.APPLICATION_JSON).put(ClientResponse.class,
writer.toString());

Assert.assertEquals(200, response.getStatus());
}
}

0 comments on commit db309a8

Please sign in to comment.