NIHVIVO-1296 Integrate login functionality into login widget.
This commit is contained in:
parent
73b881a805
commit
2973ceebf2
14 changed files with 237 additions and 148 deletions
|
@ -233,6 +233,9 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
|
|||
// We can't use shared variables in the Freemarker configuration to store anything
|
||||
// except theme-specific data, because multiple portals or apps might share the same theme. So instead
|
||||
// we'll get all the shared variables here, and put them in both root and body maps.
|
||||
// If we can eliminate this use case and use shared variables, it would simplify the implementation greatly.
|
||||
// See also directives, where since there are no shared variables we have to manually put elements
|
||||
// of the data model into the directive template model.
|
||||
public Map<String, Object> getSharedVariables(VitroRequest vreq, Map<String, Object> bodyMap) {
|
||||
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.web.widgets;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -11,18 +11,159 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.State;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.TemplateModel;
|
||||
|
||||
public class LoginWidget extends Widget {
|
||||
|
||||
private static final Log log = LogFactory.getLog(LoginWidget.class);
|
||||
|
||||
@Override
|
||||
protected WidgetTemplateValues process(Environment env, Map params,
|
||||
HttpServletRequest request, ServletContext context) {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("fruit", "bananas");
|
||||
return new WidgetTemplateValues (getMarkupMacroName(), map);
|
||||
private static enum Macro {
|
||||
LOGIN("loginForm"),
|
||||
FORCE_PASSWORD_CHANGE("forcePasswordChange"),
|
||||
SERVER_ERROR("error");
|
||||
|
||||
private final String macroName;
|
||||
|
||||
Macro(String macroName) {
|
||||
this.macroName = macroName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return macroName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static enum TemplateVariable {
|
||||
LOGIN_NAME("loginName"),
|
||||
FORM_ACTION("formAction"),
|
||||
INFO_MESSAGE("infoMessage"),
|
||||
ERROR_MESSAGE("errorMessage"),
|
||||
CANCEL_URL("cancelUrl");
|
||||
|
||||
private final String variableName;
|
||||
|
||||
TemplateVariable(String variableName) {
|
||||
this.variableName = variableName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return variableName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WidgetTemplateValues process(Environment env, Map params,
|
||||
HttpServletRequest request, ServletContext context) {
|
||||
|
||||
WidgetTemplateValues values = null;
|
||||
TemplateModel urls = null;
|
||||
|
||||
try {
|
||||
urls = env.getDataModel().get("urls");
|
||||
State state = getCurrentLoginState(request);
|
||||
log.debug("State on exit: " + state);
|
||||
|
||||
switch (state) {
|
||||
case LOGGED_IN:
|
||||
return null;
|
||||
case FORCED_PASSWORD_CHANGE:
|
||||
values = showPasswordChangeScreen(request);
|
||||
break;
|
||||
default:
|
||||
values = showLoginScreen(request);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e);
|
||||
values = showError(e);
|
||||
}
|
||||
values.put("urls", urls);
|
||||
return values;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* User is just starting the login process. Be sure that we have a
|
||||
* {@link LoginProcessBean} with the correct status. Show them the login
|
||||
* screen.
|
||||
*/
|
||||
private WidgetTemplateValues showLoginScreen(HttpServletRequest request)
|
||||
throws IOException {
|
||||
LoginProcessBean bean = LoginProcessBean.getBean(request);
|
||||
bean.setState(State.LOGGING_IN);
|
||||
log.trace("Going to login screen: " + bean);
|
||||
|
||||
WidgetTemplateValues values = new WidgetTemplateValues(Macro.LOGIN.toString());
|
||||
values.put(TemplateVariable.FORM_ACTION.toString(), getAuthenticateUrl(request));
|
||||
values.put(TemplateVariable.LOGIN_NAME.toString(), bean.getUsername());
|
||||
|
||||
String infoMessage = bean.getInfoMessage();
|
||||
if (!infoMessage.isEmpty()) {
|
||||
values.put(TemplateVariable.INFO_MESSAGE.toString(), infoMessage);
|
||||
}
|
||||
String errorMessage = bean.getErrorMessage();
|
||||
if (!errorMessage.isEmpty()) {
|
||||
values.put(TemplateVariable.ERROR_MESSAGE.toString(), errorMessage);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has given the correct password, but now they are required to
|
||||
* change it (unless they cancel out).
|
||||
*/
|
||||
private WidgetTemplateValues showPasswordChangeScreen(HttpServletRequest request) {
|
||||
LoginProcessBean bean = LoginProcessBean.getBean(request);
|
||||
bean.setState(State.FORCED_PASSWORD_CHANGE);
|
||||
log.trace("Going to password change screen: " + bean);
|
||||
|
||||
WidgetTemplateValues values = new WidgetTemplateValues(
|
||||
Macro.FORCE_PASSWORD_CHANGE.toString());
|
||||
values.put(TemplateVariable.FORM_ACTION.toString(), getAuthenticateUrl(request));
|
||||
values.put(TemplateVariable.CANCEL_URL.toString(), getCancelUrl(request));
|
||||
|
||||
String errorMessage = bean.getErrorMessage();
|
||||
if (!errorMessage.isEmpty()) {
|
||||
values.put(TemplateVariable.ERROR_MESSAGE.toString(), errorMessage);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private WidgetTemplateValues showError(Exception e) {
|
||||
WidgetTemplateValues values = new WidgetTemplateValues(
|
||||
Macro.SERVER_ERROR.toString());
|
||||
values.put(TemplateVariable.ERROR_MESSAGE.toString(), "Internal server error:<br /> " + e);
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Where are we in the process? Logged in? Not? Somewhere in between?
|
||||
*/
|
||||
private State getCurrentLoginState(HttpServletRequest request) {
|
||||
if (LoginStatusBean.getBean(request).isLoggedIn()) {
|
||||
return State.LOGGED_IN;
|
||||
} else {
|
||||
return LoginProcessBean.getBean(request).getState();
|
||||
}
|
||||
}
|
||||
|
||||
/** What's the URL for this servlet? */
|
||||
private String getAuthenticateUrl(HttpServletRequest request) {
|
||||
String contextPath = request.getContextPath();
|
||||
return contextPath + "/authenticate";
|
||||
}
|
||||
|
||||
/** What's the URL for this servlet, with the cancel parameter added? */
|
||||
private String getCancelUrl(HttpServletRequest request) {
|
||||
String contextPath = request.getContextPath();
|
||||
String urlParams = "?cancel=true";
|
||||
return contextPath + "/authenticate" + urlParams;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,6 +56,11 @@ public abstract class Widget {
|
|||
ServletContext context = (ServletContext) env.getCustomAttribute("context");
|
||||
|
||||
WidgetTemplateValues values = process(env, params, request, context);
|
||||
// The widget process() method may determine that nothing should display for the widget:
|
||||
// for example, the login widget doesn't display if the user is already logged in.
|
||||
if (values == null) {
|
||||
return "";
|
||||
}
|
||||
String widgetName = params.get("name").toString(); // getWidgetName();
|
||||
return processMacroToString(env, widgetName, values);
|
||||
}
|
||||
|
@ -106,7 +111,9 @@ public abstract class Widget {
|
|||
} catch (Throwable th) {
|
||||
log.error("Could not process widget " + widgetName, th);
|
||||
}
|
||||
return out.toString();
|
||||
String output = out.toString();
|
||||
log.debug("Macro output: " + output);
|
||||
return output;
|
||||
}
|
||||
|
||||
private String processMacroToString(Environment env, String widgetName, String macroName, Map<String, Object> map) {
|
||||
|
@ -135,8 +142,13 @@ public abstract class Widget {
|
|||
private final String macroName;
|
||||
private final Map<String, Object> map;
|
||||
|
||||
public WidgetTemplateValues(String templateName, Map<String, Object> map) {
|
||||
this.macroName = templateName;
|
||||
public WidgetTemplateValues(String macroName) {
|
||||
this.macroName = macroName;
|
||||
this.map = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
public WidgetTemplateValues(String macroName, Map<String, Object> map) {
|
||||
this.macroName = macroName;
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,12 +133,8 @@
|
|||
color:#900;
|
||||
}
|
||||
|
||||
/* In IE6/7, .hidden defined in screen.css doesn't override
|
||||
* display: inline-block defined for #adminDashboard .pageBodyGroup,
|
||||
* so define again with context selector here.
|
||||
*/
|
||||
#adminDashboard .pageBodyGroup.hidden {
|
||||
display: none !important;
|
||||
#loginFormAndLinks {
|
||||
display: none;
|
||||
}
|
||||
|
||||
p.passwordNote {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
// login form is hidden by default; use JavaScript to reveal
|
||||
$("#formLogin").removeClass("hidden");
|
||||
$("#loginFormAndLinks").show();
|
||||
|
||||
// focus on email or newpassword field
|
||||
$('.focus').focus();
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
// login form is hidden by default; use JavaScript to reveal
|
||||
$("#formLogin").removeClass("hidden");
|
||||
|
||||
// focus on email or newpassword field
|
||||
$('.focus').focus();
|
||||
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
// login form is hidden by default; use JavaScript to reveal
|
||||
$("#formLogin").removeClass("hidden");
|
||||
|
||||
// focus on email or newpassword field
|
||||
$('.focus').focus();
|
||||
|
||||
});
|
||||
|
||||
//The above code for revealing the login form doesn't work IE 6 or 7. The code below fix the problem
|
||||
|
||||
var Browser = {
|
||||
Version: function() {
|
||||
var version;
|
||||
if (navigator.appVersion.indexOf("MSIE") != -1)
|
||||
version = parseFloat(navigator.appVersion.split("MSIE")[1]);
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
if (Browser.Version() <= 7) {
|
||||
document.getElementById('formLogin').style.display = 'block';
|
||||
}
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
// login form is hidden by default; use JavaScript to reveal
|
||||
$("#formLogin").removeClass("hidden");
|
||||
|
||||
// focus on email or newpassword field
|
||||
$('.focus').focus();
|
||||
|
||||
});
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#-- Log in template for accessing site admin -->
|
||||
|
||||
<div id="formLogin">
|
||||
<h2>Create Your New Password</h2>
|
||||
|
||||
<#if errorMessage??>
|
||||
<div id="errorAlert"><img src="${urls.siteIcons}/iconAlert.png" width="24" height="24" alert="Error alert icon"/>
|
||||
<p>${errorMessage}</p>
|
||||
</div>
|
||||
</#if>
|
||||
|
||||
<form action="${formAction}" method="post">
|
||||
<label for="newPassword">New Password</label>
|
||||
<input id="newPassword" class="focus" type="password" name="newPassword" />
|
||||
<p class="passwordNote">Minimum of 6 characters in length.</p>
|
||||
<label for="confirmPassword">Confirm Password</label>
|
||||
<input id="confirmPassword" type="password" name="confirmPassword" />
|
||||
<input name="passwordChangeForm" type="submit" class="submit" value="Save Changes"/> <span class="or">or <a class="cancel" href="${cancelUrl}">Cancel</a></span>
|
||||
</form>
|
||||
</div>
|
|
@ -1,35 +0,0 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#-- Template for login form -->
|
||||
|
||||
<noscript>
|
||||
<div id="javascriptDisableWrapper">
|
||||
<div id="javascriptDisableContent">
|
||||
<img src="${urls.siteIcons}/iconAlertBig.png" alt="Alert Icon"/>
|
||||
<p>In order to edit VIVO content, you'll need to enable JavaScript.</p>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<div id="formLogin" class="hidden" >
|
||||
|
||||
<h2>Log in</h2>
|
||||
|
||||
<#if infoMessage??>
|
||||
<h3>${infoMessage}</h3>
|
||||
</#if>
|
||||
|
||||
<#if errorMessage??>
|
||||
<div id="errorAlert"><img src="${urls.siteIcons}/iconAlert.png" alert="Error alert icon"/>
|
||||
<p>${errorMessage}</p>
|
||||
</div>
|
||||
</#if>
|
||||
|
||||
<form action="${formAction}" method="post">
|
||||
<label for="loginName">Email or Username</label>
|
||||
<input id="loginName" class="focus" name="loginName" type="text" value="${loginName}" />
|
||||
<label for="loginPassword">Password</label>
|
||||
<input id="loginPassword" type="password" name="loginPassword" />
|
||||
<input name="loginForm" type="submit" class="submit" value="Log in"/>
|
||||
</form>
|
||||
</div>
|
|
@ -1,10 +0,0 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#-- Main template for the login panel -->
|
||||
|
||||
<#if loginTemplate??>
|
||||
<#include loginTemplate>
|
||||
|
||||
${stylesheets.add("/css/login.css")}
|
||||
${scripts.add("/js/jquery.js", "/js/login/loginUtils.js")}
|
||||
</#if>
|
|
@ -0,0 +1,8 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#-- Main template for the login page -->
|
||||
|
||||
<#-- Use this container to define styles that apply to the login widget only on the dedicated login page. -->
|
||||
<section id="login-full-page">
|
||||
<@widget name="login" />
|
||||
</section>
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
|
||||
<div id="adminDashboard">
|
||||
<#include "login-main.ftl">
|
||||
<#include "siteAdmin-login.ftl">
|
||||
<#include "siteAdmin-dataInput.ftl">
|
||||
<#include "siteAdmin-siteConfiguration.ftl">
|
||||
<#include "siteAdmin-ontologyEditor.ftl">
|
||||
|
|
|
@ -3,25 +3,47 @@
|
|||
<#-- Login widget -->
|
||||
|
||||
<#macro assets>
|
||||
<#if ! loginName??>
|
||||
<#-- RY This test should be replaced by controller logic which doesn't display any assets if the user is logged in.
|
||||
See NIHVIVO-1357. This test does nothing, since loginName has not been put into the data model.
|
||||
<#if ! loginName?has_content> -->
|
||||
${stylesheets.add("/css/login.css")}
|
||||
<#-- define any js files needed for the login widget
|
||||
${scripts.add("")}
|
||||
${headScripts.add("")} -->
|
||||
</#if>
|
||||
${scripts.add("/js/jquery.js", "/js/login/loginUtils.js")}
|
||||
<#-- ${headScripts.add("")} -->
|
||||
<#-- </#if> -->
|
||||
</#macro>
|
||||
|
||||
<#macro markup>
|
||||
<#if ! loginName??>
|
||||
<#macro loginForm>
|
||||
|
||||
<section id="log-in">
|
||||
<h2>Log in</h2>
|
||||
|
||||
<form id="log-in-form" action="${urls.home}/authenticate?login=block" method="post" name="log-in-form" />
|
||||
<noscript>
|
||||
<section id="javascriptDisableWrapper">
|
||||
<section id="javascriptDisableContent">
|
||||
<img src="${urls.siteIcons}/iconAlertBig.png" alt="Alert Icon"/>
|
||||
<p>In order to edit VIVO content, you'll need to enable JavaScript.</p>
|
||||
</section>
|
||||
</section>
|
||||
</noscript>
|
||||
|
||||
<#if infoMessage??>
|
||||
<h3>${infoMessage}</h3>
|
||||
</#if>
|
||||
|
||||
<#if errorMessage??>
|
||||
<section id="errorAlert"><img src="${urls.siteIcons}/iconAlert.png" alert="Error alert icon"/>
|
||||
<p>${errorMessage}</p>
|
||||
</section>
|
||||
</#if>
|
||||
|
||||
<section id="loginFormAndLinks">
|
||||
|
||||
<form id="log-in-form" action="${formAction}" method="post" name="log-in-form" />
|
||||
<label for="email">Email</label>
|
||||
<input class="text-field" name="loginName" id="loginName" type="text" required />
|
||||
|
||||
<label for="password">Password</label>
|
||||
<input class="text-field" name="loginPassword" id="password" type="loginPassword" required />
|
||||
<input class="text-field" name="loginPassword" id="password" type="password" required />
|
||||
|
||||
<p class="submit"><input name="loginForm" type="submit" class="green button" value="Log in"/></p>
|
||||
|
||||
|
@ -31,6 +53,31 @@
|
|||
|
||||
<p class="forgot-password"><a href="#">Forgot your password?</a></p>
|
||||
<p class="request-account"><a class=" blue button" href="#">Request an account</a> </p>
|
||||
</section>
|
||||
</section><!-- #log-in -->
|
||||
</#macro>
|
||||
|
||||
<#macro forcePasswordChange>
|
||||
<section id="log-in">
|
||||
<h2>Log in</h2>
|
||||
|
||||
<#if errorMessage??>
|
||||
<div id="errorAlert"><img src="${urls.siteIcons}/iconAlert.png" width="24" height="24" alert="Error alert icon"/>
|
||||
<p>${errorMessage}</p>
|
||||
</div>
|
||||
</#if>
|
||||
</#macro> -->
|
||||
|
||||
<form id="log-in-form" action="${formAction}" method="post" name="log-in-form" />
|
||||
<label for="newPassword">New Password</label>
|
||||
<input id="newPassword" class="focus" type="password" name="newPassword" />
|
||||
<p class="passwordNote">Minimum of 6 characters in length.</p>
|
||||
<label for="confirmPassword">Confirm Password</label>
|
||||
<input id="confirmPassword" type="password" name="confirmPassword" />
|
||||
<input name="passwordChangeForm" type="submit" class="submit" value="Save Changes"/> <span class="or">or <a class="cancel" href="${cancelUrl}">Cancel</a></span>
|
||||
</form>
|
||||
</section>
|
||||
</#macro>
|
||||
|
||||
<#macro error>
|
||||
<p>There was an error in the system.</p>
|
||||
</#macro>
|
Loading…
Add table
Add a link
Reference in a new issue