Added /token resource, ensure JSON is the default return type

some general cleanup as well.
This commit is contained in:
michaelpede 2021-04-15 13:16:41 -07:00
parent 554d1c5825
commit 05ebf0d453
10 changed files with 240 additions and 32 deletions

View File

@ -45,6 +45,12 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.olingo</groupId>
<artifactId>odata-commons-api</artifactId>

View File

@ -87,6 +87,17 @@ public class GenericEntityCollectionProcessor implements EntityCollectionProcess
EntityCollection entitySet = getData(edmEntitySet);
// 3rd: create a serializer based on the requested format (json)
try
{
uriInfo.asUriInfoAll().getFormatOption().getFormat(); // If Format is given, then we will use what it has.
}
catch (Exception e)
{
responseFormat = ContentType.JSON; // If format is not set in the $format, then use JSON.
// There is some magic that will select XML if you're viewing from a browser or something which I'm bypassing here.
// If you want a different $format, explicitly state it.
}
ODataSerializer serializer = odata.createSerializer(responseFormat);
// 4th: Now serialize the content: transform from the EntitySet object to InputStream

View File

@ -175,13 +175,6 @@ public class RESOedmProvider extends CsdlAbstractEdmProvider
List<CsdlSchema> schemas = new ArrayList<CsdlSchema>();
schemas.add(schema);
CsdlEnumType type = new CsdlEnumType();
type.setMembers(new ArrayList<CsdlEnumMember>());
type.setName("EnumTest");
type.setUnderlyingType(EdmPrimitiveTypeKind.Int64.getFullQualifiedName());
schema.getEnumTypes().add(type);
return schemas;
}

View File

@ -1,7 +1,7 @@
package org.reso.service.security;
package org.reso.service.security.providers;
import org.reso.service.servlet.RESOservlet;
import org.reso.service.security.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -1,12 +1,12 @@
package org.reso.service.security;
package org.reso.service.security.providers;
import org.reso.service.security.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Base64;
import java.util.Enumeration;
public class BearerAuthProvider implements Provider

View File

@ -1,6 +1,7 @@
package org.reso.service.servlet;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.olingo.commons.api.edmx.EdmxReference;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataHttpHandler;
@ -9,9 +10,10 @@ import org.reso.service.data.GenericEntityCollectionProcessor;
import org.reso.service.data.definition.LookupDefinition;
import org.reso.service.data.meta.ResourceInfo;
import org.reso.service.edmprovider.RESOedmProvider;
import org.reso.service.security.BasicAuthProvider;
import org.reso.service.security.BearerAuthProvider;
import org.reso.service.security.providers.BasicAuthProvider;
import org.reso.service.security.Validator;
import org.reso.service.security.providers.BearerAuthProvider;
import org.reso.service.servlet.util.SimpleError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -23,12 +25,15 @@ import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class RESOservlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(RESOservlet.class);
private Connection connect = null;
private Validator validator = null;
private OData odata = null;
ODataHttpHandler handler = null;
@Override public void init() throws ServletException
@ -44,7 +49,7 @@ public class RESOservlet extends HttpServlet
}
this.validator = new Validator();
//this.validator.addProvider(new BasicAuthProvider());
this.validator.addProvider(new BasicAuthProvider());
this.validator.addProvider(new BearerAuthProvider());
String mysqlHost = env.get("SQL_HOST");
@ -64,33 +69,42 @@ public class RESOservlet extends HttpServlet
} catch (Exception e) {
LOG.error("Server Error occurred in connecting to the database", e);
}
// Set up ODATA
this.odata = OData.newInstance();
RESOedmProvider edmProvider = new RESOedmProvider();
ResourceInfo defn = new LookupDefinition();
edmProvider.addDefinition(defn);
ServiceMetadata edm = odata.createServiceMetadata(edmProvider, new ArrayList<EdmxReference>());
// create odata handler and configure it with CsdlEdmProvider and Processor
this.handler = odata.createHandler(edm);
GenericEntityCollectionProcessor lookupEntityCollectionProcessor = new GenericEntityCollectionProcessor(this.connect, defn);
this.handler.register(lookupEntityCollectionProcessor);
}
protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
// Due to order of operations, the unauthorized response won't be called unless the verification fails.
if (!this.validator.verify(req) && this.validator.unauthorizedResponse(resp))
{ // Due to order of operations, the unauthorized response won't be called unless the verification fails.
resp.getWriter().println("<html><body><p>Unauthorized</p></body></html>");
{
SimpleError error = new SimpleError(SimpleError.AUTH_REQUIRED);
ObjectMapper objectMapper = new ObjectMapper();
PrintWriter out = resp.getWriter();
out.println(objectMapper.writeValueAsString(error));
out.flush();
return;
}
try {
// create odata handler and configure it with CsdlEdmProvider and Processor
OData odata = OData.newInstance();
RESOedmProvider edmProvider = new RESOedmProvider();
ResourceInfo defn = new LookupDefinition();
edmProvider.addDefinition(defn);
ServiceMetadata edm = odata.createServiceMetadata(edmProvider, new ArrayList<EdmxReference>());
ODataHttpHandler handler = odata.createHandler(edm);
GenericEntityCollectionProcessor lookupEntityCollectionProcessor = new GenericEntityCollectionProcessor(this.connect, defn);
handler.register(lookupEntityCollectionProcessor);
// let the handler do the work
handler.process(req, resp);
this.handler.process(req, resp);
} catch (RuntimeException e) {
LOG.error("Server Error occurred in RESOservlet", e);

View File

@ -0,0 +1,83 @@
package org.reso.service.servlet;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.reso.service.security.providers.BearerAuthProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.reso.service.servlet.util.Token;
import org.reso.service.servlet.util.SimpleError;
public class TokenServlet extends HttpServlet
{
public static final String ID_HEADER = "client_id";
public static final String SECRET_HEADER = "client_secret";
public static final String AUTH_CLIENT_ID = "reso";
public static final String AUTH_CLIENT_SECRET = "secret";
private static final Logger LOG = LoggerFactory.getLogger(HttpServlet.class);
private String getHeader(final HttpServletRequest req, String header)
{
Enumeration<String> headers = req.getHeaders(header);
while (headers.hasMoreElements())
{
return headers.nextElement();
}
return null;
}
private String getField(final HttpServletRequest req, String name)
{
String param = req.getParameter(name);
if (param==null)
{
return getHeader(req,name);
}
return param;
}
protected void service(final HttpServletRequest req, final HttpServletResponse response) throws ServletException, IOException {
String client_id = getField(req, TokenServlet.ID_HEADER);
String client_secret = getField(req, TokenServlet.SECRET_HEADER);
String jsonString = null;
PrintWriter out = response.getWriter();
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
ObjectMapper objectMapper = new ObjectMapper();
if (client_id!=null && client_secret!=null && client_id.equals(TokenServlet.AUTH_CLIENT_ID) && client_secret.equals(TokenServlet.AUTH_CLIENT_SECRET))
{
Token token = new Token(BearerAuthProvider.AUTH_BEARER_TOKEN,"bearer","create");
jsonString = objectMapper.writeValueAsString(token);
}
else
{
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
SimpleError error = new SimpleError(SimpleError.INVALID_REQUEST);
jsonString = objectMapper.writeValueAsString(error);
}
out.print(jsonString);
out.flush();
}
}

View File

@ -0,0 +1,21 @@
package org.reso.service.servlet.util;
public class SimpleError
{
String error;
static public String AUTH_REQUIRED = "auth_required";
static public String INVALID_REQUEST = "invalid_request";
public SimpleError(String error)
{
this.error = error;
}
public String getError()
{
return error;
}
}

View File

@ -0,0 +1,69 @@
package org.reso.service.servlet.util;
public class Token
{
String accessToken;
String tokenType;
String scope;
public Token(String authBearerToken, String tokenType, String scope)
{
this.accessToken = authBearerToken;
this.tokenType = tokenType;
this.scope = scope;
}
/**
* Set the attribute with the name that corresponds to this method name.
*
* @param accessToken The value to set the attribute to.
*/
public void setAccessToken(String accessToken)
{
this.accessToken = accessToken;
}
/**
* Set the attribute with the name that corresponds to this method name.
*
* @param tokenType The value to set the attribute to.
*/
public void setTokenType(String tokenType)
{
this.tokenType = tokenType;
}
/**
* Set the attribute with the name that corresponds to this method name.
*
* @param scope The value to set the attribute to.
*/
public void setScope(String scope)
{
this.scope = scope;
}
public String getAccessToken()
{
return accessToken;
}
public String getTokenType()
{
return tokenType;
}
public String getScope()
{
return scope;
}
}

View File

@ -10,6 +10,17 @@
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>TokenServlet</servlet-name>
<servlet-class>org.reso.service.servlet.TokenServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>TokenServlet</servlet-name>
<url-pattern>/token</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RESOservlet</servlet-name>
<url-pattern>/*</url-pattern>