/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.security.CatalogMode;
import org.geoserver.security.TestResourceAccessManager;
import org.geoserver.security.VectorAccessLimits;
import org.geoserver.security.decorators.ReadOnlyDataAccess;
import org.geoserver.security.decorators.SecuredDataStoreInfo;
import org.geotools.data.DataAccess;
import org.geotools.data.complex.AppSchemaDataAccess;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.Hints;
import org.geotools.filter.AttributeExpressionImpl;
import org.geotools.filter.expression.FeaturePropertyAccessorFactory;
import org.geotools.util.NullProgressListener;
import org.junit.Assert;
import org.junit.Test;
import org.opengis.feature.Feature;
import org.opengis.feature.type.FeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.expression.PropertyName;
import org.w3c.dom.Document;
import org.xml.sax.helpers.NamespaceSupport;
/**
* WFS GetFeature to test secured feature with GeoServer.
*
* @author Victor Tey (CSIRO Earth Science and Resource Engineering)
*/
public class SecuredFeatureChainingTest extends AbstractAppSchemaTestSupport {
@Override
protected FeatureChainingMockData createTestData() {
return new FeatureChainingMockData();
}
@Override
protected void setUpSpring(List<String> springContextLocations) {
super.setUpSpring(springContextLocations);
springContextLocations.add("classpath:/test-data/ResourceAccessManagerContext.xml");
}
/**
* Enable the Spring Security auth filters
*/
@Override
protected List<javax.servlet.Filter> getFilters() {
return Collections.singletonList((javax.servlet.Filter) GeoServerExtensions
.bean("filterChainProxy"));
}
@Override
protected void onSetUp(SystemTestData testData) throws Exception {
super.onSetUp(testData);
addUser("cite_readfilter", "cite", null, Arrays.asList("ROLE_DUMMY"));
addUser("cite_readatts", "cite", null, Arrays.asList("ROLE_DUMMY"));
NamespaceSupport ns = new NamespaceSupport();
Map nsMap = ((FeatureChainingMockData)testData).getNamespaces();
for (Iterator it = nsMap.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Entry) it.next();
String prefix = (String) entry.getKey();
String namespace = (String) entry.getValue();
ns.declarePrefix(prefix, namespace);
}
Hints hints = new Hints();
hints.put(FeaturePropertyAccessorFactory.NAMESPACE_CONTEXT, ns);
FilterFactory ff = CommonFactoryFinder.getFilterFactory(hints);
// populate the access manager
TestResourceAccessManager tam = (TestResourceAccessManager) applicationContext
.getBean("testResourceAccessManager");
Catalog catalog = getCatalog();
FeatureTypeInfo gu = catalog.getFeatureTypeByName("gsml:GeologicUnit");
// limits for mr readfilter
Filter f = ff.equal(new AttributeExpressionImpl("gsml:purpose", ns), ff.literal("instance"), false);
tam.putLimits("cite_readfilter", gu, new VectorAccessLimits(CatalogMode.HIDE, null, f,
null, null));
List<PropertyName> readAtts = Arrays.asList(ff.property("gsml:composition"),
ff.property("gsml:outcropCharacter"));
tam.putLimits("cite_readatts", gu, new VectorAccessLimits(CatalogMode.HIDE, readAtts, f,
null, null));
}
/**
* Test that denormalized data reports the correct number of features
*/
@Test
public void testDenormalisedFeaturesCount() {
setRequestAuth("cite_readatts", "cite");
Document doc = getAsDOM("wfs?request=GetFeature&version=1.1.0&typename=gsml:GeologicUnit" +
"&maxFeatures=3&resultType=hits");
LOGGER.info("WFS GetFeature&typename=gsml:GeologicUnit&maxFeatures=3 response:\n"
+ prettyString(doc));
assertXpathEvaluatesTo("3", "//wfs:FeatureCollection/@numberOfFeatures", doc);
}
/**
* Test that denormalized data reports the right output
*/
@Test
public void testSecureFeatureContent() {
setRequestAuth("cite_readatts", "cite");
Document doc = getAsDOM("wfs?request=GetFeature&version=1.1.0&typename=gsml:GeologicUnit&maxFeatures=3");
LOGGER.info("WFS GetFeature&typename=gsml:GeologicUnit&maxFeatures=3 response:\n"
+ prettyString(doc));
assertXpathCount(3, "//gsml:GeologicUnit", doc);
assertXpathCount(0, "//gsml:GeologicUnit[@gml:id='gu.25699']/gsml:exposureColor", doc);
assertXpathCount(0, "//gsml:GeologicUnit[@gml:id='gu.25678']/gsml:exposureColor", doc);
assertXpathCount(0, "//gsml:GeologicUnit[@gml:id='gu.25682']/gsml:exposureColor", doc);
assertXpathCount(1, "//gsml:GeologicUnit[@gml:id='gu.25699']/gsml:composition", doc);
assertXpathCount(2, "//gsml:GeologicUnit[@gml:id='gu.25678']/gsml:composition", doc);
assertXpathCount(1, "//gsml:GeologicUnit[@gml:id='gu.25682']/gsml:composition", doc);
}
/**
* Tests that {@link SecuredDataStoreInfo#getDataStore(org.opengis.util.ProgressListener)} correctly
* returns a {@link DataAccess} instance.
*
* @throws IOException
*/
@Test
public void testSecuredDataStoreInfo() throws IOException {
login("cite_readatts", "cite", "ROLE_DUMMY");
FeatureTypeInfo ftInfo = getCatalog().getFeatureTypeByName("gsml:GeologicUnit");
assertNotNull(ftInfo);
DataAccess<? extends FeatureType, ? extends Feature> dataAccess = ftInfo.getStore()
.getDataStore(new NullProgressListener());
assertNotNull(dataAccess);
assertTrue(dataAccess instanceof ReadOnlyDataAccess);
}
}