NIHVIVO-2279 Implement account editing and password change.
This commit is contained in:
parent
d6bacf0c95
commit
a1915c8398
22 changed files with 1006 additions and 223 deletions
|
@ -3,8 +3,10 @@
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -18,6 +20,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import com.hp.hpl.jena.ontology.OntModel;
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
|
import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
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;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
||||||
|
@ -32,6 +35,12 @@ import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory;
|
||||||
public abstract class UserAccountsPage {
|
public abstract class UserAccountsPage {
|
||||||
private static final Log log = LogFactory.getLog(UserAccountsPage.class);
|
private static final Log log = LogFactory.getLog(UserAccountsPage.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After the account is created, or the password is reset, the user has this
|
||||||
|
* many days to repond to the email.
|
||||||
|
*/
|
||||||
|
protected static final int DAYS_TO_USE_PASSWORD_LINK = 90;
|
||||||
|
|
||||||
protected final VitroRequest vreq;
|
protected final VitroRequest vreq;
|
||||||
protected final ServletContext ctx;
|
protected final ServletContext ctx;
|
||||||
protected final OntModel userAccountsModel;
|
protected final OntModel userAccountsModel;
|
||||||
|
@ -82,6 +91,17 @@ public abstract class UserAccountsPage {
|
||||||
return (value != null);
|
return (value != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat the presence of a certain parameter, with a desired value, as a
|
||||||
|
* boolean flag.
|
||||||
|
*
|
||||||
|
* An example would be radio buttons with values of "yes" and
|
||||||
|
* "no". The expected value would be "yes".
|
||||||
|
*/
|
||||||
|
protected boolean isParameterAsExpected(String key, String expected) {
|
||||||
|
return expected.equals(getStringParameter(key, ""));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a list of all known PermissionSets.
|
* Create a list of all known PermissionSets.
|
||||||
*/
|
*/
|
||||||
|
@ -107,12 +127,25 @@ public abstract class UserAccountsPage {
|
||||||
map.put("add", UrlBuilder.getUrl("/accountsAdmin/add"));
|
map.put("add", UrlBuilder.getUrl("/accountsAdmin/add"));
|
||||||
map.put("delete", UrlBuilder.getUrl("/accountsAdmin/delete"));
|
map.put("delete", UrlBuilder.getUrl("/accountsAdmin/delete"));
|
||||||
map.put("createPassword", UrlBuilder.getUrl("/accounts/createPassword"));
|
map.put("createPassword", UrlBuilder.getUrl("/accounts/createPassword"));
|
||||||
|
map.put("resetPassword", UrlBuilder.getUrl("/accounts/resetPassword"));
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static String editAccountUrl(String uri) {
|
protected static String editAccountUrl(String uri) {
|
||||||
return UrlBuilder.getUrl("/accountsAdmin/edit",
|
return UrlBuilder.getUrl("/accountsAdmin/edit", new ParamMap(
|
||||||
new ParamMap("editAccount", uri));
|
"editAccount", uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Date figureExpirationDate() {
|
||||||
|
Calendar c = Calendar.getInstance();
|
||||||
|
c.add(Calendar.DATE, DAYS_TO_USE_PASSWORD_LINK);
|
||||||
|
return c.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean checkPasswordLength(String pw) {
|
||||||
|
return pw.length() >= UserAccount.MIN_PASSWORD_LENGTH
|
||||||
|
&& pw.length() <= UserAccount.MAX_PASSWORD_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,9 @@ public class UserAccountsAddPage extends UserAccountsPage {
|
||||||
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
|
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
|
||||||
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
|
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
|
||||||
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
|
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
|
||||||
selectedRoleUri = getRoleChoices();
|
selectedRoleUri = getStringParameter(PARAMETER_ROLE, "");
|
||||||
associateWithProfile = getAssociateFlag();
|
associateWithProfile = isParameterAsExpected(
|
||||||
|
PARAMETER_ASSOCIATE_WITH_PROFILE, "yes");
|
||||||
|
|
||||||
strategy.parseAdditionalParameters();
|
strategy.parseAdditionalParameters();
|
||||||
}
|
}
|
||||||
|
@ -126,22 +127,6 @@ public class UserAccountsAddPage extends UserAccountsPage {
|
||||||
strategy.notifyUser();
|
strategy.notifyUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** What role are they asking for? */
|
|
||||||
private String getRoleChoices() {
|
|
||||||
String[] roles = vreq.getParameterValues(PARAMETER_ROLE);
|
|
||||||
if ((roles == null) || (roles.length == 0)) {
|
|
||||||
return "";
|
|
||||||
} else {
|
|
||||||
return roles[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Are they associating with an Individual profile? */
|
|
||||||
private boolean getAssociateFlag() {
|
|
||||||
return "yes".equals(getStringParameter(
|
|
||||||
PARAMETER_ASSOCIATE_WITH_PROFILE, "no"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final ResponseValues showPage() {
|
public final ResponseValues showPage() {
|
||||||
Map<String, Object> body = new HashMap<String, Object>();
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@ import static javax.mail.Message.RecipientType.TO;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -25,7 +23,7 @@ import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
|
||||||
public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
||||||
protected final UserAccountsAddPage page;
|
protected final UserAccountsAddPage page;
|
||||||
|
|
||||||
public static UserAccountsAddPageStrategy getInstance(VitroRequest vreq,
|
public static UserAccountsAddPageStrategy getInstance(VitroRequest vreq,
|
||||||
UserAccountsAddPage page, boolean emailEnabled) {
|
UserAccountsAddPage page, boolean emailEnabled) {
|
||||||
if (emailEnabled) {
|
if (emailEnabled) {
|
||||||
return new EmailStrategy(vreq, page);
|
return new EmailStrategy(vreq, page);
|
||||||
|
@ -34,7 +32,8 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAccountsAddPageStrategy(VitroRequest vreq, UserAccountsAddPage page) {
|
public UserAccountsAddPageStrategy(VitroRequest vreq,
|
||||||
|
UserAccountsAddPage page) {
|
||||||
super(vreq);
|
super(vreq);
|
||||||
this.page = page;
|
this.page = page;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +56,6 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
||||||
|
|
||||||
private static class EmailStrategy extends UserAccountsAddPageStrategy {
|
private static class EmailStrategy extends UserAccountsAddPageStrategy {
|
||||||
public static final String CREATE_PASSWORD_URL = "/accounts/createPassword";
|
public static final String CREATE_PASSWORD_URL = "/accounts/createPassword";
|
||||||
private static final int DAYS_TO_ACTIVATE_ACCOUNT = 90;
|
|
||||||
|
|
||||||
private boolean sentEmail;
|
private boolean sentEmail;
|
||||||
|
|
||||||
|
@ -81,12 +79,6 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
||||||
u.setPasswordLinkExpires(figureExpirationDate().getTime());
|
u.setPasswordLinkExpires(figureExpirationDate().getTime());
|
||||||
u.setStatus(Status.INACTIVE);
|
u.setStatus(Status.INACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Date figureExpirationDate() {
|
|
||||||
Calendar c = Calendar.getInstance();
|
|
||||||
c.add(Calendar.DATE, DAYS_TO_ACTIVATE_ACCOUNT);
|
|
||||||
return c.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addMoreBodyValues(Map<String, Object> body) {
|
protected void addMoreBodyValues(Map<String, Object> body) {
|
||||||
|
@ -117,9 +109,9 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
||||||
String email = page.getAddedAccount().getEmailAddress();
|
String email = page.getAddedAccount().getEmailAddress();
|
||||||
String hash = page.getAddedAccount()
|
String hash = page.getAddedAccount()
|
||||||
.getPasswordLinkExpiresHash();
|
.getPasswordLinkExpiresHash();
|
||||||
String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL, "user",
|
String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL,
|
||||||
email, "key", hash);
|
"user", email, "key", hash);
|
||||||
|
|
||||||
URL context = new URL(vreq.getRequestURL().toString());
|
URL context = new URL(vreq.getRequestURL().toString());
|
||||||
URL url = new URL(context, relativeUrl);
|
URL url = new URL(context, relativeUrl);
|
||||||
return url.toExternalForm();
|
return url.toExternalForm();
|
||||||
|
@ -127,7 +119,7 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
||||||
return "error_creating_password_link";
|
return "error_creating_password_link";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean wasPasswordEmailSent() {
|
protected boolean wasPasswordEmailSent() {
|
||||||
return sentEmail;
|
return sentEmail;
|
||||||
|
@ -156,10 +148,8 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void parseAdditionalParameters() {
|
protected void parseAdditionalParameters() {
|
||||||
initialPassword = getStringParameter(
|
initialPassword = getStringParameter(PARAMETER_INITIAL_PASSWORD, "");
|
||||||
PARAMETER_INITIAL_PASSWORD, "");
|
confirmPassword = getStringParameter(PARAMETER_CONFIRM_PASSWORD, "");
|
||||||
confirmPassword = getStringParameter(
|
|
||||||
PARAMETER_CONFIRM_PASSWORD, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -184,6 +174,8 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
|
||||||
protected void addMoreBodyValues(Map<String, Object> body) {
|
protected void addMoreBodyValues(Map<String, Object> body) {
|
||||||
body.put("initialPassword", initialPassword);
|
body.put("initialPassword", initialPassword);
|
||||||
body.put("confirmPassword", confirmPassword);
|
body.put("confirmPassword", confirmPassword);
|
||||||
|
body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH);
|
||||||
|
body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,12 +9,15 @@ import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
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.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.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
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;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parcel out the different actions required of the Administrators portion of the UserAccounts GUI.
|
* Parcel out the different actions required of the Administrators portion of
|
||||||
|
* the UserAccounts GUI.
|
||||||
*/
|
*/
|
||||||
public class UserAccountsAdminController extends FreemarkerHttpServlet {
|
public class UserAccountsAdminController extends FreemarkerHttpServlet {
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
|
@ -64,7 +67,9 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
private ResponseValues handleEditRequest(VitroRequest vreq) {
|
private ResponseValues handleEditRequest(VitroRequest vreq) {
|
||||||
UserAccountsEditPage page = new UserAccountsEditPage(vreq);
|
UserAccountsEditPage page = new UserAccountsEditPage(vreq);
|
||||||
if (page.isSubmit() && page.isValid()) {
|
if (page.isBogus()) {
|
||||||
|
return showHomePage(vreq, page.getBogusMessage());
|
||||||
|
} else if (page.isSubmit() && page.isValid()) {
|
||||||
page.updateAccount();
|
page.updateAccount();
|
||||||
UserAccountsListPage listPage = new UserAccountsListPage(vreq);
|
UserAccountsListPage listPage = new UserAccountsListPage(vreq);
|
||||||
return listPage.showPageWithUpdatedAccount(
|
return listPage.showPageWithUpdatedAccount(
|
||||||
|
@ -87,4 +92,9 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
|
||||||
return page.showPage();
|
return page.showPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResponseValues showHomePage(VitroRequest vreq, String message) {
|
||||||
|
DisplayMessage.setMessage(vreq, message);
|
||||||
|
return new RedirectResponseValues("/");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,75 +2,217 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.accounts.admin;
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts.admin;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
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;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
|
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsUserController;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO present the form. Get the submission.
|
* TODO present the form. Get the submission.
|
||||||
*
|
*
|
||||||
* TODO If email is available, present the reset flag with message templage, and send email
|
* TODO If email is available, present the reset flag with message templage, and
|
||||||
|
* send email
|
||||||
*
|
*
|
||||||
* TODO if email is not available, allow password change with checks for validity
|
* TODO if email is not available, allow password change with checks for
|
||||||
|
* validity
|
||||||
*
|
*
|
||||||
* TODO If successful, go to AccountsList with message and optional password message.
|
* TODO If successful, go to AccountsList with message and optional password
|
||||||
|
* message.
|
||||||
*
|
*
|
||||||
* TODO if unsuccessful, go back to the page, with errors.
|
* TODO if unsuccessful, go back to the page, with errors.
|
||||||
*
|
*
|
||||||
* TODO How much of this can be shared with AddPage? Email templates?
|
* TODO How much of this can be shared with AddPage? Email templates?
|
||||||
*/
|
*/
|
||||||
public class UserAccountsEditPage extends UserAccountsPage {
|
public class UserAccountsEditPage extends UserAccountsPage {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(UserAccountsEditPage.class);
|
||||||
|
|
||||||
|
private static final String PARAMETER_SUBMIT = "submitEdit";
|
||||||
|
private static final String PARAMETER_USER_URI = "editAccount";
|
||||||
|
private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress";
|
||||||
|
private static final String PARAMETER_FIRST_NAME = "firstName";
|
||||||
|
private static final String PARAMETER_LAST_NAME = "lastName";
|
||||||
|
private static final String PARAMETER_ROLE = "role";
|
||||||
|
private static final String PARAMETER_ASSOCIATE_WITH_PROFILE = "associate";
|
||||||
|
|
||||||
|
private static final String ERROR_NO_EMAIL = "errorEmailIsEmpty";
|
||||||
|
private static final String ERROR_EMAIL_IN_USE = "errorEmailInUse";
|
||||||
|
private static final String ERROR_NO_FIRST_NAME = "errorFirstNameIsEmpty";
|
||||||
|
private static final String ERROR_NO_LAST_NAME = "errorLastNameIsEmpty";
|
||||||
|
private static final String ERROR_NO_ROLE = "errorNoRoleSelected";
|
||||||
|
|
||||||
private static final String TEMPLATE_NAME = "userAccounts-edit.ftl";
|
private static final String TEMPLATE_NAME = "userAccounts-edit.ftl";
|
||||||
|
|
||||||
|
private final UserAccountsEditPageStrategy strategy;
|
||||||
|
|
||||||
|
/* The request parameters */
|
||||||
|
private boolean submit;
|
||||||
|
private String userUri = "";
|
||||||
|
private String emailAddress = "";
|
||||||
|
private String firstName = "";
|
||||||
|
private String lastName = "";
|
||||||
|
private String selectedRoleUri = "";
|
||||||
|
private boolean associateWithProfile;
|
||||||
|
|
||||||
|
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 UserAccountsEditPage(VitroRequest vreq) {
|
public UserAccountsEditPage(VitroRequest vreq) {
|
||||||
super(vreq);
|
super(vreq);
|
||||||
|
|
||||||
|
this.strategy = UserAccountsEditPageStrategy.getInstance(vreq, this,
|
||||||
|
isEmailEnabled(vreq));
|
||||||
|
|
||||||
|
parseRequestParameters();
|
||||||
|
validateUserAccountInfo();
|
||||||
|
|
||||||
|
if (isSubmit() && !isBogus()) {
|
||||||
|
validateParameters();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResponseValues showPage() {
|
private void parseRequestParameters() {
|
||||||
return new TemplateResponseValues(TEMPLATE_NAME);
|
submit = isFlagOnRequest(PARAMETER_SUBMIT);
|
||||||
|
userUri = getStringParameter(PARAMETER_USER_URI, "");
|
||||||
|
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
|
||||||
|
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
|
||||||
|
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
|
||||||
|
selectedRoleUri = getStringParameter(PARAMETER_ROLE, "");
|
||||||
|
associateWithProfile = isParameterAsExpected(
|
||||||
|
PARAMETER_ASSOCIATE_WITH_PROFILE, "yes");
|
||||||
|
|
||||||
|
strategy.parseAdditionalParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void validateUserAccountInfo() {
|
||||||
* @return
|
userAccount = userAccountsDao.getUserAccountByUri(userUri);
|
||||||
*/
|
if (userAccount == null) {
|
||||||
public UserAccount updateAccount() {
|
log.warn("Edit account for '" + userUri
|
||||||
// TODO Auto-generated method stub
|
+ "' is bogus: no such user");
|
||||||
throw new RuntimeException("UserAccountsEditPage.updateAccount() not implemented.");
|
bogusMessage = UserAccountsUserController.BOGUS_STANDARD_MESSAGE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public boolean isBogus() {
|
||||||
* @return
|
return !bogusMessage.isEmpty();
|
||||||
*/
|
|
||||||
public boolean wasPasswordEmailSent() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new RuntimeException("UserAccountsEditPage.wasPasswordEmailSent() not implemented.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public String getBogusMessage() {
|
||||||
* @return
|
return bogusMessage;
|
||||||
*/
|
|
||||||
public UserAccount getUpdatedAccount() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new RuntimeException("UserAccountsEditPage.getUpdatedAccount() not implemented.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isValid() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new RuntimeException("UserAccountsEditPage.isValid() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isSubmit() {
|
public boolean isSubmit() {
|
||||||
// TODO Auto-generated method stub
|
return submit;
|
||||||
throw new RuntimeException("UserAccountsEditPage.isSubmit() not implemented.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateParameters() {
|
||||||
|
if (emailAddress.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_EMAIL;
|
||||||
|
} else if (emailIsChanged() && isEmailInUse()) {
|
||||||
|
errorCode = ERROR_EMAIL_IN_USE;
|
||||||
|
} else if (firstName.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_FIRST_NAME;
|
||||||
|
} else if (lastName.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_LAST_NAME;
|
||||||
|
} else if (selectedRoleUri.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_ROLE;
|
||||||
|
} else {
|
||||||
|
errorCode = strategy.additionalValidations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean emailIsChanged() {
|
||||||
|
return !emailAddress.equals(userAccount.getEmailAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEmailInUse() {
|
||||||
|
return userAccountsDao.getUserAccountByEmail(emailAddress) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return errorCode.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ResponseValues showPage() {
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
if (isSubmit()) {
|
||||||
|
body.put("emailAddress", emailAddress);
|
||||||
|
body.put("firstName", firstName);
|
||||||
|
body.put("lastName", lastName);
|
||||||
|
body.put("selectedRole", selectedRoleUri);
|
||||||
|
} else {
|
||||||
|
body.put("emailAddress", userAccount.getEmailAddress());
|
||||||
|
body.put("firstName", userAccount.getFirstName());
|
||||||
|
body.put("lastName", userAccount.getLastName());
|
||||||
|
body.put("selectedRole", getExistingRoleUri());
|
||||||
|
}
|
||||||
|
body.put("roles", buildRolesList());
|
||||||
|
if (associateWithProfile) {
|
||||||
|
body.put("associate", Boolean.TRUE);
|
||||||
|
}
|
||||||
|
body.put("formUrls", buildUrlsMapWithEditUrl());
|
||||||
|
|
||||||
|
if (!errorCode.isEmpty()) {
|
||||||
|
body.put(errorCode, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
strategy.addMoreBodyValues(body);
|
||||||
|
|
||||||
|
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getExistingRoleUri() {
|
||||||
|
Set<String> uris = userAccount.getPermissionSetUris();
|
||||||
|
if (uris.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return uris.iterator().next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> buildUrlsMapWithEditUrl() {
|
||||||
|
Map<String, String> map = buildUrlsMap();
|
||||||
|
map.put("edit", editAccountUrl(userAccount.getUri()));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAccount() {
|
||||||
|
userAccount.setEmailAddress(emailAddress);
|
||||||
|
userAccount.setFirstName(firstName);
|
||||||
|
userAccount.setLastName(lastName);
|
||||||
|
|
||||||
|
userAccount.setPermissionSetUris(Collections.singleton(selectedRoleUri));
|
||||||
|
|
||||||
|
strategy.setAdditionalProperties(userAccount);
|
||||||
|
|
||||||
|
userAccountsDao.updateUserAccount(userAccount);
|
||||||
|
|
||||||
|
strategy.notifyUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wasPasswordEmailSent() {
|
||||||
|
return strategy.wasPasswordEmailSent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserAccount getUpdatedAccount() {
|
||||||
|
return userAccount;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts.admin;
|
||||||
|
|
||||||
|
import static javax.mail.Message.RecipientType.TO;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
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.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the variant details of the UserAccountsAddPage.
|
||||||
|
*/
|
||||||
|
public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
|
||||||
|
protected final UserAccountsEditPage page;
|
||||||
|
|
||||||
|
public static UserAccountsEditPageStrategy getInstance(VitroRequest vreq,
|
||||||
|
UserAccountsEditPage page, boolean emailEnabled) {
|
||||||
|
if (emailEnabled) {
|
||||||
|
return new EmailStrategy(vreq, page);
|
||||||
|
} else {
|
||||||
|
return new NoEmailStrategy(vreq, page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserAccountsEditPageStrategy(VitroRequest vreq,
|
||||||
|
UserAccountsEditPage page) {
|
||||||
|
super(vreq);
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void parseAdditionalParameters();
|
||||||
|
|
||||||
|
protected abstract String additionalValidations();
|
||||||
|
|
||||||
|
protected abstract void addMoreBodyValues(Map<String, Object> body);
|
||||||
|
|
||||||
|
protected abstract void setAdditionalProperties(UserAccount u);
|
||||||
|
|
||||||
|
protected abstract void notifyUser();
|
||||||
|
|
||||||
|
protected abstract boolean wasPasswordEmailSent();
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Strategy to use if email is enabled.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private static class EmailStrategy extends UserAccountsEditPageStrategy {
|
||||||
|
private static final String PARAMETER_RESET_PASSWORD = "resetPassword";
|
||||||
|
|
||||||
|
public static final String RESET_PASSWORD_URL = "/accounts/resetPassword";
|
||||||
|
|
||||||
|
private boolean resetPassword;
|
||||||
|
private boolean sentEmail;
|
||||||
|
|
||||||
|
public EmailStrategy(VitroRequest vreq, UserAccountsEditPage page) {
|
||||||
|
super(vreq, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseAdditionalParameters() {
|
||||||
|
resetPassword = isFlagOnRequest(PARAMETER_RESET_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String additionalValidations() {
|
||||||
|
// No additional validations
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setAdditionalProperties(UserAccount u) {
|
||||||
|
if (resetPassword) {
|
||||||
|
u.setPasswordLinkExpires(figureExpirationDate().getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addMoreBodyValues(Map<String, Object> body) {
|
||||||
|
body.put("emailIsEnabled", Boolean.TRUE);
|
||||||
|
if (resetPassword) {
|
||||||
|
body.put("resetPassword", Boolean.TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void notifyUser() {
|
||||||
|
if (!resetPassword) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
body.put("userAccount", page.getUpdatedAccount());
|
||||||
|
body.put("passwordLink", buildResetPasswordLink());
|
||||||
|
body.put("subjectLine", "Reset password request");
|
||||||
|
|
||||||
|
FreemarkerEmailMessage email = FreemarkerEmailFactory
|
||||||
|
.createNewMessage(vreq);
|
||||||
|
email.addRecipient(TO, page.getUpdatedAccount().getEmailAddress());
|
||||||
|
email.setSubject("Reset password request");
|
||||||
|
email.setHtmlTemplate("userAccounts-resetPasswordEmail-html.ftl");
|
||||||
|
email.setTextTemplate("userAccounts-resetPasswordEmail-text.ftl");
|
||||||
|
email.setBodyMap(body);
|
||||||
|
email.send();
|
||||||
|
|
||||||
|
sentEmail = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildResetPasswordLink() {
|
||||||
|
try {
|
||||||
|
String email = page.getUpdatedAccount().getEmailAddress();
|
||||||
|
String hash = page.getUpdatedAccount()
|
||||||
|
.getPasswordLinkExpiresHash();
|
||||||
|
String relativeUrl = UrlBuilder.getUrl(RESET_PASSWORD_URL,
|
||||||
|
"user", email, "key", hash);
|
||||||
|
|
||||||
|
URL context = new URL(vreq.getRequestURL().toString());
|
||||||
|
URL url = new URL(context, relativeUrl);
|
||||||
|
return url.toExternalForm();
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
return "error_creating_password_link";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean wasPasswordEmailSent() {
|
||||||
|
return sentEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Strategy to use if email is not enabled.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private static class NoEmailStrategy extends UserAccountsEditPageStrategy {
|
||||||
|
private static final String PARAMETER_NEW_PASSWORD = "newPassword";
|
||||||
|
private static final String PARAMETER_CONFIRM_PASSWORD = "confirmPassword";
|
||||||
|
|
||||||
|
private static final String ERROR_WRONG_PASSWORD_LENGTH = "errorPasswordIsWrongLength";
|
||||||
|
private static final String ERROR_PASSWORDS_DONT_MATCH = "errorPasswordsDontMatch";
|
||||||
|
|
||||||
|
private String newPassword;
|
||||||
|
private String confirmPassword;
|
||||||
|
|
||||||
|
public NoEmailStrategy(VitroRequest vreq, UserAccountsEditPage page) {
|
||||||
|
super(vreq, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseAdditionalParameters() {
|
||||||
|
newPassword = getStringParameter(PARAMETER_NEW_PASSWORD, "");
|
||||||
|
confirmPassword = getStringParameter(PARAMETER_CONFIRM_PASSWORD, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String additionalValidations() {
|
||||||
|
if (newPassword.isEmpty() && confirmPassword.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
} else if (!checkPasswordLength()) {
|
||||||
|
return ERROR_WRONG_PASSWORD_LENGTH;
|
||||||
|
} else if (!newPassword.equals(confirmPassword)) {
|
||||||
|
return ERROR_PASSWORDS_DONT_MATCH;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkPasswordLength() {
|
||||||
|
return newPassword.length() >= UserAccount.MIN_PASSWORD_LENGTH
|
||||||
|
&& newPassword.length() <= UserAccount.MAX_PASSWORD_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addMoreBodyValues(Map<String, Object> body) {
|
||||||
|
body.put("newPassword", newPassword);
|
||||||
|
body.put("confirmPassword", confirmPassword);
|
||||||
|
body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH);
|
||||||
|
body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setAdditionalProperties(UserAccount u) {
|
||||||
|
u.setMd5Password(newPassword);
|
||||||
|
u.setPasswordChangeRequired(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void notifyUser() {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean wasPasswordEmailSent() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -105,6 +105,9 @@ public class UserAccountsListPage extends UserAccountsPage {
|
||||||
|
|
||||||
body.put("newUserAccount", new UserAccountWrapper(userAccount,
|
body.put("newUserAccount", new UserAccountWrapper(userAccount,
|
||||||
Collections.<String> emptyList()));
|
Collections.<String> emptyList()));
|
||||||
|
if (emailWasSent) {
|
||||||
|
body.put("emailWasSent", Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
||||||
}
|
}
|
||||||
|
@ -114,8 +117,17 @@ public class UserAccountsListPage extends UserAccountsPage {
|
||||||
*/
|
*/
|
||||||
public ResponseValues showPageWithUpdatedAccount(UserAccount userAccount,
|
public ResponseValues showPageWithUpdatedAccount(UserAccount userAccount,
|
||||||
boolean emailWasSent) {
|
boolean emailWasSent) {
|
||||||
throw new RuntimeException(
|
UserAccountsSelection selection = UserAccountsSelector.select(
|
||||||
"UserAccountsListPage.showPageWithUpdatedAccount not implemented.");
|
userAccountsModel, criteria);
|
||||||
|
Map<String, Object> body = buildTemplateBodyMap(selection);
|
||||||
|
|
||||||
|
body.put("updatedUserAccount", new UserAccountWrapper(userAccount,
|
||||||
|
Collections.<String> emptyList()));
|
||||||
|
if (emailWasSent) {
|
||||||
|
body.put("emailWasSent", Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,165 +2,68 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
|
||||||
|
|
||||||
import java.util.Date;
|
import static javax.mail.Message.RecipientType.TO;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
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.beans.UserAccount.Status;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
|
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.email.FreemarkerEmailFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the user clicks on the link in their notification email, handle their
|
* When the user clicks on the link in their notification email, handle their
|
||||||
* request to create a password.
|
* request to create a password.
|
||||||
*/
|
*/
|
||||||
public class UserAccountsCreatePasswordPage extends UserAccountsPage {
|
public class UserAccountsCreatePasswordPage extends
|
||||||
|
UserAccountsPasswordBasePage {
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
.getLog(UserAccountsCreatePasswordPage.class);
|
.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 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) {
|
public UserAccountsCreatePasswordPage(VitroRequest vreq) {
|
||||||
super(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() {
|
public void createPassword() {
|
||||||
userAccount.setMd5Password(Authenticator.applyMd5Encoding(password));
|
userAccount.setMd5Password(Authenticator.applyMd5Encoding(newPassword));
|
||||||
userAccount.setPasswordLinkExpires(0L);
|
userAccount.setPasswordLinkExpires(0L);
|
||||||
userAccount.setStatus(Status.ACTIVE);
|
userAccount.setStatus(Status.ACTIVE);
|
||||||
userAccountsDao.updateUserAccount(userAccount);
|
userAccountsDao.updateUserAccount(userAccount);
|
||||||
log.debug("Set password on '" + userAccount.getEmailAddress()
|
log.debug("Set password on '" + userAccount.getEmailAddress()
|
||||||
+ "' to '" + password + "'");
|
+ "' to '" + newPassword + "'");
|
||||||
|
|
||||||
|
notifyUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final ResponseValues showPage() {
|
@Override
|
||||||
|
protected String passwordChangeNotPendingMessage() {
|
||||||
|
return "The account for " + userEmail + " has already been activated.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String templateName() {
|
||||||
|
return TEMPLATE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyUser() {
|
||||||
Map<String, Object> body = new HashMap<String, Object>();
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
|
||||||
body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH);
|
|
||||||
body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH);
|
|
||||||
body.put("userAccount", userAccount);
|
body.put("userAccount", userAccount);
|
||||||
body.put("key", userAccount.getPasswordLinkExpiresHash());
|
body.put("subjectLine", "Password successfully created.");
|
||||||
body.put("password", password);
|
|
||||||
body.put("confirmPassword", confirmPassword);
|
|
||||||
body.put("formUrls", buildUrlsMap());
|
|
||||||
|
|
||||||
if (!errorCode.isEmpty()) {
|
FreemarkerEmailMessage email = FreemarkerEmailFactory
|
||||||
body.put(errorCode, Boolean.TRUE);
|
.createNewMessage(vreq);
|
||||||
}
|
email.addRecipient(TO, userAccount.getEmailAddress());
|
||||||
|
email.setSubject("Password successfully created.");
|
||||||
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
email.setHtmlTemplate("userAccounts-passwordCreatedEmail-html.ftl");
|
||||||
|
email.setTextTemplate("userAccounts-passwordCreatedEmail-text.ftl");
|
||||||
|
email.setBodyMap(body);
|
||||||
|
email.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
|
||||||
|
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsUserController.BOGUS_STANDARD_MESSAGE;
|
||||||
|
|
||||||
|
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.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routines in common to the "Create Password" and "Reset Password" pages.
|
||||||
|
*/
|
||||||
|
public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(UserAccountsPasswordBasePage.class);
|
||||||
|
|
||||||
|
private static final String PARAMETER_SUBMIT = "submit";
|
||||||
|
private static final String PARAMETER_USER = "user";
|
||||||
|
private static final String PARAMETER_KEY = "key";
|
||||||
|
private static final String PARAMETER_NEW_PASSWORD = "newPassword";
|
||||||
|
private static final String PARAMETER_CONFIRM_PASSWORD = "confirmPassword";
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
protected boolean submit;
|
||||||
|
protected String userEmail = "";
|
||||||
|
protected String key = "";
|
||||||
|
protected String newPassword = "";
|
||||||
|
protected String confirmPassword = "";
|
||||||
|
|
||||||
|
protected 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 = "";
|
||||||
|
|
||||||
|
protected UserAccountsPasswordBasePage(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, "");
|
||||||
|
newPassword = getStringParameter(PARAMETER_NEW_PASSWORD, "");
|
||||||
|
confirmPassword = getStringParameter(PARAMETER_CONFIRM_PASSWORD, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubmit() {
|
||||||
|
return submit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateUserAccountInfo() {
|
||||||
|
userAccount = userAccountsDao.getUserAccountByEmail(userEmail);
|
||||||
|
if (userAccount == null) {
|
||||||
|
log.warn("Password request for '" + userEmail
|
||||||
|
+ "' is bogus: no such user");
|
||||||
|
bogusMessage = BOGUS_STANDARD_MESSAGE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userAccount.getPasswordLinkExpires() == 0L) {
|
||||||
|
log.warn("Password request for '" + userEmail
|
||||||
|
+ "' is bogus: password change is not pending.");
|
||||||
|
bogusMessage = passwordChangeNotPendingMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Date expirationDate = new Date(userAccount.getPasswordLinkExpires());
|
||||||
|
if (expirationDate.before(new Date())) {
|
||||||
|
log.warn("Password request for '" + userEmail
|
||||||
|
+ "' is bogus: expiration date has passed.");
|
||||||
|
bogusMessage = BOGUS_STANDARD_MESSAGE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String expectedKey = userAccount.getPasswordLinkExpiresHash();
|
||||||
|
if (!key.equals(expectedKey)) {
|
||||||
|
log.warn("Password request for '" + userEmail + "' is bogus: key ("
|
||||||
|
+ key + ") doesn't match expected key (" + expectedKey
|
||||||
|
+ ")");
|
||||||
|
bogusMessage = BOGUS_STANDARD_MESSAGE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBogus() {
|
||||||
|
return !bogusMessage.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBogusMessage() {
|
||||||
|
return bogusMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateParameters() {
|
||||||
|
if (newPassword.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_PASSWORD;
|
||||||
|
} else if (!checkPasswordLength(newPassword)) {
|
||||||
|
errorCode = ERROR_WRONG_PASSWORD_LENGTH;
|
||||||
|
} else if (!newPassword.equals(confirmPassword)) {
|
||||||
|
errorCode = ERROR_PASSWORDS_DONT_MATCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return errorCode.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ResponseValues showPage() {
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
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("newPassword", newPassword);
|
||||||
|
body.put("confirmPassword", confirmPassword);
|
||||||
|
body.put("formUrls", buildUrlsMap());
|
||||||
|
|
||||||
|
if (!errorCode.isEmpty()) {
|
||||||
|
body.put(errorCode, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TemplateResponseValues(templateName(), body);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String passwordChangeNotPendingMessage();
|
||||||
|
protected abstract String templateName();
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
|
||||||
|
|
||||||
|
import static javax.mail.Message.RecipientType.TO;
|
||||||
|
|
||||||
|
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.Status;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the user clicks on the link in their notification email, handle their
|
||||||
|
* request to reset their password.
|
||||||
|
*/
|
||||||
|
public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(UserAccountsResetPasswordPage.class);
|
||||||
|
|
||||||
|
private static final String TEMPLATE_NAME = "userAccounts-resetPassword.ftl";
|
||||||
|
|
||||||
|
protected UserAccountsResetPasswordPage(VitroRequest vreq) {
|
||||||
|
super(vreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetPassword() {
|
||||||
|
userAccount.setMd5Password(Authenticator.applyMd5Encoding(newPassword));
|
||||||
|
userAccount.setPasswordLinkExpires(0L);
|
||||||
|
userAccount.setStatus(Status.ACTIVE);
|
||||||
|
userAccountsDao.updateUserAccount(userAccount);
|
||||||
|
log.debug("Set password on '" + userAccount.getEmailAddress()
|
||||||
|
+ "' to '" + newPassword + "'");
|
||||||
|
|
||||||
|
notifyUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String passwordChangeNotPendingMessage() {
|
||||||
|
return "The password for " + userEmail + " has already been reset.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String templateName() {
|
||||||
|
return TEMPLATE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyUser() {
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
body.put("userAccount", userAccount);
|
||||||
|
body.put("subjectLine", "Password changed.");
|
||||||
|
|
||||||
|
FreemarkerEmailMessage email = FreemarkerEmailFactory
|
||||||
|
.createNewMessage(vreq);
|
||||||
|
email.addRecipient(TO, userAccount.getEmailAddress());
|
||||||
|
email.setSubject("Password changed.");
|
||||||
|
email.setHtmlTemplate("userAccounts-passwordResetEmail-html.ftl");
|
||||||
|
email.setTextTemplate("userAccounts-passwordResetEmail-text.ftl");
|
||||||
|
email.setBodyMap(body);
|
||||||
|
email.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
||||||
public static final String BOGUS_STANDARD_MESSAGE = "Request failed. Please contact your system administrator.";
|
public static final String BOGUS_STANDARD_MESSAGE = "Request failed. Please contact your system administrator.";
|
||||||
|
|
||||||
private static final String ACTION_CREATE_PASSWORD = "/createPassword";
|
private static final String ACTION_CREATE_PASSWORD = "/createPassword";
|
||||||
|
private static final String ACTION_RESET_PASSWORD = "/resetPassword";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Actions requiredActions(VitroRequest vreq) {
|
protected Actions requiredActions(VitroRequest vreq) {
|
||||||
|
@ -39,6 +40,8 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
if (ACTION_CREATE_PASSWORD.equals(action)) {
|
if (ACTION_CREATE_PASSWORD.equals(action)) {
|
||||||
return handleCreatePasswordRequest(vreq);
|
return handleCreatePasswordRequest(vreq);
|
||||||
|
} else if (ACTION_RESET_PASSWORD.equals(action)) {
|
||||||
|
return handleResetPasswordRequest(vreq);
|
||||||
} else {
|
} else {
|
||||||
return handleInvalidRequest(vreq);
|
return handleInvalidRequest(vreq);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +62,21 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResponseValues handleResetPasswordRequest(VitroRequest vreq) {
|
||||||
|
UserAccountsResetPasswordPage page = new UserAccountsResetPasswordPage(
|
||||||
|
vreq);
|
||||||
|
if (page.isBogus()) {
|
||||||
|
return showHomePage(vreq, page.getBogusMessage());
|
||||||
|
} else if (page.isSubmit() && page.isValid()) {
|
||||||
|
page.resetPassword();
|
||||||
|
return showHomePage(vreq,
|
||||||
|
"Your password has been saved. Please log in.");
|
||||||
|
} else {
|
||||||
|
return page.showPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private ResponseValues handleInvalidRequest(VitroRequest vreq) {
|
private ResponseValues handleInvalidRequest(VitroRequest vreq) {
|
||||||
return showHomePage(vreq, BOGUS_STANDARD_MESSAGE);
|
return showHomePage(vreq, BOGUS_STANDARD_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,8 @@
|
||||||
<label for="initial-password">Initial password<span class="requiredHint"> *</span></label>
|
<label for="initial-password">Initial password<span class="requiredHint"> *</span></label>
|
||||||
<input type="password" name="initialPassword" value="${initialPassword}" id="initial-password" role="input "/>
|
<input type="password" name="initialPassword" value="${initialPassword}" id="initial-password" role="input "/>
|
||||||
|
|
||||||
|
<p>Minimum of ${minimumLength} characters in length.</p>
|
||||||
|
|
||||||
<label for="confirm-password">Confirm initial password<span class="requiredHint"> *</span></label>
|
<label for="confirm-password">Confirm initial password<span class="requiredHint"> *</span></label>
|
||||||
<input type="text" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input "/>
|
<input type="text" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input "/>
|
||||||
</#if>
|
</#if>
|
||||||
|
@ -79,10 +81,6 @@
|
||||||
<input type="radio" name="associate" value="no" role="radio" <#if !associate??>checked</#if> id="no-associate" />
|
<input type="radio" name="associate" value="no" role="radio" <#if !associate??>checked</#if> id="no-associate" />
|
||||||
<label class="inline" for="no-associate"> No</label>
|
<label class="inline" for="no-associate"> No</label>
|
||||||
|
|
||||||
<br />
|
|
||||||
<input type="checkbox" name="resetPassword" value="" id="reset-password" role="checkbox" />
|
|
||||||
<label class="inline" for="reset-password"> Reset password</label>
|
|
||||||
|
|
||||||
<#if emailIsEnabled??>
|
<#if emailIsEnabled??>
|
||||||
<p class="note">
|
<p class="note">
|
||||||
Note: An email will be sent to the address entered above
|
Note: An email will be sent to the address entered above
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<#-- Template for adding a user account -->
|
<#-- Template for adding a user account -->
|
||||||
|
|
||||||
<h3>Add new account</h3>
|
<h3>Create your Password</h3>
|
||||||
|
|
||||||
<#if errorPasswordIsEmpty??>
|
<#if errorPasswordIsEmpty??>
|
||||||
<#assign errorMessage = "No password supplied." />
|
<#assign errorMessage = "No password supplied." />
|
||||||
|
@ -23,23 +23,23 @@
|
||||||
</section>
|
</section>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<section id="add-account" role="region">
|
<section id="create-password" role="region">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Add new account</legend>
|
<legend>Please enter your new password for ${userAccount.emailAddress}</legend>
|
||||||
|
|
||||||
<form method="POST" action="${formUrls.createPassword}" class="customForm" role="create password">
|
<form method="POST" action="${formUrls.createPassword}" class="customForm" role="create password">
|
||||||
<input type="hidden" name="user" value="${userAccount.emailAddress}" />
|
<input type="hidden" name="user" value="${userAccount.emailAddress}" />
|
||||||
<input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" />
|
<input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" />
|
||||||
|
|
||||||
<label for="password">Password<span class="requiredHint"> *</span></label>
|
<label for="new-password">Password<span class="requiredHint"> *</span></label>
|
||||||
<input type="password" name="password" value="${password}" id="password" role="input "/>
|
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input "/>
|
||||||
|
|
||||||
<p>Minimum of ${minimumLength} characters in length.</p>
|
<p>Minimum of ${minimumLength} characters in length.</p>
|
||||||
|
|
||||||
<label for="confirm-password">Confirm Password<span class="requiredHint"> *</span></label>
|
<label for="confirm-password">Confirm Password<span class="requiredHint"> *</span></label>
|
||||||
<input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input "/>
|
<input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input "/>
|
||||||
|
|
||||||
<input type="submit" name="submitCreatePassword" value="Save changes" class="submit"/>
|
<input type="submit" name="submit" value="Save changes" class="submit"/>
|
||||||
|
|
||||||
<p class="requiredHint">* required fields</p>
|
<p class="requiredHint">* required fields</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,5 +2,103 @@
|
||||||
|
|
||||||
<#-- Template for editing a user account -->
|
<#-- Template for editing a user account -->
|
||||||
|
|
||||||
<h3>Edit user account</h3>
|
<h3>Edit account</h3>
|
||||||
|
|
||||||
|
<#if errorEmailIsEmpty??>
|
||||||
|
<#assign errorMessage = "You must supply an email address." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorEmailInUse??>
|
||||||
|
<#assign errorMessage = "An account with that email address already exists." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorFirstNameIsEmpty??>
|
||||||
|
<#assign errorMessage = "You must supply a first name." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorLastNameIsEmpty??>
|
||||||
|
<#assign errorMessage = "You must supply a last name." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorNoRoleSelected??>
|
||||||
|
<#assign errorMessage = "You must select a role." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorPasswordIsEmpty??>
|
||||||
|
<#assign errorMessage = "No password supplied." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorPasswordIsWrongLength??>
|
||||||
|
<#assign errorMessage = "Password must be between ${minimumLength} and ${maximumLength} characters." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorPasswordsDontMatch??>
|
||||||
|
<#assign errorMessage = "Passwords do not match." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorMessage?has_content>
|
||||||
|
<section id="error-alert" role="alert">
|
||||||
|
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon"/>
|
||||||
|
<p>${errorMessage}</p>
|
||||||
|
</section>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<section id="edit-account" role="region">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Edit new account</legend>
|
||||||
|
|
||||||
|
<form method="POST" action="${formUrls.edit}" class="customForm" role="edit account">
|
||||||
|
<label for="email-address">Email address<span class="requiredHint"> *</span></label>
|
||||||
|
<input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input "/>
|
||||||
|
|
||||||
|
<label for="first-name">First name<span class="requiredHint"> *</span></label>
|
||||||
|
<input type="text" name="firstName" value="${firstName}" id="first-name" role="input "/>
|
||||||
|
|
||||||
|
<label for="last-name">Last name<span class="requiredHint"> *</span></label>
|
||||||
|
<input type="text" name="lastName" value="${lastName}" id="last-name" role="input "/>
|
||||||
|
|
||||||
|
<p>Roles<span class="requiredHint"> *</span> </p>
|
||||||
|
<#list roles as role>
|
||||||
|
<input type="radio" name="role" value="${role.uri}" role="radio" <#if selectedRole = role.uri>selected</#if> />
|
||||||
|
<label class="inline" for="${role.label}"> ${role.label}</label>
|
||||||
|
<br />
|
||||||
|
</#list>
|
||||||
|
|
||||||
|
<#if !emailIsEnabled??>
|
||||||
|
<label for="new-password">New password<span class="requiredHint"> *</span></label>
|
||||||
|
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input "/>
|
||||||
|
|
||||||
|
<p>Minimum of ${minimumLength} characters in length.</p>
|
||||||
|
<p>Leaving this blank means that the password will not be changed.</p>
|
||||||
|
|
||||||
|
<label for="confirm-password">Confirm initial password<span class="requiredHint"> *</span></label>
|
||||||
|
<input type="text" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input "/>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<p>Associate a profile with this account</p>
|
||||||
|
<input type="radio" name="associate" value="yes" role="radio" <#if associate??>checked</#if> id="associate" />
|
||||||
|
<label class="inline" for="associate"> Yes</label>
|
||||||
|
|
||||||
|
<input type="radio" name="associate" value="no" role="radio" <#if !associate??>checked</#if> id="no-associate" />
|
||||||
|
<label class="inline" for="no-associate"> No</label>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<input type="checkbox" name="resetPassword" value="" id="reset-password" role="checkbox" />
|
||||||
|
<label class="inline" for="reset-password"> Reset password</label>
|
||||||
|
|
||||||
|
<#if emailIsEnabled??>
|
||||||
|
<p class="note">
|
||||||
|
Note: A confirmation email with instructions for resetting a password
|
||||||
|
will be sent to the address entered above.
|
||||||
|
The password will not be reset until the user follows the link provided in this email.
|
||||||
|
</p>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<input type="submit" name="submitEdit" value="Save changes" class="submit"/> or <a href="${formUrls.list}">Cancel</a>
|
||||||
|
|
||||||
|
<p class="requiredHint">* required fields</p>
|
||||||
|
</form>
|
||||||
|
</fieldset>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/customForm.css" />')}
|
|
@ -47,8 +47,26 @@
|
||||||
<p>
|
<p>
|
||||||
A new account for
|
A new account for
|
||||||
<a href="${newUserAccount.editUrl}">${newUserAccount.firstName} ${newUserAccount.lastName}</a>
|
<a href="${newUserAccount.editUrl}">${newUserAccount.firstName} ${newUserAccount.lastName}</a>
|
||||||
was successfully created. A notification email has been sent to ${newUserAccount.emailAddress}
|
was successfully created.
|
||||||
with instructions for activating the account and creating a password.
|
<#if emailWasSent?? >
|
||||||
|
A notification email has been sent to ${newUserAccount.emailAddress}
|
||||||
|
with instructions for activating the account and creating a password.
|
||||||
|
</#if>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if updatedUserAccount?? >
|
||||||
|
<section class="account-feedback">
|
||||||
|
<p>
|
||||||
|
The account for
|
||||||
|
<a href="${updatedUserAccount.editUrl}">${updatedUserAccount.firstName} ${updatedUserAccount.lastName}</a>
|
||||||
|
has been updated.
|
||||||
|
<#if emailWasSent?? >
|
||||||
|
A confirmation email has been sent to ${updatedUserAccount.emailAddress}
|
||||||
|
with instructions for resetting a password.
|
||||||
|
The password will not be reset until the user follows the link provided in this email.
|
||||||
|
</#if>
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
<#-- Confirmation that an account has been created. -->
|
<#-- Confirmation that an password has been created. -->
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Yout new password associated with ${userAccount.emailAddress} has been created.
|
Your new password associated with ${userAccount.emailAddress} has been created.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
<#-- Confirmation that an account has been created. -->
|
<#-- Confirmation that a password has been created. -->
|
||||||
|
|
||||||
${userAccount.firstName} ${userAccount.lastName}
|
${userAccount.firstName} ${userAccount.lastName}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Confirmation that an password has been reset. -->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>${subjectLine}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
${userAccount.firstName} ${userAccount.lastName}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>Password successfully changed.</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Your new password associated with ${userAccount.emailAddress} has been changed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Thank you.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Confirmation that a password has been reset. -->
|
||||||
|
|
||||||
|
${userAccount.firstName} ${userAccount.lastName}
|
||||||
|
|
||||||
|
Password successfully changed.
|
||||||
|
|
||||||
|
Your new password associated with ${userAccount.emailAddress}
|
||||||
|
has been changed.
|
||||||
|
|
||||||
|
Thank you.
|
|
@ -0,0 +1,49 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Template for adding a user account -->
|
||||||
|
|
||||||
|
<h3>Reset your Password</h3>
|
||||||
|
|
||||||
|
<#if errorPasswordIsEmpty??>
|
||||||
|
<#assign errorMessage = "No password supplied." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorPasswordIsWrongLength??>
|
||||||
|
<#assign errorMessage = "Password must be between ${minimumLength} and ${maximumLength} characters." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorPasswordsDontMatch??>
|
||||||
|
<#assign errorMessage = "Passwords do not match." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorMessage?has_content>
|
||||||
|
<section id="error-alert" role="alert">
|
||||||
|
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon"/>
|
||||||
|
<p>${errorMessage}</p>
|
||||||
|
</section>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<section id="reset-password" role="region">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Please enter your new password for ${userAccount.emailAddress}</legend>
|
||||||
|
|
||||||
|
<form method="POST" action="${formUrls.resetPassword}" class="customForm" role="create password">
|
||||||
|
<input type="hidden" name="user" value="${userAccount.emailAddress}" />
|
||||||
|
<input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" />
|
||||||
|
|
||||||
|
<label for="new-password">Password<span class="requiredHint"> *</span></label>
|
||||||
|
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input "/>
|
||||||
|
|
||||||
|
<p>Minimum of ${minimumLength} characters in length.</p>
|
||||||
|
|
||||||
|
<label for="confirm-password">Confirm Password<span class="requiredHint"> *</span></label>
|
||||||
|
<input type="password" name="confirmPassword" value="${confirmPassword}" id="confirm-password" role="input "/>
|
||||||
|
|
||||||
|
<input type="submit" name="submit" value="Save changes" class="submit"/>
|
||||||
|
|
||||||
|
<p class="requiredHint">* required fields</p>
|
||||||
|
</form>
|
||||||
|
</fieldset>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/customForm.css" />')}
|
|
@ -0,0 +1,40 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Notification that your password has been reset. -->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>${subjectLine}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
${userAccount.firstName} ${userAccount.lastName}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
We received a request to reset the password for your account (${userAccount.emailAddress}).
|
||||||
|
Please follow the instructions below to proceed with your password reset.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you did not request this new account you can safely ignore this email.
|
||||||
|
This request will expire if not acted upon for 30 days.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Click the link below to reset your password using our secure server.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="${passwordLink}">${passwordLink}</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If the link above doesn't work, you can copy and paste the link directly into your browser's address bar.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Thank you!
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,19 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Notification that your password has been reset. -->
|
||||||
|
|
||||||
|
${userAccount.firstName} ${userAccount.lastName}
|
||||||
|
|
||||||
|
We received a request to reset the password for your account
|
||||||
|
(${userAccount.emailAddress}).
|
||||||
|
Please follow the instructions below to proceed with your password reset.
|
||||||
|
|
||||||
|
If you did not request this new account you can safely ignore this email.
|
||||||
|
This request will expire if not acted upon for 30 days.
|
||||||
|
|
||||||
|
Paste the link below into your browser's address bar to reset your password
|
||||||
|
using our secure server.
|
||||||
|
|
||||||
|
${passwordLink}
|
||||||
|
|
||||||
|
Thank you!
|
Loading…
Add table
Add a link
Reference in a new issue