trunk merge
This commit is contained in:
commit
d4559a2496
20 changed files with 614 additions and 85 deletions
|
@ -129,6 +129,7 @@ public abstract class UserAccountsPage {
|
|||
map.put("myAccount", UrlBuilder.getUrl("/accounts/myAccount"));
|
||||
map.put("createPassword", UrlBuilder.getUrl("/accounts/createPassword"));
|
||||
map.put("resetPassword", UrlBuilder.getUrl("/accounts/resetPassword"));
|
||||
map.put("firstTimeExternal", UrlBuilder.getUrl("/accounts/firstTimeExternal"));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader;
|
||||
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.authenticate.Authenticator;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||
|
||||
/**
|
||||
* Handle the first-time login of an Externally Authenticated user who has no
|
||||
* UserAccount - let's create one!
|
||||
*
|
||||
* If they get here from the login, there should an externalAuthId waiting in
|
||||
* the session. Otherwise, they should get here by submitting the form, which
|
||||
* will have the externalAuthId as a hidden field.
|
||||
*/
|
||||
public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
||||
private static final String PARAMETER_SUBMIT = "submit";
|
||||
private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId";
|
||||
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 ERROR_NO_EMAIL = "errorEmailIsEmpty";
|
||||
private static final String ERROR_EMAIL_IN_USE = "errorEmailInUse";
|
||||
private static final String ERROR_EMAIL_INVALID_FORMAT = "errorEmailInvalidFormat";
|
||||
private static final String ERROR_NO_FIRST_NAME = "errorFirstNameIsEmpty";
|
||||
private static final String ERROR_NO_LAST_NAME = "errorLastNameIsEmpty";
|
||||
|
||||
private static final String TEMPLATE_NAME = "userAccounts-firstTimeExternal.ftl";
|
||||
|
||||
private static final String ATTRIBUTE_EXTERNAL_AUTH_ID = UserAccountsFirstTimeExternalPage.class
|
||||
.getName();
|
||||
|
||||
/**
|
||||
* Let some other request set the External Auth ID before redirecting to
|
||||
* here.
|
||||
*/
|
||||
public static void setExternalAuthId(HttpServletRequest req,
|
||||
String externalAuthId) {
|
||||
req.getSession().setAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID,
|
||||
externalAuthId);
|
||||
}
|
||||
|
||||
private final UserAccountsFirstTimeExternalPageStrategy strategy;
|
||||
|
||||
private boolean submit = false;
|
||||
private String externalAuthId = "";
|
||||
private String emailAddress = "";
|
||||
private String firstName = "";
|
||||
private String lastName = "";
|
||||
|
||||
private String errorCode = "";
|
||||
private String bogusMessage = "";
|
||||
|
||||
protected UserAccountsFirstTimeExternalPage(VitroRequest vreq) {
|
||||
super(vreq);
|
||||
|
||||
this.strategy = UserAccountsFirstTimeExternalPageStrategy.getInstance(
|
||||
vreq, this, isEmailEnabled());
|
||||
|
||||
checkSessionForExternalAuthId();
|
||||
if (externalAuthId.isEmpty()) {
|
||||
parseRequestParameters();
|
||||
}
|
||||
|
||||
validateExternalAuthId();
|
||||
|
||||
if (isSubmit() && !isBogus()) {
|
||||
validateParameters();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSessionForExternalAuthId() {
|
||||
HttpSession session = vreq.getSession();
|
||||
|
||||
Object o = session.getAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID);
|
||||
session.removeAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID);
|
||||
|
||||
if (o instanceof String) {
|
||||
externalAuthId = (String) o;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseRequestParameters() {
|
||||
submit = isFlagOnRequest(PARAMETER_SUBMIT);
|
||||
externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, "");
|
||||
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
|
||||
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
|
||||
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
|
||||
}
|
||||
|
||||
private void validateExternalAuthId() {
|
||||
if (externalAuthId.isEmpty()) {
|
||||
bogusMessage = "Login failed - External ID is not found.";
|
||||
return;
|
||||
}
|
||||
if (null != userAccountsDao
|
||||
.getUserAccountByExternalAuthId(externalAuthId)) {
|
||||
bogusMessage = "User account already exists for '" + externalAuthId
|
||||
+ "'";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBogus() {
|
||||
return !bogusMessage.isEmpty();
|
||||
}
|
||||
|
||||
public String getBogusMessage() {
|
||||
return bogusMessage;
|
||||
}
|
||||
|
||||
public boolean isSubmit() {
|
||||
return submit;
|
||||
}
|
||||
|
||||
private void validateParameters() {
|
||||
if (firstName.isEmpty()) {
|
||||
errorCode = ERROR_NO_FIRST_NAME;
|
||||
} else if (lastName.isEmpty()) {
|
||||
errorCode = ERROR_NO_LAST_NAME;
|
||||
} else if (emailAddress.isEmpty()) {
|
||||
errorCode = ERROR_NO_EMAIL;
|
||||
} else if (isEmailInUse()) {
|
||||
errorCode = ERROR_EMAIL_IN_USE;
|
||||
} else if (!isEmailValidFormat()) {
|
||||
errorCode = ERROR_EMAIL_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmailInUse() {
|
||||
return userAccountsDao.getUserAccountByEmail(emailAddress) != null;
|
||||
}
|
||||
|
||||
private boolean isEmailValidFormat() {
|
||||
return Authenticator.isValidEmailAddress(emailAddress);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return errorCode.isEmpty();
|
||||
}
|
||||
|
||||
public final ResponseValues showPage() {
|
||||
Map<String, Object> body = new HashMap<String, Object>();
|
||||
|
||||
body.put("emailAddress", emailAddress);
|
||||
body.put("firstName", firstName);
|
||||
body.put("lastName", lastName);
|
||||
body.put("externalAuthId", externalAuthId);
|
||||
body.put("formUrls", buildUrlsMap());
|
||||
|
||||
if (!errorCode.isEmpty()) {
|
||||
body.put(errorCode, Boolean.TRUE);
|
||||
}
|
||||
|
||||
strategy.addMoreBodyValues(body);
|
||||
|
||||
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
||||
}
|
||||
|
||||
public UserAccount createAccount() {
|
||||
UserAccount u = new UserAccount();
|
||||
u.setEmailAddress(emailAddress);
|
||||
u.setFirstName(firstName);
|
||||
u.setLastName(lastName);
|
||||
u.setExternalAuthId(externalAuthId);
|
||||
u.setPasswordChangeRequired(false);
|
||||
u.setPasswordLinkExpires(0);
|
||||
u.setLoginCount(0);
|
||||
u.setStatus(Status.ACTIVE);
|
||||
u.setPermissionSetUris(Collections
|
||||
.singleton(PermissionSetsLoader.URI_SELF_EDITOR));
|
||||
|
||||
userAccountsDao.insertUserAccount(u);
|
||||
|
||||
strategy.notifyUser(u);
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/* $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 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.email.FreemarkerEmailFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
|
||||
|
||||
/**
|
||||
* Handle the variations in the UserAccountsFirstTimeExternal page. If email is
|
||||
* available, inform the template, and send a notification to the user.
|
||||
*
|
||||
* If not, then don't.
|
||||
*/
|
||||
public abstract class UserAccountsFirstTimeExternalPageStrategy extends
|
||||
UserAccountsPage {
|
||||
|
||||
public static UserAccountsFirstTimeExternalPageStrategy getInstance(
|
||||
VitroRequest vreq, UserAccountsFirstTimeExternalPage page,
|
||||
boolean emailEnabled) {
|
||||
if (emailEnabled) {
|
||||
return new EmailStrategy(vreq, page);
|
||||
} else {
|
||||
return new NoEmailStrategy(vreq, page);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private UserAccountsFirstTimeExternalPage page;
|
||||
|
||||
public UserAccountsFirstTimeExternalPageStrategy(VitroRequest vreq,
|
||||
UserAccountsFirstTimeExternalPage page) {
|
||||
super(vreq);
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public abstract void addMoreBodyValues(Map<String, Object> body);
|
||||
|
||||
public abstract void notifyUser(UserAccount ua);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Strategy to use if email is enabled.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
public static class EmailStrategy extends
|
||||
UserAccountsFirstTimeExternalPageStrategy {
|
||||
|
||||
public EmailStrategy(VitroRequest vreq,
|
||||
UserAccountsFirstTimeExternalPage page) {
|
||||
super(vreq, page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMoreBodyValues(Map<String, Object> body) {
|
||||
body.put("emailIsEnabled", Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyUser(UserAccount ua) {
|
||||
Map<String, Object> body = new HashMap<String, Object>();
|
||||
body.put("userAccount", ua);
|
||||
body.put("subjectLine", "Your VIVO account has been created.");
|
||||
|
||||
FreemarkerEmailMessage email = FreemarkerEmailFactory
|
||||
.createNewMessage(vreq);
|
||||
email.addRecipient(TO, ua.getEmailAddress());
|
||||
email.setSubject("Your VIVO account has been created.");
|
||||
email.setHtmlTemplate("userAccounts-firstTimeExternalEmail-html.ftl");
|
||||
email.setTextTemplate("userAccounts-firstTimeExternalEmail-text.ftl");
|
||||
email.setBodyMap(body);
|
||||
email.send();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Strategy to use if email is disabled.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
public static class NoEmailStrategy extends
|
||||
UserAccountsFirstTimeExternalPageStrategy {
|
||||
|
||||
public NoEmailStrategy(VitroRequest vreq,
|
||||
UserAccountsFirstTimeExternalPage page) {
|
||||
super(vreq, page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMoreBodyValues(Map<String, Object> body) {
|
||||
// Nothing to add.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyUser(UserAccount ua) {
|
||||
// No way to notify.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,16 +2,23 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
|
||||
|
||||
import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.EXTERNAL;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOwnAccount;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginRedirector;
|
||||
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.login.LoginProcessBean;
|
||||
|
||||
/**
|
||||
* Parcel out the different actions required of the UserAccounts GUI.
|
||||
|
@ -25,6 +32,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
|||
private static final String ACTION_CREATE_PASSWORD = "/createPassword";
|
||||
private static final String ACTION_RESET_PASSWORD = "/resetPassword";
|
||||
private static final String ACTION_MY_ACCOUNT = "/myAccount";
|
||||
private static final String ACTION_FIRST_TIME_EXTERNAL = "/firstTimeExternal";
|
||||
|
||||
@Override
|
||||
protected Actions requiredActions(VitroRequest vreq) {
|
||||
|
@ -52,6 +60,8 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
|||
return handleCreatePasswordRequest(vreq);
|
||||
} else if (ACTION_RESET_PASSWORD.equals(action)) {
|
||||
return handleResetPasswordRequest(vreq);
|
||||
} else if (ACTION_FIRST_TIME_EXTERNAL.equals(action)) {
|
||||
return handleFirstTimeLoginFromExternalAccount(vreq);
|
||||
} else {
|
||||
return handleInvalidRequest(vreq);
|
||||
}
|
||||
|
@ -95,6 +105,24 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
|||
|
||||
}
|
||||
|
||||
private ResponseValues handleFirstTimeLoginFromExternalAccount(
|
||||
VitroRequest vreq) {
|
||||
UserAccountsFirstTimeExternalPage page = new UserAccountsFirstTimeExternalPage(
|
||||
vreq);
|
||||
if (page.isBogus()) {
|
||||
return showHomePage(vreq, page.getBogusMessage());
|
||||
} else if (page.isSubmit() && page.isValid()) {
|
||||
UserAccount userAccount = page.createAccount();
|
||||
Authenticator auth = Authenticator.getInstance(vreq);
|
||||
auth.recordLoginAgainstUserAccount(userAccount, EXTERNAL);
|
||||
LoginProcessBean.removeBean(vreq);
|
||||
|
||||
return showLoginRedirection(vreq);
|
||||
} else {
|
||||
return page.showPage();
|
||||
}
|
||||
}
|
||||
|
||||
private ResponseValues handleInvalidRequest(VitroRequest vreq) {
|
||||
return showHomePage(vreq, BOGUS_STANDARD_MESSAGE);
|
||||
}
|
||||
|
@ -104,4 +132,10 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
|||
return new RedirectResponseValues("/");
|
||||
}
|
||||
|
||||
private ResponseValues showLoginRedirection(VitroRequest vreq) {
|
||||
LoginRedirector lr = new LoginRedirector(vreq);
|
||||
DisplayMessage.setMessage(vreq, lr.assembleWelcomeMessage());
|
||||
String uri = lr.getRedirectionUriForLoggedInUser();
|
||||
return new RedirectResponseValues(uri);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
|
|||
getAuthenticator(req).recordLoginAgainstUserAccount(userAccount,
|
||||
AuthenticationSource.EXTERNAL);
|
||||
removeLoginProcessArtifacts(req);
|
||||
new LoginRedirector(req, resp).redirectLoggedInUser();
|
||||
new LoginRedirector(req).redirectLoggedInUser(resp);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -71,14 +71,14 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
|
|||
|
||||
getAuthenticator(req).recordLoginWithoutUserAccount(uri);
|
||||
removeLoginProcessArtifacts(req);
|
||||
new LoginRedirector(req, resp).redirectLoggedInUser();
|
||||
new LoginRedirector(req).redirectLoggedInUser(resp);
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("User is not recognized: " + externalAuthId);
|
||||
removeLoginProcessArtifacts(req);
|
||||
new LoginRedirector(req, resp)
|
||||
.redirectUnrecognizedExternalUser(externalAuthId);
|
||||
new LoginRedirector(req).redirectUnrecognizedExternalUser(resp,
|
||||
externalAuthId);
|
||||
}
|
||||
|
||||
private void removeLoginProcessArtifacts(HttpServletRequest req) {
|
||||
|
|
|
@ -29,17 +29,14 @@ public class LoginRedirector {
|
|||
private static final Log log = LogFactory.getLog(LoginRedirector.class);
|
||||
|
||||
private final HttpServletRequest request;
|
||||
private final HttpServletResponse response;
|
||||
private final HttpSession session;
|
||||
|
||||
private final String uriOfAssociatedIndividual;
|
||||
private final String afterLoginPage;
|
||||
|
||||
public LoginRedirector(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
public LoginRedirector(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
this.session = request.getSession();
|
||||
this.response = response;
|
||||
|
||||
uriOfAssociatedIndividual = getAssociatedIndividualUri();
|
||||
|
||||
|
@ -70,28 +67,45 @@ public class LoginRedirector {
|
|||
}
|
||||
}
|
||||
|
||||
public void redirectLoggedInUser() throws IOException {
|
||||
DisplayMessage.setMessage(request, assembleWelcomeMessage());
|
||||
|
||||
try {
|
||||
if (isSelfEditorWithIndividual()) {
|
||||
log.debug("Going to Individual home page.");
|
||||
response.sendRedirect(getAssociatedIndividualHomePage());
|
||||
} else if (isMerelySelfEditor()) {
|
||||
log.debug("User not recognized. Going to application home.");
|
||||
response.sendRedirect(getApplicationHomePageUrl());
|
||||
public String getRedirectionUriForLoggedInUser() {
|
||||
if (isSelfEditorWithIndividual()) {
|
||||
log.debug("Going to Individual home page.");
|
||||
return getAssociatedIndividualHomePage();
|
||||
} else if (isMerelySelfEditor()) {
|
||||
log.debug("User not recognized. Going to application home.");
|
||||
return getApplicationHomePageUrl();
|
||||
} else {
|
||||
if (isLoginPage(afterLoginPage)) {
|
||||
log.debug("Coming from /login. Going to site admin page.");
|
||||
return getSiteAdminPageUrl();
|
||||
} else if (null != afterLoginPage) {
|
||||
log.debug("Returning to requested page: " + afterLoginPage);
|
||||
return afterLoginPage;
|
||||
} else {
|
||||
if (isLoginPage(afterLoginPage)) {
|
||||
log.debug("Coming from /login. Going to site admin page.");
|
||||
response.sendRedirect(getSiteAdminPageUrl());
|
||||
} else if (null != afterLoginPage) {
|
||||
log.debug("Returning to requested page: " + afterLoginPage);
|
||||
response.sendRedirect(afterLoginPage);
|
||||
} else {
|
||||
log.debug("Don't know what to do. Go home.");
|
||||
response.sendRedirect(getApplicationHomePageUrl());
|
||||
}
|
||||
log.debug("Don't know what to do. Go home.");
|
||||
return getApplicationHomePageUrl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getRedirectionUriForCancellingUser() {
|
||||
if (isLoginPage(afterLoginPage)) {
|
||||
log.debug("Coming from /login. Going to home.");
|
||||
return getApplicationHomePageUrl();
|
||||
} else if (null != afterLoginPage) {
|
||||
log.debug("Returning to requested page: " + afterLoginPage);
|
||||
return afterLoginPage;
|
||||
} else {
|
||||
log.debug("Don't know what to do. Go home.");
|
||||
return getApplicationHomePageUrl();
|
||||
}
|
||||
}
|
||||
|
||||
public void redirectLoggedInUser(HttpServletResponse response)
|
||||
throws IOException {
|
||||
try {
|
||||
DisplayMessage.setMessage(request, assembleWelcomeMessage());
|
||||
response.sendRedirect(getRedirectionUriForLoggedInUser());
|
||||
LoginProcessBean.removeBean(request);
|
||||
} catch (IOException e) {
|
||||
log.debug("Problem with re-direction", e);
|
||||
|
@ -99,7 +113,7 @@ public class LoginRedirector {
|
|||
}
|
||||
}
|
||||
|
||||
private String assembleWelcomeMessage() {
|
||||
public String assembleWelcomeMessage() {
|
||||
if (isMerelySelfEditor() && !isSelfEditorWithIndividual()) {
|
||||
// A special message for unrecognized self-editors:
|
||||
return "You have logged in, "
|
||||
|
@ -124,18 +138,10 @@ public class LoginRedirector {
|
|||
return "Welcome" + backString + ", " + greeting;
|
||||
}
|
||||
|
||||
public void redirectCancellingUser() throws IOException {
|
||||
public void redirectCancellingUser(HttpServletResponse response)
|
||||
throws IOException {
|
||||
try {
|
||||
if (isLoginPage(afterLoginPage)) {
|
||||
log.debug("Coming from /login. Going to home.");
|
||||
response.sendRedirect(getApplicationHomePageUrl());
|
||||
} else if (null != afterLoginPage) {
|
||||
log.debug("Returning to requested page: " + afterLoginPage);
|
||||
response.sendRedirect(afterLoginPage);
|
||||
} else {
|
||||
log.debug("Don't know what to do. Go home.");
|
||||
response.sendRedirect(getApplicationHomePageUrl());
|
||||
}
|
||||
response.sendRedirect(getRedirectionUriForCancellingUser());
|
||||
LoginProcessBean.removeBean(request);
|
||||
} catch (IOException e) {
|
||||
log.debug("Problem with re-direction", e);
|
||||
|
@ -143,8 +149,8 @@ public class LoginRedirector {
|
|||
}
|
||||
}
|
||||
|
||||
public void redirectUnrecognizedExternalUser(String username)
|
||||
throws IOException {
|
||||
public void redirectUnrecognizedExternalUser(HttpServletResponse response,
|
||||
String username) throws IOException {
|
||||
log.debug("Redirecting unrecognized external user: " + username);
|
||||
DisplayMessage.setMessage(request,
|
||||
"VIVO cannot find a profile for your account.");
|
||||
|
|
|
@ -124,7 +124,7 @@ public class Authenticate extends VitroHttpServlet {
|
|||
// Send them on their way.
|
||||
switch (exitState) {
|
||||
case NOWHERE:
|
||||
new LoginRedirector(vreq, response).redirectCancellingUser();
|
||||
new LoginRedirector(vreq).redirectCancellingUser(response);
|
||||
break;
|
||||
case LOGGING_IN:
|
||||
showLoginScreen(vreq, response);
|
||||
|
@ -133,7 +133,7 @@ public class Authenticate extends VitroHttpServlet {
|
|||
showLoginScreen(vreq, response);
|
||||
break;
|
||||
default: // LOGGED_IN:
|
||||
new LoginRedirector(vreq, response).redirectLoggedInUser();
|
||||
new LoginRedirector(vreq).redirectLoggedInUser(response);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
|
|||
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Keyword;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
|
||||
import edu.cornell.mannlib.vitro.webapp.search.beans.ObjectSourceIface;
|
||||
|
||||
public interface IndividualDao extends ObjectSourceIface {
|
||||
|
@ -136,6 +137,8 @@ public interface IndividualDao extends ObjectSourceIface {
|
|||
*/
|
||||
String getUnusedURI(Individual individual) throws InsertException;
|
||||
|
||||
EditLiteral getLabelEditLiteral(String individualUri);
|
||||
|
||||
@Deprecated
|
||||
public abstract Individual getIndividualByExternalId(int externalIdType,
|
||||
String externalIdValue);
|
||||
|
|
|
@ -19,6 +19,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
|||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
|
||||
|
||||
|
||||
class IndividualDaoFiltering extends BaseFiltering implements IndividualDao{
|
||||
|
@ -242,4 +243,10 @@ class IndividualDaoFiltering extends BaseFiltering implements IndividualDao{
|
|||
return innerIndividualDao.getUnusedURI(individual);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EditLiteral getLabelEditLiteral(String individualUri) {
|
||||
return innerIndividualDao.getLabelEditLiteral(individualUri);
|
||||
}
|
||||
|
||||
}
|
|
@ -58,6 +58,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
|||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualCreationEvent;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualDeletionEvent;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualUpdateEvent;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
|
||||
|
||||
public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
|
||||
|
||||
|
@ -1048,4 +1049,19 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
|
|||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
// This method returns an EditLiteral rather than a Jena Literal, since IndividualDao
|
||||
// should not reference Jena objects. (However, the problem isn't really solved
|
||||
// because EditLiteral currently references the Jena API.)
|
||||
public EditLiteral getLabelEditLiteral(String individualUri) {
|
||||
Literal literal = getLabelLiteral(individualUri);
|
||||
if (literal == null) {
|
||||
return null;
|
||||
}
|
||||
String value = literal.getLexicalForm();
|
||||
String datatype = literal.getDatatypeURI();
|
||||
String lang = literal.getLanguage();
|
||||
return new EditLiteral(value, datatype, lang);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -777,11 +777,16 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
return label;
|
||||
}
|
||||
|
||||
protected Literal getLabelLiteral(String individualUri) {
|
||||
OntResource resource = webappDaoFactory.getOntModel().createOntResource(individualUri);
|
||||
return getLabelLiteral(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* works through list of PREFERRED_LANGUAGES to find an appropriate
|
||||
* label, or NULL if not found.
|
||||
*/
|
||||
public Literal getLabelLiteral(OntResource r) {
|
||||
protected Literal getLabelLiteral(OntResource r) {
|
||||
Literal labelLiteral = null;
|
||||
r.getOntModel().enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
|
|
|
@ -29,7 +29,7 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat
|
|||
protected String value = null;
|
||||
|
||||
// Used for editing
|
||||
private String dataPropHash = null;
|
||||
protected String dataPropHash = null;
|
||||
//Useful in case additional params to be retrieved for URL
|
||||
private VitroRequest vitroRequest= null;
|
||||
|
||||
|
@ -84,7 +84,7 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat
|
|||
}
|
||||
|
||||
// Determine whether the statement can be deleted
|
||||
// Hack for rdfs:label - the policy doesn't prevent deletion
|
||||
// Hack for rdfs:label - the policy doesn't prevent deletion.
|
||||
if ( ! propertyUri.equals(VitroVocabulary.LABEL) ) {
|
||||
action = new DropDataPropStmt(dps);
|
||||
if (policyHelper.isAuthorizedAction(action)) {
|
||||
|
|
|
@ -9,16 +9,21 @@ import org.apache.commons.logging.LogFactory;
|
|||
import org.openrdf.model.URI;
|
||||
import org.openrdf.model.impl.URIImpl;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.ontology.OntResource;
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.DropDataPropStmt;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.EditDataPropStmt;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaBaseDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash;
|
||||
|
||||
public class NameStatementTemplateModel extends
|
||||
DataPropertyStatementTemplateModel {
|
||||
|
@ -27,43 +32,49 @@ public class NameStatementTemplateModel extends
|
|||
|
||||
/*
|
||||
* This method handles the special case where we are creating a DataPropertyStatementTemplateModel outside the GroupedPropertyList.
|
||||
* Specifically, it allows rdfs:label to be treated like a data property statement and thus have editing links. It is not possible
|
||||
* to handle rdfs:label like vitro links and vitroPublic image, because it is not possible to construct a DataProperty from
|
||||
* rdfs:label.
|
||||
* Specifically, it allows rdfs:label to be treated like a data property statement and thus have editing links.
|
||||
*/
|
||||
NameStatementTemplateModel(String subjectUri, VitroRequest vreq, EditingPolicyHelper policyHelper) {
|
||||
super(subjectUri, VitroVocabulary.LABEL, vreq, policyHelper);
|
||||
|
||||
Literal literal = null;
|
||||
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
|
||||
|
||||
// Use the same methods to get the label that are used elsewhere in the application, to
|
||||
// guarantee consistent results for individuals with multiple labels.
|
||||
// RY The problem here is we have a WebappDaoFactoryFiltering instead of WebappDaoFactoryJena.
|
||||
if (wdf instanceof WebappDaoFactoryJena) {
|
||||
WebappDaoFactoryJena wdfj = (WebappDaoFactoryJena) wdf;
|
||||
OntResource resource = wdfj.getOntModel().createOntResource(subjectUri);
|
||||
JenaBaseDao baseDao = wdfj.getJenaBaseDao();
|
||||
literal = baseDao.getLabelLiteral(resource);
|
||||
} else {
|
||||
DataPropertyStatementDao dpsDao = vreq.getWebappDaoFactory().getDataPropertyStatementDao();
|
||||
List<Literal> literals = dpsDao.getDataPropertyValuesForIndividualByProperty(subjectUri, VitroVocabulary.LABEL);
|
||||
// Make sure the subject has a value for this property
|
||||
if (literals.size() > 0) {
|
||||
literal = literals.get(0);
|
||||
}
|
||||
}
|
||||
// NIHVIVO-2466 Use the same methods to get the label that are used elsewhere in the
|
||||
// application, to guarantee consistent results for individuals with multiple labels
|
||||
// across the application.
|
||||
IndividualDao iDao = wdf.getIndividualDao();
|
||||
EditLiteral literal = iDao.getLabelEditLiteral(subjectUri);
|
||||
|
||||
if (literal != null) {
|
||||
value = literal.getLexicalForm();
|
||||
setEditAccess(literal, policyHelper);
|
||||
} else {
|
||||
// If the individual has no rdfs:label, use the local name. It will not be editable (this replicates previous behavior;
|
||||
// If the individual has no rdfs:label, use the local name. It will not be editable. (This replicates previous behavior;
|
||||
// perhaps we would want to allow a label to be added. But such individuals do not usually have their profiles viewed or
|
||||
// edited directly.
|
||||
// edited directly.)
|
||||
URI uri = new URIImpl(subjectUri);
|
||||
value = uri.getLocalName();
|
||||
}
|
||||
}
|
||||
|
||||
protected void setEditAccess(EditLiteral value, EditingPolicyHelper policyHelper) {
|
||||
|
||||
if (policyHelper != null) { // we're editing
|
||||
DataPropertyStatement dps = new DataPropertyStatementImpl(subjectUri, propertyUri, value.getLexicalForm());
|
||||
// Language and datatype are needed to get the correct hash value
|
||||
dps.setLanguage(value.getLanguage());
|
||||
dps.setDatatypeURI(value.getDatatypeURI());
|
||||
this.dataPropHash = String.valueOf(RdfLiteralHash.makeRdfLiteralHash(dps));
|
||||
|
||||
// Determine whether the statement can be edited
|
||||
RequestedAction action = new EditDataPropStmt(dps);
|
||||
if (policyHelper.isAuthorizedAction(action)) {
|
||||
markEditable();
|
||||
}
|
||||
|
||||
// The label cannot be deleted, so we don't need to check
|
||||
// the policy for the delete action.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Keyword;
|
|||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
|
||||
|
||||
/**
|
||||
* A minimal implementation of the IndividualDao.
|
||||
|
@ -237,4 +238,10 @@ public class IndividualDaoStub implements IndividualDao {
|
|||
"IndividualDaoStub.getIndividualByExternalId() not implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditLiteral getLabelEditLiteral(String individualUri) {
|
||||
throw new RuntimeException(
|
||||
"IndividualDaoStub.getLabelLiteral() not implemented.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,11 +64,13 @@ ul#browse-classgroups .count-classes {
|
|||
border: 1px solid #dde6e5;
|
||||
background: #fff;
|
||||
min-height: 230px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
a.browse-superclass {
|
||||
position: absolute;
|
||||
right: 0.5em;
|
||||
font-size: 0.9em;
|
||||
top: 3px;
|
||||
}
|
||||
ul#classes-in-classgroup {
|
||||
float: left;
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
// Change form actions in account main page
|
||||
function changeAction(form, url) {
|
||||
form.action = url;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
//Accounts per page
|
||||
//Hide is javascrip is disable
|
||||
$('.accounts-per-page-form input[type="submit"]').hide();
|
||||
//Hide is javascrip is enable
|
||||
$('input[name="accounts-per-page"]').addClass('hide');
|
||||
|
||||
$('.accounts-per-page').change(function() {
|
||||
$('#account-display').submit();
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#-- Template for creating an account for the first time an external user logs in. -->
|
||||
|
||||
<h3>First time log in</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 errorEmailInvalidFormat??>
|
||||
<#assign errorMessage = "'${emailAddress}' is not a valid email address." />
|
||||
</#if>
|
||||
|
||||
<#if errorFirstNameIsEmpty??>
|
||||
<#assign errorMessage = "You must supply a first name." />
|
||||
</#if>
|
||||
|
||||
<#if errorLastNameIsEmpty??>
|
||||
<#assign errorMessage = "You must supply a last name." />
|
||||
</#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="first-time-login" role="region">
|
||||
<fieldset>
|
||||
<p class="note">
|
||||
Please provide your contact information to finish creating your account.
|
||||
</p>
|
||||
|
||||
<form method="POST" action="${formUrls.firstTimeExternal}" class="customForm" role="my account">
|
||||
<input type="hidden" name="externalAuthId" value="${externalAuthId}" />
|
||||
|
||||
<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 "/>
|
||||
|
||||
<label for="email-address">Email address<span class="requiredHint"> *</span></label>
|
||||
<input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input "/>
|
||||
|
||||
<#if emailIsEnabled??>
|
||||
<p class="note">
|
||||
Note: An email will be sent to the address entered above notifying
|
||||
that an account has been created.
|
||||
</p>
|
||||
</#if>
|
||||
|
||||
<input type="submit" name="submit" value="Create account" class="submit"/> or <a href="${urls.home}">Cancel</a>
|
||||
</form>
|
||||
</fieldset>
|
||||
</section>
|
||||
|
||||
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/customForm.css" />')}
|
|
@ -0,0 +1,26 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#-- Confirmation that an account has been created for an externally-authenticated user. -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>${subjectLine}</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
${userAccount.firstName} ${userAccount.lastName}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<strong>Congratulations!</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We have created your new VIVO account associated with ${userAccount.emailAddress}.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Thanks!
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#-- Confirmation that an account has been created for an externally-authenticated user. -->
|
||||
|
||||
${userAccount.firstName} ${userAccount.lastName}
|
||||
|
||||
Congratulations!
|
||||
|
||||
We have created your new VIVO account associated with
|
||||
${userAccount.emailAddress}.
|
||||
|
||||
Thanks!
|
|
@ -107,13 +107,6 @@
|
|||
</section>
|
||||
</form>
|
||||
|
||||
<SCRIPT TYPE="text/javascript">
|
||||
function changeAction(form, url) {
|
||||
form.action = url;
|
||||
return true;
|
||||
}
|
||||
</SCRIPT>
|
||||
|
||||
<form method="POST" action="${formUrls.list}" id="account-display" class="customForm" role="">
|
||||
<section class="accounts">
|
||||
<input type="submit" name="delete-account" class="delete-account submit" value="Delete" onClick="changeAction(this.form, '${formUrls.delete}')" />
|
||||
|
@ -126,6 +119,7 @@
|
|||
<span>| <a href="#">n</a> accounts | </span>
|
||||
|
||||
<#assign counts = [25, 50, 100]>
|
||||
|
||||
<select name="accountsPerPage" class="accounts-per-page">
|
||||
<#list counts as count>
|
||||
<option value="${count}" <#if accountsPerPage= count>selected</#if> >${count}</option>
|
||||
|
@ -137,9 +131,7 @@
|
|||
-->
|
||||
</select>
|
||||
|
||||
<input class="hide" type="submit" value="Update" />
|
||||
|
||||
accounts per page |
|
||||
accounts per page <input type="submit" name="accounts-per-page" value="Update" /> |
|
||||
|
||||
<#if page.previous?has_content>
|
||||
<a href="${formUrls.list}?accountsPerPage=${accountsPerPage}&pageIndex=${page.previous}">Previous</a> <!-- only present if current page is not 1.-->
|
||||
|
@ -192,6 +184,41 @@
|
|||
</#list>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<section class="accounts">
|
||||
<input type="submit" name="delete-account" class="delete-account submit" value="Delete" onClick="changeAction(this.form, '${formUrls.delete}')" />
|
||||
<!--
|
||||
When this is clicked, the checkboxes are noticed and all other fields are ignored.
|
||||
submit the form (submit action is formUrls.delete)
|
||||
-->
|
||||
|
||||
<nav class="display-tools">
|
||||
<span>| <a href="#">n</a> accounts | </span>
|
||||
|
||||
<#assign counts = [25, 50, 100]>
|
||||
|
||||
<select name="accountsPerPage" class="accounts-per-page">
|
||||
<#list counts as count>
|
||||
<option value="${count}" <#if accountsPerPage= count>selected</#if> >${count}</option>
|
||||
</#list>
|
||||
<!--
|
||||
When accountsPerPage changes,
|
||||
set pageIndex to 1
|
||||
submit the form (submit action is formUrls.list)
|
||||
-->
|
||||
</select>
|
||||
|
||||
accounts per page <input type="submit" name="accounts-per-page" value="Update" /> |
|
||||
|
||||
<#if page.previous?has_content>
|
||||
<a href="${formUrls.list}?accountsPerPage=${accountsPerPage}&pageIndex=${page.previous}">Previous</a> <!-- only present if current page is not 1.-->
|
||||
</#if>
|
||||
${page.current} of ${page.last}
|
||||
<#if page.next?has_content>
|
||||
<a href="${formUrls.list}?accountsPerPage=${accountsPerPage}&pageIndex=${page.next}">Next</a><!-- only present if current page is not last page.-->
|
||||
</#if>
|
||||
</nav>
|
||||
</section>
|
||||
</form>
|
||||
|
||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/account/accountUtils.js"></script>')}
|
Loading…
Add table
Reference in a new issue