ソースを参照

refactor configeditor and solve issue with @PwmContextPath@ macro not resolving in setting descriptions.

Jason Rivard 7 年 前
コミット
ba039dd8f8

+ 9 - 33
server/src/main/java/password/pwm/http/servlet/configeditor/CategoryInfo.java

@@ -22,11 +22,14 @@
 
 package password.pwm.http.servlet.configeditor;
 
+import lombok.Data;
 import password.pwm.config.PwmSettingCategory;
+import password.pwm.util.macro.MacroMachine;
 
 import java.io.Serializable;
 import java.util.Locale;
 
+@Data
 public class CategoryInfo implements Serializable {
     private int level;
     private String key;
@@ -37,43 +40,16 @@ public class CategoryInfo implements Serializable {
     private boolean profiles;
     private String menuLocation;
 
-    public int getLevel() {
-        return level;
-    }
-
-    public String getKey() {
-        return key;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    public String getParent() {
-        return parent;
-    }
-
-    public boolean isHidden() {
-        return hidden;
-    }
-
-    public boolean isProfiles() {
-        return profiles;
-    }
-
-    public String getMenuLocation() {
-        return menuLocation;
-    }
 
-    public static CategoryInfo forCategory(final PwmSettingCategory category, final Locale locale) {
+    public static CategoryInfo forCategory(
+            final PwmSettingCategory category,
+            final MacroMachine macroMachine,
+            final Locale locale)
+    {
         final CategoryInfo categoryInfo = new CategoryInfo();
         categoryInfo.key = category.getKey();
         categoryInfo.level = category.getLevel();
-        categoryInfo.description = category.getDescription(locale);
+        categoryInfo.description = macroMachine.expandMacros(category.getDescription(locale));
         categoryInfo.label = category.getLabel(locale);
         categoryInfo.hidden = category.isHidden();
         if (category.getParent() != null) {

+ 143 - 208
server/src/main/java/password/pwm/http/servlet/configeditor/ConfigEditorServlet.java

@@ -58,19 +58,19 @@ import password.pwm.health.HealthTopic;
 import password.pwm.health.LDAPStatusChecker;
 import password.pwm.http.HttpMethod;
 import password.pwm.http.JspUrl;
+import password.pwm.http.ProcessStatus;
 import password.pwm.http.PwmHttpRequestWrapper;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmSession;
 import password.pwm.http.bean.ConfigManagerBean;
 import password.pwm.http.servlet.AbstractPwmServlet;
+import password.pwm.http.servlet.ControlledPwmServlet;
 import password.pwm.http.servlet.configmanager.ConfigManagerServlet;
 import password.pwm.i18n.Config;
 import password.pwm.i18n.Message;
 import password.pwm.i18n.PwmLocaleBundle;
 import password.pwm.ldap.LdapBrowser;
 import password.pwm.util.PasswordData;
-import password.pwm.util.Validator;
-import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.JsonUtil;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.TimeDuration;
@@ -113,7 +113,7 @@ import java.util.concurrent.ConcurrentHashMap;
                 PwmConstants.URL_PREFIX_PRIVATE + "/config/ConfigEditor/*",
         }
 )
-public class ConfigEditorServlet extends AbstractPwmServlet {
+public class ConfigEditorServlet extends ControlledPwmServlet {
 
     private static final PwmLogger LOGGER = PwmLogger.forClass(ConfigEditorServlet.class);
 
@@ -151,123 +151,39 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
         }
     }
 
-    protected ConfigEditorAction readProcessAction(final PwmRequest request)
-            throws PwmUnrecoverableException {
-        try {
-            return ConfigEditorAction.valueOf(request.readParameterAsString(PwmConstants.PARAM_ACTION_REQUEST));
-        } catch (IllegalArgumentException e) {
-            return null;
-        }
+    @Override
+    public Class<? extends ProcessAction> getProcessActionsClass() {
+        return ConfigEditorAction.class;
     }
 
-
-    protected void processAction(final PwmRequest pwmRequest)
-            throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException
-    {
-        final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ConfigManagerBean.class);
+    @Override
+    public ProcessStatus preProcessCheck(final PwmRequest pwmRequest) throws PwmUnrecoverableException, IOException, ServletException {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
 
         if (configManagerBean.getStoredConfiguration() == null) {
             final StoredConfigurationImpl loadedConfig = ConfigManagerServlet.readCurrentConfiguration(pwmRequest);
             configManagerBean.setConfiguration(loadedConfig);
         }
 
-        final ConfigEditorAction action = readProcessAction(pwmRequest);
-
-        if (action != null) {
-            Validator.validatePwmFormID(pwmRequest);
-
-            switch (action) {
-                case readSetting:
-                    restReadSetting(pwmRequest, configManagerBean);
-                    return;
-
-                case writeSetting:
-                    restWriteSetting(pwmRequest, configManagerBean);
-                    return;
-
-                case resetSetting:
-                    restResetSetting(pwmRequest, configManagerBean);
-                    return;
-
-                case ldapHealthCheck:
-                    restLdapHealthCheck(pwmRequest, configManagerBean);
-                    return;
-
-                case databaseHealthCheck:
-                    restDatabaseHealthCheck(pwmRequest, configManagerBean);
-                    return;
-
-                case smsHealthCheck:
-                    restSmsHealthCheck(pwmRequest, configManagerBean);
-                    return;
-
-                case finishEditing:
-                    restFinishEditing(pwmRequest, configManagerBean);
-                    return;
-
-                case executeSettingFunction:
-                    restExecuteSettingFunction(pwmRequest, configManagerBean);
-                    return;
-
-                case setConfigurationPassword:
-                    restSetConfigurationPassword(pwmRequest, configManagerBean);
-                    return;
-
-                case readChangeLog:
-                    restReadChangeLog(pwmRequest, configManagerBean);
-                    return;
-
-                case search:
-                    restSearchSettings(pwmRequest, configManagerBean);
-                    return;
-
-                case cancelEditing:
-                    restCancelEditing(pwmRequest, configManagerBean);
-                    return;
-
-                case uploadFile:
-                    doUploadFile(pwmRequest, configManagerBean);
-                    return;
-
-                case setOption:
-                    setOptions(pwmRequest, configManagerBean);
-                    return;
-
-                case menuTreeData:
-                    restMenuTreeData(pwmRequest, configManagerBean);
-                    return;
-
-                case settingData:
-                    restConfigSettingData(pwmRequest, configManagerBean);
-                    return;
-
-                case testMacro:
-                    restTestMacro(pwmRequest);
-                    return;
-
-                case browseLdap:
-                    restBrowseLdap(pwmRequest, configManagerBean);
-                    return;
-
-                case copyProfile:
-                    restCopyProfile(pwmRequest, configManagerBean);
-                    return;
+        return ProcessStatus.Continue;
+    }
 
-                default:
-                    JavaHelper.unhandledSwitchStatement(action);
-            }
-        }
+    @Override
+    protected void nextStep(final PwmRequest pwmRequest) throws PwmUnrecoverableException, IOException, ChaiUnavailableException, ServletException {
+        pwmRequest.forwardToJsp(JspUrl.CONFIG_MANAGER_EDITOR);
+    }
 
-        if (!pwmRequest.getPwmResponse().isCommitted()) {
-            pwmRequest.forwardToJsp(JspUrl.CONFIG_MANAGER_EDITOR);
-        }
+    private ConfigManagerBean getBean(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
+        return pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ConfigManagerBean.class);
     }
 
-    private void restExecuteSettingFunction(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "executeSettingFunction")
+    private ProcessStatus restExecuteSettingFunction(
+            final PwmRequest pwmRequest
     )
-            throws IOException, PwmUnrecoverableException {
+            throws IOException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final String bodyString = pwmRequest.readRequestBodyAsString();
         final Map<String, String> requestMap = JsonUtil.deserializeStringMap(bodyString);
         final PwmSetting pwmSetting = PwmSetting.forKey(requestMap.get("setting"));
@@ -291,14 +207,17 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
             }
             pwmRequest.outputJsonResult(restResultBean);
         }
+
+        return ProcessStatus.Halt;
     }
 
-    private void restReadSetting(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "readSetting")
+    private ProcessStatus restReadSetting(
+            final PwmRequest pwmRequest
     )
             throws IOException, PwmUnrecoverableException
     {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final StoredConfigurationImpl storedConfig = configManagerBean.getStoredConfiguration();
 
         final String key = pwmRequest.readParameterAsString("key");
@@ -338,7 +257,7 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
             final String errorStr = "readSettingAsString request for unknown key: " + key;
             LOGGER.warn(errorStr);
             pwmRequest.outputJsonResult(RestResultBean.fromError(new ErrorInformation(PwmError.ERROR_UNKNOWN, errorStr)));
-            return;
+            return ProcessStatus.Halt;
         } else {
             final String profile = theSetting.getCategory().hasProfiles() ? pwmRequest.readParameterAsString("profile") : null;
             switch (theSetting.getSyntax()) {
@@ -392,13 +311,16 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
         }
         returnMap.put("value", returnValue);
         pwmRequest.outputJsonResult(RestResultBean.withData(returnMap));
+        return ProcessStatus.Halt;
     }
 
-    private void restWriteSetting(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "writeSetting")
+    private ProcessStatus restWriteSetting(
+            final PwmRequest pwmRequest
     )
-            throws IOException, PwmUnrecoverableException {
+            throws IOException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final StoredConfigurationImpl storedConfig = configManagerBean.getStoredConfiguration();
         final String key = pwmRequest.readParameterAsString("key");
         final String bodyString = pwmRequest.readRequestBodyAsString();
@@ -439,13 +361,16 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
             returnMap.put("isDefault", storedConfig.isDefaultValue(setting, profileID));
         }
         pwmRequest.outputJsonResult(RestResultBean.withData(returnMap));
+        return ProcessStatus.Halt;
     }
 
-    private void restResetSetting(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "resetSetting")
+    private ProcessStatus restResetSetting(
+            final PwmRequest pwmRequest
     )
-            throws IOException, PwmUnrecoverableException {
+            throws IOException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final StoredConfigurationImpl storedConfig = configManagerBean.getStoredConfiguration();
         final UserIdentity loggedInUser = pwmRequest.getUserInfoIfLoggedIn();
         final String key = pwmRequest.readParameterAsString("key");
@@ -463,14 +388,17 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
         }
 
         pwmRequest.outputJsonResult(RestResultBean.forSuccessMessage(pwmRequest, Message.Success_Unknown));
+        return ProcessStatus.Halt;
     }
 
-
-    private void restSetConfigurationPassword(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "setConfigurationPassword")
+    private ProcessStatus restSetConfigurationPassword(
+            final PwmRequest pwmRequest
     )
-            throws IOException, ServletException, PwmUnrecoverableException {
+            throws IOException, ServletException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
+
         try {
             final Map<String, String> postData = pwmRequest.readBodyAsJsonStringMap();
             final String password = postData.get("password");
@@ -484,20 +412,23 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
             final RestResultBean restResultBean = RestResultBean.fromError(e.getErrorInformation(), pwmRequest);
             pwmRequest.outputJsonResult(restResultBean);
         }
+
+        return ProcessStatus.Halt;
     }
 
-    private void restFinishEditing(final PwmRequest pwmRequest, final ConfigManagerBean configManagerBean)
-            throws IOException, ServletException, PwmUnrecoverableException {
+    @ActionHandler(action = "finishEditing")
+    private ProcessStatus restFinishEditing(final PwmRequest pwmRequest)
+            throws IOException, ServletException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final PwmSession pwmSession = pwmRequest.getPwmSession();
-
-
         final List<String> validationErrors = configManagerBean.getStoredConfiguration().validateValues();
         if (!validationErrors.isEmpty()) {
             final String errorString = validationErrors.get(0);
             final ErrorInformation errorInfo = new ErrorInformation(PwmError.CONFIG_FORMAT_ERROR, errorString, new String[]{errorString});
             pwmRequest.outputJsonResult(RestResultBean.fromError(errorInfo, pwmRequest));
             LOGGER.error(pwmSession, errorInfo);
-            return;
+            return ProcessStatus.Halt;
         } else {
             try {
                 ConfigManagerServlet.saveConfiguration(pwmRequest, configManagerBean.getStoredConfiguration());
@@ -509,26 +440,32 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
                 final ErrorInformation errorInfo = e.getErrorInformation();
                 pwmRequest.outputJsonResult(RestResultBean.fromError(errorInfo, pwmRequest));
                 LOGGER.error(pwmSession, errorInfo);
-                return;
             }
         }
 
+        return ProcessStatus.Halt;
     }
 
-    private void restCancelEditing(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "cancelEditing")
+    private ProcessStatus restCancelEditing(
+            final PwmRequest pwmRequest
     )
-            throws IOException, ServletException, PwmUnrecoverableException {
+            throws IOException, ServletException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         configManagerBean.setConfiguration(null);
         pwmRequest.outputJsonResult(RestResultBean.forSuccessMessage(pwmRequest, Message.Success_Unknown));
+        return ProcessStatus.Halt;
     }
 
-    private void setOptions(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "setOption")
+    private ProcessStatus setOptions(
+            final PwmRequest pwmRequest
+
     )
-            throws IOException, PwmUnrecoverableException {
+            throws IOException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         {
             final String updateDescriptionTextCmd = pwmRequest.readParameterAsString("updateNotesText");
             if (updateDescriptionTextCmd != null && "true".equalsIgnoreCase(updateDescriptionTextCmd)) {
@@ -558,13 +495,17 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
                 }
             }
         }
+
+        return ProcessStatus.Halt;
     }
 
-    void restReadChangeLog(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "readChangeLog")
+    private ProcessStatus restReadChangeLog(
+            final PwmRequest pwmRequest
     )
-            throws IOException {
+            throws IOException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final Locale locale = pwmRequest.getLocale();
         final HashMap<String, Object> returnObj = new HashMap<>();
         returnObj.put("html", configManagerBean.getStoredConfiguration().changeLogAsDebugString(locale, true));
@@ -588,15 +529,17 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
 
         final RestResultBean restResultBean = RestResultBean.withData(returnObj);
         pwmRequest.outputJsonResult(restResultBean);
+        return ProcessStatus.Halt;
     }
 
-    void restSearchSettings(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "search")
+    private ProcessStatus restSearchSettings(
+            final PwmRequest pwmRequest
     )
             throws IOException, PwmUnrecoverableException
     {
         final Instant startTime = Instant.now();
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final String bodyData = pwmRequest.readRequestBodyAsString();
         final Map<String, String> valueMap = JsonUtil.deserializeStringMap(bodyData);
         final Locale locale = pwmRequest.getLocale();
@@ -639,15 +582,17 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
         }
 
         pwmRequest.outputJsonResult(restResultBean);
+        return ProcessStatus.Halt;
     }
 
-    private void restLdapHealthCheck(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "ldapHealthCheck")
+    private ProcessStatus restLdapHealthCheck(
+            final PwmRequest pwmRequest
     )
             throws IOException, PwmUnrecoverableException
     {
         final Instant startTime = Instant.now();
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         LOGGER.debug(pwmRequest, "beginning restLdapHealthCheck");
         final String profileID = pwmRequest.readParameterAsString("profile");
         final Configuration config = new Configuration(configManagerBean.getStoredConfiguration());
@@ -656,14 +601,17 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
 
         pwmRequest.outputJsonResult(restResultBean);
         LOGGER.debug(pwmRequest, "completed restLdapHealthCheck in " + TimeDuration.fromCurrent(startTime).asCompactString());
+        return ProcessStatus.Halt;
     }
 
-    private void restDatabaseHealthCheck(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "databaseHealthCheck")
+    private ProcessStatus restDatabaseHealthCheck(
+            final PwmRequest pwmRequest
     )
-            throws IOException, PwmUnrecoverableException {
+            throws IOException, PwmUnrecoverableException
+    {
         final Instant startTime = Instant.now();
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         LOGGER.debug(pwmRequest, "beginning restDatabaseHealthCheck");
         final Configuration config = new Configuration(configManagerBean.getStoredConfiguration());
         final List<HealthRecord> healthRecords = DatabaseStatusChecker.checkNewDatabaseStatus(pwmRequest.getPwmApplication(), config);
@@ -671,14 +619,17 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
         final RestResultBean restResultBean = RestResultBean.withData(healthData);
         pwmRequest.outputJsonResult(restResultBean);
         LOGGER.debug(pwmRequest, "completed restDatabaseHealthCheck in " + TimeDuration.fromCurrent(startTime).asCompactString());
+        return ProcessStatus.Halt;
     }
 
-    private void restSmsHealthCheck(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "smsHealthCheck")
+    private ProcessStatus restSmsHealthCheck(
+            final PwmRequest pwmRequest
     )
-            throws IOException, PwmUnrecoverableException {
+            throws IOException, PwmUnrecoverableException
+    {
         final Instant startTime = Instant.now();
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         LOGGER.debug(pwmRequest, "beginning restSmsHealthCheck");
 
         final List<HealthRecord> returnRecords = new ArrayList<>();
@@ -702,14 +653,16 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
         final RestResultBean restResultBean = RestResultBean.withData(healthData);
         pwmRequest.outputJsonResult(restResultBean);
         LOGGER.debug(pwmRequest, "completed restSmsHealthCheck in " + TimeDuration.fromCurrent(startTime).asCompactString());
+        return ProcessStatus.Halt;
     }
 
-    private void doUploadFile(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "uploadFile")
+    private ProcessStatus doUploadFile(
+            final PwmRequest pwmRequest
     )
             throws PwmUnrecoverableException, IOException, ServletException
     {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final String key = pwmRequest.readParameterAsString("key");
         final PwmSetting setting = PwmSetting.forKey(key);
         final int maxFileSize = Integer.parseInt(pwmRequest.getConfig().readAppProperty(AppProperty.CONFIG_MAX_JDBC_JAR_SIZE));
@@ -738,15 +691,15 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
                 );
 
                 pwmRequest.outputJsonResult(RestResultBean.forSuccessMessage(pwmRequest, Message.Success_Unknown));
-                return;
+                return ProcessStatus.Halt;
             } catch (PwmException e) {
                 LOGGER.error(pwmRequest, "error during https certificate upload: " + e.getMessage());
                 pwmRequest.respondWithError(e.getErrorInformation(),false);
-                return;
+                return ProcessStatus.Halt;
             }
         }
 
-        final FileValue fileValue = readFileUploadToSettingValue(pwmRequest, maxFileSize);
+        final FileValue fileValue = ConfigEditorServletUtils.readFileUploadToSettingValue(pwmRequest, maxFileSize);
         if (fileValue != null) {
             final UserIdentity userIdentity = pwmRequest.isAuthenticated()
                     ? pwmRequest.getPwmSession().getUserInfo().getUserIdentity()
@@ -755,51 +708,18 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
             configManagerBean.getStoredConfiguration().writeSetting(setting, fileValue, userIdentity);
             pwmRequest.outputJsonResult(RestResultBean.forSuccessMessage(pwmRequest, Message.Success_Unknown));
         }
-    }
-
-    public static FileValue readFileUploadToSettingValue(
-            final PwmRequest pwmRequest,
-            final int maxFileSize
-    )
-            throws PwmUnrecoverableException, IOException, ServletException
-    {
-
-        final Map<String, PwmRequest.FileUploadItem> fileUploads;
-        try {
-            fileUploads = pwmRequest.readFileUploads(maxFileSize, 1);
-        } catch (PwmException e) {
-            pwmRequest.outputJsonResult(RestResultBean.fromError(e.getErrorInformation(), pwmRequest));
-            LOGGER.error(pwmRequest, "error during file upload: " + e.getErrorInformation().toDebugStr());
-            return null;
-        } catch (Throwable e) {
-            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN, "error during file upload: " + e.getMessage());
-            pwmRequest.outputJsonResult(RestResultBean.fromError(errorInformation, pwmRequest));
-            LOGGER.error(pwmRequest, errorInformation);
-            return null;
-        }
-
-        if (fileUploads.containsKey(PwmConstants.PARAM_FILE_UPLOAD)) {
-            final PwmRequest.FileUploadItem uploadItem = fileUploads.get(PwmConstants.PARAM_FILE_UPLOAD);
 
-            final Map<FileValue.FileInformation, FileValue.FileContent> newFileValueMap = new LinkedHashMap<>();
-            newFileValueMap.put(new FileValue.FileInformation(uploadItem.getName(), uploadItem.getType()), new FileValue.FileContent(uploadItem.getContent()));
-
-            return new FileValue(newFileValueMap);
-        }
-
-        final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN, "no file found in upload");
-        pwmRequest.outputJsonResult(RestResultBean.fromError(errorInformation, pwmRequest));
-        LOGGER.error(pwmRequest, "error during file upload: " + errorInformation.toDebugStr());
-        return null;
+        return ProcessStatus.Halt;
     }
 
-    private void restMenuTreeData(
-            final PwmRequest pwmRequest,
-            final ConfigManagerBean configManagerBean
+    @ActionHandler(action = "menuTreeData")
+    private ProcessStatus restMenuTreeData(
+            final PwmRequest pwmRequest
     )
             throws IOException, PwmUnrecoverableException
     {
         final Instant startTime = Instant.now();
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
 
         final ArrayList<NavTreeItem> navigationData = new ArrayList<>();
         final Map<String,Object> inputParameters = pwmRequest.readBodyAsJsonMap(PwmHttpRequestWrapper.Flag.BypassValidation);
@@ -863,25 +783,31 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
 
         LOGGER.trace(pwmRequest,"completed navigation tree data request in " + TimeDuration.fromCurrent(startTime).asCompactString());
         pwmRequest.outputJsonResult(RestResultBean.withData(navigationData));
+        return ProcessStatus.Halt;
     }
 
-    private void restConfigSettingData(final PwmRequest pwmRequest, final ConfigManagerBean configManagerBean)
-            throws IOException, PwmUnrecoverableException {
+    @ActionHandler(action = "settingData")
+    private ProcessStatus restConfigSettingData(final PwmRequest pwmRequest)
+            throws IOException, PwmUnrecoverableException
+    {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final PwmSettingTemplateSet template = configManagerBean.getStoredConfiguration().getTemplateSet();
         final LinkedHashMap<String, Object> returnMap = new LinkedHashMap<>();
         final Locale locale = pwmRequest.getLocale();
+        final MacroMachine macroMachine = MacroMachine.forNonUserSpecific(pwmRequest.getPwmApplication(), pwmRequest.getSessionLabel());
+
         {
             final LinkedHashMap<String, Object> settingMap = new LinkedHashMap<>();
             for (final PwmSetting setting : PwmSetting.values()) {
 
-                settingMap.put(setting.getKey(), SettingInfo.forSetting(setting, template, locale));
+                settingMap.put(setting.getKey(), SettingInfo.forSetting(setting, template, macroMachine, locale));
             }
             returnMap.put("settings", settingMap);
         }
         {
             final LinkedHashMap<String, Object> categoryMap = new LinkedHashMap<>();
             for (final PwmSettingCategory category : PwmSettingCategory.values()) {
-                categoryMap.put(category.getKey(), CategoryInfo.forCategory(category, locale));
+                categoryMap.put(category.getKey(), CategoryInfo.forCategory(category, macroMachine, locale));
             }
             returnMap.put("categories", categoryMap);
         }
@@ -912,14 +838,16 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
 
         final RestResultBean restResultBean = RestResultBean.withData(returnMap);
         pwmRequest.outputJsonResult(restResultBean);
+        return ProcessStatus.Halt;
     }
 
-    private void restTestMacro(final PwmRequest pwmRequest) throws IOException, ServletException {
+    @ActionHandler(action = "testMacro")
+    private ProcessStatus restTestMacro(final PwmRequest pwmRequest) throws IOException, ServletException {
         try {
             final Map<String, String> inputMap = pwmRequest.readBodyAsJsonStringMap(PwmHttpRequestWrapper.Flag.BypassValidation);
             if (inputMap == null || !inputMap.containsKey("input")) {
                 pwmRequest.outputJsonResult(RestResultBean.withData("missing input"));
-                return;
+                return ProcessStatus.Halt;
             }
 
             final MacroMachine macroMachine;
@@ -935,12 +863,15 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
             LOGGER.error(pwmRequest, e.getErrorInformation());
             pwmRequest.respondWithError(e.getErrorInformation());
         }
+        return ProcessStatus.Halt;
     }
 
-    private void restBrowseLdap(final PwmRequest pwmRequest, final ConfigManagerBean configManagerBean)
+    @ActionHandler(action = "browseLdap")
+    private ProcessStatus restBrowseLdap(final PwmRequest pwmRequest)
             throws IOException, ServletException, PwmUnrecoverableException
     {
         final Instant startTime = Instant.now();
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final Map<String, String> inputMap = pwmRequest.readBodyAsJsonStringMap(PwmHttpRequestWrapper.Flag.BypassValidation);
         final String profile = inputMap.get("profile");
         final String dn = inputMap.containsKey("dn") ? inputMap.get("dn") : "";
@@ -962,11 +893,14 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
                 + ", result=" + JsonUtil.serialize(result));
 
         pwmRequest.outputJsonResult(RestResultBean.withData(result));
+        return ProcessStatus.Halt;
     }
 
-    private void restCopyProfile(final PwmRequest pwmRequest, final ConfigManagerBean configManagerBean)
+    @ActionHandler(action = "copyProfile")
+    private ProcessStatus restCopyProfile(final PwmRequest pwmRequest)
             throws IOException, ServletException, PwmUnrecoverableException
     {
+        final ConfigManagerBean configManagerBean = getBean(pwmRequest);
         final Map<String, String> inputMap = pwmRequest.readBodyAsJsonStringMap(PwmHttpRequestWrapper.Flag.BypassValidation);
 
         final String settingKey = inputMap.get("setting");
@@ -988,5 +922,6 @@ public class ConfigEditorServlet extends AbstractPwmServlet {
         } catch (PwmUnrecoverableException e) {
             pwmRequest.outputJsonResult(RestResultBean.fromError(e.getErrorInformation(), pwmRequest));
         }
+        return ProcessStatus.Halt;
     }
 }

+ 59 - 0
server/src/main/java/password/pwm/http/servlet/configeditor/ConfigEditorServletUtils.java

@@ -0,0 +1,59 @@
+package password.pwm.http.servlet.configeditor;
+
+import password.pwm.PwmConstants;
+import password.pwm.config.value.FileValue;
+import password.pwm.error.ErrorInformation;
+import password.pwm.error.PwmError;
+import password.pwm.error.PwmException;
+import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.http.PwmRequest;
+import password.pwm.util.logging.PwmLogger;
+import password.pwm.ws.server.RestResultBean;
+
+import javax.servlet.ServletException;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class ConfigEditorServletUtils {
+
+    private static final PwmLogger LOGGER = PwmLogger.forClass(ConfigEditorServletUtils.class);
+
+
+    public static FileValue readFileUploadToSettingValue(
+            final PwmRequest pwmRequest,
+            final int maxFileSize
+    )
+            throws PwmUnrecoverableException, IOException, ServletException
+    {
+
+        final Map<String, PwmRequest.FileUploadItem> fileUploads;
+        try {
+            fileUploads = pwmRequest.readFileUploads(maxFileSize, 1);
+        } catch (PwmException e) {
+            pwmRequest.outputJsonResult(RestResultBean.fromError(e.getErrorInformation(), pwmRequest));
+            LOGGER.error(pwmRequest, "error during file upload: " + e.getErrorInformation().toDebugStr());
+            return null;
+        } catch (Throwable e) {
+            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN, "error during file upload: " + e.getMessage());
+            pwmRequest.outputJsonResult(RestResultBean.fromError(errorInformation, pwmRequest));
+            LOGGER.error(pwmRequest, errorInformation);
+            return null;
+        }
+
+        if (fileUploads.containsKey(PwmConstants.PARAM_FILE_UPLOAD)) {
+            final PwmRequest.FileUploadItem uploadItem = fileUploads.get(PwmConstants.PARAM_FILE_UPLOAD);
+
+            final Map<FileValue.FileInformation, FileValue.FileContent> newFileValueMap = new LinkedHashMap<>();
+            newFileValueMap.put(new FileValue.FileInformation(uploadItem.getName(), uploadItem.getType()), new FileValue.FileContent(uploadItem.getContent()));
+
+            return new FileValue(newFileValueMap);
+        }
+
+        final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN, "no file found in upload");
+        pwmRequest.outputJsonResult(RestResultBean.fromError(errorInformation, pwmRequest));
+        LOGGER.error(pwmRequest, "error during file upload: " + errorInformation.toDebugStr());
+        return null;
+    }
+
+}

+ 4 - 54
server/src/main/java/password/pwm/http/servlet/configeditor/SettingInfo.java

@@ -22,6 +22,7 @@
 
 package password.pwm.http.servlet.configeditor;
 
+import lombok.Data;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSettingCategory;
 import password.pwm.config.PwmSettingFlag;
@@ -36,6 +37,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
+@Data
 public class SettingInfo implements Serializable {
     private String key;
     private String label;
@@ -51,64 +53,12 @@ public class SettingInfo implements Serializable {
     private int level;
     private List<PwmSettingFlag> flags;
 
-    public String getKey() {
-        return key;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public PwmSettingCategory getCategory() {
-        return category;
-    }
-
-    public PwmSettingSyntax getSyntax() {
-        return syntax;
-    }
-
-    public boolean isHidden() {
-        return hidden;
-    }
-
-    public boolean isRequired() {
-        return required;
-    }
-
-    public Map<String, String> getOptions() {
-        return options;
-    }
-
-    public Map<PwmSettingProperty, String> getProperties() {
-        return properties;
-    }
-
-    public String getPattern() {
-        return pattern;
-    }
-
-    public String getPlaceholder() {
-        return placeholder;
-    }
-
-    public int getLevel() {
-        return level;
-    }
-
-    public List<PwmSettingFlag> getFlags() {
-        return flags;
-    }
-
-    public static SettingInfo forSetting(
+    static SettingInfo forSetting(
             final PwmSetting setting,
             final PwmSettingTemplateSet template,
+            final MacroMachine macroMachine,
             final Locale locale
     ) {
-        final MacroMachine macroMachine = MacroMachine.forStatic();
         final SettingInfo settingInfo = new SettingInfo();
         settingInfo.key = setting.getKey();
         settingInfo.description = macroMachine.expandMacros(setting.getDescription(locale));

+ 2 - 2
server/src/main/java/password/pwm/http/servlet/configguide/ConfigGuideServlet.java

@@ -57,7 +57,7 @@ import password.pwm.http.PwmURL;
 import password.pwm.http.bean.ConfigGuideBean;
 import password.pwm.http.servlet.AbstractPwmServlet;
 import password.pwm.http.servlet.ControlledPwmServlet;
-import password.pwm.http.servlet.configeditor.ConfigEditorServlet;
+import password.pwm.http.servlet.configeditor.ConfigEditorServletUtils;
 import password.pwm.i18n.Message;
 import password.pwm.ldap.LdapBrowser;
 import password.pwm.ldap.schema.SchemaOperationResult;
@@ -463,7 +463,7 @@ public class ConfigGuideServlet extends ControlledPwmServlet {
         try {
             final ConfigGuideBean configGuideBean = getBean(pwmRequest);
             final int maxFileSize = Integer.parseInt(pwmRequest.getConfig().readAppProperty(AppProperty.CONFIG_MAX_JDBC_JAR_SIZE));
-            final FileValue fileValue = ConfigEditorServlet.readFileUploadToSettingValue(pwmRequest, maxFileSize);
+            final FileValue fileValue = ConfigEditorServletUtils.readFileUploadToSettingValue(pwmRequest, maxFileSize);
             configGuideBean.setDatabaseDriver(fileValue);
             final RestResultBean restResultBean = RestResultBean.forSuccessMessage(pwmRequest, Message.Success_Unknown);
             pwmRequest.getPwmResponse().outputJsonResult(restResultBean);

+ 4 - 1
server/src/main/webapp/public/reference/settings.jsp

@@ -6,6 +6,8 @@
 <%@ page import="password.pwm.util.LocaleHelper" %>
 <%@ page import="password.pwm.util.java.StringUtil" %>
 <%@ page import="java.util.*" %>
+<%@ page import="password.pwm.util.macro.MacroMachine" %>
+<%@ page import="com.novell.ldapchai.util.StringHelper" %>
 <%--
   ~ Password Management Servlets (PWM)
   ~ http://www.pwm-project.org
@@ -42,6 +44,7 @@
     final PwmRequest pwmRequest = JspUtility.getPwmRequest(pageContext);
     final boolean advancedMode = false;
     final List<PwmSettingCategory> sortedCategories = PwmSettingCategory.valuesForReferenceDoc(userLocale);
+    final MacroMachine macroMachine = MacroMachine.forNonUserSpecific(pwmRequest.getPwmApplication(), pwmRequest.getSessionLabel());
 %>
 <html lang="<pwm:value name="<%=PwmValue.localeCode%>"/>" dir="<pwm:value name="<%=PwmValue.localeDir%>"/>">
 <%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
@@ -208,7 +211,7 @@
                 </tr>
                 <tr>
                     <td colspan="2">
-                        <%=setting.getDescription(userLocale)%>
+                        <%= macroMachine.expandMacros(setting.getDescription(userLocale)) %>
                     </td>
                 </tr>
                 <% } %>