Skip to content

Commit

Permalink
Added filtering by group name for the external resources search list.
Browse files Browse the repository at this point in the history
  • Loading branch information
axl8713 committed Jan 13, 2025
1 parent dc396e6 commit 7b99b60
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public interface FilterVisitor {

void visit(CategoryFilter filter) throws InternalErrorServiceEx;

void visit(GroupFilter filter) throws InternalErrorServiceEx;

void visit(FieldFilter filter) throws InternalErrorServiceEx;

void visit(NotFilter filter) throws BadRequestServiceEx, InternalErrorServiceEx;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (C) 2007 - 2011 GeoSolutions S.A.S.
* http://www.geo-solutions.it
*
* GPLv3 + Classpath exception
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.geosolutions.geostore.services.dto.search;

import it.geosolutions.geostore.services.exception.BadRequestServiceEx;
import it.geosolutions.geostore.services.exception.InternalErrorServiceEx;

import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;

/**
* Filter by group name
*/
@XmlRootElement(name = "GroupFilter")
public class GroupFilter extends SearchFilter implements Serializable {

private List<String> names = Collections.emptyList();

private SearchOperator operator;

/**
*
*/
public GroupFilter() {
}

/**
* @param names
* @param operator
*/
public GroupFilter(List<String> names, SearchOperator operator) {
this.names = names;
setOperator(operator);
}

/**
* @return the name
*/
public List<String> getNames() {
return names;
}

/**
* @param names the name to set
*/
public void setNames(List<String> names) {
this.names = names;
}

/**
* @return the operator
*/
public SearchOperator getOperator() {
return operator;
}

/**
* @param operator the operator to set
*/
public final void setOperator(SearchOperator operator) {
checkOperator(operator);
this.operator = operator;
}

public static void checkOperator(SearchOperator operator) {
if (operator != SearchOperator.EQUAL_TO && operator != SearchOperator.LIKE && operator != SearchOperator.ILIKE && operator != SearchOperator.IN)
throw new IllegalArgumentException("Only EQUAL, LIKE, ILIKE, or IN operators are acceptable");
}

@Override
public void accept(FilterVisitor visitor) throws BadRequestServiceEx, InternalErrorServiceEx {
visitor.visit(this);
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getClass().getSimpleName() + '[' +
(operator != null ? operator : "!op!") +
' ' +
(names != null ? names : "[!names!]") +
']';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,7 @@ public enum SearchOperator {
ILIKE,

IS_NULL,
IS_NOT_NULL;
IS_NOT_NULL,

IN
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import it.geosolutions.geostore.services.dto.search.CategoryFilter;
import it.geosolutions.geostore.services.dto.search.FieldFilter;
import it.geosolutions.geostore.services.dto.search.FilterVisitor;
import it.geosolutions.geostore.services.dto.search.GroupFilter;
import it.geosolutions.geostore.services.dto.search.NotFilter;
import it.geosolutions.geostore.services.dto.search.OrFilter;
import it.geosolutions.geostore.services.dto.search.SearchFilter;
Expand All @@ -38,6 +39,7 @@
import java.util.Collections;
import java.util.Date;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -66,6 +68,7 @@ public class SearchConverter implements FilterVisitor {
ops.put(SearchOperator.LESS_THAN_OR_EQUAL_TO, Filter.OP_LESS_OR_EQUAL);
ops.put(SearchOperator.LIKE, Filter.OP_LIKE);
ops.put(SearchOperator.ILIKE, Filter.OP_ILIKE);
ops.put(SearchOperator.IN, Filter.OP_IN);

ops_rest_trg = Collections.unmodifiableMap(ops);
}
Expand Down Expand Up @@ -221,11 +224,9 @@ public void visit(FieldFilter filter) throws InternalErrorServiceEx {

/**
* This is a leaf filter.
*
* @throws InternalErrorServiceEx
*/
@Override
public void visit(CategoryFilter filter) throws InternalErrorServiceEx {
public void visit(CategoryFilter filter) {
CategoryFilter.checkOperator(filter.getOperator());

Integer op = ops_rest_trg.get(filter.getOperator());
Expand All @@ -242,6 +243,38 @@ public void visit(CategoryFilter filter) throws InternalErrorServiceEx {
trgFilter = f;
}

/**
* This is a leaf filter.
*/
@Override
public void visit(GroupFilter filter) {
GroupFilter.checkOperator(filter.getOperator());

Integer op = ops_rest_trg.get(filter.getOperator());

if (op == null) {
throw new IllegalStateException("Unknown op " + filter.getOperator());
}

Filter f = new Filter();
f.setOperator(op);
f.setProperty("security.group.groupName");

List<String> names = filter.getNames();

if (SearchOperator.IN != filter.getOperator() && names.size() != 1) {
throw new IllegalStateException("Erroneous search op " + filter.getOperator());
}

if (SearchOperator.IN == filter.getOperator()) {
f.setValue(names);
} else {
f.setValue(names.get(0));
}

trgFilter = f;
}

/*
* (non-Javadoc) @see it.geosolutions.geostore.services.dto.search.FilterVisitor#visit(it.geosolutions.geostore.services.dto.search.NotFilter)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

package it.geosolutions.geostore.services.rest.impl;

import static org.junit.Assert.*;

import com.googlecode.genericdao.search.Search;
import it.geosolutions.geostore.core.model.Category;
import it.geosolutions.geostore.core.model.Resource;
Expand All @@ -29,25 +27,35 @@
import it.geosolutions.geostore.services.dto.search.AndFilter;
import it.geosolutions.geostore.services.dto.search.BaseField;
import it.geosolutions.geostore.services.dto.search.FieldFilter;
import it.geosolutions.geostore.services.dto.search.GroupFilter;
import it.geosolutions.geostore.services.dto.search.SearchOperator;
import it.geosolutions.geostore.services.model.ExtResourceList;
import it.geosolutions.geostore.services.rest.model.SecurityRuleList;
import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import org.junit.Before;
import org.junit.Test;

import javax.ws.rs.core.SecurityContext;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.ws.rs.core.SecurityContext;
import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import org.junit.Before;
import org.junit.Test;

/** @author ETj (etj at geo-solutions.it) */
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

/**
* @author ETj (etj at geo-solutions.it)
*/
public class RESTExtJsServiceImplTest extends ServiceTestBase {

private final RESTExtJsServiceImpl restExtJsService;
Expand Down Expand Up @@ -395,7 +403,6 @@ public void testExtResourcesList_sorted() throws Exception {
assertEquals(3, resources.size());
List<String> resourcesDescriptions = resources.stream().map(Resource::getName).collect(Collectors.toList());
assertEquals(List.of(RES_ATTRIBUTE_A, RES_ATTRIBUTE_B, RES_ATTRIBUTE_C), resourcesDescriptions);

}

{
Expand Down Expand Up @@ -440,7 +447,6 @@ public void testExtResourcesList_creatorFiltered() throws Exception {
assertEquals(1, resources.size());
Resource resource = resources.get(0);
assertEquals(CREATOR_B, resource.getCreator());

}

{
Expand Down Expand Up @@ -484,7 +490,6 @@ public void testExtResourcesList_editorFiltered() throws Exception {
assertEquals(1, resources.size());
Resource resource = resources.get(0);
assertEquals(EDITOR_A, resource.getEditor());

}

{
Expand All @@ -497,6 +502,85 @@ public void testExtResourcesList_editorFiltered() throws Exception {
}
}

@Test
public void testExtResourcesList_groupFiltered() throws Exception {
final String CAT0_NAME = "CAT000";
final String RESOURCE_A_NAME = "resourceA";
final String RESOURCE_B_NAME = "resourceB";
final String GROUP_A_NAME = "groupA";
final String GROUP_B_NAME = "groupB";

long user0Id = restCreateUser("u0", Role.USER, null, "p0");
SecurityContext sc = new SimpleSecurityContext(user0Id);

createCategory(CAT0_NAME);

long resourceAId = restCreateResource(RESOURCE_A_NAME, "description_A", CAT0_NAME, user0Id, true);
long resourceBId = restCreateResource(RESOURCE_B_NAME, "description_B", CAT0_NAME, user0Id, true);

SecurityRule securityRuleGroupA = new SecurityRule();
securityRuleGroupA.setGroup(userGroupService.get(createGroup(GROUP_A_NAME)));
securityRuleGroupA.setCanWrite(true);

List<SecurityRule> securityRulesResourceA = resourceService.getSecurityRules(resourceAId);
securityRulesResourceA.add(securityRuleGroupA);
restResourceService.updateSecurityRules(sc, resourceAId, new SecurityRuleList(securityRulesResourceA));

SecurityRule securityRuleGroupB = new SecurityRule();
securityRuleGroupB.setGroup(userGroupService.get(createGroup(GROUP_B_NAME)));
securityRuleGroupB.setCanRead(true);

List<SecurityRule> securityRulesResourceB = resourceService.getSecurityRules(resourceBId);
securityRulesResourceB.add(securityRuleGroupB);
restResourceService.updateSecurityRules(sc, resourceBId, new SecurityRuleList(securityRulesResourceB));

{
/* search for name equality of a single group */
GroupFilter groupFilter = new GroupFilter(Collections.singletonList("groupA"), SearchOperator.EQUAL_TO);

ExtResourceList response = restExtJsService.getExtResourcesList(sc, 0, 1000, "", "", false, false, groupFilter);

List<Resource> resources = response.getList();
assertEquals(1, resources.size());
Resource resource = resources.get(0);
assertEquals(RESOURCE_A_NAME, resource.getName());
}

{
/* search for name similarity (ignoring case) of multiple groups */
GroupFilter groupFilter = new GroupFilter(Collections.singletonList("GROUP_"), SearchOperator.ILIKE);

ExtResourceList response = restExtJsService.getExtResourcesList(sc, 0, 1000, "", "", false, false, groupFilter);

List<Resource> resources = response.getList();
assertEquals(2, resources.size());
}

{
/* search for name equality of multiple groups */
GroupFilter groupFilter = new GroupFilter(List.of("groupA", "groupB", "groupC"), SearchOperator.IN);

ExtResourceList response = restExtJsService.getExtResourcesList(sc, 0, 1000, "", "", false, false, groupFilter);

List<Resource> resources = response.getList();
assertEquals(2, resources.size());
}

{
/* erroneous search for similarity of multiple groups */
GroupFilter groupFilter = new GroupFilter(List.of("a", "b"), SearchOperator.LIKE);

assertThrows(IllegalStateException.class, () -> restExtJsService.getExtResourcesList(sc, 0, 1000, "", "", false, false, groupFilter));
}

{
/* erroneous search for equality in empty group list */
GroupFilter groupFilter = new GroupFilter(Collections.emptyList(), SearchOperator.EQUAL_TO);

assertThrows(IllegalStateException.class, () -> restExtJsService.getExtResourcesList(sc, 0, 1000, "", "", false, false, groupFilter));
}
}

private JSONResult parse(String jsonString) {
JSONResult ret = new JSONResult();

Expand Down

0 comments on commit 7b99b60

Please sign in to comment.