Added check for supported organizations in list/search method

This commit is contained in:
Luca Frosini 2020-06-22 19:39:29 +02:00
parent 1ef0537f0e
commit 7a0dbf48a9
2 changed files with 86 additions and 71 deletions

View File

@ -1,5 +1,6 @@
package org.gcube.gcat.persistence.ckan;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -75,7 +76,7 @@ public class CKANPackage extends CKAN {
protected static final String ORGANIZATION_FILTER_TEMPLATE = GCatConstants.ORGANIZATION_PARAMETER + ":%s";
protected static final String ORGANIZATION_REGEX = GCatConstants.ORGANIZATION_PARAMETER + ":[a-zA-Z_\"]*";
protected static final String ORGANIZATION_REGEX = GCatConstants.ORGANIZATION_PARAMETER + ":[a-zA-Z0-9_\"]*";
protected static final Pattern ORGANIZATION_REGEX_PATTERN;
@ -203,8 +204,6 @@ public class CKANPackage extends CKAN {
}
protected CKANOrganization checkGotOrganization(String gotOrganization) throws ForbiddenException {
// TODO Check if it is allowed to publish in such organization by reading an IS resource
if(!supportedOrganizations.contains(gotOrganization)) {
String error = String.format(
"IS Configuration does not allow to publish in %s organizations. Allowed organization are: %s",
@ -336,81 +335,65 @@ public class CKANPackage extends CKAN {
return list(parameters);
}
/*
* TODO support the allowed organization in the VRE
*/
protected void checkOrganizationFilter(String q) {
protected Set<String> checkOrganizationFilter(String q) {
Matcher m = ORGANIZATION_REGEX_PATTERN.matcher(q);
List<String> matches = new ArrayList<>();
Set<String> matches = new HashSet<>();
while(m.find()) {
matches.add(q.substring(m.start(), m.end()));
matches.add(q.substring(m.start(), m.end()).replace(GCatConstants.ORGANIZATION_PARAMETER+":", ""));
}
if(matches.size() > 0) {
StringBuilder error = new StringBuilder();
error.append("Organization filters is constrained to VRE. ");
if(matches.size() > 1) {
error.append("Remove these filters ");
} else {
error.append("Remove this filter ");
}
boolean first = true;
for(String match : matches) {
if(!first) {
error.append(", ");
} else {
first = false;
}
error.append("[");
error.append(match);
error.append("]");
}
throw new BadRequestException(error.toString());
}
return matches;
}
protected static String[] allowedListQueryParameters = new String[] {"q", "fq", "fq_list", "sort",
/* "facet", "facet.mincount", "facet.limit", "facet.field", */
"include_drafts", "include_private", "ext_bbox"};
protected String getFilterForOrganizations() {
StringWriter stringWriter = new StringWriter();
int i=1;
for(String organizationName : supportedOrganizations) {
stringWriter.append(String.format(GCatConstants.ORGANIZATION_FILTER_TEMPLATE, organizationName));
if(i!=supportedOrganizations.size()) {
// Please note that an item can only belong to a single organization.
// Hence the query must put supported organizations in OR.
stringWriter.append(" OR ");
}
i++;
}
return stringWriter.toString();
}
protected Map<String,String> checkListParameters(MultivaluedMap<String,String> queryParameters,
Map<String,String> parameters) {
String organizationName = getOrganizationName();
ScopeBean scopeBean = new ScopeBean(ContextUtility.getCurrentContext());
String q = null;
if(queryParameters.containsKey(GCatConstants.Q_KEY)) {
q = queryParameters.getFirst(GCatConstants.Q_KEY);
}
// TODO check against feature #19365
/*
* List is filter per organization only is the request arriving in a VRE.
* If the request arrive form a VO or from ROOT the request return the item in all organizations
* in the catalog.
*/
if(scopeBean.is(Type.VRE)) {
if(q != null) {
checkOrganizationFilter(q);
if(q != null) {
Set<String> organizations = checkOrganizationFilter(q);
if(organizations.size()==0) {
// Adding organization filter to q
parameters.put(GCatConstants.Q_KEY,
String.format("%s:%s AND %s", GCatConstants.ORGANIZATION_PARAMETER, organizationName, q));
} else {
parameters.put(GCatConstants.Q_KEY,
String.format(GCatConstants.ORGANIZATION_FILTER_TEMPLATE, organizationName));
String filter = getFilterForOrganizations();
parameters.put(GCatConstants.Q_KEY, String.format("%s AND %s", q, filter));
}else {
organizations.removeAll(this.supportedOrganizations);
if(organizations.size()>0) {
String error = String.format("It is not possible to query the following organizations %s. Supported organization in this context are %s", organizations.toString(), supportedOrganizations.toString());
throw new ForbiddenException(error);
}
}
} else {
// We are in VO or in ROOT.
// The organization filtering is allowed for the client which must provide q parameter in the form:
// q=organization:nextnext
String filter = getFilterForOrganizations();
parameters.put(GCatConstants.Q_KEY, filter);
}
for(String key : allowedListQueryParameters) {
if(queryParameters.containsKey(key)) {

View File

@ -8,6 +8,7 @@ import java.util.Map;
import java.util.Set;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
@ -56,33 +57,64 @@ public class CKANPackageTest extends ContextTest {
@Test
public void listWithParameters() throws Exception {
String contextName = "/gcube/devNext/NextNext";
ScopeBean scopeBean = new ScopeBean(contextName);
String ckanOrganizationName = CKANPackage.getOrganizationName(scopeBean);
ContextTest.setContextByName(contextName);
CKANPackage ckanPackage = new CKANPackage();
ObjectMapper mapper = new ObjectMapper();
Map<String, String> parameters = new HashMap<>();
parameters.put(GCatConstants.Q_KEY, "organization:ckand4scienceharvest OR organization:dorne");
// parameters.put(GCatConstants.Q_KEY, "organization:ckand4scienceharvest");
// parameters.put(GCatConstants.Q_KEY, "organization:dorne");
Map<String,String> parameters = new HashMap<>();
parameters.put(CKANPackage.ROWS_KEY, String.valueOf(10));
parameters.put(CKANPackage.START_KEY, String.valueOf(0));
/*
parameters.put("fl","[\"name\"]");
*/
boolean[] values = new boolean[]{true, false};
/*
parameters.put("facet.field","[\"name\"]");
parameters.put("sort","name asc");
*/
for(boolean includeFakeOrganization : values) {
String ret = ckanPackage.list(parameters);
JsonNode gotList = mapper.readTree(ret);
Assert.assertTrue(gotList instanceof ArrayNode);
logger.debug("List :\n{}", mapper.writeValueAsString(gotList));
MultivaluedMap<String,String> queryParameters = new MultivaluedHashMap<>();
if(includeFakeOrganization) {
queryParameters.add(GCatConstants.Q_KEY, "organization:ckand4scienceharvest OR organization:"+ckanOrganizationName);
}else {
queryParameters.add(GCatConstants.Q_KEY, "organization:"+ckanOrganizationName);
}
// parameters.put(GCatConstants.Q_KEY, "organization:ckand4scienceharvest");
// parameters.put(GCatConstants.Q_KEY, "organization:dorne");
/*
queryParameters.add(CKANPackage.ROWS_KEY, String.valueOf(10));
queryParameters.add(CKANPackage.START_KEY, String.valueOf(0));
*/
/*
parameters.put("fl","[\"name\"]");
*/
/*
parameters.put("facet.field","[\"name\"]");
parameters.put("sort","name asc");
*/
try {
parameters = ckanPackage.checkListParameters(queryParameters, parameters);
}catch (ForbiddenException e) {
if(includeFakeOrganization) {
// This is the expected behaviour
continue;
}else {
throw e;
}
}
String ret = ckanPackage.list(parameters);
JsonNode gotList = mapper.readTree(ret);
Assert.assertTrue(gotList instanceof ArrayNode);
logger.debug("List :\n{}", mapper.writeValueAsString(gotList));
}
}
protected GenericResource instantiateGenericResource(String secondaryType, String name, String xml) throws Exception {
GenericResource genericResource = new GenericResource();
org.gcube.common.resources.gcore.GenericResource.Profile profile = genericResource.newProfile();