gcat/src/main/java/org/gcube/gcat/rest/Configuration.java

373 lines
14 KiB
Java

package org.gcube.gcat.rest;
import java.util.Iterator;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
//import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.xml.ws.WebServiceException;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
//import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
import org.gcube.gcat.annotation.PATCH;
import org.gcube.gcat.annotation.PURGE;
import org.gcube.gcat.api.GCatConstants;
import org.gcube.gcat.api.roles.Role;
import org.gcube.gcat.configuration.CatalogueConfigurationFactory;
import org.gcube.gcat.configuration.ServiceCatalogueConfiguration;
import org.gcube.gcat.persistence.ckan.CKANUser;
import org.gcube.gcat.persistence.ckan.CKANUserCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* @author Luca Frosini (ISTI - CNR)
*/
@Path(Configuration.CONFIGURATIONS)
public class Configuration extends BaseREST implements org.gcube.gcat.api.interfaces.Configuration<Response,Response> {
private static Logger logger = LoggerFactory.getLogger(Configuration.class);
public static final String CONTEXT_FULLNAME_PARAMETER = "CONTEXT_FULLNAME_PARAMETER";
protected String checkContext(String context) throws WebServiceException {
if(context==null || context.compareTo("")==0) {
throw new BadRequestException("Please provide a valid context as path parameter");
}
String c = SecretManagerProvider.instance.get().getContext();
if(context.compareTo(Configuration.CURRENT_CONTEXT_PATH_PARAMETER)==0) {
return c;
}
if(context.compareTo(c)!=0) {
throw new BadRequestException("Context provided as path parameter (i.e. " + context + ") does not match with token request context (i.e. " + c + ")");
}
return c;
}
protected String checkContext(String context, ServiceCatalogueConfiguration catalogueConfiguration) {
String c = checkContext(context);
if(c.compareTo(catalogueConfiguration.getContext())!=0) {
throw new BadRequestException("Context provided in the configuration (i.e. " + catalogueConfiguration.getContext() + ") does not match with token request context (i.e. " + c + ")");
}
return c;
}
protected void checkRole(Role required) {
CKANUser ckanUser = CKANUserCache.getCurrrentCKANUser();
if(ckanUser.getRole().ordinal() < required.ordinal()) {
throw new ForbiddenException("To perform such a request you must have " + required.getPortalRole() + " role");
}
}
private String createOrUpdate(ServiceCatalogueConfiguration catalogueConfiguration) throws WebServiceException {
try {
ServiceCatalogueConfiguration gotCatalogueConfiguration = CatalogueConfigurationFactory.createOrUpdate(catalogueConfiguration);
String configuration = gotCatalogueConfiguration.toJsonString();
logger.debug("The new configuration in context {} is {}", catalogueConfiguration.getContext(), configuration);
return configuration;
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@POST
@Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8)
@Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8)
@Override
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
@StatusCodes ({
@ResponseCode(code = 201, condition = "Catalogue configuration successfully created."),
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can create catalogue configuration."),
@ResponseCode(code = 500, condition = "Error while persisting catalogue configuration."),
})
/**
* Creates the catalogue configuration for the current context using the json provided as parameter
* @param json the configuration representation
*
* {
* "id": "584b8503-a490-4a89-8372-e21830fa716c",
* "context": "/gcube/devsec/devVRE",
* "defaultOrganization": "devvre",
* "supportedOrganizations": [ "devvre" ],
* "ckanURL": "https://ckan-d-d4s.d4science.org",
* "solrURL": "https://ckan-d-d4s.d4science.org/solr/",
* "socialPostEnabled": false,
* "notificationToUsersEnabled": true,
* "moderationEnabled": true
* }
*
* @return the created configuration
*
* {
* "id": "584b8503-a490-4a89-8372-e21830fa716c",
* "context": "/gcube/devsec/devVRE",
* "defaultOrganization": "devvre",
* "supportedOrganizations": [ "devvre" ],
* "ckanURL": "https://ckan-d-d4s.d4science.org",
* "solrURL": "https://ckan-d-d4s.d4science.org/solr/",
* "socialPostEnabled": false,
* "notificationToUsersEnabled": true,
* "moderationEnabled": true
* }
*
* @throws WebServiceException
*/
public Response create(String json) throws WebServiceException {
try {
ServiceCatalogueConfiguration catalogueConfiguration = ServiceCatalogueConfiguration.getServiceCatalogueConfiguration(json);
checkContext(CURRENT_CONTEXT_PATH_PARAMETER, catalogueConfiguration);
String ret = createOrUpdate(catalogueConfiguration);
ResponseBuilder responseBuilder = Response.status(Status.CREATED);
if(ret!=null) {
responseBuilder.entity(ret).type(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8);
}
return responseBuilder.build();
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@GET
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
@Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8)
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_EDITOR, Role.CATALOGUE_ADMIN, Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
@StatusCodes ({
@ResponseCode(code = 200, condition = "Catalogue configuration successfully read."),
@ResponseCode(code = 401, condition = "Only User with role Catalogue-Editors or above can read a catalogue configuration."),
@ResponseCode(code = 500, condition = "Error while reading catalogue configuration."),
})
/**
* @param context
* @return
* @throws WebServiceException
*/
public Response read(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context) throws WebServiceException {
try {
checkContext(context);
return read();
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@Override
public Response read() throws WebServiceException {
try {
ServiceCatalogueConfiguration catalogueConfiguration = CatalogueConfigurationFactory.getInstance();
String configuration = catalogueConfiguration.toJsonString();
logger.debug("Configuration in context {} is {}", catalogueConfiguration.getContext(), configuration);
ResponseBuilder responseBuilder = Response.status(Status.OK);
if(configuration!=null) {
responseBuilder.entity(configuration).type(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8);
}
return responseBuilder.build();
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@PUT
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
@Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8)
@Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8)
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
@StatusCodes ({
@ResponseCode(code = 200, condition = "Catalogue configuration successfully created/updated."),
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can create/update catalogue configuration."),
@ResponseCode(code = 500, condition = "Error while creating/updating catalogue configuration."),
})
public String createOrUpdate(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context, String json) throws WebServiceException {
try {
ServiceCatalogueConfiguration catalogueConfiguration = ServiceCatalogueConfiguration.getServiceCatalogueConfiguration(json);
checkContext(context, catalogueConfiguration);
return createOrUpdate(catalogueConfiguration);
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@Override
public Response update(String json) throws WebServiceException {
try {
ServiceCatalogueConfiguration catalogueConfiguration = ServiceCatalogueConfiguration.getServiceCatalogueConfiguration(json);
checkContext(CURRENT_CONTEXT_PATH_PARAMETER);
catalogueConfiguration = CatalogueConfigurationFactory.createOrUpdate(catalogueConfiguration);
String configuration = catalogueConfiguration.toJsonString();
logger.debug("Configuration in context {} has been updated to {}", catalogueConfiguration.getContext(), configuration);
ResponseBuilder responseBuilder = Response.status(Status.OK);
if(configuration!=null) {
responseBuilder.entity(configuration).type(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8);
}
return responseBuilder.build();
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@PATCH
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
@Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8)
@Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8)
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
@StatusCodes ({
@ResponseCode(code = 200, condition = "Catalogue configuration successfully updated."),
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can update catalogue configuration."),
@ResponseCode(code = 500, condition = "Error while updating catalogue configuration."),
})
public Response patch(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context, String json) throws WebServiceException {
try {
checkContext(context);
return patch(json);
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@Override
public Response patch(String json) throws WebServiceException {
try {
ServiceCatalogueConfiguration catalogueConfiguration = CatalogueConfigurationFactory.getInstance();
ObjectMapper mapper = new ObjectMapper();
ObjectNode node = (ObjectNode) mapper.readTree(json);
if(node.has(ServiceCatalogueConfiguration.CONTEXT_KEY)) {
String context = node.get(ServiceCatalogueConfiguration.CONTEXT_KEY).asText();
String c = SecretManagerProvider.instance.get().getContext();
if(c.compareTo(context)!=0) {
throw new BadRequestException("Context provided in the configuration (i.e. " + catalogueConfiguration.getContext() + ") does not match with token request context (i.e. " + c + ")");
}
node.remove(CURRENT_CONTEXT_PATH_PARAMETER);
}
ObjectNode configuration = mapper.valueToTree(catalogueConfiguration);
Iterator<String> fieldNames = node.fieldNames();
while(fieldNames.hasNext()) {
String fieldName = fieldNames.next();
configuration.set(fieldName, node.get(fieldName));
}
ServiceCatalogueConfiguration newCatalogueConfiguration = ServiceCatalogueConfiguration.getServiceCatalogueConfiguration(configuration);
newCatalogueConfiguration = CatalogueConfigurationFactory.createOrUpdate(newCatalogueConfiguration);
String ret = newCatalogueConfiguration.toJsonString();
logger.debug("Configuration in context {} has been patched to {}", catalogueConfiguration.getContext(), ret);
ResponseBuilder responseBuilder = Response.status(Status.OK);
if(ret!=null) {
responseBuilder.entity(ret).type(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8);
}
return responseBuilder.build();
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@DELETE
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
@StatusCodes ({
@ResponseCode(code = 200, condition = "Catalogue configuration successfully deleted."),
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can delete catalogue configuration."),
@ResponseCode(code = 500, condition = "Error while deleting catalogue configuration."),
})
public Response delete(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context,
@QueryParam(GCatConstants.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) throws WebServiceException {
try {
checkContext(context);
if(purge) {
return purge();
}else {
return delete();
}
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
// Remove the configuration from cache and force reload
@Override
public Response delete() throws WebServiceException {
try {
CatalogueConfigurationFactory.renew();
return Response.status(Status.NO_CONTENT).build();
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
@PURGE
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
@StatusCodes ({
@ResponseCode(code = 200, condition = "Catalogue configuration successfully deleted."),
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can delete catalogue configuration."),
@ResponseCode(code = 500, condition = "Error while deleting catalogue configuration."),
})
public Response purge(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context) throws WebServiceException {
try {
checkContext(context);
return purge();
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
// Remove the configuration from cache and from IS
@Override
public Response purge() throws WebServiceException {
try {
CatalogueConfigurationFactory.purge();
return Response.status(Status.NO_CONTENT).build();
}catch (WebApplicationException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
}