/*
* Password Management Servlets (PWM)
* http://www.pwm-project.org
*
* Copyright (c) 2006-2009 Novell, Inc.
* Copyright (c) 2009-2017 The PWM Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package password.pwm.http.servlet;
import com.novell.ldapchai.exception.ChaiUnavailableException;
import com.novell.ldapchai.util.StringHelper;
import password.pwm.PwmApplication;
import password.pwm.PwmConstants;
import password.pwm.config.PwmSetting;
import password.pwm.config.ShortcutItem;
import password.pwm.error.PwmError;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.http.HttpMethod;
import password.pwm.http.JspUrl;
import password.pwm.http.PwmRequest;
import password.pwm.http.PwmRequestAttribute;
import password.pwm.http.PwmSession;
import password.pwm.http.bean.ShortcutsBean;
import password.pwm.ldap.LdapPermissionTester;
import password.pwm.svc.stats.Statistic;
import password.pwm.util.java.JavaHelper;
import password.pwm.util.logging.PwmLogger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@WebServlet(
name="ShortcutServlet",
urlPatterns = {
PwmConstants.URL_PREFIX_PRIVATE + "/shortcuts",
PwmConstants.URL_PREFIX_PRIVATE + "/Shortcuts",
}
)
public class ShortcutServlet extends AbstractPwmServlet {
private static final PwmLogger LOGGER = PwmLogger.forClass(ShortcutServlet.class);
public enum ShortcutAction implements AbstractPwmServlet.ProcessAction {
selectShortcut,
;
public Collection<HttpMethod> permittedMethods() {
return Collections.singletonList(HttpMethod.GET);
}
}
protected ShortcutAction readProcessAction(final PwmRequest request)
throws PwmUnrecoverableException {
try {
return ShortcutAction.valueOf(request.readParameterAsString(PwmConstants.PARAM_ACTION_REQUEST));
} catch (IllegalArgumentException e) {
return null;
}
}
protected void processAction(final PwmRequest pwmRequest)
throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException {
final PwmSession pwmSession = pwmRequest.getPwmSession();
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
if (!pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.SHORTCUT_ENABLE)) {
pwmRequest.respondWithError(PwmError.ERROR_SERVICE_NOT_AVAILABLE.toInfo());
return;
}
final ShortcutsBean shortcutsBean = pwmApplication.getSessionStateService().getBean(pwmRequest, ShortcutsBean.class);
if (shortcutsBean.getVisibleItems() == null) {
LOGGER.debug(pwmSession, "building visible shortcut list for user");
final Map<String, ShortcutItem> visibleItems = figureVisibleShortcuts(pwmRequest);
shortcutsBean.setVisibleItems(visibleItems);
} else {
LOGGER.trace(pwmSession, "using cashed shortcut values");
}
final ShortcutAction action = readProcessAction(pwmRequest);
if (action != null) {
pwmRequest.validatePwmFormID();
switch (action) {
case selectShortcut:
handleUserSelection(pwmRequest, shortcutsBean);
return;
default:
JavaHelper.unhandledSwitchStatement(action);
}
}
forwardToJsp(pwmRequest, shortcutsBean);
}
private void forwardToJsp(final PwmRequest pwmRequest, final ShortcutsBean shortcutsBean)
throws ServletException, PwmUnrecoverableException, IOException {
final ArrayList<ShortcutItem> shortcutItems = new ArrayList<>();
shortcutItems.addAll(shortcutsBean.getVisibleItems().values());
pwmRequest.setAttribute(PwmRequestAttribute.ShortcutItems, shortcutItems);
pwmRequest.forwardToJsp(JspUrl.SHORTCUT);
}
/**
* Loop through each configured shortcut setting to determine if the shortcut is is able to the user pwmSession.
*/
private static Map<String, ShortcutItem> figureVisibleShortcuts(
final PwmRequest pwmRequest
)
throws PwmUnrecoverableException, ChaiUnavailableException {
final Collection<String> configValues = pwmRequest.getConfig().readSettingAsLocalizedStringArray(PwmSetting.SHORTCUT_ITEMS, pwmRequest.getLocale());
final Set<String> labelsFromHeader = new HashSet<>();
{
final Map<String, List<String>> headerValueMap = pwmRequest.readHeaderValuesMap();
final List<String> interestedHeaderNames = pwmRequest.getConfig().readSettingAsStringArray(PwmSetting.SHORTCUT_HEADER_NAMES);
for (final String headerName : headerValueMap.keySet()) {
if (interestedHeaderNames.contains(headerName)) {
for (final String loopValues : headerValueMap.get(headerName)) {
labelsFromHeader.addAll(StringHelper.tokenizeString(loopValues, ","));
}
}
}
}
final List<ShortcutItem> configuredItems = new ArrayList<>();
for (final String loopStr : configValues) {
final ShortcutItem item = ShortcutItem.parsePwmConfigInput(loopStr);
configuredItems.add(item);
}
final Map<String, ShortcutItem> visibleItems = new LinkedHashMap<>();
if (!labelsFromHeader.isEmpty()) {
LOGGER.trace("detected the following labels from headers: " + StringHelper.stringCollectionToString(labelsFromHeader, ","));
visibleItems.keySet().retainAll(labelsFromHeader);
} else {
for (final ShortcutItem item : configuredItems) {
final boolean queryMatch = LdapPermissionTester.testQueryMatch(
pwmRequest.getPwmApplication(),
pwmRequest.getSessionLabel(),
pwmRequest.getPwmSession().getUserInfoBean().getUserIdentity(),
item.getLdapQuery()
);
if (queryMatch) {
visibleItems.put(item.getLabel(), item);
}
}
}
return visibleItems;
}
private void handleUserSelection(
final PwmRequest pwmRequest,
final ShortcutsBean shortcutsBean
)
throws PwmUnrecoverableException, ChaiUnavailableException, IOException, ServletException {
final PwmSession pwmSession = pwmRequest.getPwmSession();
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
final String link = pwmRequest.readParameterAsString("link");
final Map<String, ShortcutItem> visibleItems = shortcutsBean.getVisibleItems();
if (link != null && visibleItems.keySet().contains(link)) {
final ShortcutItem item = visibleItems.get(link);
pwmApplication.getStatisticsManager().incrementValue(Statistic.SHORTCUTS_SELECTED);
LOGGER.trace(pwmSession, "shortcut link selected: " + link + ", setting link for 'forwardURL' to " + item.getShortcutURI());
pwmSession.getSessionStateBean().setForwardURL(item.getShortcutURI().toString());
pwmRequest.sendRedirectToContinue();
return;
}
LOGGER.error(pwmSession, "unknown/unexpected link requested to " + link);
pwmRequest.forwardToJsp(JspUrl.SHORTCUT);
}
}