/* (c) 2014 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.
*/
/* (c) 2014 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.security.decorators;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.security.AccessLevel;
import org.geoserver.security.SecureCatalogImpl;
import org.geoserver.security.VectorAccessLimits;
import org.geoserver.security.WrapperPolicy;
import org.geotools.data.FeatureSource;
import org.geotools.data.Query;
import org.geotools.factory.Hints;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.FeatureType;
import org.opengis.filter.Filter;
import org.opengis.util.ProgressListener;
/**
* Wraps a {@link FeatureTypeInfo} so that it will return a secured
* FeatureSource
*
* @author Andrea Aime - TOPP
*/
public class SecuredFeatureTypeInfo extends DecoratingFeatureTypeInfo {
WrapperPolicy policy;
public SecuredFeatureTypeInfo(FeatureTypeInfo info, WrapperPolicy policy) {
super(info);
this.policy = policy;
}
@Override
public FeatureType getFeatureType() throws IOException {
FeatureType ft = super.getFeatureType();
if(policy.getLimits() == null) {
return ft;
} else if(policy.getLimits() instanceof VectorAccessLimits) {
VectorAccessLimits val = (VectorAccessLimits) policy.getLimits();
// get what we can actually read (and it makes it easier to deal with property names)
Query query = val.getReadQuery();
// do we have any attribute filtering?
if(query.getPropertyNames() == Query.ALL_NAMES) {
return ft;
}
if(ft instanceof SimpleFeatureType) {
SimpleFeatureType sft = (SimpleFeatureType) ft;
Set<String> properties = new HashSet<String>(Arrays.asList(query.getPropertyNames()));
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
tb.init(sft);
for (AttributeDescriptor at : sft.getAttributeDescriptors()) {
String attName = at.getLocalName();
if(!properties.contains(attName)) {
tb.remove(attName);
}
}
return tb.buildFeatureType();
} else {
// if it's a complex type, we don't have a type builder on all branches, so
// we'll run an empty query instead
query.setFilter(Filter.EXCLUDE);
FeatureSource fs = getFeatureSource(null, null);
FeatureCollection fc = fs.getFeatures(query);
return fc.getSchema();
}
} else {
throw new IllegalArgumentException("SecureFeatureSources has been fed " +
"with unexpected AccessLimits class " + policy.getLimits().getClass());
}
}
//--------------------------------------------------------------------------
// WRAPPED METHODS TO ENFORCE SECURITY POLICY
//--------------------------------------------------------------------------
public FeatureSource getFeatureSource(ProgressListener listener, Hints hints)
throws IOException {
final FeatureSource fs = delegate.getFeatureSource(listener, hints);
if(policy.level == AccessLevel.METADATA) {
throw SecureCatalogImpl.unauthorizedAccess(this.getName());
} else {
return (FeatureSource) SecuredObjects.secure(fs, policy);
}
}
public DataStoreInfo getStore() {
return (DataStoreInfo) SecuredObjects.secure(delegate.getStore(), policy);
}
}