NIHVIVO-2694 Create a new page that allows an admin or root to restrict logins.
This commit is contained in:
parent
16c36079db
commit
486dc1dd7d
7 changed files with 308 additions and 0 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue