SEC-2194: Add Java Config samples

This commit is contained in:
Rob Winch
2013-08-01 14:14:18 -05:00
parent 36418b964d
commit 388a4dd9db
435 changed files with 71210 additions and 51 deletions

View File

@@ -0,0 +1,84 @@
package sample.dms;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.springframework.util.Assert;
/**
* @author Ben Alex
*
*/
public abstract class AbstractElement {
/** The name of this token (a filename or directory segment name */
private String name;
/** The parent of this token (a directory, or null if referring to root) */
private AbstractElement parent;
/** The database identifier for this object (null if not persisted) */
private Long id;
/**
* Constructor to use to represent a root element. A root element has an id of -1.
*/
protected AbstractElement() {
this.name = "/";
this.parent = null;
this.id = new Long(-1);
}
/**
* Constructor to use to represent a non-root element.
*
* @param name name for this element (required, cannot be "/")
* @param parent for this element (required, cannot be null)
*/
protected AbstractElement(String name, AbstractElement parent) {
Assert.hasText(name, "Name required");
Assert.notNull(parent, "Parent required");
Assert.notNull(parent.getId(), "The parent must have been saved in order to create a child");
this.name = name;
this.parent = parent;
}
public Long getId() {
return id;
}
/**
* @return the name of this token (never null, although will be "/" if root, otherwise it won't include separators)
*/
public String getName() {
return name;
}
public AbstractElement getParent() {
return parent;
}
/**
* @return the fully-qualified name of this element, including any parents
*/
public String getFullName() {
List<String> strings = new ArrayList<String>();
AbstractElement currentElement = this;
while (currentElement != null) {
strings.add(0, currentElement.getName());
currentElement = currentElement.getParent();
}
StringBuilder sb = new StringBuilder();
String lastCharacter = null;
for (Iterator<String> i = strings.iterator(); i.hasNext();) {
String token = i.next();
if (!"/".equals(lastCharacter) && lastCharacter != null) {
sb.append("/");
}
sb.append(token);
lastCharacter = token.substring(token.length()-1);
}
return sb.toString();
}
}

View File

@@ -0,0 +1,150 @@
package sample.dms;
import javax.sql.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
/**
* Populates the DMS in-memory database with document and ACL information.
*
* @author Ben Alex
*/
public class DataSourcePopulator implements InitializingBean {
protected static final int LEVEL_NEGATE_READ = 0;
protected static final int LEVEL_GRANT_READ = 1;
protected static final int LEVEL_GRANT_WRITE = 2;
protected static final int LEVEL_GRANT_ADMIN = 3;
protected JdbcTemplate template;
protected DocumentDao documentDao;
public DataSourcePopulator(DataSource dataSource, DocumentDao documentDao) {
Assert.notNull(dataSource, "DataSource required");
Assert.notNull(documentDao, "DocumentDao required");
this.template = new JdbcTemplate(dataSource);
this.documentDao = documentDao;
}
public void afterPropertiesSet() throws Exception {
// ACL tables
template.execute("CREATE TABLE ACL_SID(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,PRINCIPAL BOOLEAN NOT NULL,SID VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL));");
template.execute("CREATE TABLE ACL_CLASS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,CLASS VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS));");
template.execute("CREATE TABLE ACL_OBJECT_IDENTITY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,OBJECT_ID_CLASS BIGINT NOT NULL,OBJECT_ID_IDENTITY BIGINT NOT NULL,PARENT_OBJECT BIGINT,OWNER_SID BIGINT,ENTRIES_INHERITING BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY),CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID),CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID));");
template.execute("CREATE TABLE ACL_ENTRY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY BIGINT NOT NULL,ACE_ORDER INT NOT NULL,SID BIGINT NOT NULL,MASK INTEGER NOT NULL,GRANTING BOOLEAN NOT NULL,AUDIT_SUCCESS BOOLEAN NOT NULL,AUDIT_FAILURE BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER),CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID));");
// Normal authentication tables
template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL);");
template.execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");
// Document management system business tables
template.execute("CREATE TABLE DIRECTORY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, DIRECTORY_NAME VARCHAR_IGNORECASE(50) NOT NULL, PARENT_DIRECTORY_ID BIGINT)");
template.execute("CREATE TABLE FILE(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, FILE_NAME VARCHAR_IGNORECASE(50) NOT NULL, CONTENT VARCHAR_IGNORECASE(1024), PARENT_DIRECTORY_ID BIGINT)");
// Populate the authentication and role tables
template.execute("INSERT INTO USERS VALUES('rod','$2a$10$75pBjapg4Nl8Pzd.3JRnUe7PDJmk9qBGwNEJDAlA3V.dEJxcDKn5O',TRUE);");
template.execute("INSERT INTO USERS VALUES('dianne','$2a$04$bCMEyxrdF/7sgfUiUJ6Ose2vh9DAMaVBldS1Bw2fhi1jgutZrr9zm',TRUE);");
template.execute("INSERT INTO USERS VALUES('scott','$2a$06$eChwvzAu3TSexnC3ynw4LOSw1qiEbtNItNeYv5uI40w1i3paoSfLu',TRUE);");
template.execute("INSERT INTO USERS VALUES('peter','$2a$04$8.H8bCMROLF4CIgd7IpeQ.tcBXLP5w8iplO0n.kCIkISwrIgX28Ii',FALSE);");
template.execute("INSERT INTO USERS VALUES('bill','$2a$04$8.H8bCMROLF4CIgd7IpeQ.3khQlPVNWbp8kzSQqidQHGFurim7P8O',TRUE);");
template.execute("INSERT INTO USERS VALUES('bob','$2a$06$zMgxlMf01SfYNcdx7n4NpeFlAGU8apCETz/i2C7VlYWu6IcNyn4Ay',TRUE);");
template.execute("INSERT INTO USERS VALUES('jane','$2a$05$ZrdS7yMhCZ1J.AAidXZhCOxdjD8LO/dhlv4FJzkXA6xh9gdEbBT/u',TRUE);");
template.execute("INSERT INTO AUTHORITIES VALUES('rod','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('rod','ROLE_SUPERVISOR');");
template.execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('bill','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('bob','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('jane','ROLE_USER');");
// Now create an ACL entry for the root directory
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("rod", "ignored", AuthorityUtils.createAuthorityList(("ROLE_IGNORED"))));
addPermission(documentDao, Directory.ROOT_DIRECTORY, "ROLE_USER", LEVEL_GRANT_WRITE);
// Now go off and create some directories and files for our users
createSampleData("rod", "koala");
createSampleData("dianne", "emu");
createSampleData("scott", "wombat");
}
/**
* Creates a directory for the user, and a series of sub-directories. The
* root directory is the parent for the user directory. The sub-directories
* are "confidential" and "shared". The ROLE_USER will be given read and
* write access to "shared".
*/
private void createSampleData(String username, String password) {
Assert.notNull(documentDao, "DocumentDao required");
Assert.hasText(username, "Username required");
Authentication auth = new UsernamePasswordAuthenticationToken(username, password);
try {
// Set the SecurityContextHolder ThreadLocal so any subclasses
// automatically know which user is operating
SecurityContextHolder.getContext().setAuthentication(auth);
// Create the home directory first
Directory home = new Directory(username, Directory.ROOT_DIRECTORY);
documentDao.create(home);
addPermission(documentDao, home, username, LEVEL_GRANT_ADMIN);
addPermission(documentDao, home, "ROLE_USER", LEVEL_GRANT_READ);
createFiles(documentDao, home);
// Now create the confidential directory
Directory confid = new Directory("confidential", home);
documentDao.create(confid);
addPermission(documentDao, confid, "ROLE_USER", LEVEL_NEGATE_READ);
createFiles(documentDao, confid);
// Now create the shared directory
Directory shared = new Directory("shared", home);
documentDao.create(shared);
addPermission(documentDao, shared, "ROLE_USER", LEVEL_GRANT_READ);
addPermission(documentDao, shared, "ROLE_USER", LEVEL_GRANT_WRITE);
createFiles(documentDao, shared);
} finally {
// Clear the SecurityContextHolder ThreadLocal so future calls are
// guaranteed to be clean
SecurityContextHolder.clearContext();
}
}
private void createFiles(DocumentDao documentDao, Directory parent) {
Assert.notNull(documentDao, "DocumentDao required");
Assert.notNull(parent, "Parent required");
int countBeforeInsert = documentDao.findElements(parent).length;
for (int i = 0; i < 10; i++) {
File file = new File("file_" + i + ".txt", parent);
documentDao.create(file);
}
Assert.isTrue(countBeforeInsert + 10 == documentDao.findElements(parent).length,
"Failed to increase count by 10");
}
/**
* Allows subclass to add permissions.
*
* @param documentDao
* that will presumably offer methods to enable the operation to
* be completed
* @param element
* to the subject of the new permissions
* @param recipient
* to receive permission (if it starts with ROLE_ it is assumed
* to be a GrantedAuthority, else it is a username)
* @param level
* based on the static final integer fields on this class
*/
protected void addPermission(DocumentDao documentDao, AbstractElement element, String recipient, int level) {
}
}

View File

@@ -0,0 +1,23 @@
package sample.dms;
/**
*
* @author Ben Alex
*
*/
public class Directory extends AbstractElement {
public static final Directory ROOT_DIRECTORY = new Directory();
private Directory() {
super();
}
public Directory(String name, Directory parent) {
super(name, parent);
}
public String toString() {
return "Directory[fullName='" + getFullName() + "'; name='" + getName() + "'; id='" + getId() + "'; parent='" + getParent() + "']";
}
}

View File

@@ -0,0 +1,38 @@
package sample.dms;
/**
*
* @author Ben Alex
*
*/
public interface DocumentDao {
/**
* Creates an entry in the database for the element.
*
* @param element an unsaved element (the "id" will be updated after method is invoked)
*/
public void create(AbstractElement element);
/**
* Removes a file from the database for the specified element.
*
* @param file the file to remove (cannot be null)
*/
public void delete(File file);
/**
* Modifies a file in the database.
*
* @param file the file to update (cannot be null)
*/
public void update(File file);
/**
* Locates elements in the database which appear under the presented directory
*
* @param directory the directory (cannot be null - use {@link Directory#ROOT_DIRECTORY} for root)
* @return zero or more elements in the directory (an empty array may be returned - never null)
*/
public AbstractElement[] findElements(Directory directory);
}

View File

@@ -0,0 +1,114 @@
package sample.dms;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.security.util.FieldUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
/**
* Basic JDBC implementation of {@link DocumentDao}.
*
* @author Ben Alex
*/
public class DocumentDaoImpl extends JdbcDaoSupport implements DocumentDao {
private static final String INSERT_INTO_DIRECTORY = "insert into directory(directory_name, parent_directory_id) values (?,?)";
private static final String INSERT_INTO_FILE = "insert into file(file_name, content, parent_directory_id) values (?,?,?)";
private static final String SELECT_FROM_DIRECTORY = "select id from directory where parent_directory_id = ?";
private static final String SELECT_FROM_DIRECTORY_NULL = "select id from directory where parent_directory_id is null";
private static final String SELECT_FROM_FILE = "select id, file_name, content, parent_directory_id from file where parent_directory_id = ?";
private static final String SELECT_FROM_DIRECTORY_SINGLE = "select id, directory_name, parent_directory_id from directory where id = ?";
private static final String DELETE_FROM_FILE = "delete from file where id = ?";
private static final String UPDATE_FILE = "update file set content = ? where id = ?";
private static final String SELECT_IDENTITY = "call identity()";
private Long obtainPrimaryKey() {
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
return new Long(getJdbcTemplate().queryForLong(SELECT_IDENTITY));
}
public void create(AbstractElement element) {
Assert.notNull(element, "Element required");
Assert.isNull(element.getId(), "Element has previously been saved");
if (element instanceof Directory) {
Directory directory = (Directory) element;
Long parentId = directory.getParent() == null ? null : directory.getParent().getId();
getJdbcTemplate().update(INSERT_INTO_DIRECTORY, new Object[] {directory.getName(), parentId});
FieldUtils.setProtectedFieldValue("id", directory, obtainPrimaryKey());
} else if (element instanceof File) {
File file = (File) element;
Long parentId = file.getParent() == null ? null : file.getParent().getId();
getJdbcTemplate().update(INSERT_INTO_FILE, new Object[] {file.getName(), file.getContent(), parentId});
FieldUtils.setProtectedFieldValue("id", file, obtainPrimaryKey());
} else {
throw new IllegalArgumentException("Unsupported AbstractElement");
}
}
public void delete(File file) {
Assert.notNull(file, "File required");
Assert.notNull(file.getId(), "File ID required");
getJdbcTemplate().update(DELETE_FROM_FILE, new Object[] {file.getId()});
}
/** Executes recursive SQL as needed to build a full Directory hierarchy of objects */
private Directory getDirectoryWithImmediateParentPopulated(final Long id) {
return getJdbcTemplate().queryForObject(SELECT_FROM_DIRECTORY_SINGLE, new Object[] {id}, new RowMapper<Directory>() {
public Directory mapRow(ResultSet rs, int rowNumber) throws SQLException {
Long parentDirectoryId = new Long(rs.getLong("parent_directory_id"));
Directory parentDirectory = Directory.ROOT_DIRECTORY;
if (parentDirectoryId != null && !parentDirectoryId.equals(new Long(-1))) {
// Need to go and lookup the parent, so do that first
parentDirectory = getDirectoryWithImmediateParentPopulated(parentDirectoryId);
}
Directory directory = new Directory(rs.getString("directory_name"), parentDirectory);
FieldUtils.setProtectedFieldValue("id", directory, new Long(rs.getLong("id")));
return directory;
}
});
}
public AbstractElement[] findElements(Directory directory) {
Assert.notNull(directory, "Directory required (the ID can be null to refer to root)");
if (directory.getId() == null) {
List<Directory> directories = getJdbcTemplate().query(SELECT_FROM_DIRECTORY_NULL, new RowMapper<Directory>() {
public Directory mapRow(ResultSet rs, int rowNumber) throws SQLException {
return getDirectoryWithImmediateParentPopulated(new Long(rs.getLong("id")));
}
});
return (AbstractElement[]) directories.toArray(new AbstractElement[] {});
}
List<AbstractElement> directories = getJdbcTemplate().query(SELECT_FROM_DIRECTORY, new Object[] {directory.getId()}, new RowMapper<AbstractElement>() {
public Directory mapRow(ResultSet rs, int rowNumber) throws SQLException {
return getDirectoryWithImmediateParentPopulated(new Long(rs.getLong("id")));
}
});
List<File> files = getJdbcTemplate().query(SELECT_FROM_FILE, new Object[] {directory.getId()}, new RowMapper<File>() {
public File mapRow(ResultSet rs, int rowNumber) throws SQLException {
Long parentDirectoryId = new Long(rs.getLong("parent_directory_id"));
Directory parentDirectory = null;
if (parentDirectoryId != null) {
parentDirectory = getDirectoryWithImmediateParentPopulated(parentDirectoryId);
}
File file = new File(rs.getString("file_name"), parentDirectory);
FieldUtils.setProtectedFieldValue("id", file, new Long(rs.getLong("id")));
return file;
}
});
// Add the File elements after the Directory elements
directories.addAll(files);
return (AbstractElement[]) directories.toArray(new AbstractElement[] {});
}
public void update(File file) {
Assert.notNull(file, "File required");
Assert.notNull(file.getId(), "File ID required");
getJdbcTemplate().update(UPDATE_FILE, new Object[] {file.getContent(), file.getId()});
}
}

View File

@@ -0,0 +1,31 @@
package sample.dms;
import org.springframework.util.Assert;
/**
*
* @author Ben Alex
*/
public class File extends AbstractElement {
/** Content of the file, which can be null */
private String content;
public File(String name, Directory parent) {
super(name, parent);
Assert.isTrue(!parent.equals(Directory.ROOT_DIRECTORY), "Cannot insert File into root directory");
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String toString() {
return "File[fullName='" + getFullName() + "'; name='" + getName() + "'; id='" + getId() + "'; content=" + getContent() + "'; parent='" + getParent() + "']";
}
}

View File

@@ -0,0 +1,87 @@
package sample.dms.secured;
import javax.sql.DataSource;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
import sample.dms.AbstractElement;
import sample.dms.DataSourcePopulator;
import sample.dms.DocumentDao;
public class SecureDataSourcePopulator extends DataSourcePopulator {
private MutableAclService aclService;
public SecureDataSourcePopulator(DataSource dataSource, SecureDocumentDao documentDao, MutableAclService aclService) {
super(dataSource, documentDao);
Assert.notNull(aclService, "MutableAclService required");
this.aclService = aclService;
}
protected void addPermission(DocumentDao documentDao, AbstractElement element, String recipient, int level) {
Assert.notNull(documentDao, "DocumentDao required");
Assert.isInstanceOf(SecureDocumentDao.class, documentDao, "DocumentDao should have been a SecureDocumentDao");
Assert.notNull(element, "Element required");
Assert.hasText(recipient, "Recipient required");
Assert.notNull(SecurityContextHolder.getContext().getAuthentication(), "SecurityContextHolder must contain an Authentication");
// We need SecureDocumentDao to assign different permissions
//SecureDocumentDao dao = (SecureDocumentDao) documentDao;
// We need to construct an ACL-specific Sid. Note the prefix contract is defined on the superclass method's JavaDocs
Sid sid = null;
if (recipient.startsWith("ROLE_")) {
sid = new GrantedAuthoritySid(recipient);
} else {
sid = new PrincipalSid(recipient);
}
// We need to identify the target domain object and create an ObjectIdentity for it
// This works because AbstractElement has a "getId()" method
ObjectIdentity identity = new ObjectIdentityImpl(element);
// ObjectIdentity identity = new ObjectIdentityImpl(element.getClass(), element.getId()); // equivalent
// Next we need to create a Permission
Permission permission = null;
if (level == LEVEL_NEGATE_READ || level == LEVEL_GRANT_READ) {
permission = BasePermission.READ;
} else if (level == LEVEL_GRANT_WRITE) {
permission = BasePermission.WRITE;
} else if (level == LEVEL_GRANT_ADMIN) {
permission = BasePermission.ADMINISTRATION;
} else {
throw new IllegalArgumentException("Unsupported LEVEL_");
}
// Attempt to retrieve the existing ACL, creating an ACL if it doesn't already exist for this ObjectIdentity
MutableAcl acl = null;
try {
acl = (MutableAcl) aclService.readAclById(identity);
} catch (NotFoundException nfe) {
acl = aclService.createAcl(identity);
Assert.notNull(acl, "Acl could not be retrieved or created");
}
// Now we have an ACL, add another ACE to it
if (level == LEVEL_NEGATE_READ) {
acl.insertAce(acl.getEntries().size(), permission, sid, false); // not granting
} else {
acl.insertAce(acl.getEntries().size(), permission, sid, true); // granting
}
// Finally, persist the modified ACL
aclService.updateAcl(acl);
}
}

View File

@@ -0,0 +1,16 @@
package sample.dms.secured;
import sample.dms.DocumentDao;
/**
* Extends the {@link DocumentDao} and introduces ACL-related methods.
*
* @author Ben Alex
*
*/
public interface SecureDocumentDao extends DocumentDao {
/**
* @return all the usernames existing in the system.
*/
public String[] getUsers();
}

View File

@@ -0,0 +1,60 @@
package sample.dms.secured;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
import sample.dms.AbstractElement;
import sample.dms.DocumentDaoImpl;
/**
* Adds extra {@link SecureDocumentDao} methods.
*
* @author Ben Alex
*
*/
public class SecureDocumentDaoImpl extends DocumentDaoImpl implements SecureDocumentDao {
private static final String SELECT_FROM_USERS = "SELECT USERNAME FROM USERS ORDER BY USERNAME";
private MutableAclService mutableAclService;
public SecureDocumentDaoImpl(MutableAclService mutableAclService) {
Assert.notNull(mutableAclService, "MutableAclService required");
this.mutableAclService = mutableAclService;
}
public String[] getUsers() {
return (String[]) getJdbcTemplate().query(SELECT_FROM_USERS, new RowMapper<String>() {
public String mapRow(ResultSet rs, int rowNumber) throws SQLException {
return rs.getString("USERNAME");
}
}).toArray(new String[] {});
}
public void create(AbstractElement element) {
super.create(element);
// Create an ACL identity for this element
ObjectIdentity identity = new ObjectIdentityImpl(element);
MutableAcl acl = mutableAclService.createAcl(identity);
// If the AbstractElement has a parent, go and retrieve its identity (it should already exist)
if (element.getParent() != null) {
ObjectIdentity parentIdentity = new ObjectIdentityImpl(element.getParent());
MutableAcl aclParent = (MutableAcl) mutableAclService.readAclById(parentIdentity);
acl.setParent(aclParent);
}
acl.insertAce(acl.getEntries().size(), BasePermission.ADMINISTRATION, new PrincipalSid(SecurityContextHolder.getContext().getAuthentication()), true);
mutableAclService.updateAcl(acl);
}
}