diff --git a/src/gui/web/pom.xml b/src/gui/web/pom.xml index 7915df72..d9d65655 100644 --- a/src/gui/web/pom.xml +++ b/src/gui/web/pom.xml @@ -276,8 +276,8 @@ 3.1 utf8 - 1.5 - 1.5 + 1.8 + 1.8 diff --git a/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/AdminRuleDAOImpl.java b/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/AdminRuleDAOImpl.java index 4d2589b2..657bdaa4 100644 --- a/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/AdminRuleDAOImpl.java +++ b/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/AdminRuleDAOImpl.java @@ -20,6 +20,7 @@ import org.apache.log4j.LogManager; import org.apache.log4j.Logger; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** @@ -66,6 +67,7 @@ public int shift(long priorityStart, long offset) { } @Override + @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager") public long persist(AdminRule entity, InsertPosition position) { return super.persist(AdminRule.class, entity, position); diff --git a/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/RuleDAOImpl.java b/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/RuleDAOImpl.java index a36aac97..f26ab7f0 100644 --- a/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/RuleDAOImpl.java +++ b/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/RuleDAOImpl.java @@ -21,6 +21,7 @@ import org.apache.log4j.Logger; import org.geoserver.geofence.core.dao.DuplicateKeyException; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** diff --git a/src/services/core/services-api/pom.xml b/src/services/core/services-api/pom.xml index 5f169682..108ced3b 100644 --- a/src/services/core/services-api/pom.xml +++ b/src/services/core/services-api/pom.xml @@ -25,6 +25,10 @@ + + commons-lang + commons-lang + org.geoserver.geofence @@ -70,7 +74,10 @@ junit test - + + org.javatuples + javatuples + diff --git a/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/AdminRuleAdminService.java b/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/AdminRuleAdminService.java index 0b6e45af..2e391498 100644 --- a/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/AdminRuleAdminService.java +++ b/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/AdminRuleAdminService.java @@ -11,7 +11,10 @@ import org.geoserver.geofence.services.dto.ShortAdminRule; import org.geoserver.geofence.services.exception.BadRequestServiceEx; import org.geoserver.geofence.services.exception.NotFoundServiceEx; +import org.javatuples.Pair; +import org.javatuples.Tuple; +import java.util.ArrayList; import java.util.List; @@ -28,6 +31,20 @@ public interface AdminRuleAdminService long insert(AdminRule rule); + /** + * Inserts a list of admin rules + * + * @param rules list of pair of admin rules to be inserted along with the position. + */ + default List insert(List> rules) { + List results=new ArrayList<>(rules.size()); + for (Pair rule: rules) { + long id=insert(rule.getValue0(),rule.getValue1()); + results.add(id); + } + return results; + } + long insert(AdminRule rule, InsertPosition position); long update(AdminRule rule) throws NotFoundServiceEx; @@ -128,7 +145,7 @@ public interface AdminRuleAdminService * @throws BadRequestServiceEx if a wildcard type is used in filter */ ShortAdminRule getRule(RuleFilter filter) throws BadRequestServiceEx; - + /** * Return the Rules according to the filter. * Rules will be enriched with all their joined data, so this method may be heavy to execute. diff --git a/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/RuleAdminService.java b/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/RuleAdminService.java index 97bd8825..a85ae77c 100644 --- a/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/RuleAdminService.java +++ b/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/RuleAdminService.java @@ -5,6 +5,9 @@ package org.geoserver.geofence.services; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import org.geoserver.geofence.core.model.LayerDetails; import org.geoserver.geofence.core.model.Rule; import org.geoserver.geofence.core.model.RuleLimits; @@ -13,7 +16,8 @@ import org.geoserver.geofence.services.dto.ShortRule; import org.geoserver.geofence.services.exception.BadRequestServiceEx; import org.geoserver.geofence.services.exception.NotFoundServiceEx; - +import org.javatuples.Quartet; +import org.javatuples.Triplet; import java.util.List; import java.util.Set; @@ -33,6 +37,23 @@ public interface RuleAdminService long insert(Rule rule, InsertPosition position); + /** + * @param rules to be inserted + * @return map of inserted rules along with their ids. + */ + default List insert(List> rules) { + List ids = new ArrayList<>(); + for (Quartet rule: rules) { + long id = insert(rule.getValue0(),rule.getValue3()); + RuleLimits limits=rule.getValue1(); + if (limits!=null) setLimits(id,limits); + LayerDetails details=rule.getValue2(); + if (details!=null) setDetails(id,details); + ids.add(id); + } + return ids; + } + long update(Rule rule) throws NotFoundServiceEx; /** @@ -134,7 +155,7 @@ public interface RuleAdminService * @throws BadRequestServiceEx if a wildcard type is used in filter */ ShortRule getRule(RuleFilter filter) throws BadRequestServiceEx; - + /** * Return the Rules according to the filter. * Rules will be enriched with all their joined data, so this method may be heavy to execute. diff --git a/src/services/core/services-impl/pom.xml b/src/services/core/services-impl/pom.xml index c5244f83..bb656ce5 100644 --- a/src/services/core/services-impl/pom.xml +++ b/src/services/core/services-impl/pom.xml @@ -193,6 +193,11 @@ test + + org.javatuples + javatuples + + diff --git a/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/AdminRuleAdminServiceImpl.java b/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/AdminRuleAdminServiceImpl.java index 10f81f78..d2fa40cd 100644 --- a/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/AdminRuleAdminServiceImpl.java +++ b/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/AdminRuleAdminServiceImpl.java @@ -26,6 +26,10 @@ import org.apache.log4j.LogManager; import org.apache.log4j.Logger; +import org.javatuples.Pair; +import org.javatuples.Tuple; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; /** * @@ -47,6 +51,13 @@ public long insert(AdminRule rule) { return rule.getId(); } + + @Override + @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager") + public List insert(List> rules) { + return AdminRuleAdminService.super.insert(rules); + } + @Override public long insert(AdminRule rule, InsertPosition position) { ruleDAO.persist(rule, position); diff --git a/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/RuleAdminServiceImpl.java b/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/RuleAdminServiceImpl.java index 7b5e98b0..d629902e 100644 --- a/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/RuleAdminServiceImpl.java +++ b/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/RuleAdminServiceImpl.java @@ -7,6 +7,10 @@ import com.googlecode.genericdao.search.Filter; import com.googlecode.genericdao.search.Search; +import java.util.HashMap; +import java.util.Map; + +import org.geoserver.geofence.core.dao.DuplicateKeyException; import org.geoserver.geofence.core.dao.LayerDetailsDAO; import org.geoserver.geofence.core.dao.RuleDAO; import org.geoserver.geofence.core.dao.RuleLimitsDAO; @@ -29,6 +33,10 @@ import org.geoserver.geofence.services.exception.BadRequestServiceEx; import org.geoserver.geofence.services.exception.NotFoundServiceEx; +import org.javatuples.Quartet; +import org.javatuples.Triplet; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import static org.geoserver.geofence.services.util.FilterUtils.addCriteria; import static org.geoserver.geofence.services.util.FilterUtils.addFixedCriteria; @@ -64,6 +72,16 @@ public long insert(Rule rule) { return rule.getId(); } + /** + * @param rules to be inserted + * @return map of inserted rules along with their ids. + */ + @Override + @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager") + public List insert(List> rules) { + return RuleAdminService.super.insert(rules); + } + @Override public long insert(Rule rule, InsertPosition position) { sanitizeFields(rule); diff --git a/src/services/modules/rest/api/pom.xml b/src/services/modules/rest/api/pom.xml index ee2b9a29..4c23f86f 100644 --- a/src/services/modules/rest/api/pom.xml +++ b/src/services/modules/rest/api/pom.xml @@ -75,8 +75,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.8 + 1.8 diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTAdminRuleService.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTAdminRuleService.java index 13fcad54..71afca46 100644 --- a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTAdminRuleService.java +++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTAdminRuleService.java @@ -5,6 +5,7 @@ package org.geoserver.geofence.services.rest; +import java.util.List; import org.geoserver.geofence.services.rest.exception.BadRequestRestEx; import org.geoserver.geofence.services.rest.exception.InternalErrorRestEx; import org.geoserver.geofence.services.rest.exception.NotFoundRestEx; @@ -23,6 +24,7 @@ import org.apache.cxf.jaxrs.ext.multipart.Multipart; import org.geoserver.geofence.services.rest.model.RESTInputAdminRule; +import org.geoserver.geofence.services.rest.model.RESTInputAdminRuleList; import org.geoserver.geofence.services.rest.model.RESTOutputAdminRule; import org.geoserver.geofence.services.rest.model.RESTOutputAdminRuleList; @@ -40,6 +42,11 @@ public interface RESTAdminRuleService @Produces(MediaType.APPLICATION_XML) Response insert(@Multipart("rule") RESTInputAdminRule rule) throws BadRequestRestEx, NotFoundRestEx; + @POST + @Path("/many") + @Produces(MediaType.APPLICATION_XML) + Response insertMany(@Multipart("AdminRuleList") RESTInputAdminRuleList rules) throws BadRequestRestEx, NotFoundRestEx; + @GET @Path("/id/{id}") @Produces(MediaType.APPLICATION_XML) diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTRuleService.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTRuleService.java index 2b2a1b89..01fd4318 100644 --- a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTRuleService.java +++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTRuleService.java @@ -5,10 +5,12 @@ package org.geoserver.geofence.services.rest; +import java.util.List; import org.geoserver.geofence.services.rest.exception.BadRequestRestEx; import org.geoserver.geofence.services.rest.exception.InternalErrorRestEx; import org.geoserver.geofence.services.rest.exception.NotFoundRestEx; import org.geoserver.geofence.services.rest.model.RESTInputRule; +import org.geoserver.geofence.services.rest.model.RESTInputRuleList; import org.geoserver.geofence.services.rest.model.RESTOutputRule; import org.geoserver.geofence.services.rest.model.RESTOutputRuleList; @@ -40,6 +42,16 @@ public interface RESTRuleService @Produces(MediaType.TEXT_PLAIN) Response insert(@Multipart("rule") RESTInputRule rule) throws BadRequestRestEx, NotFoundRestEx; + @POST + @Path("/many") + @Produces(MediaType.TEXT_PLAIN) + default Response insertMany(@Multipart("RuleList") RESTInputRuleList rules) throws BadRequestRestEx, NotFoundRestEx { + for (RESTInputRule r: rules){ + insert(r); + } + return Response.status(Response.Status.CREATED).build(); + } + @GET @Path("/id/{id}") @Produces(MediaType.APPLICATION_XML) diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputAdminRuleList.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputAdminRuleList.java new file mode 100644 index 00000000..5e651cfe --- /dev/null +++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputAdminRuleList.java @@ -0,0 +1,37 @@ +/* (c) 2022 Open Source Geospatial Foundation - all rights reserved + * This code is licensed under the GPL 2.0 license, available at the root + * application directory. + */ +package org.geoserver.geofence.services.rest.model; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Iterator; +import java.util.List; + +@XmlRootElement(name = "AdminRuleList") +public class RESTInputAdminRuleList implements Iterable { + + private List list; + + + + @XmlElement(name = "adminrule") + public List getList() { + return list; + } + + public void setList(List userList) { + this.list = userList; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + list.size() + " users]"; + } + + @Override + public Iterator iterator() { + return list.iterator(); + } +} diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRule.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRule.java index f30c5319..fc068207 100644 --- a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRule.java +++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRule.java @@ -18,7 +18,7 @@ * @author Etj (etj at geo-solutions.it) */ @XmlRootElement(name = "rule") -@XmlType(name="Rule", propOrder={"position","grant","username","rolename","instance","ipaddress","service","request","workspace","layer","constraints"}) +@XmlType(name="Rule", propOrder={"position","grant","username","rolename","instance","ipaddress","service","request","workspace","layer","limits","constraints"}) public class RESTInputRule extends AbstractRESTPayload { private RESTRulePosition position; @@ -38,6 +38,8 @@ public class RESTInputRule extends AbstractRESTPayload { private GrantType grant; + private RESTRuleLimits limits; + private RESTLayerConstraints constraints; public RESTInputRule() { @@ -118,6 +120,13 @@ public void setWorkspace(String workspace) { } + public RESTRuleLimits getLimits() { + return limits; + } + + public void setLimits(RESTRuleLimits limits) { + this.limits = limits; + } public RESTLayerConstraints getConstraints() { return constraints; diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRuleList.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRuleList.java new file mode 100644 index 00000000..5b6178ac --- /dev/null +++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRuleList.java @@ -0,0 +1,43 @@ +/* (c) 2022 Open Source Geospatial Foundation - all rights reserved + * This code is licensed under the GPL 2.0 license, available at the root + * application directory. + */ + +package org.geoserver.geofence.services.rest.model; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * + * @author ETj (etj at geo-solutions.it) + */ +@XmlRootElement(name = "RuleList") +public class RESTInputRuleList implements Iterable{ + + private List list; + + + + @XmlElement(name = "rule") + public List getList() { + return list; + } + + public void setList(List userList) { + this.list = userList; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + list.size() + " users]"; + } + + @Override + public Iterator iterator() { + return list.iterator(); + } +} diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTOutputRule.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTOutputRule.java index f4ef7b24..323b6272 100644 --- a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTOutputRule.java +++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTOutputRule.java @@ -20,7 +20,7 @@ * @author Etj (etj at geo-solutions.it) */ @XmlRootElement(name = "Rule") -@XmlType(propOrder={"id", "priority","grant","username","rolename","instance","ipaddress","service","request","workspace","layer","constraints"}) +@XmlType(propOrder={"id", "priority","grant","username","rolename","instance","ipaddress","service","request","workspace","layer","limits","constraints"}) public class RESTOutputRule implements Serializable { private Long id; @@ -43,6 +43,8 @@ public class RESTOutputRule implements Serializable { private RESTLayerConstraints constraints; + private RESTRuleLimits limits; + public RESTOutputRule() { } @@ -126,10 +128,18 @@ public RESTLayerConstraints getConstraints() { return constraints; } + public RESTRuleLimits getLimits() { + return limits; + } + public void setConstraints(RESTLayerConstraints constraints) { this.constraints = constraints; } + public void setLimits(RESTRuleLimits limits) { + this.limits = limits; + } + public Long getPriority() { return priority; } diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTRuleLimits.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTRuleLimits.java new file mode 100644 index 00000000..1c6756cf --- /dev/null +++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTRuleLimits.java @@ -0,0 +1,53 @@ +/* (c) 2022 Open Source Geospatial Foundation - all rights reserved + * This code is licensed under the GPL 2.0 license, available at the root + * application directory. + */ +package org.geoserver.geofence.services.rest.model; + +import org.geoserver.geofence.core.model.enums.CatalogMode; +import org.geoserver.geofence.core.model.enums.SpatialFilterType; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +@XmlRootElement(name = "Limits") +@XmlType(propOrder={"restrictedAreaWkt","spatialFilterType","catalogMode"}) +public class RESTRuleLimits { + + private String restrictedAreaWkt; + private SpatialFilterType spatialFilterType; + private CatalogMode catalogMode; + + public String getRestrictedAreaWkt() { + return restrictedAreaWkt; + } + + public void setRestrictedAreaWkt(String restrictedAreaWkt) { + this.restrictedAreaWkt = restrictedAreaWkt; + } + + public SpatialFilterType getSpatialFilterType() { + return spatialFilterType; + } + + public void setSpatialFilterType(SpatialFilterType spatialFilterType) { + this.spatialFilterType = spatialFilterType; + } + + public CatalogMode getCatalogMode() { + return catalogMode; + } + + public void setCatalogMode(CatalogMode catalogMode) { + this.catalogMode = catalogMode; + } + + @Override + public String toString() { + return "RESTRuleLimits{" + + "restrictedAreaWkt='" + restrictedAreaWkt + '\'' + + ", spatialFilterType=" + spatialFilterType + + ", catalogMode=" + catalogMode + + '}'; + } +} diff --git a/src/services/modules/rest/impl/pom.xml b/src/services/modules/rest/impl/pom.xml index 286ea511..74e4aa92 100644 --- a/src/services/modules/rest/impl/pom.xml +++ b/src/services/modules/rest/impl/pom.xml @@ -153,8 +153,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.8 + 1.8 diff --git a/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImpl.java b/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImpl.java index 79e5c50a..3b11280d 100644 --- a/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImpl.java +++ b/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImpl.java @@ -5,8 +5,13 @@ package org.geoserver.geofence.services.rest.impl; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + import org.geoserver.geofence.core.model.AdminRule; import org.geoserver.geofence.core.model.enums.InsertPosition; @@ -20,6 +25,7 @@ import org.geoserver.geofence.services.rest.exception.GeoFenceRestEx; import org.geoserver.geofence.services.rest.exception.InternalErrorRestEx; import org.geoserver.geofence.services.rest.exception.NotFoundRestEx; +import org.geoserver.geofence.services.rest.model.RESTInputAdminRuleList; import org.geoserver.geofence.services.rest.model.util.IdName; import org.geoserver.geofence.services.rest.model.RESTInputAdminRule; import org.geoserver.geofence.services.rest.model.RESTOutputAdminRule; @@ -33,6 +39,7 @@ import org.apache.log4j.LogManager; import org.apache.log4j.Logger; +import org.javatuples.Pair; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -61,7 +68,6 @@ public RESTOutputAdminRule get(Long id) throws BadRequestRestEx, NotFoundRestEx, } @Override - @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager") public Response insert(RESTInputAdminRule inputAdminRule) throws NotFoundRestEx, BadRequestRestEx, InternalErrorRestEx { if (inputAdminRule.getPosition() == null || inputAdminRule.getPosition().getPosition() == null) { @@ -74,14 +80,10 @@ public Response insert(RESTInputAdminRule inputAdminRule) throws NotFoundRestEx, AdminRule rule = fromInput(inputAdminRule); - InsertPosition position = - inputAdminRule.getPosition().getPosition() == RulePosition.fixedPriority ? InsertPosition.FIXED - : inputAdminRule.getPosition().getPosition() == RulePosition.offsetFromBottom ? InsertPosition.FROM_END - : inputAdminRule.getPosition().getPosition() == RulePosition.offsetFromTop ? InsertPosition.FROM_START : null; // ok: insert it try { - Long id = adminRuleAdminService.insert(rule, position); + Long id = adminRuleAdminService.insert(rule, insertPosition(inputAdminRule)); return Response.status(Status.CREATED).tag(id.toString()).entity(id).build(); } catch (BadRequestServiceEx ex) { @@ -93,6 +95,40 @@ public Response insert(RESTInputAdminRule inputAdminRule) throws NotFoundRestEx, } } + @Override + public Response insertMany(RESTInputAdminRuleList inputAdminRules) throws NotFoundRestEx, BadRequestRestEx, InternalErrorRestEx { + + List> rules=new ArrayList>(); + for (RESTInputAdminRule inputAdminRule : inputAdminRules) { + if (inputAdminRule.getPosition() == null || inputAdminRule.getPosition().getPosition() == null) { + throw new BadRequestRestEx("Bad position: " + inputAdminRule.getPosition()); + } + + if (inputAdminRule.getGrant() == null) { + throw new BadRequestRestEx("Missing grant type"); + } + rules.add(Pair.with(fromInput(inputAdminRule),insertPosition(inputAdminRule))); + } + try { + List ids=adminRuleAdminService.insert(rules); + String strIds=ids.stream().map(id->id.toString()).collect(Collectors.joining(",")); + return Response.status(Status.CREATED).tag(strIds).entity(strIds).build(); + } catch (BadRequestServiceEx ex) { + LOGGER.error(ex.getMessage()); + throw new BadRequestRestEx(ex.getMessage()); + } catch (Exception ex) { + LOGGER.error(ex.getMessage(), ex); + throw new InternalErrorRestEx(ex.getMessage()); + } + } + + private InsertPosition insertPosition(RESTInputAdminRule inputAdminRule){ + return + inputAdminRule.getPosition().getPosition() == RulePosition.fixedPriority ? InsertPosition.FIXED + : inputAdminRule.getPosition().getPosition() == RulePosition.offsetFromBottom ? InsertPosition.FROM_END + : inputAdminRule.getPosition().getPosition() == RulePosition.offsetFromTop ? InsertPosition.FROM_START : null; + } + @Override public void update(Long id, RESTInputAdminRule rule) throws BadRequestRestEx, NotFoundRestEx, InternalErrorRestEx { diff --git a/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImpl.java b/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImpl.java index ca5f237c..85321f79 100644 --- a/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImpl.java +++ b/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImpl.java @@ -5,8 +5,10 @@ package org.geoserver.geofence.services.rest.impl; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; @@ -14,6 +16,11 @@ import org.apache.commons.lang.StringUtils; +import org.geoserver.geofence.core.model.RuleLimits; +import org.geoserver.geofence.services.rest.model.RESTInputRuleList; +import org.geoserver.geofence.services.rest.model.RESTRuleLimits; +import org.javatuples.Quartet; +import org.javatuples.Triplet; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.MultiPolygon; import org.locationtech.jts.io.ParseException; @@ -55,6 +62,7 @@ import java.util.Arrays; import java.util.ArrayList; import java.util.Comparator; +import java.util.stream.Collectors; /** * @@ -88,7 +96,6 @@ public RESTOutputRule get(Long id) throws BadRequestRestEx, NotFoundRestEx, Inte } @Override - @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager") public Response insert(RESTInputRule inputRule) throws NotFoundRestEx, BadRequestRestEx, InternalErrorRestEx { if (inputRule.getPosition() == null || inputRule.getPosition().getPosition() == null) { @@ -115,6 +122,11 @@ public Response insert(RESTInputRule inputRule) throws NotFoundRestEx, BadReques ruleAdminService.setDetails(id, details); } + RuleLimits limits=limitsFromInput(inputRule.getLimits()); + if (limits!=null) { + ruleAdminService.setLimits(id,limits); + } + return Response.status(Status.CREATED).tag(id.toString()).entity(id).build(); } catch (BadRequestServiceEx ex) { LOGGER.error(ex.getMessage()); @@ -125,6 +137,45 @@ public Response insert(RESTInputRule inputRule) throws NotFoundRestEx, BadReques } } + + @Override + public Response insertMany(RESTInputRuleList inputRules) throws NotFoundRestEx, BadRequestRestEx, InternalErrorRestEx { + + List> rules= + new ArrayList>(); + for (RESTInputRule inputRule : inputRules) { + if (inputRule.getPosition() == null || inputRule.getPosition().getPosition() == null) { + throw new BadRequestRestEx("Bad position: " + inputRule.getPosition()); + } + + if (inputRule.getGrant() == null) { + throw new BadRequestRestEx("Missing grant type"); + } + Rule rule = fromInput(inputRule); + InsertPosition insertPosition=insertPosition(inputRule); + RuleLimits limits=limitsFromInput(inputRule.getLimits()); + rules.add(Quartet.with(rule, limits, detailsFromInput(inputRule),insertPosition)); + } + try { + List ids = ruleAdminService.insert(rules); + String strIds=ids.stream().map(id->id.toString()).collect(Collectors.joining(",")); + return Response.status(Status.CREATED).tag(strIds).entity(strIds).build(); + } catch (BadRequestServiceEx ex) { + LOGGER.error(ex.getMessage()); + throw new BadRequestRestEx(ex.getMessage()); + } catch (Exception ex) { + LOGGER.error(ex.getMessage(), ex); + throw new InternalErrorRestEx(ex.getMessage()); + } + } + + private InsertPosition insertPosition(RESTInputRule inputRule){ + return + inputRule.getPosition().getPosition() == RulePosition.fixedPriority ? InsertPosition.FIXED + : inputRule.getPosition().getPosition() == RulePosition.offsetFromBottom ? InsertPosition.FROM_END + : inputRule.getPosition().getPosition() == RulePosition.offsetFromTop ? InsertPosition.FROM_START : null; + } + @Override public void update(Long id, RESTInputRule rule) throws BadRequestRestEx, NotFoundRestEx, InternalErrorRestEx { @@ -579,6 +630,25 @@ protected RESTOutputRule toOutput(Rule rule) { out.setConstraints(constraints); } + if (rule.getRuleLimits()!=null){ + RESTRuleLimits ruleLimits=new RESTRuleLimits(); + RuleLimits limits=rule.getRuleLimits(); + if (limits.getSpatialFilterType()!=null) + ruleLimits.setSpatialFilterType(limits.getSpatialFilterType()); + if (limits.getCatalogMode()!=null) + ruleLimits.setCatalogMode(limits.getCatalogMode()); + if (limits.getAllowedArea()!=null) { + MultiPolygon area = limits.getAllowedArea(); + if (area != null) { + String areaWKT = "SRID=" + area.getSRID() + ";" + area.toText(); + ruleLimits.setRestrictedAreaWkt(areaWKT); + } + if (limits.getSpatialFilterType()!=null) + ruleLimits.setSpatialFilterType(limits.getSpatialFilterType()); + } + out.setLimits(ruleLimits); + } + return out; } @@ -608,6 +678,28 @@ protected Rule fromInput(RESTInputRule in) { return rule; } + protected RuleLimits limitsFromInput(RESTRuleLimits in){ + RuleLimits limits=null; + if (in!=null && (in.getCatalogMode()!=null || in.getRestrictedAreaWkt()!=null)){ + limits=new RuleLimits(); + limits.setCatalogMode(in.getCatalogMode()); + limits.setSpatialFilterType(in.getSpatialFilterType()); + if (StringUtils.isNotBlank(in.getRestrictedAreaWkt())) { + if (in.getRestrictedAreaWkt() != null) { + Geometry g; + try { + g = toGeometryAllowedArea(in.getRestrictedAreaWkt()); + } catch (ParseException ex) { + throw new BadRequestRestEx("Error parsing WKT:" + ex.getMessage()); + } + limits.setAllowedArea((MultiPolygon) g); + } + } + } + return limits; + } + + protected LayerDetails detailsFromInput(RESTInputRule in) { RESTLayerConstraints constraints = in.getConstraints(); if (constraints != null) { diff --git a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImplTest.java b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImplTest.java new file mode 100644 index 00000000..5a88c6d8 --- /dev/null +++ b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImplTest.java @@ -0,0 +1,63 @@ +package org.geoserver.geofence.services.rest.impl; + +import org.geoserver.geofence.core.model.enums.AdminGrantType; +import org.geoserver.geofence.core.model.enums.GrantType; +import org.geoserver.geofence.services.rest.exception.BadRequestRestEx; +import org.geoserver.geofence.services.rest.model.RESTInputAdminRule; +import org.geoserver.geofence.services.rest.model.RESTInputAdminRuleList; +import org.geoserver.geofence.services.rest.model.RESTInputGroup; +import org.geoserver.geofence.services.rest.model.RESTInputRule; +import org.geoserver.geofence.services.rest.model.RESTInputUser; +import org.geoserver.geofence.services.rest.model.RESTOutputAdminRule; +import org.geoserver.geofence.services.rest.model.RESTOutputRule; +import org.geoserver.geofence.services.rest.model.RESTRulePosition; +import org.geoserver.geofence.services.rest.model.util.IdName; +import org.junit.Test; + +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +public class RESTAdminRuleServiceImplTest extends RESTBaseTest { + + @Test + public void testInsert() { + List inputAdminRules=new ArrayList<>(); + RESTInputAdminRule adminRule=new RESTInputAdminRule(); + adminRule.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0)); + adminRule.setGrant(AdminGrantType.ADMIN); + adminRule.setRolename("ROLE_TEST1"); + adminRule.setWorkspace("wsAdmin00"); + inputAdminRules.add(adminRule); + RESTInputAdminRule adminRule2=new RESTInputAdminRule(); + adminRule2.setGrant(AdminGrantType.USER); + adminRule2.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 1)); + adminRule2.setRolename("ROLE_TEST2"); + adminRule2.setWorkspace("wsAdmin01"); + RESTInputAdminRuleList list=new RESTInputAdminRuleList(); + list.setList(inputAdminRules); + Response res = restAdminRuleService.insertMany(list); + String ids = (String) res.getEntity(); + assertNotNull(ids); + List longList= Arrays.asList(ids.split(",")).stream().map(s->Long.valueOf(s)).collect(Collectors.toList()); + for(Long id: longList) { + RESTOutputAdminRule out = restAdminRuleService.get(id); + assertNotNull(out); + String ws=out.getWorkspace(); + if (ws.equals("wsAdmin00")){ + assertEquals("ROLE_TEST1",out.getRolename()); + assertEquals(AdminGrantType.ADMIN,out.getGrant()); + } else { + assertEquals("ROLE_TEST2",out.getRolename()); + assertEquals(AdminGrantType.USER,out.getGrant()); + } + } + } +} diff --git a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTBaseTest.java b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTBaseTest.java index 53bb3590..cec2584b 100644 --- a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTBaseTest.java +++ b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTBaseTest.java @@ -7,6 +7,7 @@ import org.geoserver.geofence.services.RuleAdminService; import org.geoserver.geofence.services.dto.ShortGroup; +import org.geoserver.geofence.services.rest.RESTAdminRuleService; import org.geoserver.geofence.services.rest.RESTRuleService; import org.geoserver.geofence.services.rest.RESTUserGroupService; import org.geoserver.geofence.services.rest.RESTUserService; @@ -39,6 +40,7 @@ public abstract class RESTBaseTest { protected static RESTUserService restUserService; protected static RESTUserGroupService restUserGroupService; protected static RESTRuleService restRuleService; + protected static RESTAdminRuleService restAdminRuleService; public RESTBaseTest() { @@ -59,6 +61,7 @@ public RESTBaseTest() { restUserService = (RESTUserService)ctx.getBean("restUserService"); restUserGroupService = (RESTUserGroupService)ctx.getBean("restUserGroupService"); restRuleService = (RESTRuleService)ctx.getBean("restRuleService"); + restAdminRuleService = (RESTAdminRuleService) ctx.getBean("restAdminRuleService"); } assertNotNull(restUserService); diff --git a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImplTest.java b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImplTest.java index a470b3f8..ce802b8d 100644 --- a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImplTest.java +++ b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImplTest.java @@ -5,8 +5,14 @@ package org.geoserver.geofence.services.rest.impl; +import java.util.List; + import org.geoserver.geofence.core.model.Rule; +import org.geoserver.geofence.core.model.enums.CatalogMode; +import org.geoserver.geofence.core.model.enums.LayerType; +import org.geoserver.geofence.core.model.enums.SpatialFilterType; import org.geoserver.geofence.services.RuleAdminService; +import org.geoserver.geofence.services.rest.model.RESTInputRuleList; import org.geoserver.geofence.services.rest.model.RESTInputUser; import org.geoserver.geofence.services.rest.model.RESTInputRule; import org.geoserver.geofence.services.rest.model.RESTOutputRule; @@ -16,10 +22,12 @@ import org.geoserver.geofence.core.model.enums.AccessType; import org.geoserver.geofence.core.model.enums.GrantType; import org.geoserver.geofence.services.rest.exception.BadRequestRestEx; +import org.geoserver.geofence.services.rest.model.RESTRuleLimits; import org.geoserver.geofence.services.rest.model.util.IdName; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.stream.Collectors; import javax.ws.rs.core.Response; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; @@ -332,5 +340,154 @@ public void testAllowedAreaSRID() { } + @Test + public void testInsertAll() { + RESTInputGroup group = new RESTInputGroup(); + group.setName("g1"); + restUserGroupService.insert(group); + + RESTInputUser user = new RESTInputUser(); + user.setName("user0"); + user.setEnabled(Boolean.TRUE); + user.setGroups(new ArrayList()); + user.getGroups().add(new IdName("g1")); + restUserService.insert(user); + + RESTInputRule rule0 = new RESTInputRule(); + rule0.setUsername("user0"); + rule0.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0)); + rule0.setGrant(GrantType.ALLOW); + RESTInputRule rule1 = new RESTInputRule(); + rule1.setUsername("user1"); + rule1.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0)); + rule1.setGrant(GrantType.ALLOW); + List rules = new ArrayList(); + rules.add(rule0); + rules.add(rule1); + RESTInputRuleList list= new RESTInputRuleList(); + list.setList(rules); + String ids = (String) restRuleService.insertMany(list).getEntity(); + assertNotNull(ids); + List longList=Arrays.asList(ids.split(",")).stream().map(s->Long.valueOf(s)).collect(Collectors.toList()); + for(Long id: longList) { + RESTOutputRule out = restRuleService.get(id); + assertNotNull(out); + } + } + + @Test + public void testLimits() { + + RESTInputRule rule = new RESTInputRule(); + rule.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.fixedPriority, 42)); + rule.setGrant(GrantType.ALLOW); + rule.setWorkspace("wLimits0"); + rule.setLayer("lLimits0"); + restRuleService.insert(rule); + rule = new RESTInputRule(); + rule.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0)); + rule.setGrant(GrantType.LIMIT); + rule.setWorkspace("wLimits0"); + rule.setLayer("lLimits0"); + + RESTRuleLimits limits = new RESTRuleLimits(); + String allowedArea = "MULTIPOLYGON (((4146.5 1301.4, 4147.5 1301.1, 4147.8 1301.4, 4146.5 1301.4)))"; + limits.setRestrictedAreaWkt(allowedArea); + limits.setCatalogMode(CatalogMode.HIDE); + limits.setSpatialFilterType(SpatialFilterType.CLIP); + rule.setLimits(limits); + + Long rid = (Long) restRuleService.insert(rule).getEntity(); + assertNotNull(rid); + RESTOutputRule out = restRuleService.get(rid); + assertNotNull(out); + limits = out.getLimits(); + assertEquals(CatalogMode.HIDE, limits.getCatalogMode()); + assertEquals(SpatialFilterType.CLIP, limits.getSpatialFilterType()); + assertEquals("SRID=4326;" + allowedArea, limits.getRestrictedAreaWkt()); + } + + @Test + public void testInsertAllWithLimits() { + + RESTInputRule rule0 = new RESTInputRule(); + rule0.setWorkspace("wsLimits01"); + rule0.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 30)); + rule0.setGrant(GrantType.ALLOW); + restRuleService.insert(rule0); + + RESTInputRule rule1 = new RESTInputRule(); + rule1.setWorkspace("wsLimits01"); + rule1.setUsername("userLimits01"); + rule1.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 30)); + rule1.setGrant(GrantType.LIMIT); + RESTRuleLimits limits=new RESTRuleLimits(); + limits.setCatalogMode(CatalogMode.HIDE); + rule1.setLimits(limits); + RESTInputRule rule2 = new RESTInputRule(); + rule2.setWorkspace("wsLimits01"); + rule2.setUsername("userLimits02"); + rule2.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0)); + rule2.setGrant(GrantType.LIMIT); + limits=new RESTRuleLimits(); + limits.setCatalogMode(CatalogMode.HIDE); + rule2.setLimits(limits); + List rules = new ArrayList(); + rules.add(rule1); + rules.add(rule2); + RESTInputRuleList list= new RESTInputRuleList(); + list.setList(rules); + String ids = (String) restRuleService.insertMany(list).getEntity(); + assertNotNull(ids); + List longList=Arrays.asList(ids.split(",")).stream().map(s->Long.valueOf(s)).collect(Collectors.toList()); + for(Long id: longList) { + RESTOutputRule out = restRuleService.get(id); + assertNotNull(out); + assertNotNull(out.getLimits()); + assertEquals(CatalogMode.HIDE, out.getLimits().getCatalogMode()); + } + } + + + @Test + public void testInsertAllWithConstraints() { + + RESTInputRule rule1 = new RESTInputRule(); + rule1.setWorkspace("wsConstraints00"); + rule1.setUsername("userConstraints00"); + rule1.setLayer("layerConstraints00"); + rule1.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 1)); + rule1.setGrant(GrantType.ALLOW); + RESTLayerConstraints constraints = new RESTLayerConstraints(); + constraints.setType(LayerType.VECTOR); + constraints.setAllowedStyles(new HashSet<>(Arrays.asList("s1","s2"))); + rule1.setConstraints(constraints); + RESTInputRule rule2 = new RESTInputRule(); + rule2.setWorkspace("wsConstraints01"); + rule2.setUsername("userConstraints01"); + rule2.setLayer("layerConstraints01"); + + rule2.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0)); + rule2.setGrant(GrantType.ALLOW); + constraints = new RESTLayerConstraints(); + constraints.setType(LayerType.VECTOR); + constraints.setAllowedStyles(new HashSet<>(Arrays.asList("s1","s2"))); + rule2.setConstraints(constraints); + List rules = new ArrayList(); + rules.add(rule1); + rules.add(rule2); + RESTInputRuleList list= new RESTInputRuleList(); + list.setList(rules); + String ids = (String) restRuleService.insertMany(list).getEntity(); + assertNotNull(ids); + List longList=Arrays.asList(ids.split(",")).stream().map(s->Long.valueOf(s)).collect(Collectors.toList()); + for(Long id: longList) { + RESTOutputRule out = restRuleService.get(id); + assertNotNull(out); + assertNotNull(out.getConstraints()); + assertEquals(2,out.getConstraints().getAllowedStyles().size()); + } + } + } diff --git a/src/services/pom.xml b/src/services/pom.xml index adb1c861..0dc3877b 100644 --- a/src/services/pom.xml +++ b/src/services/pom.xml @@ -797,6 +797,12 @@ gt-epsg-wkt ${gt-version} + + + org.javatuples + javatuples + 1.2 +