NIHVIVO-2694 Create a new page that allows an admin or root to restrict logins.

This commit is contained in:
j2blake 2012-02-02 21:56:48 +00:00
parent 16c36079db
commit 486dc1dd7d
7 changed files with 308 additions and 0 deletions

View file

@ -0,0 +1,125 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.admin;
import java.util.HashMap;
import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.controller.AbstractPageHandler;
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.BasicAuthenticator;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.RestrictedAuthenticator;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
/**
* Offer the user the ability to apply a RestrictedAuthenticator or revert to a
* BasicAuthenticator.
*/
public class RestrictLoginsController extends FreemarkerHttpServlet {
public static final String PARAMETER_RESTRICT = "restrict";
public static final String PARAMETER_OPEN = "open";
public static final String MESSAGE_NO_MESSAGE = "message";
public static final String MESSAGE_RESTRICTING = "messageRestricting";
public static final String MESSAGE_OPENING = "messageOpening";
public static final String MESSAGE_ALREADY_RESTRICTED = "messageAlreadyRestricted";
public static final String MESSAGE_ALREADY_OPEN = "messageAlreadyOpen";
@Override
protected Actions requiredActions(VitroRequest vreq) {
return SimplePermission.LOGIN_DURING_MAINTENANCE.ACTIONS;
}
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
Core pageHandler = new Core(vreq);
pageHandler.processInput();
return pageHandler.prepareOutput();
}
private static class Core extends AbstractPageHandler {
private enum State {
OPEN, RESTRICTED
}
private String messageCode;
Core(VitroRequest vreq) {
super(vreq);
}
void processInput() {
State desired = figureDesiredState();
State current = figureCurrentlyState();
if (desired == null) {
messageCode = MESSAGE_NO_MESSAGE;
} else if (desired == State.OPEN) {
if (current == State.OPEN) {
messageCode = MESSAGE_ALREADY_OPEN;
} else {
openLogins();
messageCode = MESSAGE_OPENING;
}
} else if (desired == State.RESTRICTED) {
if (current == State.RESTRICTED) {
messageCode = MESSAGE_ALREADY_RESTRICTED;
} else {
restrictLogins();
messageCode = MESSAGE_RESTRICTING;
}
}
}
ResponseValues prepareOutput() {
boolean restricted = figureCurrentlyState() == State.RESTRICTED;
Map<String, Object> body = new HashMap<String, Object>();
body.put("title", "Restrict Logins");
body.put("restricted", restricted);
if (!MESSAGE_NO_MESSAGE.equals(messageCode)) {
body.put(messageCode, Boolean.TRUE);
}
body.put("restrictUrl", UrlBuilder.getUrl("/admin/restrictLogins",
PARAMETER_RESTRICT, "true"));
body.put("openUrl", UrlBuilder.getUrl("/admin/restrictLogins",
PARAMETER_OPEN, "true"));
return new TemplateResponseValues("admin-restrictLogins.ftl", body);
}
private State figureDesiredState() {
if (isFlagOnRequest(PARAMETER_RESTRICT)) {
return State.RESTRICTED;
} else if (isFlagOnRequest(PARAMETER_OPEN)) {
return State.OPEN;
} else {
return null;
}
}
private State figureCurrentlyState() {
Authenticator auth = Authenticator.getInstance(vreq);
if (auth instanceof RestrictedAuthenticator) {
return State.RESTRICTED;
} else {
return State.OPEN;
}
}
private void openLogins() {
Authenticator.setAuthenticatorFactory(
new BasicAuthenticator.Factory(), ctx);
}
private void restrictLogins() {
Authenticator.setAuthenticatorFactory(
new RestrictedAuthenticator.Factory(), ctx);
}
}
}

View file

@ -0,0 +1,115 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.ActiveIdentifierBundleFactories;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.ArrayIdentifierBundle;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
/**
* A "restricted" authenticator, that will not allow logins except for root and
* for users that are authorized to maintain the system.
*/
public class RestrictedAuthenticator extends Authenticator {
// ----------------------------------------------------------------------
// The factory
// ----------------------------------------------------------------------
public static class Factory implements AuthenticatorFactory {
@Override
public Authenticator getInstance(HttpServletRequest req) {
return new RestrictedAuthenticator(req, new BasicAuthenticator(req));
}
}
// ----------------------------------------------------------------------
// The authenticator
// ----------------------------------------------------------------------
private final HttpServletRequest req;
private final Authenticator auth;
public RestrictedAuthenticator(HttpServletRequest req, Authenticator auth) {
this.req = req;
this.auth = auth;
}
@Override
public boolean isUserPermittedToLogin(UserAccount userAccount) {
if (userAccount == null) {
return false;
}
ArrayIdentifierBundle ids = new ArrayIdentifierBundle();
ids.addAll(getIdsForUserAccount(req, userAccount));
ids.addAll(RequestIdentifiers.getIdBundleForRequest(req));
return PolicyHelper.isAuthorizedForActions(ids,
ServletPolicyList.getPolicies(req),
SimplePermission.LOGIN_DURING_MAINTENANCE.ACTIONS);
}
@Override
public void recordLoginAgainstUserAccount(UserAccount userAccount,
AuthenticationSource authSource) throws LoginNotPermitted {
if (!isUserPermittedToLogin(userAccount)) {
throw new LoginNotPermitted();
}
auth.recordLoginAgainstUserAccount(userAccount, authSource);
}
@Override
public UserAccount getAccountForExternalAuth(String externalAuthId) {
return auth.getAccountForExternalAuth(externalAuthId);
}
@Override
public UserAccount getAccountForInternalAuth(String emailAddress) {
return auth.getAccountForInternalAuth(emailAddress);
}
@Override
public boolean isCurrentPassword(UserAccount userAccount,
String clearTextPassword) {
return auth.isCurrentPassword(userAccount, clearTextPassword);
}
@Override
public void recordNewPassword(UserAccount userAccount,
String newClearTextPassword) {
auth.recordNewPassword(userAccount, newClearTextPassword);
}
@Override
public boolean accountRequiresEditing(UserAccount userAccount) {
return auth.accountRequiresEditing(userAccount);
}
@Override
public List<String> getAssociatedIndividualUris(UserAccount userAccount) {
return auth.getAssociatedIndividualUris(userAccount);
}
@Override
public void recordUserIsLoggedOut() {
auth.recordUserIsLoggedOut();
}
@Override
public String toString() {
return "RestrictedAuthenticator[" + auth + "]";
}
}

View file

@ -141,6 +141,10 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet {
data.put("startupStatusAlert", !StartupStatus.getBean(getServletContext()).allClear());
}
if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.LOGIN_DURING_MAINTENANCE.ACTIONS)) {
data.put("restrictLogins", UrlBuilder.getUrl("/admin/restrictLogins"));
}
return data;
}

View file

@ -730,6 +730,15 @@
<url-pattern>/startupStatus</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>RestrictLogins</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.admin.RestrictLoginsController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RestrictLogins</servlet-name>
<url-pattern>/admin/restrictLogins</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>StatementChangeListingController</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.listing.jena.StatementChangeListingController</servlet-class>

View file

@ -0,0 +1,44 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for restricting (or opening) access to logins. -->
<h2>Restrict Logins</h2>
<#if messageAlreadyRestricted??>
<#assign errorMessage = "Logins are already restricted." />
</#if>
<#if messageAlreadyOpen??>
<#assign errorMessage = "Logins are already not restricted." />
</#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>
<#if messageRestricting??>
<#assign successMessage = "Logins are now restricted." />
</#if>
<#if messageOpening??>
<#assign successMessage = "Logins are no longer restricted." />
</#if>
<#if successMessage?has_content>
<section class="success">
<p>${successMessage}</p>
</section>
</#if>
<section id="restrict-login" role="region">
<#if restricted == true>
<h4>Logins are restricted</h4>
<p><a href="${openUrl}" title="Remove Restrictions">Remove Restrictions</a></p>
<#else>
<h4>Logins are open to all</h4>
<p><a href="${restrictUrl}" title="Restrict Logins">Restrict Logins</a></p>
</#if>
</section>

View file

@ -75,4 +75,11 @@ ${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/showAuth.css" /
</tr>
</#list>
</table>
<h4>Authenticator:</h4>
<table summary="Authenticator" width="100%">
<tr>
<td>${authenticator}</td>
</tr>
</table>
</section>

View file

@ -19,6 +19,10 @@
<li role="listitem"><a href="${siteConfig.menuManagement}" title="Menu management">Menu management</a></li>
</#if>
<#if siteConfig.restrictLogins?has_content>
<li role="listitem"><a href="${siteConfig.restrictLogins}" title="Restrict Logins">Restrict Logins</a></li>
</#if>
<#if siteConfig.siteInfo?has_content>
<li role="listitem"><a href="${siteConfig.siteInfo}" title="Site information">Site information</a></li>
</#if>