/** * Notifies the caller the requested operation is not supported, using a plain {@link * UnsupportedOperationException} in case we have to conceal the fact the data is actually * writable, using an Spring security exception otherwise to force an authentication from the user */ protected RuntimeException unsupportedOperation() { String typeName = getSchema().getName().getLocalPart(); if (policy.response == Response.CHALLENGE) { return SecureCatalogImpl.unauthorizedAccess(typeName); } else { return new UnsupportedOperationException(typeName + " is read only"); } }
@Override public DataAccess<? extends FeatureType, ? extends Feature> getDataStore( ProgressListener listener) throws IOException { final DataAccess<? extends FeatureType, ? extends Feature> ds = super.getDataStore(listener); if (ds == null) return null; else if (policy.level == AccessLevel.METADATA) throw SecureCatalogImpl.unauthorizedAccess(this.getName()); else return (DataAccess<? extends FeatureType, ? extends Feature>) SecuredObjects.secure(ds, policy); }
public List<FeatureId> addFeatures(FeatureCollection<T, F> collection) throws IOException { Query writeQuery = getWriteQuery(policy); if (writeQuery.getFilter() == Filter.EXCLUDE || writeQuery.getPropertyNames() == Query.NO_NAMES) { throw unsupportedOperation(); } else if (writeQuery == Query.ALL) { // make sure it behaves like native when no write limits are imposed (even if this // case makes no sense, we should not wrap at all) return storeDelegate.addFeatures(collection); } else { // check if any of the inserted features does not pass the write filters if (writeQuery.getFilter() != null && writeQuery.getFilter() != Filter.INCLUDE) { final FilteringFeatureCollection<T, F> filtered = new FilteringFeatureCollection<T, F>(collection, writeQuery.getFilter()); if (filtered.size() < collection.size()) { String typeName = getSchema().getName().getLocalPart(); if (policy.response == Response.CHALLENGE) { throw SecureCatalogImpl.unauthorizedAccess(typeName); } else { throw new UnsupportedOperationException( "At least one of the features inserted does not satisfy your write restrictions"); } } } // deal with writable properties if (writeQuery.getPropertyNames() == Query.ALL_NAMES) { return storeDelegate.addFeatures(collection); } else { if (collection.getSchema() instanceof SimpleFeatureType && storeDelegate instanceof SimpleFeatureStore) { // see if the user specified the value of any attribute she cannot write final SimpleFeatureCollection simpleCollection = (SimpleFeatureCollection) collection; // wrap it with a collection that will check if any non writable attribute has // been given a value List<String> writableAttributes = Arrays.asList(writeQuery.getPropertyNames()); CheckAttributesFeatureCollection checker = new CheckAttributesFeatureCollection( simpleCollection, writableAttributes, policy.getResponse()); return ((SimpleFeatureStore) storeDelegate).addFeatures(checker); } else { // TODO: add retyping to shave off attributes we cannot write LOGGER.log( Level.SEVERE, "Unfinished implementation, we need to shave off " + "the attributes one cannot write off complex features. " + "However at this time there is no writable complex feature!"); return storeDelegate.addFeatures(collection); } } } }
@Test public void testAccessToLayer() throws Exception { CatalogFilterAccessManager mgr = setupAccessManager(); SecureCatalogImpl sc = new SecureCatalogImpl(catalog, mgr) {}; assertNotNull(sc.getLayerByName("topp:states")); WorkspaceInfo ws = sc.getWorkspaceByName("nurc"); LocalWorkspace.set(ws); assertNull(sc.getWorkspaceByName("topp")); assertNull(sc.getResourceByName("topp:states", ResourceInfo.class)); assertNull(sc.getLayerByName("topp:states")); }
@Test public void testAccessToLayerGroup() throws Exception { CatalogFilterAccessManager mgr = setupAccessManager(); SecureCatalogImpl sc = new SecureCatalogImpl(catalog, mgr) {}; assertEquals(3, sc.getLayerGroups().size()); WorkspaceInfo ws = sc.getWorkspaceByName("topp"); LocalWorkspace.set(ws); assertEquals(3, sc.getLayerGroups().size()); LocalWorkspace.remove(); ws = sc.getWorkspaceByName("nurc"); LocalWorkspace.set(ws); assertEquals(1, sc.getLayerGroups().size()); assertEquals("layerGroup", sc.getLayerGroups().get(0).getName()); LocalWorkspace.remove(); }
public void modifyFeatures(Name[] names, Object[] values, Filter filter) throws IOException { // are we limiting anything? Query writeQuery = getWriteQuery(policy); if (writeQuery == Query.ALL) { storeDelegate.modifyFeatures(names, values, filter); } else if (writeQuery.getFilter() == Filter.EXCLUDE || writeQuery.getPropertyNames() == Query.NO_NAMES) { throw unsupportedOperation(); } // get the mixed filter final Query local = new Query(null, filter); Query mixed = mixQueries(local, writeQuery); if (writeQuery.getPropertyNames() == Query.ALL_NAMES) { // it was just a matter of filtering. storeDelegate.modifyFeatures(names, values, mixed.getFilter()); } else { // get the writable attribute set Set<String> queryNames = new HashSet<String>(Arrays.asList(writeQuery.getPropertyNames())); // check the update fields for (int i = 0; i < names.length; i++) { final String localName = names[i].getLocalPart(); if (queryNames.contains(localName)) { String typeName = getSchema().getName().getLocalPart(); if (policy.getResponse() == Response.CHALLENGE) { throw SecureCatalogImpl.unauthorizedAccess(typeName); } else { throw new UnsupportedOperationException( "Trying to write on the write protected attribute " + names[i]); } } } storeDelegate.modifyFeatures(names, values, mixed.getFilter()); } }