From 486dc1dd7d9fb48476a8d268a2853ce66ae490d9 Mon Sep 17 00:00:00 2001 From: j2blake Date: Thu, 2 Feb 2012 21:56:48 +0000 Subject: [PATCH] NIHVIVO-2694 Create a new page that allows an admin or root to restrict logins. --- .../admin/RestrictLoginsController.java | 125 ++++++++++++++++++ .../authenticate/RestrictedAuthenticator.java | 115 ++++++++++++++++ .../freemarker/BaseSiteAdminController.java | 4 + webapp/web/WEB-INF/web.xml | 9 ++ .../body/admin/admin-restrictLogins.ftl | 44 ++++++ .../freemarker/body/admin/admin-showAuth.ftl | 7 + .../siteAdmin/siteAdmin-siteConfiguration.ftl | 4 + 7 files changed, 308 insertions(+) create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/admin/RestrictLoginsController.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java create mode 100644 webapp/web/templates/freemarker/body/admin/admin-restrictLogins.ftl diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/admin/RestrictLoginsController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/admin/RestrictLoginsController.java new file mode 100644 index 000000000..2d3eea28b --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/admin/RestrictLoginsController.java @@ -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 body = new HashMap(); + 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); + } + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java new file mode 100644 index 000000000..0da3e3bf8 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java @@ -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 getAssociatedIndividualUris(UserAccount userAccount) { + return auth.getAssociatedIndividualUris(userAccount); + } + + @Override + public void recordUserIsLoggedOut() { + auth.recordUserIsLoggedOut(); + } + + @Override + public String toString() { + return "RestrictedAuthenticator[" + auth + "]"; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java index 159141d3b..454f3da96 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java @@ -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; } diff --git a/webapp/web/WEB-INF/web.xml b/webapp/web/WEB-INF/web.xml index 1e8e7205b..3d437cad1 100644 --- a/webapp/web/WEB-INF/web.xml +++ b/webapp/web/WEB-INF/web.xml @@ -730,6 +730,15 @@ /startupStatus + + RestrictLogins + edu.cornell.mannlib.vitro.webapp.controller.admin.RestrictLoginsController + + + RestrictLogins + /admin/restrictLogins + + StatementChangeListingController edu.cornell.mannlib.vitro.webapp.controller.edit.listing.jena.StatementChangeListingController diff --git a/webapp/web/templates/freemarker/body/admin/admin-restrictLogins.ftl b/webapp/web/templates/freemarker/body/admin/admin-restrictLogins.ftl new file mode 100644 index 000000000..bcea8f669 --- /dev/null +++ b/webapp/web/templates/freemarker/body/admin/admin-restrictLogins.ftl @@ -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. --> + +

Restrict Logins

+ <#if messageAlreadyRestricted??> + <#assign errorMessage = "Logins are already restricted." /> + + + <#if messageAlreadyOpen??> + <#assign errorMessage = "Logins are already not restricted." /> + + + <#if errorMessage?has_content> + + + + <#if messageRestricting??> + <#assign successMessage = "Logins are now restricted." /> + + + <#if messageOpening??> + <#assign successMessage = "Logins are no longer restricted." /> + + + <#if successMessage?has_content> +
+

${successMessage}

+
+ + + +
+ <#if restricted == true> +

Logins are restricted

+

Remove Restrictions

+ <#else> +

Logins are open to all

+

Restrict Logins

+ +
diff --git a/webapp/web/templates/freemarker/body/admin/admin-showAuth.ftl b/webapp/web/templates/freemarker/body/admin/admin-showAuth.ftl index 49ff06f30..6a7c981f4 100644 --- a/webapp/web/templates/freemarker/body/admin/admin-showAuth.ftl +++ b/webapp/web/templates/freemarker/body/admin/admin-showAuth.ftl @@ -75,4 +75,11 @@ ${stylesheets.add(' + +

Authenticator:

+ + + + +
${authenticator}
diff --git a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl index cb2ce4f2e..4f96db431 100644 --- a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl +++ b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl @@ -19,6 +19,10 @@
  • Menu management
  • + <#if siteConfig.restrictLogins?has_content> +
  • Restrict Logins
  • + + <#if siteConfig.siteInfo?has_content>
  • Site information