VIVO-274 move permission_config.n3 to rdf/auth/everytime

Get rid of the PermissionSetsLoader, keep the smoke tests.
This commit is contained in:
j2blake 2013-08-27 17:26:24 -04:00
parent dcda958d8d
commit d69bb824ac
10 changed files with 163 additions and 372 deletions

View file

@ -0,0 +1,20 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.VITRO_AUTH;
/**
* Constants and static methods to help manipulate PermissionSet instances.
*/
public class PermissionSets {
public static final String URI_SELF_EDITOR = VITRO_AUTH + "SELF_EDITOR";
public static final String URI_EDITOR = VITRO_AUTH + "EDITOR";
public static final String URI_CURATOR = VITRO_AUTH + "CURATOR";
public static final String URI_DBA = VITRO_AUTH + "ADMIN";
/** No need to create an instance. */
private PermissionSets() {
// Nothing to initialize.
}
}

View file

@ -1,355 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.VITRO_AUTH;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Selector;
import com.hp.hpl.jena.rdf.model.SimpleSelector;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.util.iterator.ClosableIterator;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
/**
* Load the initial configuration of PermissionSets and Permissions.
*
* The UserAccounts model must be created before this runs.
*
* The PermissionRegistry must be created before this runs.
*/
public class PermissionSetsLoader implements ServletContextListener {
private static final Log log = LogFactory
.getLog(PermissionSetsLoader.class);
public static final String FILE_OF_PERMISSION_SETS_INFO = "/WEB-INF/resources/permission_config.n3";
public static final String URI_SELF_EDITOR = VITRO_AUTH + "SELF_EDITOR";
public static final String URI_EDITOR = VITRO_AUTH + "EDITOR";
public static final String URI_CURATOR = VITRO_AUTH + "CURATOR";
public static final String URI_DBA = VITRO_AUTH + "ADMIN";
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
StartupStatus ss = StartupStatus.getBean(ctx);
try {
new Loader(this, ctx, ss).load();
new SmokeTester(this, ctx, ss).test();
} catch (Exception e) {
ss.fatal(this, "Failed to load the PermissionSets", e);
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// Nothing to tear down.
}
// ----------------------------------------------------------------------
// Loader class
// ----------------------------------------------------------------------
private static class Loader {
private static final int MAX_STATEMENTS_IN_WARNING = 5;
private ServletContextListener listener;
private final ServletContext ctx;
private final StartupStatus ss;
private final OntModel userAccountsModel;
private final Property permissionSetType;
private Model modelFromFile;
private Model filteredModel;
private int howManyNewPermissionSets;
private int howManyOldPermissionSets;
public Loader(ServletContextListener listener, ServletContext ctx,
StartupStatus ss) {
this.listener = listener;
this.ctx = ctx;
this.ss = ss;
this.userAccountsModel = ModelAccess.on(ctx).getUserAccountsModel();
this.permissionSetType = this.userAccountsModel
.getProperty(VitroVocabulary.PERMISSIONSET);
}
public void load() {
try {
createModelFromFile();
filterModelFromFile();
checkForLeftoverStatements();
removeExistingPermissionSetsFromUserAccountsModel();
addNewStatementsToUserAccountsModel();
ss.info(listener, buildInfoMessage());
} catch (LoaderException e) {
Throwable cause = e.getCause();
if (cause == null) {
ss.warning(listener, e.getMessage());
} else {
ss.warning(listener, e.getMessage(), e.getCause());
}
}
}
private void createModelFromFile() throws LoaderException {
InputStream stream = ctx
.getResourceAsStream(FILE_OF_PERMISSION_SETS_INFO);
if (stream == null) {
throw new LoaderException("The permission sets config file "
+ "doesn't exist in the servlet context: '"
+ FILE_OF_PERMISSION_SETS_INFO + "'");
}
try {
modelFromFile = ModelFactory.createDefaultModel();
modelFromFile.read(stream, null, "N3");
} finally {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
log.debug("Loaded " + modelFromFile.size() + " statements");
}
/**
* Move all statements that relate to PermissionSets from the loaded
* model to the filtered model.
*/
private void filterModelFromFile() {
filteredModel = ModelFactory.createDefaultModel();
for (Resource r : iterable(modelFromFile.listResourcesWithProperty(
RDF.type, permissionSetType))) {
moveStatementsToFilteredModel(r);
howManyNewPermissionSets++;
}
log.debug("Filtered " + filteredModel.size() + " statements for "
+ howManyNewPermissionSets + " PermissionSets; "
+ modelFromFile.size() + " extraneous statements.");
}
/**
* Move the statements about this PermissionSet from the loaded model to
* the filtered model.
*/
private void moveStatementsToFilteredModel(Resource ps) {
Selector sel = new SimpleSelector(ps, null, (String) null);
for (Statement stmt : iterable(modelFromFile.listStatements(sel))) {
filteredModel.add(stmt);
modelFromFile.remove(stmt);
}
}
/**
* Complain about any statements that were not moved to the filtered
* model.
*/
private void checkForLeftoverStatements() {
List<Statement> list = iterable(modelFromFile.listStatements());
if (list.isEmpty()) {
return;
}
String message = "The PermissionSets configuration file contained "
+ list.size()
+ " statements that didn't describe PermissionSets: ";
for (int i = 0; i < Math
.min(list.size(), MAX_STATEMENTS_IN_WARNING); i++) {
Statement stmt = list.get(i);
message += "(" + stmt.asTriple() + ") ";
}
if (list.size() > MAX_STATEMENTS_IN_WARNING) {
message += ", ...";
}
ss.warning(listener, message);
}
private void removeExistingPermissionSetsFromUserAccountsModel() {
userAccountsModel.enterCriticalSection(Lock.WRITE);
try {
for (Resource r : iterable(userAccountsModel
.listResourcesWithProperty(RDF.type, permissionSetType))) {
Selector sel = new SimpleSelector(r, null, (String) null);
StmtIterator stmts = userAccountsModel.listStatements(sel);
userAccountsModel.remove(stmts);
howManyOldPermissionSets++;
}
} finally {
userAccountsModel.leaveCriticalSection();
}
log.debug("Deleted " + howManyOldPermissionSets
+ " old PermissionSets from the user model.");
}
private void addNewStatementsToUserAccountsModel() {
userAccountsModel.enterCriticalSection(Lock.WRITE);
try {
userAccountsModel.add(filteredModel);
} finally {
userAccountsModel.leaveCriticalSection();
}
}
private String buildInfoMessage() {
String message = "Loaded " + howManyNewPermissionSets
+ " PermissionSets: ";
Selector sel = new SimpleSelector(null, RDFS.label, (String) null);
for (Statement stmt : iterable(filteredModel.listStatements(sel))) {
String label = stmt.getObject().asLiteral().getString();
message += "'" + label + "' ";
}
return message;
}
private <T> List<T> iterable(ClosableIterator<T> iterator) {
List<T> list = new ArrayList<T>();
try {
while (iterator.hasNext()) {
list.add(iterator.next());
}
} finally {
iterator.close();
}
return list;
}
}
// ----------------------------------------------------------------------
// SmokeTester class
// ----------------------------------------------------------------------
private static class SmokeTester {
private ServletContextListener listener;
private final ServletContext ctx;
private final StartupStatus ss;
private final UserAccountsDao uaDao;
public SmokeTester(ServletContextListener listener, ServletContext ctx,
StartupStatus ss) {
this.listener = listener;
this.ctx = ctx;
this.ss = ss;
WebappDaoFactory wadf = ModelAccess.on(ctx).getWebappDaoFactory();
if (wadf == null) {
throw new IllegalStateException(
"No webappDaoFactory on the servlet context");
}
this.uaDao = wadf.getUserAccountsDao();
}
public void test() {
checkForPermissionSetsWithoutLabels();
checkForReferencesToNonexistentPermissionSets();
checkForReferencesToNonexistentPermissions();
warnIfNoPermissionSetsForNewUsers();
}
private void checkForPermissionSetsWithoutLabels() {
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
if (ps.getLabel().isEmpty()) {
ss.warning(listener, "This PermissionSet has no label: "
+ ps.getUri());
}
}
}
private void checkForReferencesToNonexistentPermissionSets() {
for (UserAccount user : uaDao.getAllUserAccounts()) {
for (String psUri : user.getPermissionSetUris()) {
if (uaDao.getPermissionSetByUri(psUri) == null) {
ss.warning(listener, "The user '" + user.getFirstName()
+ " " + user.getLastName()
+ "' has the PermissionSet '" + psUri
+ "', but the PermissionSet doesn't exist.");
}
}
}
}
private void checkForReferencesToNonexistentPermissions() {
PermissionRegistry registry = PermissionRegistry.getRegistry(ctx);
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
for (String pUri : ps.getPermissionUris()) {
if (!registry.isPermission(pUri)) {
ss.warning(listener,
"The PermissionSet '" + ps.getLabel()
+ "' has the Permission '" + pUri
+ "', but the Permission "
+ "is not found in the registry.");
}
}
}
}
private void warnIfNoPermissionSetsForNewUsers() {
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
if (ps.isForNewUsers()) {
return;
}
}
ss.warning(listener, "No PermissionSet has been declared to be a "
+ "PermissionSet for new users.");
}
}
// ----------------------------------------------------------------------
// Handy dandy exception.
// ----------------------------------------------------------------------
private static class LoaderException extends Exception {
public LoaderException(String message) {
super(message);
}
public LoaderException(String message, Throwable cause) {
super(message, cause);
}
}
}

View file

@ -0,0 +1,124 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
/**
* Load the initial configuration of PermissionSets and Permissions.
*
* The UserAccounts model must be created before this runs.
*
* The PermissionRegistry must be created before this runs.
*/
public class PermissionSetsSmokeTest implements ServletContextListener {
@SuppressWarnings("unused")
private static final Log log = LogFactory
.getLog(PermissionSetsSmokeTest.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
StartupStatus ss = StartupStatus.getBean(ctx);
try {
new SmokeTester(this, ctx, ss).test();
} catch (Exception e) {
ss.fatal(this, "Found a problem while testing the PermissionSets",
e);
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// Nothing to tear down.
}
// ----------------------------------------------------------------------
// SmokeTester class
// ----------------------------------------------------------------------
private static class SmokeTester {
private ServletContextListener listener;
private final ServletContext ctx;
private final StartupStatus ss;
private final UserAccountsDao uaDao;
public SmokeTester(ServletContextListener listener, ServletContext ctx,
StartupStatus ss) {
this.listener = listener;
this.ctx = ctx;
this.ss = ss;
this.uaDao = ModelAccess.on(ctx).getWebappDaoFactory()
.getUserAccountsDao();
}
public void test() {
checkForPermissionSetsWithoutLabels();
checkForReferencesToNonexistentPermissionSets();
checkForReferencesToNonexistentPermissions();
warnIfNoPermissionSetsForNewUsers();
}
private void checkForPermissionSetsWithoutLabels() {
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
if (ps.getLabel().isEmpty()) {
ss.warning(listener, "This PermissionSet has no label: "
+ ps.getUri());
}
}
}
private void checkForReferencesToNonexistentPermissionSets() {
for (UserAccount user : uaDao.getAllUserAccounts()) {
for (String psUri : user.getPermissionSetUris()) {
if (uaDao.getPermissionSetByUri(psUri) == null) {
ss.warning(listener, "The user '" + user.getFirstName()
+ " " + user.getLastName()
+ "' has the PermissionSet '" + psUri
+ "', but the PermissionSet doesn't exist.");
}
}
}
}
private void checkForReferencesToNonexistentPermissions() {
PermissionRegistry registry = PermissionRegistry.getRegistry(ctx);
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
for (String pUri : ps.getPermissionUris()) {
if (!registry.isPermission(pUri)) {
ss.warning(listener,
"The PermissionSet '" + ps.getLabel()
+ "' has the Permission '" + pUri
+ "', but the Permission "
+ "is not found in the registry.");
}
}
}
}
private void warnIfNoPermissionSetsForNewUsers() {
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
if (ps.isForNewUsers()) {
return;
}
}
ss.warning(listener, "No PermissionSet has been declared to be a "
+ "PermissionSet for new users.");
}
}
}

View file

@ -13,7 +13,7 @@ import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.rdf.model.ResourceFactory;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean; import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader; import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSets;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
public class BaseResourceBean implements ResourceBean { public class BaseResourceBean implements ResourceBean {
@ -80,13 +80,13 @@ public class BaseResourceBean implements ResourceBean {
} }
Set<String> roles = u.getPermissionSetUris(); Set<String> roles = u.getPermissionSetUris();
if (roles.contains(PermissionSetsLoader.URI_DBA)) { if (roles.contains(PermissionSets.URI_DBA)) {
return DB_ADMIN; return DB_ADMIN;
} else if (roles.contains(PermissionSetsLoader.URI_CURATOR)) { } else if (roles.contains(PermissionSets.URI_CURATOR)) {
return CURATOR; return CURATOR;
} else if (roles.contains(PermissionSetsLoader.URI_EDITOR)) { } else if (roles.contains(PermissionSets.URI_EDITOR)) {
return EDITOR; return EDITOR;
} else if (roles.contains(PermissionSetsLoader.URI_SELF_EDITOR)) { } else if (roles.contains(PermissionSets.URI_SELF_EDITOR)) {
return SELF; return SELF;
} else { } else {
// Logged in but with no recognized role? Make them SELF // Logged in but with no recognized role? Make them SELF

View file

@ -11,7 +11,7 @@ import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader; import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSets;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
@ -200,7 +200,7 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
u.setLoginCount(0); u.setLoginCount(0);
u.setStatus(Status.ACTIVE); u.setStatus(Status.ACTIVE);
u.setPermissionSetUris(Collections u.setPermissionSetUris(Collections
.singleton(PermissionSetsLoader.URI_SELF_EDITOR)); .singleton(PermissionSets.URI_SELF_EDITOR));
userAccountsDao.insertUserAccount(u); userAccountsDao.insertUserAccount(u);

View file

@ -57,15 +57,17 @@ public class UserModelSetup extends JenaDataSourceSetupBase implements
OntModel userAccountsModel = ModelFactory OntModel userAccountsModel = ModelFactory
.createOntologyModel(MEM_ONT_MODEL_SPEC); .createOntologyModel(MEM_ONT_MODEL_SPEC);
// This is used in Selenium testing, to load accounts from a file.
RDFFilesLoader.loadFirstTimeFiles(ctx, "auth", userAccountsDbModel,
userAccountsDbModel.isEmpty());
userAccountsModel.add(userAccountsDbModel); userAccountsModel.add(userAccountsDbModel);
userAccountsModel.getBaseModel().register( userAccountsModel.getBaseModel().register(
new ModelSynchronizer(userAccountsDbModel)); new ModelSynchronizer(userAccountsDbModel));
ModelAccess.on(ctx).setUserAccountsModel(userAccountsModel);
// This is used in Selenium testing, to load accounts from a file.
RDFFilesLoader.loadFirstTimeFiles(ctx, "auth", userAccountsModel,
userAccountsDbModel.isEmpty());
// This gets the permissions configuration.
RDFFilesLoader.loadEveryTimeFiles(ctx, "auth", userAccountsModel);
ModelAccess.on(ctx).setUserAccountsModel(userAccountsModel);
} catch (Throwable t) { } catch (Throwable t) {
log.error("Unable to load user accounts model from DB", t); log.error("Unable to load user accounts model from DB", t);
ss.fatal(this, "Unable to load user accounts model from DB", t); ss.fatal(this, "Unable to load user accounts model from DB", t);

View file

@ -27,7 +27,7 @@ import stubs.javax.servlet.http.HttpServletResponseStub;
import stubs.javax.servlet.http.HttpSessionStub; import stubs.javax.servlet.http.HttpSessionStub;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean; import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass; import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader; import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSets;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
/** /**
@ -97,7 +97,7 @@ public class ProgramLoginTest extends AbstractTestClass {
user.setEmailAddress(name); user.setEmailAddress(name);
user.setUri(uri); user.setUri(uri);
user.setPermissionSetUris(Collections user.setPermissionSetUris(Collections
.singleton(PermissionSetsLoader.URI_DBA)); .singleton(PermissionSets.URI_DBA));
user.setMd5Password(Authenticator.applyMd5Encoding(password)); user.setMd5Password(Authenticator.applyMd5Encoding(password));
user.setLoginCount(loginCount); user.setLoginCount(loginCount);
user.setPasswordChangeRequired(loginCount == 0); user.setPasswordChangeRequired(loginCount == 0);

View file

@ -2,8 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.controller.edit; package edu.cornell.mannlib.vitro.webapp.controller.edit;
import static edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader.URI_DBA; import static edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSets.URI_DBA;
import static edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader.URI_SELF_EDITOR; import static edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSets.URI_SELF_EDITOR;
import static edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.State.FORCED_PASSWORD_CHANGE; import static edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.State.FORCED_PASSWORD_CHANGE;
import static edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.State.LOGGING_IN; import static edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.State.LOGGING_IN;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;

View file

@ -43,7 +43,7 @@ edu.cornell.mannlib.vitro.webapp.servlet.setup.ThemeInfoSetup
edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionRegistry$Setup edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionRegistry$Setup
edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsSmokeTest
edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper$Setup edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper$Setup