Commit 098a8a4c authored by redmitry@list.ru's avatar redmitry@list.ru

initial commit

parents
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>es.bsc.inb.elixir</groupId>
<artifactId>openebench-rest-api</artifactId>
<version>0.1.0</version>
<packaging>war</packaging>
<name>OpenEBench Data Access API</name>
<organization>
<name>Barcelona Supercomputing Center</name>
<url>https://www.bsc.es/</url>
</organization>
<developers>
<developer>
<id>redmitry</id>
<name>Dmitry Repchevsky</name>
<email>redmitry@list.ru</email>
</developer>
</developers>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.enterprise.concurrent</groupId>
<artifactId>javax.enterprise.concurrent-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-filter-adapter</artifactId>
<version>10.0.1</version>
</dependency>
<dependency>
<groupId>es.bsc.inb.elixir</groupId>
<artifactId>openebench-data-model</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>es.elixir.bsc.json.schema</groupId>
<artifactId>jaronuinga</artifactId>
<version>0.4</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.12.5</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2</artifactId>
<version>2.0.10</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jaronuinga</id>
<url>https://raw.github.com/inab/jaronuinga/maven/</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<webResources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</webResources>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
package es.bsc.inb.elixir.openebench.rest;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* @author Dmitry Repchevsky
*/
//@WebFilter("/*")
public class AnonymousUserFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final AuthorizationHeaderRequestWrapper wrapper = new AuthorizationHeaderRequestWrapper((HttpServletRequest)req);
chain.doFilter(wrapper, res);
}
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.ws.rs.core.HttpHeaders;
/**
* Wrapper that injects HTTP BASIC 'anonymous:anonymous' authorization when there is no any.
*
* @author Dmitry Repchevsky
*/
public class AuthorizationHeaderRequestWrapper extends HttpServletRequestWrapper {
public final static String ANONYMOUSE_USER_CREDENTIALS = "Basic YW5vbnltb3VzOmFub255bW91cw==";
public AuthorizationHeaderRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getAuthType() {
return super.getAuthType();
}
@Override
public String getHeader(String name) {
final String header = super.getHeader(name);
if (HttpHeaders.AUTHORIZATION.equals(name) && header == null) {
return ANONYMOUSE_USER_CREDENTIALS;
}
return header;
}
@Override
public Enumeration<String> getHeaders(String name) {
if (HttpHeaders.AUTHORIZATION.equals(name) && super.getHeader(HttpHeaders.AUTHORIZATION) == null) {
List<String> auths = Collections.list(super.getHeaders(name));
auths.add(ANONYMOUSE_USER_CREDENTIALS);
return Collections.enumeration(auths);
}
return super.getHeaders(name);
}
@Override
public Enumeration getHeaderNames() {
if (super.getHeader(HttpHeaders.AUTHORIZATION) != null) {
return super.getHeaderNames();
}
List<String> names = Collections.list(super.getHeaderNames());
names.add(HttpHeaders.AUTHORIZATION);
return Collections.enumeration(names);
}
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;
/**
* @author Dmitry Repchevsky
*/
@Provider
@PreMatching
public class CorsResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
responseContext.getHeaders().add("Access-Control-Allow-Origin","*");
responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, OPTIONS");
responseContext.getHeaders().add("Access-Control-Allow-Headers", "X-Requested-With");
}
}
\ No newline at end of file
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.ext.Provider;
/**
* The filter that add "application/json" content to be accepted.
* For instance some browsers expect "text/html" or "application/xml" what
* makes impossible to get JSON back from the REST services.
*
* @author Dmitry Repchevsky
*/
@Provider
@PreMatching
public class JSONContentTypeFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext rc) throws IOException {
rc.getHeaders().add(HttpHeaders.ACCEPT, "application/json;q=.9");
}
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
* Benchmarking JAX-RS configuration (match everything from the root).
*
* @author Dmitry Repchevsky
*/
@ApplicationPath("/")
public class OpenEBenchApplication extends Application {
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest;
import es.bsc.inb.elixir.openebench.rest.dao.Database;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLDecoder;
import java.security.Principal;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.security.PermitAll;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.ws.rs.Encoded;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.StreamingOutput;
/**
* @author Dmitry Repchevsky
*/
@Path("/")
@RequestScoped
public class OpenEBenchService {
@Inject
private Database dao;
@Path("/{path: .*}")
@OPTIONS
public Response compliance() {
return Response.ok().header("Allow", "GET")
.header("Allow", "HEAD")
.header("Allow", "PUT")
.header("Allow", "POST")
.header("Allow", "PATCH")
.header("Allow", "DELETE")
.build();
}
@GET
@Path("/")
@Hidden
@PermitAll
public Response get(@Context ServletContext ctx) {
return Response.ok(ctx.getResourceAsStream("/index.html"), MediaType.TEXT_HTML).build();
}
@GET
@Path("/{collection}")
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public Response getObjects(@Context SecurityContext sc,
@PathParam("collection")
@Parameter(description = "OpenEBench collection",
example = "Contact")
@Encoded final String collection) {
switch (collection) {
case "Community":
case "Tool":
case "Reference": break;
default: return Response.status(Status.FORBIDDEN).build();
}
StreamingOutput stream = (OutputStream out) -> {
try (Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))) {
dao.write(writer, collection);
} catch(Exception ex) {
Logger.getLogger(OpenEBenchService.class.getName()).log(Level.SEVERE, null, ex);
}
};
return Response.ok(stream, MediaType.APPLICATION_JSON).build();
}
@Operation(
summary = "Check whether the object exists",
responses = {
@ApiResponse(responseCode = "200", description = "object exists"),
@ApiResponse(responseCode = "400", description = "invalid id"),
@ApiResponse(responseCode = "404", description = "object not found")
}
)
@HEAD
@Path("/{collection}/{id : .*}")
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public Response hasObject(@Context final SecurityContext sc,
@PathParam("collection")
@Parameter(description = "data collection",
example = "BenchmarkingEvent")
final String collection,
@PathParam("id")
@Parameter(description = "object id",
example = "OEBD00200001FO")
@Encoded final String id) {
try {
final String _id = URLDecoder.decode(id, "UTF-8");
final Boolean exist = dao.hasObject(_id, collection);
return exist != null && exist ?
Response.ok(MediaType.APPLICATION_JSON).build() :
Response.status(Response.Status.NOT_FOUND).build();
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(OpenEBenchService.class.getName()).log(Level.SEVERE, null, ex);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
@GET
@Path("/{collection}/{id : .*}")
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public Response getObject(@Context SecurityContext sc,
@PathParam("collection")
@Parameter(description = "OpenEBench collection",
example = "Contact")
@Encoded final String collection,
@PathParam("id")
@Parameter(description = "object id",
example = "OEBD00200001FO")
@Encoded final String id) {
switch (collection) {
case "Contact":
case "Community":
case "Tool":
case "Reference": break;
default: return Response.status(Status.FORBIDDEN).build();
}
final String object = dao.getObject(id, collection);
if (object == null) {
return Response.status(Status.NOT_FOUND).build();
}
return Response.ok(object, MediaType.APPLICATION_JSON).build();
}
@GET
@Path("/Contact")
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public Response getContacts(@Context SecurityContext sc,
@QueryParam("email")
@Parameter(description = "contact email",
example = "someone@gmai.com")
@Encoded final String email) {
StreamingOutput stream = (OutputStream out) -> {
try (Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))) {
dao.findContactsByEmail(writer, email);
} catch(Exception ex) {
Logger.getLogger(OpenEBenchService.class.getName()).log(Level.SEVERE, null, ex);
}
};
return Response.ok(stream, MediaType.APPLICATION_JSON).build();
}
@GET
@Path("/Dataset")
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public Response getDatasets(@Context SecurityContext sc) {
final Principal principal = sc.getUserPrincipal();
final String email = principal != null ? principal.getName() : "";
StreamingOutput stream = (OutputStream out) -> {
try (Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))) {
dao.getDatasets(writer, email);
} catch(Exception ex) {
Logger.getLogger(OpenEBenchService.class.getName()).log(Level.SEVERE, null, ex);
}
};
return Response.ok(stream, MediaType.APPLICATION_JSON).build();
}
@GET
@Path("/Dataset/{id : .*}")
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public Response getDataset(@Context SecurityContext sc,
@PathParam("id")
@Parameter(description = "dataset id",
example = "OEBD00200001FO")
@Encoded final String id) {
final Principal principal = sc.getUserPrincipal();
final String email = principal != null ? principal.getName() : "";
final String dataset = dao.getDataset(id, email);
if (dataset == null) {
return Response.status(Status.NOT_FOUND).build();
}
if ("{}".equals(dataset)) {
return Response.status(Status.UNAUTHORIZED).build();
}
return Response.ok(dataset, MediaType.APPLICATION_JSON).build();
}
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest.model;
/**
* @author Dmitry Repchevsky
*/
public class BenchmarkingEvent extends es.bsc.inb.elixir.openebench.datamodel.BenchmarkingEvent {
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest.model;
/**
* @author Dmitry Repchevsky
*/
public class Challenge extends es.bsc.inb.elixir.openebench.datamodel.Challenge {
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software