NIHVIVO-2696 External user gets an account on first login.
This commit is contained in:
parent
cedd095a07
commit
4282da5ef2
7 changed files with 94 additions and 80 deletions
|
@ -9,6 +9,8 @@ import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader;
|
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;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
|
||||||
|
@ -22,13 +24,14 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Tem
|
||||||
* Handle the first-time login of an Externally Authenticated user who has no
|
* Handle the first-time login of an Externally Authenticated user who has no
|
||||||
* UserAccount - let's create one!
|
* UserAccount - let's create one!
|
||||||
*
|
*
|
||||||
* If they get here from the login, there should an externalAuthId waiting in
|
* If they get here from the login, there should be an ExternalLoginInfo waiting
|
||||||
* the session. Otherwise, they should get here by submitting the form, which
|
* in the session. Otherwise, they should get here by submitting the form, which
|
||||||
* will have the externalAuthId as a hidden field.
|
* will have the info in hidden fields.
|
||||||
*/
|
*/
|
||||||
public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
||||||
private static final String PARAMETER_SUBMIT = "submit";
|
private static final String PARAMETER_SUBMIT = "submit";
|
||||||
private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId";
|
private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId";
|
||||||
|
private static final String PARAMETER_AFTER_LOGIN_URL = "afterLoginUrl";
|
||||||
private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress";
|
private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress";
|
||||||
private static final String PARAMETER_FIRST_NAME = "firstName";
|
private static final String PARAMETER_FIRST_NAME = "firstName";
|
||||||
private static final String PARAMETER_LAST_NAME = "lastName";
|
private static final String PARAMETER_LAST_NAME = "lastName";
|
||||||
|
@ -41,23 +44,25 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
||||||
|
|
||||||
private static final String TEMPLATE_NAME = "userAccounts-firstTimeExternal.ftl";
|
private static final String TEMPLATE_NAME = "userAccounts-firstTimeExternal.ftl";
|
||||||
|
|
||||||
private static final String ATTRIBUTE_EXTERNAL_AUTH_ID = UserAccountsFirstTimeExternalPage.class
|
private static final String ATTRIBUTE_EXTERNAL_LOGIN_INFO = UserAccountsFirstTimeExternalPage.class
|
||||||
.getName();
|
.getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Let some other request set the External Auth ID before redirecting to
|
* Let some other request set the External Auth ID and the afterLogin URL
|
||||||
* here.
|
* before redirecting to here.
|
||||||
*/
|
*/
|
||||||
public static void setExternalAuthId(HttpServletRequest req,
|
public static void setExternalLoginInfo(HttpServletRequest req,
|
||||||
String externalAuthId) {
|
String externalAuthId, String afterLoginUrl) {
|
||||||
req.getSession().setAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID,
|
req.getSession().setAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO,
|
||||||
externalAuthId);
|
new ExternalLoginInfo(externalAuthId, afterLoginUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final UserAccountsFirstTimeExternalPageStrategy strategy;
|
private final UserAccountsFirstTimeExternalPageStrategy strategy;
|
||||||
|
|
||||||
private boolean submit = false;
|
|
||||||
private String externalAuthId = "";
|
private String externalAuthId = "";
|
||||||
|
private String afterLoginUrl = "";
|
||||||
|
|
||||||
|
private boolean submit = false;
|
||||||
private String emailAddress = "";
|
private String emailAddress = "";
|
||||||
private String firstName = "";
|
private String firstName = "";
|
||||||
private String lastName = "";
|
private String lastName = "";
|
||||||
|
@ -71,7 +76,7 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
||||||
this.strategy = UserAccountsFirstTimeExternalPageStrategy.getInstance(
|
this.strategy = UserAccountsFirstTimeExternalPageStrategy.getInstance(
|
||||||
vreq, this, isEmailEnabled());
|
vreq, this, isEmailEnabled());
|
||||||
|
|
||||||
checkSessionForExternalAuthId();
|
checkSessionForExternalLoginInfo();
|
||||||
if (externalAuthId.isEmpty()) {
|
if (externalAuthId.isEmpty()) {
|
||||||
parseRequestParameters();
|
parseRequestParameters();
|
||||||
}
|
}
|
||||||
|
@ -83,20 +88,26 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSessionForExternalAuthId() {
|
private void checkSessionForExternalLoginInfo() {
|
||||||
HttpSession session = vreq.getSession();
|
HttpSession session = vreq.getSession();
|
||||||
|
|
||||||
Object o = session.getAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID);
|
Object o = session.getAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO);
|
||||||
session.removeAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID);
|
session.removeAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO);
|
||||||
|
|
||||||
if (o instanceof String) {
|
if (o instanceof ExternalLoginInfo) {
|
||||||
externalAuthId = (String) o;
|
externalAuthId = ((ExternalLoginInfo) o).externalAuthId;
|
||||||
|
afterLoginUrl = ((ExternalLoginInfo) o).afterLoginUrl;
|
||||||
|
if (afterLoginUrl == null) {
|
||||||
|
afterLoginUrl = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseRequestParameters() {
|
private void parseRequestParameters() {
|
||||||
submit = isFlagOnRequest(PARAMETER_SUBMIT);
|
|
||||||
externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, "");
|
externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, "");
|
||||||
|
afterLoginUrl = getStringParameter(PARAMETER_AFTER_LOGIN_URL, "");
|
||||||
|
|
||||||
|
submit = isFlagOnRequest(PARAMETER_SUBMIT);
|
||||||
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, "");
|
||||||
|
@ -156,10 +167,12 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
||||||
public final ResponseValues showPage() {
|
public final ResponseValues showPage() {
|
||||||
Map<String, Object> body = new HashMap<String, Object>();
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
body.put("externalAuthId", externalAuthId);
|
||||||
|
body.put("afterLoginUrl", afterLoginUrl);
|
||||||
|
|
||||||
body.put("emailAddress", emailAddress);
|
body.put("emailAddress", emailAddress);
|
||||||
body.put("firstName", firstName);
|
body.put("firstName", firstName);
|
||||||
body.put("lastName", lastName);
|
body.put("lastName", lastName);
|
||||||
body.put("externalAuthId", externalAuthId);
|
|
||||||
body.put("formUrls", buildUrlsMap());
|
body.put("formUrls", buildUrlsMap());
|
||||||
|
|
||||||
if (!errorCode.isEmpty()) {
|
if (!errorCode.isEmpty()) {
|
||||||
|
@ -191,4 +204,25 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the afterLoginUrl is missing, go to the home page. If it is relative,
|
||||||
|
* make sure it doesn't start with the cotext path.
|
||||||
|
*/
|
||||||
|
public String getAfterLoginUrl() {
|
||||||
|
if (StringUtils.isEmpty(afterLoginUrl)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return afterLoginUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ExternalLoginInfo {
|
||||||
|
final String externalAuthId;
|
||||||
|
final String afterLoginUrl;
|
||||||
|
|
||||||
|
public ExternalLoginInfo(String externalAuthId, String afterLoginUrl) {
|
||||||
|
this.externalAuthId = externalAuthId;
|
||||||
|
this.afterLoginUrl = afterLoginUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
|
||||||
|
|
||||||
import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.EXTERNAL;
|
import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.EXTERNAL;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
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.vedit.beans.LoginStatusBean.AuthenticationSource;
|
|
||||||
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.EditOwnAccount;
|
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.DisplayMessage;
|
||||||
|
@ -115,9 +115,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
||||||
UserAccount userAccount = page.createAccount();
|
UserAccount userAccount = page.createAccount();
|
||||||
Authenticator auth = Authenticator.getInstance(vreq);
|
Authenticator auth = Authenticator.getInstance(vreq);
|
||||||
auth.recordLoginAgainstUserAccount(userAccount, EXTERNAL);
|
auth.recordLoginAgainstUserAccount(userAccount, EXTERNAL);
|
||||||
LoginProcessBean.removeBean(vreq);
|
return showLoginRedirection(vreq, page.getAfterLoginUrl());
|
||||||
|
|
||||||
return showLoginRedirection(vreq);
|
|
||||||
} else {
|
} else {
|
||||||
return page.showPage();
|
return page.showPage();
|
||||||
}
|
}
|
||||||
|
@ -132,10 +130,31 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
|
||||||
return new RedirectResponseValues("/");
|
return new RedirectResponseValues("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResponseValues showLoginRedirection(VitroRequest vreq) {
|
private ResponseValues showLoginRedirection(VitroRequest vreq,
|
||||||
LoginRedirector lr = new LoginRedirector(vreq, null);
|
String afterLoginUrl) {
|
||||||
|
LoginRedirector lr = new LoginRedirector(vreq, afterLoginUrl);
|
||||||
DisplayMessage.setMessage(vreq, lr.assembleWelcomeMessage());
|
DisplayMessage.setMessage(vreq, lr.assembleWelcomeMessage());
|
||||||
String uri = lr.getRedirectionUriForLoggedInUser();
|
String uri = lr.getRedirectionUriForLoggedInUser();
|
||||||
return new RedirectResponseValues(uri);
|
return new RedirectResponseValues(stripContextPath(vreq, uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO The LoginRedirector gives a URI that includes the context path. But
|
||||||
|
* the RedirectResponseValues wants a URI that does not include the context
|
||||||
|
* path.
|
||||||
|
*
|
||||||
|
* Bridge the gap.
|
||||||
|
*/
|
||||||
|
private String stripContextPath(VitroRequest vreq, String uri) {
|
||||||
|
if ((uri == null) || uri.isEmpty() || uri.equals(vreq.getContextPath())) {
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
if (uri.contains("://")) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
if (uri.startsWith(vreq.getContextPath() + '/')) {
|
||||||
|
return uri.substring(vreq.getContextPath().length());
|
||||||
|
}
|
||||||
|
return uri;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,17 +105,6 @@ public abstract class Authenticator {
|
||||||
public abstract void recordLoginAgainstUserAccount(UserAccount userAccount,
|
public abstract void recordLoginAgainstUserAccount(UserAccount userAccount,
|
||||||
AuthenticationSource authSource);
|
AuthenticationSource authSource);
|
||||||
|
|
||||||
/**
|
|
||||||
* <pre>
|
|
||||||
* Record that the user has logged in but with only external authentication
|
|
||||||
* info, so no internal user account.
|
|
||||||
* - this involves everything except updating the user record.
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* TODO JB This goes away.
|
|
||||||
*/
|
|
||||||
public abstract void recordLoginWithoutUserAccount(String individualUri);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* Record that the current user has logged out: - notify other users of the
|
* Record that the current user has logged out: - notify other users of the
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
|
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -123,24 +122,12 @@ public class BasicAuthenticator extends Authenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
recordLoginOnUserRecord(userAccount);
|
recordLoginOnUserRecord(userAccount);
|
||||||
recordLoginWithOrWithoutUserAccount(userAccount.getUri(), authSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO JB This goes away.
|
|
||||||
@Override
|
|
||||||
public void recordLoginWithoutUserAccount(String individualUri) {
|
|
||||||
recordLoginWithOrWithoutUserAccount(individualUri,
|
|
||||||
AuthenticationSource.EXTERNAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This much is in common on login, whether or not you have a user account. */
|
|
||||||
private void recordLoginWithOrWithoutUserAccount(String userUri,
|
|
||||||
AuthenticationSource authSource) {
|
|
||||||
HttpSession session = request.getSession();
|
HttpSession session = request.getSession();
|
||||||
createLoginStatusBean(userUri, authSource, session);
|
createLoginStatusBean(userAccount.getUri(), authSource, session);
|
||||||
setSessionTimeoutLimit(session);
|
setSessionTimeoutLimit(session);
|
||||||
recordInUserSessionMap(userUri, session);
|
recordInUserSessionMap(userAccount.getUri(), session);
|
||||||
notifyOtherUsers(userUri, session);
|
notifyOtherUsers(userAccount.getUri(), session);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,7 +5,6 @@ package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
|
||||||
import static edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginExternalAuthSetup.ATTRIBUTE_REFERRER;
|
import static edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginExternalAuthSetup.ATTRIBUTE_REFERRER;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -16,6 +15,8 @@ import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
|
import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsFirstTimeExternalPage;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
|
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,31 +64,20 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
|
||||||
|
|
||||||
UserAccount userAccount = getAuthenticator(req)
|
UserAccount userAccount = getAuthenticator(req)
|
||||||
.getAccountForExternalAuth(externalAuthId);
|
.getAccountForExternalAuth(externalAuthId);
|
||||||
if (userAccount != null) {
|
if (userAccount == null) {
|
||||||
|
log.debug("Creating new account for " + externalAuthId
|
||||||
|
+ ", return to '" + afterLoginUrl + "'");
|
||||||
|
UserAccountsFirstTimeExternalPage.setExternalLoginInfo(req,
|
||||||
|
externalAuthId, afterLoginUrl);
|
||||||
|
resp.sendRedirect(UrlBuilder.getUrl("/accounts/firstTimeExternal"));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
log.debug("Logging in as " + userAccount.getUri());
|
log.debug("Logging in as " + userAccount.getUri());
|
||||||
getAuthenticator(req).recordLoginAgainstUserAccount(userAccount,
|
getAuthenticator(req).recordLoginAgainstUserAccount(userAccount,
|
||||||
AuthenticationSource.EXTERNAL);
|
AuthenticationSource.EXTERNAL);
|
||||||
new LoginRedirector(req, afterLoginUrl).redirectLoggedInUser(resp);
|
new LoginRedirector(req, afterLoginUrl).redirectLoggedInUser(resp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> associatedUris = getAuthenticator(req)
|
|
||||||
.getAssociatedIndividualUris(userAccount);
|
|
||||||
// TODO JB - this case should lead to creating a new account.
|
|
||||||
if (!associatedUris.isEmpty()) {
|
|
||||||
log.debug("Recognize '" + externalAuthId + "' as self-editor for "
|
|
||||||
+ associatedUris);
|
|
||||||
String uri = associatedUris.get(0);
|
|
||||||
|
|
||||||
getAuthenticator(req).recordLoginWithoutUserAccount(uri);
|
|
||||||
new LoginRedirector(req, afterLoginUrl).redirectLoggedInUser(resp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("User is not recognized: " + externalAuthId);
|
|
||||||
removeLoginProcessArtifacts(req);
|
|
||||||
new LoginRedirector(req, afterLoginUrl).redirectUnrecognizedExternalUser(resp,
|
|
||||||
externalAuthId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeLoginProcessArtifacts(HttpServletRequest req) {
|
private void removeLoginProcessArtifacts(HttpServletRequest req) {
|
||||||
|
|
|
@ -182,10 +182,4 @@ public class AuthenticatorStub extends Authenticator {
|
||||||
"AuthenticatorStub.accountRequiresEditing() not implemented.");
|
"AuthenticatorStub.accountRequiresEditing() not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recordLoginWithoutUserAccount(String individualUri) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"AuthenticatorStub.recordLoginWithoutUserAccount() not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
<form method="POST" action="${formUrls.firstTimeExternal}" class="customForm" role="my account">
|
<form method="POST" action="${formUrls.firstTimeExternal}" class="customForm" role="my account">
|
||||||
<input type="hidden" name="externalAuthId" value="${externalAuthId}" />
|
<input type="hidden" name="externalAuthId" value="${externalAuthId}" />
|
||||||
|
<input type="hidden" name="afterLoginUrl" value="${afterLoginUrl}" />
|
||||||
|
|
||||||
<label for="first-name">First name<span class="requiredHint"> *</span></label>
|
<label for="first-name">First name<span class="requiredHint"> *</span></label>
|
||||||
<input type="text" name="firstName" value="${firstName}" id="first-name" role="input "/>
|
<input type="text" name="firstName" value="${firstName}" id="first-name" role="input "/>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue