diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java index 93bb20116..03234a2a1 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java @@ -2,6 +2,10 @@ package edu.cornell.mannlib.vitro.webapp.auth.policy; +import java.util.Collections; +import java.util.Set; +import java.util.TreeSet; + import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -26,8 +30,10 @@ import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; /** * If the user has an IsRootUser identifier, they can do anything! * - * On setup, check to see that there is a root user. If not, create one. If we - * can't create one, abort. + * On setup, check to see that the specified root user exists. If not, create + * it. If we can't create it, abort. + * + * If any other root users exist, warn about them. */ public class RootUserPolicy implements PolicyIface { private static final Log log = LogFactory.getLog(RootUserPolicy.class); @@ -62,8 +68,10 @@ public class RootUserPolicy implements PolicyIface { public static class Setup implements ServletContextListener { private ServletContext ctx; private StartupStatus ss; - private String configRootEmail; private UserAccountsDao uaDao; + private String configuredRootUser; + private boolean configuredRootUserExists; + private TreeSet otherRootUsers; @Override public void contextInitialized(ServletContextEvent sce) { @@ -72,14 +80,23 @@ public class RootUserPolicy implements PolicyIface { try { uaDao = getUserAccountsDao(); - configRootEmail = getRootEmailFromConfig(); + configuredRootUser = getRootEmailFromConfig(); - checkForWrongRootUser(); + otherRootUsers = getEmailsOfAllRootUsers(); + configuredRootUserExists = otherRootUsers + .remove(configuredRootUser); - if (rootUserExists()) { - ss.info(this, "root user is " + configRootEmail); + if (configuredRootUserExists) { + if (otherRootUsers.isEmpty()) { + informThatRootUserExists(); + } else { + complainAboutMultipleRootUsers(); + } } else { createRootUser(); + if (!otherRootUsers.isEmpty()) { + complainAboutWrongRootUsers(); + } } ServletPolicyList.addPolicy(ctx, new RootUserPolicy()); @@ -110,37 +127,14 @@ public class RootUserPolicy implements PolicyIface { } } - private void checkForWrongRootUser() { - UserAccount root = getRootUser(); - if (root == null) { - return; - } - - String actualRootEmail = root.getEmailAddress(); - if (actualRootEmail.equals(configRootEmail)) { - return; - } - - ss.warning( - this, - "The deploy.properties file specifies a root user of '" - + configRootEmail - + "', but the system already contains a root user named '" - + actualRootEmail + "'. The user '" - + configRootEmail + "' will not be created."); - } - - private boolean rootUserExists() { - return (getRootUser() != null); - } - - private UserAccount getRootUser() { + private TreeSet getEmailsOfAllRootUsers() { + TreeSet rootUsers = new TreeSet(); for (UserAccount ua : uaDao.getAllUserAccounts()) { if (ua.isRootUser()) { - return ua; + rootUsers.add(ua.getEmailAddress()); } } - return null; + return rootUsers; } /** @@ -148,29 +142,21 @@ public class RootUserPolicy implements PolicyIface { * be forced to edit them. However, that's not in place yet. */ private void createRootUser() { - String emailAddress = ConfigurationProperties.getBean(ctx) - .getProperty(PROPERTY_ROOT_USER_EMAIL); - if (emailAddress == null) { - throw new IllegalStateException( - "deploy.properties must contain a value for '" - + PROPERTY_ROOT_USER_EMAIL + "'"); - } - - if (!Authenticator.isValidEmailAddress(emailAddress)) { + if (!Authenticator.isValidEmailAddress(configuredRootUser)) { throw new IllegalStateException("Value for '" + PROPERTY_ROOT_USER_EMAIL - + "' is not a valid email address: '" + emailAddress - + "'"); + + "' is not a valid email address: '" + + configuredRootUser + "'"); } - if (null != uaDao.getUserAccountByEmail(emailAddress)) { + if (null != uaDao.getUserAccountByEmail(configuredRootUser)) { throw new IllegalStateException("Can't create root user - " + "an account already exists with email address '" - + emailAddress + "'"); + + configuredRootUser + "'"); } UserAccount ua = new UserAccount(); - ua.setEmailAddress(emailAddress); + ua.setEmailAddress(configuredRootUser); ua.setFirstName("root"); ua.setLastName("user"); ua.setMd5Password(Authenticator @@ -182,7 +168,36 @@ public class RootUserPolicy implements PolicyIface { uaDao.insertUserAccount(ua); StartupStatus.getBean(ctx).info(this, - "Created root user as '" + emailAddress + "'"); + "Created root user '" + configuredRootUser + "'"); + } + + private void informThatRootUserExists() { + ss.info(this, "Root user is " + configuredRootUser); + } + + private void complainAboutMultipleRootUsers() { + for (String other : otherRootUsers) { + ss.warning(this, "deploy.properties specifies '" + + configuredRootUser + "' as the value for '" + + PROPERTY_ROOT_USER_EMAIL + + "', but the system also contains this root user: " + + other); + } + ss.warning(this, "For security, " + + "it is best to delete unneeded root user accounts."); + } + + private void complainAboutWrongRootUsers() { + for (String other : otherRootUsers) { + ss.warning(this, "deploy.properties specifies '" + + configuredRootUser + "' as the value for '" + + PROPERTY_ROOT_USER_EMAIL + + "', but the system contains this root user instead: " + + other); + } + ss.warning(this, "Creating root user '" + configuredRootUser + "'"); + ss.warning(this, "For security, " + + "it is best to delete unneeded root user accounts."); } @Override diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/FriendController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/FriendController.java deleted file mode 100644 index bfdc810ce..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/FriendController.java +++ /dev/null @@ -1,149 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.controller.authenticate; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Date; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.ibm.icu.text.SimpleDateFormat; - -import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource; -import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; -import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao; - -/** - * Back door to log in as the root user. - * - * If the classpath contains a file called friend.xml, which contains a magic - * line (see below) with today's date, or some date less than a week ago, then - * you are logged in as root. - * - * If anything else, return a 404. - */ -public class FriendController extends HttpServlet { - private static final Log log = LogFactory.getLog(FriendController.class); - - private static final long MILLIS_IN_A_WEEK = 7L * 24L * 60L * 60L * 1000L; - - // To be valid XML, it could look like this: - // but we don't care as long as it contains this: 9999-99-99 - private static final String DATE_PATTERN = "\\d\\d\\d\\d-\\d\\d-\\d\\d"; - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - try { - if (fileContentsAreAcceptable()) { - writeWarningToTheLog(req); - loginAsRootUser(req); - redirectToHomePage(resp); - } - } catch (Exception e) { - log.debug("problem: " + e.getMessage()); - resp.sendError(HttpStatus.SC_NOT_FOUND); - } - } - - private boolean fileContentsAreAcceptable() throws Exception { - InputStream stream = null; - try { - stream = openTheFile(); - String string = readFromStream(stream); - return checkDateString(string); - } finally { - if (stream != null) { - stream.close(); - } - } - } - - private InputStream openTheFile() throws Exception { - InputStream stream = this.getClass().getClassLoader() - .getResourceAsStream("/friend.xml"); - if (stream == null) { - throw new Exception("can't find the file."); - } - return stream; - } - - private String readFromStream(InputStream stream) throws IOException { - byte[] buffer = new byte[1024]; - int howMany = stream.read(buffer); - - if (howMany == -1) { - return ""; - } else { - return new String(buffer, 0, howMany); - } - } - - private boolean checkDateString(String string) throws Exception { - long date = parseDateFromFile(string); - compareAgainstDateRange(date); - return true; - } - - private long parseDateFromFile(String string) throws Exception { - Pattern p = Pattern.compile(DATE_PATTERN); - Matcher m = p.matcher(string); - - if (!m.find()) { - throw new Exception("no date string in the file."); - } - - return new SimpleDateFormat("yyyy-MM-dd").parse(m.group()).getTime(); - } - - private void compareAgainstDateRange(long date) throws Exception { - long now = new Date().getTime(); - long then = now - MILLIS_IN_A_WEEK; - if ((date > now) || (date < then)) { - throw new Exception("date out of range."); - } - } - - private void writeWarningToTheLog(HttpServletRequest req) { - log.warn("LOGGING IN VIA FRIEND FROM ADDR=" + req.getRemoteAddr() - + ", PORT=" + req.getRemotePort() + ", HOST=" - + req.getRemoteHost() + ", USER=" + req.getRemoteUser()); - } - - private void loginAsRootUser(HttpServletRequest req) throws Exception { - UserAccount rootUser = getRootUser(req); - Authenticator.getInstance(req).recordLoginAgainstUserAccount(rootUser, - AuthenticationSource.INTERNAL); - } - - private UserAccount getRootUser(HttpServletRequest req) throws Exception { - UserAccountsDao uaDao = new VitroRequest(req).getWebappDaoFactory() - .getUserAccountsDao(); - - for (UserAccount ua : uaDao.getAllUserAccounts()) { - if (ua.isRootUser()) { - return ua; - } - } - - throw new Exception("couldn't find root user."); - } - - private void redirectToHomePage(HttpServletResponse resp) - throws IOException { - resp.sendRedirect(UrlBuilder.getUrl("/")); - } - -} diff --git a/webapp/web/WEB-INF/web.xml b/webapp/web/WEB-INF/web.xml index 961b1e170..430ac32f2 100644 --- a/webapp/web/WEB-INF/web.xml +++ b/webapp/web/WEB-INF/web.xml @@ -1042,15 +1042,6 @@ /admin/login - - friend - edu.cornell.mannlib.vitro.webapp.controller.authenticate.FriendController - - - friend - /admin/friend - - logout edu.cornell.mannlib.vitro.webapp.controller.edit.Logout