SecureSession.java
/***************************************************************************
Copyright 2013 Emily Estes
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
***************************************************************************/
package net.metanotion.contentstore;
import java.io.InputStream;
import java.util.ArrayList;
import net.metanotion.io.FileSource;
/** This class wraps ContentStore instance and implements a security model as determined by the
instance of {@link net.metanotion.contentstore.PermissionModel} provided to the constructor. This
class can be used to make your own implementation of the {@link net.metanotion.contentstore.ContentStore}
component by providing a version of {@link net.metanotion.contentstore.PermissionModel} that
implements the access control model required. */
public final class SecureSession implements ContentStore {
/** A proxy implementation of Entry that gates access to the underlying entry via a Permission model instance. */
private static final class SecureEntry implements Entry {
/** The Entry secured by this class. */
private final Entry e;
/** The permission model used to determine what is allowed. */
private final PermissionModel pm;
/** Create an Entry instance protected by a PermissionModel.
@param e Entry to protect.
@param pm PermissionModel to determine whether access is allowed.
*/
public SecureEntry(final Entry e, final PermissionModel pm) {
this.e = e;
this.pm = pm;
}
@Override public long oid() { return e.oid(); }
@Override public String getTitle() { return e.getTitle(); }
@Override public Iterable<Header> header(final int pageSize, final int offset) { return e.header(pageSize, offset); }
@Override public Iterable<Collection> elements(final int pageSize, final int offset) {
final ArrayList<Collection> list = new ArrayList<>();
for(Collection c: e.elements(pageSize, offset)) {
list.add(new SecureCollection(c, pm));
}
return list;
}
@Override public Collection getCollection() { return new SecureCollection(e.getCollection(), pm); }
@Override public String getContentType() { return e.getContentType(); }
@Override public String getFilename() { return e.getFilename(); }
@Override public boolean isFile() { return e.isFile(); }
@Override public InputStream readFile() { return e.readFile(); }
@Override public String readContent() { return e.readContent(); }
@Override public Collection append(final String title) {
pm.canCollectionCreate(title);
return pm.setOwner(new SecureCollection(e.append(title), pm));
}
@Override public Entry setTitle(final String title) {
pm.canEntryModify(e.oid());
return new SecureEntry(e.setTitle(title), pm);
}
@Override public void delete() {
pm.canEntryDelete(e.oid());
e.delete();
}
@Override public Entry update(final String entry, final String contentType) {
pm.canEntryModify(e.oid());
return new SecureEntry(e.update(entry, contentType), pm);
}
@Override public Entry update(final InputStream entry, final String fileName, final String contentType) {
pm.canEntryModify(e.oid());
return new SecureEntry(e.update(entry, fileName, contentType), pm);
}
@Override public Entry update(final FileSource entry, final String fileName, final String contentType) {
pm.canEntryModify(e.oid());
return new SecureEntry(e.update(entry, fileName, contentType), pm);
}
@Override public Entry move(final Collection collection) {
pm.canEntryCreate(collection.oid());
pm.canEntryModify(e.oid());
return new SecureEntry(e.move(collection), pm);
}
}
/** A proxy implementation of Collection that gates access to the underlying collection via a Permission model instance. */
private static final class SecureCollection implements Collection {
/** The Collection secured by this class. */
private final Collection c;
/** The permission model used to determine what is allowed. */
private final PermissionModel pm;
/** Create a Collection instance protected by a PermissionModel.
@param c Collection to protect.
@param pm PermissionModel to determine whether access is allowed.
*/
public SecureCollection(final Collection c, final PermissionModel pm) {
this.c = c;
this.pm = pm;
}
@Override public long oid() { return c.oid(); }
@Override public String getTitle() { return c.getTitle(); }
@Override public Iterable<Header> header(final int pageSize, final int offset) { return c.header(pageSize, offset); }
@Override public Iterable<Entry> elements(final int pageSize, final int offset) {
/* Note, since read permissions are at the collection level, we don't have to do a security check here. */
final ArrayList<Entry> list = new ArrayList<>();
for(Entry e: c.elements(pageSize, offset)) {
list.add(new SecureEntry(e, pm));
}
return list;
}
@Override public Entry append(final String title) {
pm.canEntryCreate(c.oid());
return pm.setOwner(new SecureEntry(c.append(title), pm));
}
@Override public Collection setTitle(final String title) {
pm.canCollectionModify(c.oid());
return new SecureCollection(c.setTitle(title), pm);
}
@Override public void delete() {
pm.canCollectionDelete(c.oid());
c.delete();
}
@Override public void attach(final Entry e) {
pm.canCollectionModify(c.oid());
pm.canEntryModify(e.oid());
c.attach(e);
}
@Override public void detach(final Entry e) {
pm.canCollectionModify(c.oid());
pm.canEntryModify(e.oid());
c.detach(e);
}
}
/** The content store object secured by this session class. */
private final ContentStore store;
/** The permission model to determine what is allowed. */
private final PermissionModel pm;
/** Create a ContentStore instance protected by a PermissionModel.
@param store The ContentStore to protect.
@param pm PermissionModel to determine whether access is allowed.
*/
public SecureSession(final ContentStore store, final PermissionModel pm) {
this.store = store;
this.pm = pm;
}
@Override public Collection getCollection(final long id) {
pm.canCollectionRead(id);
return new SecureCollection(store.getCollection(id), pm);
}
@Override public Collection getCollection(final String name) {
final Collection c = store.getCollection(name);
pm.canCollectionRead(c.oid());
return new SecureCollection(c, pm);
}
@Override public Collection makeCollection(final String name) {
pm.canCollectionCreate(name);
return pm.setOwner(new SecureCollection(store.makeCollection(name), pm));
}
@Override public Entry getEntry(final long id) {
pm.canEntryRead(id);
return new SecureEntry(store.getEntry(id), pm);
}
}