diff --git a/webapp/config/web.xml b/webapp/config/web.xml index 01f7cfdc1..ef04d81c1 100644 --- a/webapp/config/web.xml +++ b/webapp/config/web.xml @@ -766,12 +766,21 @@ - UserAccounts - edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsController + AccountsAdmin + edu.cornell.mannlib.vitro.webapp.controller.accounts.admin.UserAccountsAdminController - UserAccounts - /userAccounts/* + AccountsAdmin + /accountsAdmin/* + + + + AccountsUser + edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsUserController + + + AccountsUser + /accounts/* diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java index cb0dba311..55e6e2f4b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java @@ -11,11 +11,17 @@ import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator; /** * Information about the account of a user. URI, email, password, etc. + * + * The "password link expires hash" is just a string that is derived from the + * value in the passwordLinkExpires field. It doesn't have to be a hash, and + * there is no need for it to be cryptographic, but it seems embarrassing to + * just send the value as a clear string. There is no real need for security + * here, except that a brute force attack would allow someone to change the + * password on an account that they know has a password change pending. */ public class UserAccount { - - public final static int MIN_PASSWORD_LENGTH = 6; - public final static int MAX_PASSWORD_LENGTH = 12; + public static final int MIN_PASSWORD_LENGTH = 6; + public static final int MAX_PASSWORD_LENGTH = 12; public enum Status { ACTIVE, INACTIVE; @@ -110,8 +116,8 @@ public class UserAccount { } public String getPasswordLinkExpiresHash() { - return Authenticator.applyMd5Encoding(String - .valueOf(passwordLinkExpires)); + return limitStringLength(8, Authenticator.applyMd5Encoding(String + .valueOf(passwordLinkExpires))); } public void setPasswordLinkExpires(long passwordLinkExpires) { @@ -169,6 +175,16 @@ public class UserAccount { private T nonNull(T value, T defaultValue) { return (value == null) ? defaultValue : value; } + + private String limitStringLength(int limit, String s) { + if (s == null) { + return ""; + } else if (s.length() <= limit) { + return s; + } else { + return s.substring(0, limit); + } + } @Override public String toString() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsAddPageStrategy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsAddPageStrategy.java index fd3aa8f99..bba175df5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsAddPageStrategy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsAddPageStrategy.java @@ -6,12 +6,14 @@ import static javax.mail.Message.RecipientType.TO; import java.net.MalformedURLException; import java.net.URL; +import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status; +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory; import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage; @@ -52,7 +54,8 @@ public abstract class UserAccountsAddPageStrategy { // ---------------------------------------------------------------------- private static class EmailStrategy extends UserAccountsAddPageStrategy { - public static final String CREATE_PASSWORD_URL = "/userAccounts/createPassword"; + public static final String CREATE_PASSWORD_URL = "/accounts/createPassword"; + private static final int DAYS_TO_ACTIVATE_ACCOUNT = 90; private boolean sentEmail; @@ -73,9 +76,15 @@ public abstract class UserAccountsAddPageStrategy { @Override protected void setAdditionalProperties(UserAccount u) { - u.setPasswordLinkExpires(new Date().getTime()); + u.setPasswordLinkExpires(figureExpirationDate().getTime()); u.setStatus(Status.INACTIVE); } + + private Date figureExpirationDate() { + Calendar c = Calendar.getInstance(); + c.add(Calendar.DATE, DAYS_TO_ACTIVATE_ACCOUNT); + return c.getTime(); + } @Override protected void addMoreBodyValues(Map body) { @@ -93,8 +102,8 @@ public abstract class UserAccountsAddPageStrategy { .createNewMessage(page.vreq); email.addRecipient(TO, page.getAddedAccount().getEmailAddress()); email.setSubject("Your VIVO account has been created."); - email.setHtmlTemplate("userAccounts-createdEmail-html.ftl"); - email.setTextTemplate("userAccounts-createdEmail-text.ftl"); + email.setHtmlTemplate("userAccounts-acctCreatedEmail-html.ftl"); + email.setTextTemplate("userAccounts-acctCreatedEmail-text.ftl"); email.setBodyMap(body); email.send(); @@ -103,11 +112,11 @@ public abstract class UserAccountsAddPageStrategy { private String buildCreatePasswordLink() { try { - String uri = page.getAddedAccount().getUri(); + String email = page.getAddedAccount().getEmailAddress(); String hash = page.getAddedAccount() .getPasswordLinkExpiresHash(); String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL, "user", - uri, "key", hash); + email, "key", hash); URL context = new URL(page.vreq.getRequestURL().toString()); URL url = new URL(context, relativeUrl); @@ -116,7 +125,7 @@ public abstract class UserAccountsAddPageStrategy { return "error_creating_password_link"; } } - + @Override protected boolean wasPasswordEmailSent() { return sentEmail; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsController.java index 4e3846f99..92e20e8e8 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsController.java @@ -9,8 +9,10 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageUserAccounts; +import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; /** @@ -23,6 +25,7 @@ public class UserAccountsController extends FreemarkerHttpServlet { private static final String ACTION_ADD = "/add"; private static final String ACTION_DELETE = "/delete"; private static final String ACTION_EDIT = "/edit"; + private static final String ACTION_CREATE_PASSWORD = "/createPassword"; @Override protected Actions requiredActions(VitroRequest vreq) { @@ -44,6 +47,8 @@ public class UserAccountsController extends FreemarkerHttpServlet { return handleEditRequest(vreq); } else if (ACTION_DELETE.equals(action)) { return handleDeleteRequest(vreq); + } else if (ACTION_CREATE_PASSWORD.equals(action)) { + return handleCreatePasswordRequest(vreq); } else { return handleListRequest(vreq); } @@ -64,7 +69,6 @@ public class UserAccountsController extends FreemarkerHttpServlet { private ResponseValues handleEditRequest(VitroRequest vreq) { UserAccountsEditPage page = new UserAccountsEditPage(vreq); - page.parseParametersAndValidate(); if (page.isSubmit() && page.isValid()) { page.updateAccount(); UserAccountsListPage listPage = new UserAccountsListPage(vreq); @@ -83,8 +87,30 @@ public class UserAccountsController extends FreemarkerHttpServlet { .showPageWithDeletions(deletedUris); } + private ResponseValues handleCreatePasswordRequest(VitroRequest vreq) { + UserAccountsCreatePasswordPage page = new UserAccountsCreatePasswordPage( + vreq); + if (page.isBogus()) { + return showHomePage(vreq, + "Request failed. Please contact your system administrator."); + } else if (page.isSubmit() && page.isValid()) { + page.createPassword(); + return showHomePage(vreq, + "Your password has been saved. Please log in."); + } else { + return page.showPage(); + } + + } + private ResponseValues handleListRequest(VitroRequest vreq) { UserAccountsListPage page = new UserAccountsListPage(vreq); return page.showPage(); } + + private ResponseValues showHomePage(VitroRequest vreq, String message) { + DisplayMessage.setMessage(vreq, message); + return new RedirectResponseValues("/"); + } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsCreatePasswordPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsCreatePasswordPage.java new file mode 100644 index 000000000..3297a5043 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsCreatePasswordPage.java @@ -0,0 +1,165 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.accounts; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; +import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsUserController; +import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; + +/** + * TODO + */ +public class UserAccountsCreatePasswordPage extends UserAccountsPage { + private static final Log log = LogFactory + .getLog(UserAccountsCreatePasswordPage.class); + + private static final String PARAMETER_SUBMIT = "submitCreatePassword"; + private static final String PARAMETER_USER = "user"; + private static final String PARAMETER_KEY = "key"; + private static final String PARAMETER_PASSWORD = "password"; + private static final String PARAMETER_CONFIRM_PASSWORD = "confirmPassword"; + + private static final String TEMPLATE_NAME = "userAccounts-createPassword.ftl"; + + private static final String ERROR_NO_PASSWORD = "errorPasswordIsEmpty"; + private static final String ERROR_WRONG_PASSWORD_LENGTH = "errorPasswordIsWrongLength"; + private static final String ERROR_PASSWORDS_DONT_MATCH = "errorPasswordsDontMatch"; + + private boolean submit; + private String userEmail = ""; + private String key = ""; + private String password = ""; + private String confirmPassword = ""; + + private UserAccount userAccount; + + /** The result of checking whether this request is even appropriate. */ + private String bogusMessage = ""; + + /** The result of validating a "submit" request. */ + private String errorCode = ""; + + public UserAccountsCreatePasswordPage(VitroRequest vreq) { + super(vreq); + + parseRequestParameters(); + validateUserAccountInfo(); + + if (isSubmit() && !isBogus()) { + validateParameters(); + } + } + + private void parseRequestParameters() { + submit = isFlagOnRequest(PARAMETER_SUBMIT); + userEmail = getStringParameter(PARAMETER_USER, ""); + key = getStringParameter(PARAMETER_KEY, ""); + password = getStringParameter(PARAMETER_PASSWORD, ""); + confirmPassword = getStringParameter(PARAMETER_CONFIRM_PASSWORD, ""); + } + + private void validateUserAccountInfo() { + userAccount = userAccountsDao.getUserAccountByEmail(userEmail); + if (userAccount == null) { + log.warn("Create password for '" + userEmail + + "' is bogus: no such user"); + bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; + return; + } + + if (userAccount.getPasswordLinkExpires() == 0L) { + log.warn("Create password for '" + userEmail + + "' is bogus: password change is not pending."); + bogusMessage = "The account for " + userEmail + + " has already been activated."; + return; + } + + Date expirationDate = new Date(userAccount.getPasswordLinkExpires()); + if (expirationDate.before(new Date())) { + log.warn("Create password for '" + userEmail + + "' is bogus: expiration date has passed."); + bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; + return; + } + + String expectedKey = userAccount.getPasswordLinkExpiresHash(); + if (!key.equals(expectedKey)) { + log.warn("Create password for '" + userEmail + "' is bogus: key (" + + key + ") doesn't match expected key (" + expectedKey + + ")"); + bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE; + return; + } + } + + private void validateParameters() { + if (password.isEmpty()) { + errorCode = ERROR_NO_PASSWORD; + } else if (!checkPasswordLength(password)) { + errorCode = ERROR_WRONG_PASSWORD_LENGTH; + } else if (!password.equals(confirmPassword)) { + errorCode = ERROR_PASSWORDS_DONT_MATCH; + } + } + + private boolean checkPasswordLength(String pw) { + return pw.length() >= UserAccount.MIN_PASSWORD_LENGTH + && pw.length() <= UserAccount.MAX_PASSWORD_LENGTH; + } + + public boolean isBogus() { + return bogusMessage.isEmpty(); + } + + public String getBogusMessage() { + return bogusMessage; + } + + public boolean isSubmit() { + return submit; + } + + public boolean isValid() { + return errorCode.isEmpty(); + } + + public void createPassword() { + userAccount.setMd5Password(Authenticator.applyMd5Encoding(password)); + userAccount.setPasswordLinkExpires(0L); + userAccount.setStatus(Status.ACTIVE); + userAccountsDao.updateUserAccount(userAccount); + log.debug("Set password on '" + userAccount.getEmailAddress() + + "' to '" + password + "'"); + } + + public final ResponseValues showPage() { + Map body = new HashMap(); + + body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH); + body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH); + body.put("userAccount", userAccount); + body.put("key", userAccount.getPasswordLinkExpiresHash()); + body.put("password", password); + body.put("confirmPassword", confirmPassword); + body.put("formUrls", buildUrlsMap()); + + if (!errorCode.isEmpty()) { + body.put(errorCode, Boolean.TRUE); + } + + return new TemplateResponseValues(TEMPLATE_NAME, body); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsDeleter.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsDeleter.java index 4096081c5..6549e329c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsDeleter.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsDeleter.java @@ -21,7 +21,7 @@ public class UserAccountsDeleter extends UserAccountsPage { /** Might be empty, but never null. */ private final String[] uris; - protected UserAccountsDeleter(VitroRequest vreq) { + public UserAccountsDeleter(VitroRequest vreq) { super(vreq); String[] values = vreq.getParameterValues(PARAMETER_DELETE_ACCOUNT); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsEditPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsEditPage.java index f9bd23c64..878e9bb6d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsEditPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsEditPage.java @@ -55,14 +55,6 @@ public class UserAccountsEditPage extends UserAccountsPage { throw new RuntimeException("UserAccountsEditPage.getUpdatedAccount() not implemented."); } - /** - * - */ - public void parseParametersAndValidate() { - // TODO Auto-generated method stub - throw new RuntimeException("UserAccountsEditPage.parseParametersAndValidate() not implemented."); - } - /** * @return */ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsListPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsListPage.java index 500f53921..a3d44f2ef 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsListPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsListPage.java @@ -20,8 +20,6 @@ import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Direction; import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; @@ -100,7 +98,7 @@ public class UserAccountsListPage extends UserAccountsPage { userAccountsModel, criteria); Map body = buildTemplateBodyMap(selection); - body.put("newUserAccount", new UserAccountWrapper(vreq, userAccount, + body.put("newUserAccount", new UserAccountWrapper(userAccount, Collections. emptyList())); return new TemplateResponseValues(TEMPLATE_NAME, body); @@ -215,7 +213,7 @@ public class UserAccountsListPage extends UserAccountsPage { UserAccountsSelection selection) { List list = new ArrayList(); for (UserAccount account : selection.getUserAccounts()) { - list.add(new UserAccountWrapper(vreq, account, + list.add(new UserAccountWrapper(account, findPermissionSetLabels(account))); } return list; @@ -240,14 +238,11 @@ public class UserAccountsListPage extends UserAccountsPage { private final List permissionSets; private final String editUrl; - public UserAccountWrapper(VitroRequest vreq, UserAccount account, + public UserAccountWrapper(UserAccount account, List permissionSets) { this.account = account; this.permissionSets = permissionSets; - - UrlBuilder urlBuilder = new UrlBuilder(vreq.getAppBean()); - this.editUrl = urlBuilder.getPortalUrl("/userAccounts/edit", - new ParamMap("editAccount", account.getUri())); + this.editUrl = UserAccountsPage.editAccountUrl(account.getUri()); } public String getUri() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsPage.java index 768e684f3..62254d186 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsPage.java @@ -20,6 +20,7 @@ import com.hp.hpl.jena.ontology.OntModel; import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; @@ -102,11 +103,16 @@ public abstract class UserAccountsPage { protected Map buildUrlsMap() { Map map = new HashMap(); - map.put("list", UrlBuilder.getUrl("/userAccounts/list")); - map.put("add", UrlBuilder.getUrl("/userAccounts/add")); - map.put("delete", UrlBuilder.getUrl("/userAccounts/delete")); + map.put("list", UrlBuilder.getUrl("/accountsAdmin/list")); + map.put("add", UrlBuilder.getUrl("/accountsAdmin/add")); + map.put("delete", UrlBuilder.getUrl("/accountsAdmin/delete")); + map.put("createPassword", UrlBuilder.getUrl("/accounts/createPassword")); return map; } + protected static String editAccountUrl(String uri) { + return UrlBuilder.getUrl("/accountsAdmin/edit", + new ParamMap("editAccount", uri)); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAdminController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAdminController.java new file mode 100644 index 000000000..0747e3b86 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAdminController.java @@ -0,0 +1,94 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.accounts.admin; + +import java.util.Collection; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageUserAccounts; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsAddPage; +import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsDeleter; +import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsEditPage; +import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsListPage; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; + +/** + * Parcel out the different actions required of the Administrators portion of the UserAccounts GUI. + */ +public class UserAccountsAdminController extends FreemarkerHttpServlet { + private static final Log log = LogFactory + .getLog(UserAccountsAdminController.class); + + private static final String ACTION_ADD = "/add"; + private static final String ACTION_DELETE = "/delete"; + private static final String ACTION_EDIT = "/edit"; + + @Override + protected Actions requiredActions(VitroRequest vreq) { + return new Actions(new ManageUserAccounts()); + } + + @Override + protected ResponseValues processRequest(VitroRequest vreq) { + if (log.isDebugEnabled()) { + dumpRequestParameters(vreq); + } + + String action = vreq.getPathInfo(); + log.debug("action = '" + action + "'"); + + if (ACTION_ADD.equals(action)) { + return handleAddRequest(vreq); + } else if (ACTION_EDIT.equals(action)) { + return handleEditRequest(vreq); + } else if (ACTION_DELETE.equals(action)) { + return handleDeleteRequest(vreq); + } else { + return handleListRequest(vreq); + } + } + + private ResponseValues handleAddRequest(VitroRequest vreq) { + UserAccountsAddPage page = new UserAccountsAddPage(vreq); + if (page.isSubmit() && page.isValid()) { + page.createNewAccount(); + + UserAccountsListPage listPage = new UserAccountsListPage(vreq); + return listPage.showPageWithNewAccount(page.getAddedAccount(), + page.wasPasswordEmailSent()); + } else { + return page.showPage(); + } + } + + private ResponseValues handleEditRequest(VitroRequest vreq) { + UserAccountsEditPage page = new UserAccountsEditPage(vreq); + if (page.isSubmit() && page.isValid()) { + page.updateAccount(); + UserAccountsListPage listPage = new UserAccountsListPage(vreq); + return listPage.showPageWithUpdatedAccount( + page.getUpdatedAccount(), page.wasPasswordEmailSent()); + } else { + return page.showPage(); + } + } + + private ResponseValues handleDeleteRequest(VitroRequest vreq) { + UserAccountsDeleter deleter = new UserAccountsDeleter(vreq); + Collection deletedUris = deleter.delete(); + + return new UserAccountsListPage(vreq) + .showPageWithDeletions(deletedUris); + } + + private ResponseValues handleListRequest(VitroRequest vreq) { + UserAccountsListPage page = new UserAccountsListPage(vreq); + return page.showPage(); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java new file mode 100644 index 000000000..761ed0e3a --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java @@ -0,0 +1,72 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.accounts.user; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; +import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsCreatePasswordPage; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; + +/** + * Parcel out the different actions required of the UserAccounts GUI. + */ +public class UserAccountsUserController extends FreemarkerHttpServlet { + private static final Log log = LogFactory + .getLog(UserAccountsUserController.class); + + public static final String BOGUS_STANDARD_MESSAGE = "Request failed. Please contact your system administrator."; + + private static final String ACTION_CREATE_PASSWORD = "/createPassword"; + + @Override + protected Actions requiredActions(VitroRequest vreq) { + return Actions.AUTHORIZED; + } + + @Override + protected ResponseValues processRequest(VitroRequest vreq) { + if (log.isDebugEnabled()) { + dumpRequestParameters(vreq); + } + + String action = vreq.getPathInfo(); + log.debug("action = '" + action + "'"); + + if (ACTION_CREATE_PASSWORD.equals(action)) { + return handleCreatePasswordRequest(vreq); + } else { + return handleInvalidRequest(vreq); + } + } + + private ResponseValues handleCreatePasswordRequest(VitroRequest vreq) { + UserAccountsCreatePasswordPage page = new UserAccountsCreatePasswordPage( + vreq); + if (page.isBogus()) { + return showHomePage(vreq, page.getBogusMessage()); + } else if (page.isSubmit() && page.isValid()) { + page.createPassword(); + return showHomePage(vreq, + "Your password has been saved. Please log in."); + } else { + return page.showPage(); + } + + } + + private ResponseValues handleInvalidRequest(VitroRequest vreq) { + return showHomePage(vreq, BOGUS_STANDARD_MESSAGE); + } + + private ResponseValues showHomePage(VitroRequest vreq, String message) { + DisplayMessage.setMessage(vreq, message); + return new RedirectResponseValues("/"); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/SiteAdminController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/SiteAdminController.java index ebc82cd76..00058d3d9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/SiteAdminController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/SiteAdminController.java @@ -124,7 +124,7 @@ public class SiteAdminController extends FreemarkerHttpServlet { urls.put("users", urlBuilder.getPortalUrl("/listUsers")); } if (PolicyHelper.isAuthorizedForActions(vreq, new ManageUserAccounts())) { - urls.put("userList", urlBuilder.getPortalUrl("/userAccounts")); + urls.put("userList", urlBuilder.getPortalUrl("/accountsAdmin")); } if (PolicyHelper.isAuthorizedForActions(vreq, new EditSiteInformation())) { diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-createdEmail-html.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-html.ftl similarity index 100% rename from webapp/web/templates/freemarker/body/accounts/userAccounts-createdEmail-html.ftl rename to webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-html.ftl diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-createdEmail-text.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-text.ftl similarity index 100% rename from webapp/web/templates/freemarker/body/accounts/userAccounts-createdEmail-text.ftl rename to webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-text.ftl diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl index 58bbca38c..4cbce0936 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl @@ -24,6 +24,18 @@ <#assign errorMessage = "You must select a role." /> + <#if errorPasswordIsEmpty??> + <#assign errorMessage = "No password supplied." /> + + + <#if errorPasswordIsWrongLength??> + <#assign errorMessage = "Password must be between ${minimumLength} and ${maximumLength} characters." /> + + + <#if errorPasswordsDontMatch??> + <#assign errorMessage = "Passwords do not match." /> + + <#if errorMessage?has_content>