/*
*
* Copyright 2013 Entando S.r.l. (http://www.entando.com) All rights reserved.
*
* This file is part of Entando software.
* Entando is a free software;
* You can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; version 2.
*
* See the file License for the specific language governing permissions
* and limitations under the License
*
*
*
* Copyright 2013 Entando S.r.l. (http://www.entando.com) All rights reserved.
*
*/
package org.entando.entando.plugins.jptokenapi.aps.system.server;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import org.entando.entando.aps.system.services.api.IApiErrorCodes;
import org.entando.entando.aps.system.services.api.model.ApiException;
import org.entando.entando.aps.system.services.api.model.ApiMethod;
import org.entando.entando.aps.system.services.api.provider.json.JSONProvider;
import com.agiletec.aps.system.SystemConstants;
import com.agiletec.aps.system.services.authorization.IAuthorizationManager;
import com.agiletec.aps.system.services.user.IAuthenticationProviderManager;
import com.agiletec.aps.system.services.user.UserDetails;
import com.agiletec.aps.util.ApsWebApplicationUtils;
import org.entando.entando.aps.system.services.api.server.IResponseBuilder;
import org.entando.entando.plugins.jptokenapi.aps.system.JpTokenApiSystemConstants;
import org.entando.entando.plugins.jptokenapi.aps.system.token.IApiTokenizerManager;
/**
* @author E.Santoboni
*/
public class ApiRestServer extends org.entando.entando.aps.system.services.api.server.ApiRestServer {
@Override
protected Object buildGetDeleteResponse(String langCode, ApiMethod.HttpMethod httpMethod,
String namespace, String resourceName, HttpServletRequest request, HttpServletResponse response, UriInfo ui) {
Object responseObject = null;
try {
IResponseBuilder responseBuilder = (IResponseBuilder) ApsWebApplicationUtils.getBean(SystemConstants.API_RESPONSE_BUILDER, request);
Properties properties = this.extractRequestParameters(ui);
properties.put(SystemConstants.API_LANG_CODE_PARAMETER, langCode);
ApiMethod apiMethod = responseBuilder.extractApiMethod(httpMethod, namespace, resourceName);
String entandoApiToken = this.extractApiToken(request, ui);
if (null != entandoApiToken) {
this.extractTokenParameters(entandoApiToken, apiMethod, request, properties);
} else {
this.extractOAuthParameters(apiMethod, request, response, properties);
}
responseObject = responseBuilder.createResponse(apiMethod, properties);
} catch (ApiException ae) {
responseObject = this.buildErrorResponse(httpMethod, namespace, resourceName, ae);
} catch (Throwable t) {
responseObject = this.buildErrorResponse(httpMethod, namespace, resourceName, t);
}
return this.createResponse(responseObject);
}
@Override
protected Object buildPostPutResponse(String langCode, ApiMethod.HttpMethod httpMethod,
String namespace, String resourceName, HttpServletRequest request, HttpServletResponse response, UriInfo ui, MediaType mediaType) {
Object responseObject = null;
try {
IResponseBuilder responseBuilder = (IResponseBuilder) ApsWebApplicationUtils.getBean(SystemConstants.API_RESPONSE_BUILDER, request);
Properties properties = this.extractRequestParameters(ui);
properties.put(SystemConstants.API_LANG_CODE_PARAMETER, langCode);
ApiMethod apiMethod = responseBuilder.extractApiMethod(httpMethod, namespace, resourceName);
String entandoApiToken = this.extractApiToken(request, ui);
if (null != entandoApiToken) {
this.extractTokenParameters(entandoApiToken, apiMethod, request, properties);
} else {
this.extractOAuthParameters(apiMethod, request, response, properties);
}
Class expectedType = apiMethod.getExpectedType();
Object bodyObject = null;
if (MediaType.APPLICATION_JSON_TYPE.equals(mediaType)) {
JSONProvider jsonProvider = new JSONProvider();
bodyObject = jsonProvider.readFrom(expectedType, expectedType.getGenericSuperclass(),
expectedType.getAnnotations(), mediaType, null, request.getInputStream());
} else {
JAXBContext context = JAXBContext.newInstance(expectedType);
Unmarshaller unmarshaller = context.createUnmarshaller();
bodyObject = (Object) unmarshaller.unmarshal(request.getInputStream());
}
responseObject = responseBuilder.createResponse(apiMethod, bodyObject, properties);
} catch (ApiException ae) {
responseObject = this.buildErrorResponse(httpMethod, namespace, resourceName, ae);
} catch (Throwable t) {
responseObject = this.buildErrorResponse(httpMethod, namespace, resourceName, t);
}
return this.createResponse(responseObject);
}
private String extractApiToken(HttpServletRequest request, UriInfo ui) {
String token = request.getHeader(API_TOKEN_PARAM_NAME);
if (null != token && token.trim().length() > 0) {
return token;
}
MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
if (null != queryParams) {
Set<Entry<String, List<String>>> entries = queryParams.entrySet();
Iterator<Entry<String, List<String>>> iter = entries.iterator();
while (iter.hasNext()) {
Map.Entry<String, List<String>> entry = (Entry<String, List<String>>) iter.next();
String key = entry.getKey();
if (API_TOKEN_PARAM_NAME.equals(key)) {
//extract only the first value
return entry.getValue().get(0);
}
}
}
return null;
}
protected void extractTokenParameters(String entandoApiToken, ApiMethod apiMethod,
HttpServletRequest request, Properties properties) throws ApiException, IOException, ServletException {
UserDetails user = null;
IApiTokenizerManager tokenizerManager =
(IApiTokenizerManager) ApsWebApplicationUtils.getBean(JpTokenApiSystemConstants.TOKENIZER_MANAGER, request);
IAuthenticationProviderManager authenticationProvider =
(IAuthenticationProviderManager) ApsWebApplicationUtils.getBean(SystemConstants.AUTHENTICATION_PROVIDER_MANAGER, request);
IAuthorizationManager authorizationManager =
(IAuthorizationManager) ApsWebApplicationUtils.getBean(SystemConstants.AUTHORIZATION_SERVICE, request);
try {
String username = tokenizerManager.getUser(entandoApiToken);
user = authenticationProvider.getUser(username);
if (null != user) {
properties.put(SystemConstants.API_USER_PARAMETER, user);
} else if (apiMethod.getRequiredAuth()) {
throw new ApiException(IApiErrorCodes.API_AUTHENTICATION_REQUIRED, "Invalid or missing user for token '" + entandoApiToken + "'", Response.Status.UNAUTHORIZED);
}
} catch (Exception e) {
if (apiMethod.getRequiredAuth()) {
throw new ApiException(IApiErrorCodes.API_AUTHENTICATION_REQUIRED, "Authentication Required", Response.Status.UNAUTHORIZED);
}
}
if (null == user && (apiMethod.getRequiredAuth() || null != apiMethod.getRequiredPermission())) {
throw new ApiException(IApiErrorCodes.API_AUTHENTICATION_REQUIRED, "Authentication Required", Response.Status.UNAUTHORIZED);
} else if (null != user && null != apiMethod.getRequiredPermission()
&& !authorizationManager.isAuthOnPermission(user, apiMethod.getRequiredPermission())) {
throw new ApiException(IApiErrorCodes.API_AUTHORIZATION_REQUIRED, "Authorization Required", Response.Status.UNAUTHORIZED);
}
}
public static final String API_TOKEN_PARAM_NAME = "entandoApiToken";
}