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());
|
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;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -730,6 +730,15 @@
|
||||||
<url-pattern>/startupStatus</url-pattern>
|
<url-pattern>/startupStatus</url-pattern>
|
||||||
</servlet-mapping>
|
</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>
|
||||||
<servlet-name>StatementChangeListingController</servlet-name>
|
<servlet-name>StatementChangeListingController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.listing.jena.StatementChangeListingController</servlet-class>
|
<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>
|
</tr>
|
||||||
</#list>
|
</#list>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<h4>Authenticator:</h4>
|
||||||
|
<table summary="Authenticator" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td>${authenticator}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
<li role="listitem"><a href="${siteConfig.menuManagement}" title="Menu management">Menu management</a></li>
|
<li role="listitem"><a href="${siteConfig.menuManagement}" title="Menu management">Menu management</a></li>
|
||||||
</#if>
|
</#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>
|
<#if siteConfig.siteInfo?has_content>
|
||||||
<li role="listitem"><a href="${siteConfig.siteInfo}" title="Site information">Site information</a></li>
|
<li role="listitem"><a href="${siteConfig.siteInfo}" title="Site information">Site information</a></li>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
Loading…
Add table
Reference in a new issue