Ver Fonte

change reporting setting filter to user permission

jrivard@gmail.com há 6 anos atrás
pai
commit
9b1f0063be

+ 5 - 2
server/src/main/java/password/pwm/config/PwmSetting.java

@@ -1131,8 +1131,8 @@ public enum PwmSetting
     // reporting
     REPORTING_ENABLE(
             "reporting.enable", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.REPORTING ),
-    REPORTING_SEARCH_FILTER(
-            "reporting.ldap.searchFilter", PwmSettingSyntax.STRING, PwmSettingCategory.REPORTING ),
+    REPORTING_USER_MATCH(
+            "reporting.ldap.userMatch", PwmSettingSyntax.USER_PERMISSION, PwmSettingCategory.REPORTING ),
     REPORTING_MAX_CACHE_AGE(
             "reporting.maxCacheAge", PwmSettingSyntax.DURATION, PwmSettingCategory.REPORTING ),
     REPORTING_MAX_QUERY_SIZE(
@@ -1220,6 +1220,9 @@ public enum PwmSetting
 
 
     // deprecated.
+    // deprecated 2018-12-05
+    REPORTING_SEARCH_FILTER(
+            "reporting.ldap.searchFilter", PwmSettingSyntax.STRING, PwmSettingCategory.REPORTING ),
 
     // deprecated 2018-10-15
     PEOPLE_SEARCH_SEARCH_ATTRIBUTES(

+ 384 - 0
server/src/main/java/password/pwm/config/stored/ConfigurationCleaner.java

@@ -0,0 +1,384 @@
+/*
+ * Password Management Servlets (PWM)
+ * http://www.pwm-project.org
+ *
+ * Copyright (c) 2006-2009 Novell, Inc.
+ * Copyright (c) 2009-2018 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.config.stored;
+
+import org.jdom2.Comment;
+import org.jdom2.Document;
+import org.jdom2.Element;
+import org.jdom2.xpath.XPathExpression;
+import org.jdom2.xpath.XPathFactory;
+import password.pwm.PwmConstants;
+import password.pwm.bean.UserIdentity;
+import password.pwm.config.PwmSetting;
+import password.pwm.config.StoredValue;
+import password.pwm.config.option.ADPolicyComplexity;
+import password.pwm.config.value.FormValue;
+import password.pwm.config.value.StringArrayValue;
+import password.pwm.config.value.StringValue;
+import password.pwm.config.value.UserPermissionValue;
+import password.pwm.config.value.data.FormConfiguration;
+import password.pwm.config.value.data.UserPermission;
+import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.util.logging.PwmLogger;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+class ConfigurationCleaner
+{
+    private static final PwmLogger LOGGER = PwmLogger.forClass( ConfigurationCleaner.class );
+    private static final String NEW_PROFILE_NAME = "default";
+
+    static void cleanup( final StoredConfigurationImpl configuration, final Document document )
+            throws PwmUnrecoverableException
+    {
+        updateProperitiesWithoutType( configuration, document );
+        updateMandatoryElements( document );
+        profilizeNonProfiledSettings( configuration, document );
+        stripOrphanedProfileSettings( configuration, document );
+        migrateAppProperties( configuration, document );
+        updateDeprecatedSettings( configuration );
+        migrateDeprecatedProperties( configuration, document );
+    }
+
+
+    static void updateMandatoryElements( final Document document )
+    {
+        final Element rootElement = document.getRootElement();
+
+        {
+            final XPathExpression commentXPath = XPathFactory.instance().compile( "//comment()[1]" );
+            final Comment existingComment = ( Comment ) commentXPath.evaluateFirst( rootElement );
+            if ( existingComment != null )
+            {
+                existingComment.detach();
+            }
+            final Comment comment = new Comment( generateCommentText() );
+            rootElement.addContent( 0, comment );
+        }
+
+        rootElement.setAttribute( "pwmVersion", PwmConstants.BUILD_VERSION );
+        rootElement.setAttribute( "pwmBuild", PwmConstants.BUILD_NUMBER );
+        rootElement.setAttribute( "xmlVersion", StoredConfigurationImpl.XML_FORMAT_VERSION );
+
+        // migrate old properties
+        {
+
+            // read correct (new) //properties[@type="config"]
+            final XPathExpression configPropertiesXpath = XPathFactory.instance().compile(
+                    "//" + StoredConfiguration.XML_ELEMENT_PROPERTIES + "[@" + StoredConfiguration.XML_ATTRIBUTE_TYPE + "=\""
+                            + StoredConfiguration.XML_ATTRIBUTE_VALUE_CONFIG + "\"]" );
+            final Element configPropertiesElement = ( Element ) configPropertiesXpath.evaluateFirst( rootElement );
+
+            // read list of old //properties[not (@type)]/property
+            final XPathExpression nonAttributedProperty = XPathFactory.instance().compile(
+                    "//" + StoredConfiguration.XML_ELEMENT_PROPERTIES + "[not (@" + StoredConfiguration.XML_ATTRIBUTE_TYPE + ")]/"
+                            + StoredConfiguration.XML_ELEMENT_PROPERTY );
+            final List<Element> nonAttributedProperties = nonAttributedProperty.evaluate( rootElement );
+
+            if ( configPropertiesElement != null && nonAttributedProperties != null )
+            {
+                for ( final Element element : nonAttributedProperties )
+                {
+                    element.detach();
+                    configPropertiesElement.addContent( element );
+                }
+            }
+
+            // remove old //properties[not (@type] element
+            final XPathExpression oldPropertiesXpath = XPathFactory.instance().compile(
+                    "//" + StoredConfiguration.XML_ELEMENT_PROPERTIES + "[not (@" + StoredConfiguration.XML_ATTRIBUTE_TYPE + ")]" );
+            final List<Element> oldPropertiesElements = oldPropertiesXpath.evaluate( rootElement );
+            if ( oldPropertiesElements != null )
+            {
+                for ( final Element element : oldPropertiesElements )
+                {
+                    element.detach();
+                }
+            }
+        }
+    }
+
+    private static String generateCommentText( )
+    {
+        final StringBuilder commentText = new StringBuilder();
+        commentText.append( "\t\t" ).append( " " ).append( "\n" );
+        commentText.append( "\t\t" ).append( "This configuration file has been auto-generated by the " ).append( PwmConstants.PWM_APP_NAME )
+                .append( " password self service application." ).append( "\n" );
+        commentText.append( "\t\t" ).append( "" ).append( "\n" );
+        commentText.append( "\t\t" ).append( "WARNING: This configuration file contains sensitive security information, please handle with care!" ).append( "\n" );
+        commentText.append( "\t\t" ).append( "" ).append( "\n" );
+        commentText.append( "\t\t" ).append( "WARNING: If a server is currently running using this configuration file, it will be restarted" ).append( "\n" );
+        commentText.append( "\t\t" ).append( "         and the configuration updated immediately when it is modified." ).append( "\n" );
+        commentText.append( "\t\t" ).append( "" ).append( "\n" );
+        commentText.append( "\t\t" ).append( "NOTICE: This file is encoded as UTF-8.  Do not save or edit this file with an editor that does not" ).append( "\n" );
+        commentText.append( "\t\t" ).append( "        support UTF-8 encoding." ).append( "\n" );
+        commentText.append( "\t\t" ).append( "" ).append( "\n" );
+        commentText.append( "\t\t" ).append( "If unable to edit using the application ConfigurationEditor web UI, the following options are available." ).append( "\n" );
+        commentText.append( "\t\t" ).append( "   or 1. Edit this file directly by hand." ).append( "\n" );
+        commentText.append( "\t\t" ).append( "   or 2. Remove restrictions of the configuration by setting the property 'configIsEditable' to 'true' in this file.  This will " )
+                .append( "\n" );
+        commentText.append( "\t\t" ).append( "         allow access to the ConfigurationEditor web UI without having to authenticate to an LDAP server first." ).append( "\n" );
+        commentText.append( "\t\t" ).append( "   or 3. Remove restrictions of the configuration by using the the command line utility. " ).append( "\n" );
+        commentText.append( "\t\t" ).append( "" ).append( "\n" );
+        return commentText.toString();
+    }
+
+
+    private static void profilizeNonProfiledSettings( final StoredConfigurationImpl storedConfiguration, final Document document ) throws PwmUnrecoverableException
+    {
+        for ( final PwmSetting setting : PwmSetting.values() )
+        {
+            if ( setting.getCategory().hasProfiles() )
+            {
+
+                final XPathExpression xp = StoredConfigurationImpl.XPathBuilder.xpathForSetting( setting, null );
+                final Element settingElement = ( Element ) xp.evaluateFirst( document );
+                if ( settingElement != null )
+                {
+                    settingElement.detach();
+
+                    final PwmSetting profileSetting = setting.getCategory().getProfileSetting();
+                    final List<String> profileStringDefinitions = new ArrayList<>();
+                    {
+                        final StringArrayValue profileDefinitions = ( StringArrayValue ) storedConfiguration.readSetting( profileSetting );
+                        if ( profileDefinitions != null )
+                        {
+                            if ( profileDefinitions.toNativeObject() != null )
+                            {
+                                profileStringDefinitions.addAll( profileDefinitions.toNativeObject() );
+                            }
+                        }
+                    }
+
+                    if ( profileStringDefinitions.isEmpty() )
+                    {
+                        profileStringDefinitions.add( NEW_PROFILE_NAME );
+                    }
+
+                    final UserIdentity userIdentity = settingElement.getAttribute( StoredConfiguration.XML_ATTRIBUTE_MODIFY_USER ) != null
+                            ? UserIdentity.fromDelimitedKey( settingElement.getAttribute(  StoredConfiguration.XML_ATTRIBUTE_MODIFY_USER ).getValue() )
+                            : null;
+
+                    for ( final String destProfile : profileStringDefinitions )
+                    {
+                        LOGGER.info( () -> "moving setting " + setting.getKey() + " without profile attribute to profile \"" + destProfile + "\"." );
+                        {
+                            storedConfiguration.writeSetting( profileSetting, new StringArrayValue( profileStringDefinitions ), userIdentity );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private static void migrateDeprecatedProperties(
+            final StoredConfigurationImpl storedConfiguration,
+            final Document document
+    )
+            throws PwmUnrecoverableException
+    {
+        final XPathFactory xpfac = XPathFactory.instance();
+        {
+            final String xpathString = "//property[@key=\"" + ConfigurationProperty.LDAP_TEMPLATE.getKey() + "\"]";
+            final XPathExpression xp = xpfac.compile( xpathString );
+            final List<Element> propertyElement = ( List<Element> ) xp.evaluate( document );
+            if ( propertyElement != null && !propertyElement.isEmpty() )
+            {
+                final String value = propertyElement.get( 0 ).getText();
+                storedConfiguration.writeSetting( PwmSetting.TEMPLATE_LDAP, new StringValue( value ), null );
+                propertyElement.get( 0 ).detach();
+            }
+        }
+        {
+            final String xpathString = "//property[@key=\"" + ConfigurationProperty.NOTES.getKey() + "\"]";
+            final XPathExpression xp = xpfac.compile( xpathString );
+            final List<Element> propertyElement = ( List<Element> ) xp.evaluate( document );
+            if ( propertyElement != null && !propertyElement.isEmpty() )
+            {
+                final String value = propertyElement.get( 0 ).getText();
+                storedConfiguration.writeSetting( PwmSetting.NOTES, new StringValue( value ), null );
+                propertyElement.get( 0 ).detach();
+            }
+        }
+    }
+
+    private static void updateProperitiesWithoutType( final StoredConfigurationImpl storedConfiguration, final Document document )
+    {
+        final String xpathString = "//properties[not(@type)]";
+        final XPathFactory xpfac = XPathFactory.instance();
+        final XPathExpression xp = xpfac.compile( xpathString );
+        final List<Element> propertiesElements = ( List<Element> ) xp.evaluate( document );
+        for ( final Element propertiesElement : propertiesElements )
+        {
+            propertiesElement.setAttribute( StoredConfiguration.XML_ATTRIBUTE_TYPE, StoredConfiguration.XML_ATTRIBUTE_VALUE_CONFIG );
+        }
+    }
+
+    private static void stripOrphanedProfileSettings( final StoredConfigurationImpl storedConfiguration, final Document document )
+    {
+        final XPathFactory xpfac = XPathFactory.instance();
+        for ( final PwmSetting setting : PwmSetting.values() )
+        {
+            if ( setting.getCategory().hasProfiles() )
+            {
+                final List<String> validProfiles = storedConfiguration.profilesForSetting( setting );
+                final String xpathString = "//setting[@key=\"" + setting.getKey() + "\"]";
+                final XPathExpression xp = xpfac.compile( xpathString );
+                final List<Element> settingElements = ( List<Element> ) xp.evaluate( document );
+                for ( final Element settingElement : settingElements )
+                {
+                    final String profileID = settingElement.getAttributeValue( StoredConfiguration.XML_ATTRIBUTE_PROFILE );
+                    if ( profileID != null )
+                    {
+                        if ( !validProfiles.contains( profileID ) )
+                        {
+                            LOGGER.info( () -> "removing setting " + setting.getKey() + " with profile \"" + profileID + "\", profile is not a valid profile" );
+                            settingElement.detach();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private static void migrateAppProperties( final StoredConfigurationImpl storedConfiguration, final Document document ) throws PwmUnrecoverableException
+    {
+        final XPathExpression xPathExpression = StoredConfigurationImpl.XPathBuilder.xpathForAppProperties();
+        final List<Element> appPropertiesElements = ( List<Element> ) xPathExpression.evaluate( document );
+        for ( final Element element : appPropertiesElements )
+        {
+            final List<Element> properties = element.getChildren();
+            for ( final Element property : properties )
+            {
+                final String key = property.getAttributeValue( "key" );
+                final String value = property.getText();
+                if ( key != null && !key.isEmpty() && value != null && !value.isEmpty() )
+                {
+                    LOGGER.info( () -> "migrating app-property config element '" + key + "' to setting " + PwmSetting.APP_PROPERTY_OVERRIDES.getKey() );
+                    final String newValue = key + "=" + value;
+                    List<String> existingValues = ( List<String> ) storedConfiguration.readSetting( PwmSetting.APP_PROPERTY_OVERRIDES ).toNativeObject();
+                    if ( existingValues == null )
+                    {
+                        existingValues = new ArrayList<>();
+                    }
+                    existingValues = new ArrayList<>( existingValues );
+                    existingValues.add( newValue );
+                    storedConfiguration.writeSetting( PwmSetting.APP_PROPERTY_OVERRIDES, new StringArrayValue( existingValues ), null );
+                }
+            }
+            element.detach();
+        }
+    }
+
+    private static void updateDeprecatedSettings( final StoredConfigurationImpl storedConfiguration ) throws PwmUnrecoverableException
+    {
+        final UserIdentity actor = new UserIdentity( "UpgradeProcessor", null );
+        for ( final String profileID : storedConfiguration.profilesForSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY ) )
+        {
+            if ( !storedConfiguration.isDefaultValue( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID ) )
+            {
+                final boolean ad2003Enabled = ( boolean ) storedConfiguration.readSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID ).toNativeObject();
+                final StoredValue value;
+                if ( ad2003Enabled )
+                {
+                    value = new StringValue( ADPolicyComplexity.AD2003.toString() );
+                }
+                else
+                {
+                    value = new StringValue( ADPolicyComplexity.NONE.toString() );
+                }
+                LOGGER.warn( "converting deprecated non-default setting " + PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY.getKey() + "/" + profileID
+                        + " to replacement setting " + PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY_LEVEL + ", value=" + value.toNativeObject().toString() );
+                storedConfiguration.writeSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY_LEVEL, profileID, value, actor );
+                storedConfiguration.resetSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID, actor );
+            }
+        }
+
+        for ( final String profileID : storedConfiguration.profilesForSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME ) )
+        {
+            if ( !storedConfiguration.isDefaultValue( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID ) )
+            {
+                final boolean enforceEnabled = ( boolean ) storedConfiguration.readSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID ).toNativeObject();
+                final StoredValue value = enforceEnabled
+                        ? new StringValue( "NONE" )
+                        : new StringValue( "ALLOW" );
+                final ValueMetaData existingData = storedConfiguration.readSettingMetadata( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID );
+                LOGGER.warn( "converting deprecated non-default setting "
+                        + PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME.toMenuLocationDebug( profileID, PwmConstants.DEFAULT_LOCALE ) + "/" + profileID
+                        + " to replacement setting " + PwmSetting.RECOVERY_MINIMUM_PASSWORD_LIFETIME_OPTIONS.toMenuLocationDebug( profileID, PwmConstants.DEFAULT_LOCALE )
+                        + ", value=" + value.toNativeObject().toString() );
+                final UserIdentity newActor = existingData != null && existingData.getUserIdentity() != null
+                        ? existingData.getUserIdentity()
+                        : actor;
+                storedConfiguration.writeSetting( PwmSetting.RECOVERY_MINIMUM_PASSWORD_LIFETIME_OPTIONS, profileID, value, newActor );
+                storedConfiguration.resetSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID, actor );
+            }
+        }
+
+        {
+            if ( !storedConfiguration.isDefaultValue( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES ) )
+            {
+                final List<String> oldValues = ( List<String> ) storedConfiguration.readSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES ).toNativeObject();
+
+                final List<FormConfiguration> newValues = new ArrayList<>();
+                for ( final String attribute : oldValues )
+                {
+                    final FormConfiguration formConfiguration = FormConfiguration.builder()
+                            .name( attribute )
+                            .labels( Collections.singletonMap( "", attribute ) )
+                            .build();
+                    newValues.add( formConfiguration );
+                }
+
+                final ValueMetaData existingData = storedConfiguration.readSettingMetadata( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES, null );
+                final UserIdentity newActor = existingData != null && existingData.getUserIdentity() != null
+                        ? existingData.getUserIdentity()
+                        : actor;
+
+                storedConfiguration.writeSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_FORM, null, new FormValue( newValues ), newActor );
+                storedConfiguration.resetSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES, null, actor );
+            }
+        }
+
+        {
+            if ( !storedConfiguration.isDefaultValue( PwmSetting.REPORTING_SEARCH_FILTER ) )
+            {
+                final String oldValue = ( String ) storedConfiguration.readSetting( PwmSetting.REPORTING_SEARCH_FILTER ).toNativeObject();
+
+                final List<UserPermission> newValues = new ArrayList<>();
+                final UserPermission newPermission = new UserPermission( UserPermission.Type.ldapQuery, PwmConstants.PROFILE_ID_ALL, oldValue, null );
+                newValues.add( newPermission );
+
+                final ValueMetaData existingData = storedConfiguration.readSettingMetadata( PwmSetting.REPORTING_SEARCH_FILTER, null );
+                final UserIdentity newActor = existingData != null && existingData.getUserIdentity() != null
+                        ? existingData.getUserIdentity()
+                        : actor;
+
+                storedConfiguration.writeSetting( PwmSetting.REPORTING_USER_MATCH, null, new UserPermissionValue( newValues ), newActor );
+                storedConfiguration.resetSetting( PwmSetting.REPORTING_SEARCH_FILTER, null, actor );
+            }
+        }
+    }
+}

+ 6 - 322
server/src/main/java/password/pwm/config/stored/StoredConfigurationImpl.java

@@ -40,15 +40,11 @@ import password.pwm.config.PwmSettingSyntax;
 import password.pwm.config.PwmSettingTemplate;
 import password.pwm.config.PwmSettingTemplateSet;
 import password.pwm.config.StoredValue;
-import password.pwm.config.option.ADPolicyComplexity;
-import password.pwm.config.value.FormValue;
 import password.pwm.config.value.NamedSecretValue;
 import password.pwm.config.value.PasswordValue;
 import password.pwm.config.value.PrivateKeyValue;
 import password.pwm.config.value.StringArrayValue;
-import password.pwm.config.value.StringValue;
 import password.pwm.config.value.ValueFactory;
-import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmException;
@@ -103,7 +99,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
 {
 
     private static final PwmLogger LOGGER = PwmLogger.forClass( StoredConfigurationImpl.class );
-    private static final String XML_FORMAT_VERSION = "4";
+    static final String XML_FORMAT_VERSION = "4";
 
     private Document document = new Document( new Element( XML_ELEMENT_ROOT ) );
     private ChangeLog changeLog = new ChangeLog();
@@ -137,7 +133,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
         {
             newConfiguration.document = inputDocument;
             newConfiguration.createTime(); // verify create time;
-            ConfigurationCleaner.cleanup( newConfiguration );
+            ConfigurationCleaner.cleanup( newConfiguration, newConfiguration.document );
         }
         catch ( Exception e )
         {
@@ -220,7 +216,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
 
     public StoredConfigurationImpl( ) throws PwmUnrecoverableException
     {
-        ConfigurationCleaner.cleanup( this );
+        ConfigurationCleaner.cleanup( this, document );
         final String createTime = JavaHelper.toIsoDate( Instant.now() );
         document.getRootElement().setAttribute( XML_ATTRIBUTE_CREATE_TIME, createTime );
     }
@@ -1067,7 +1063,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
         return passwordHash != null && passwordHash.length() > 0;
     }
 
-    private abstract static class XPathBuilder
+    abstract static class XPathBuilder
     {
         private static XPathExpression xpathForLocaleBundleSetting( final String bundleName, final String keyName )
         {
@@ -1077,7 +1073,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
             return xpfac.compile( xpathString );
         }
 
-        private static XPathExpression xpathForSetting( final PwmSetting setting, final String profileID )
+        static XPathExpression xpathForSetting( final PwmSetting setting, final String profileID )
         {
             final XPathFactory xpfac = XPathFactory.instance();
             final String xpathString;
@@ -1102,7 +1098,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
             return xpfac.compile( xpathString );
         }
 
-        private static XPathExpression xpathForAppProperties( )
+        static XPathExpression xpathForAppProperties()
         {
             final XPathFactory xpfac = XPathFactory.instance();
             final String xpathString;
@@ -1129,318 +1125,6 @@ public class StoredConfigurationImpl implements StoredConfiguration
     }
 
 
-    private static class ConfigurationCleaner
-    {
-        private static void cleanup( final StoredConfigurationImpl configuration ) throws PwmUnrecoverableException
-        {
-            updateProperitiesWithoutType( configuration );
-            updateMandatoryElements( configuration.document );
-            profilizeNonProfiledSettings( configuration );
-            stripOrphanedProfileSettings( configuration );
-            migrateAppProperties( configuration );
-            updateDeprecatedSettings( configuration );
-            migrateDeprecatedProperties( configuration );
-        }
-
-
-        private static void updateMandatoryElements( final Document document )
-        {
-            final Element rootElement = document.getRootElement();
-
-            {
-                final XPathExpression commentXPath = XPathFactory.instance().compile( "//comment()[1]" );
-                final Comment existingComment = ( Comment ) commentXPath.evaluateFirst( rootElement );
-                if ( existingComment != null )
-                {
-                    existingComment.detach();
-                }
-                final Comment comment = new Comment( generateCommentText() );
-                rootElement.addContent( 0, comment );
-            }
-
-            rootElement.setAttribute( "pwmVersion", PwmConstants.BUILD_VERSION );
-            rootElement.setAttribute( "pwmBuild", PwmConstants.BUILD_NUMBER );
-            rootElement.setAttribute( "xmlVersion", XML_FORMAT_VERSION );
-
-            { // migrate old properties
-
-                // read correct (new) //properties[@type="config"]
-                final XPathExpression configPropertiesXpath = XPathFactory.instance().compile(
-                        "//" + XML_ELEMENT_PROPERTIES + "[@" + XML_ATTRIBUTE_TYPE + "=\"" + XML_ATTRIBUTE_VALUE_CONFIG + "\"]" );
-                final Element configPropertiesElement = ( Element ) configPropertiesXpath.evaluateFirst( rootElement );
-
-                // read list of old //properties[not (@type)]/property
-                final XPathExpression nonAttributedProperty = XPathFactory.instance().compile(
-                        "//" + XML_ELEMENT_PROPERTIES + "[not (@" + XML_ATTRIBUTE_TYPE + ")]/" + XML_ELEMENT_PROPERTY );
-                final List<Element> nonAttributedProperties = nonAttributedProperty.evaluate( rootElement );
-
-                if ( configPropertiesElement != null && nonAttributedProperties != null )
-                {
-                    for ( final Element element : nonAttributedProperties )
-                    {
-                        element.detach();
-                        configPropertiesElement.addContent( element );
-                    }
-                }
-
-                // remove old //properties[not (@type] element
-                final XPathExpression oldPropertiesXpath = XPathFactory.instance().compile(
-                        "//" + XML_ELEMENT_PROPERTIES + "[not (@" + XML_ATTRIBUTE_TYPE + ")]" );
-                final List<Element> oldPropertiesElements = oldPropertiesXpath.evaluate( rootElement );
-                if ( oldPropertiesElements != null )
-                {
-                    for ( final Element element : oldPropertiesElements )
-                    {
-                        element.detach();
-                    }
-                }
-            }
-        }
-
-        private static String generateCommentText( )
-        {
-            final StringBuilder commentText = new StringBuilder();
-            commentText.append( "\t\t" ).append( " " ).append( "\n" );
-            commentText.append( "\t\t" ).append( "This configuration file has been auto-generated by the " ).append( PwmConstants.PWM_APP_NAME ).append( " password self service application." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "WARNING: This configuration file contains sensitive security information, please handle with care!" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "WARNING: If a server is currently running using this configuration file, it will be restarted" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "         and the configuration updated immediately when it is modified." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "NOTICE: This file is encoded as UTF-8.  Do not save or edit this file with an editor that does not" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "        support UTF-8 encoding." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "If unable to edit using the application ConfigurationEditor web UI, the following options are available." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "   or 1. Edit this file directly by hand." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "   or 2. Remove restrictions of the configuration by setting the property 'configIsEditable' to 'true' in this file.  This will " ).append( "\n" );
-            commentText.append( "\t\t" ).append( "         allow access to the ConfigurationEditor web UI without having to authenticate to an LDAP server first." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "   or 3. Remove restrictions of the configuration by using the the command line utility. " ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            return commentText.toString();
-        }
-
-
-        private static void profilizeNonProfiledSettings( final StoredConfigurationImpl storedConfiguration ) throws PwmUnrecoverableException
-        {
-            final String NEW_PROFILE_NAME = "default";
-            final Document document = storedConfiguration.document;
-            for ( final PwmSetting setting : PwmSetting.values() )
-            {
-                if ( setting.getCategory().hasProfiles() )
-                {
-
-                    final XPathExpression xp = XPathBuilder.xpathForSetting( setting, null );
-                    final Element settingElement = ( Element ) xp.evaluateFirst( document );
-                    if ( settingElement != null )
-                    {
-                        settingElement.detach();
-
-                        final PwmSetting profileSetting = setting.getCategory().getProfileSetting();
-                        final List<String> profileStringDefinitions = new ArrayList<>();
-                        {
-                            final StringArrayValue profileDefinitions = ( StringArrayValue ) storedConfiguration.readSetting( profileSetting );
-                            if ( profileDefinitions != null )
-                            {
-                                if ( profileDefinitions.toNativeObject() != null )
-                                {
-                                    profileStringDefinitions.addAll( profileDefinitions.toNativeObject() );
-                                }
-                            }
-                        }
-
-                        if (profileStringDefinitions.isEmpty()) {
-                            profileStringDefinitions.add( NEW_PROFILE_NAME );
-                        }
-
-                        final UserIdentity userIdentity = settingElement.getAttribute( XML_ATTRIBUTE_MODIFY_USER ) != null
-                                ? UserIdentity.fromDelimitedKey( settingElement.getAttribute(  XML_ATTRIBUTE_MODIFY_USER ).getValue() )
-                                : null;
-
-                        for ( final String destProfile : profileStringDefinitions )
-                        {
-                            LOGGER.info( () -> "moving setting " + setting.getKey() + " without profile attribute to profile \"" + destProfile + "\"." );
-                            {
-                                storedConfiguration.writeSetting( profileSetting, new StringArrayValue( profileStringDefinitions ), userIdentity );
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        private static void migrateDeprecatedProperties( final StoredConfigurationImpl storedConfiguration ) throws PwmUnrecoverableException
-        {
-            final Document document = storedConfiguration.document;
-            final XPathFactory xpfac = XPathFactory.instance();
-            {
-                final String xpathString = "//property[@key=\"" + ConfigurationProperty.LDAP_TEMPLATE.getKey() + "\"]";
-                final XPathExpression xp = xpfac.compile( xpathString );
-                final List<Element> propertyElement = ( List<Element> ) xp.evaluate( document );
-                if ( propertyElement != null && !propertyElement.isEmpty() )
-                {
-                    final String value = propertyElement.get( 0 ).getText();
-                    storedConfiguration.writeSetting( PwmSetting.TEMPLATE_LDAP, new StringValue( value ), null );
-                    propertyElement.get( 0 ).detach();
-                }
-            }
-            {
-                final String xpathString = "//property[@key=\"" + ConfigurationProperty.NOTES.getKey() + "\"]";
-                final XPathExpression xp = xpfac.compile( xpathString );
-                final List<Element> propertyElement = ( List<Element> ) xp.evaluate( document );
-                if ( propertyElement != null && !propertyElement.isEmpty() )
-                {
-                    final String value = propertyElement.get( 0 ).getText();
-                    storedConfiguration.writeSetting( PwmSetting.NOTES, new StringValue( value ), null );
-                    propertyElement.get( 0 ).detach();
-                }
-            }
-        }
-
-        private static void updateProperitiesWithoutType( final StoredConfigurationImpl storedConfiguration )
-        {
-            final Document document = storedConfiguration.document;
-            final String xpathString = "//properties[not(@type)]";
-            final XPathFactory xpfac = XPathFactory.instance();
-            final XPathExpression xp = xpfac.compile( xpathString );
-            final List<Element> propertiesElements = ( List<Element> ) xp.evaluate( document );
-            for ( final Element propertiesElement : propertiesElements )
-            {
-                propertiesElement.setAttribute( XML_ATTRIBUTE_TYPE, XML_ATTRIBUTE_VALUE_CONFIG );
-            }
-        }
-
-        private static void stripOrphanedProfileSettings( final StoredConfigurationImpl storedConfiguration )
-        {
-            final Document document = storedConfiguration.document;
-            final XPathFactory xpfac = XPathFactory.instance();
-            for ( final PwmSetting setting : PwmSetting.values() )
-            {
-                if ( setting.getCategory().hasProfiles() )
-                {
-                    final List<String> validProfiles = storedConfiguration.profilesForSetting( setting );
-                    final String xpathString = "//setting[@key=\"" + setting.getKey() + "\"]";
-                    final XPathExpression xp = xpfac.compile( xpathString );
-                    final List<Element> settingElements = ( List<Element> ) xp.evaluate( document );
-                    for ( final Element settingElement : settingElements )
-                    {
-                        final String profileID = settingElement.getAttributeValue( XML_ATTRIBUTE_PROFILE );
-                        if ( profileID != null )
-                        {
-                            if ( !validProfiles.contains( profileID ) )
-                            {
-                                LOGGER.info( () -> "removing setting " + setting.getKey() + " with profile \"" + profileID + "\", profile is not a valid profile" );
-                                settingElement.detach();
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        private static void migrateAppProperties( final StoredConfigurationImpl storedConfiguration ) throws PwmUnrecoverableException
-        {
-            final Document document = storedConfiguration.document;
-            final XPathExpression xPathExpression = XPathBuilder.xpathForAppProperties();
-            final List<Element> appPropertiesElements = ( List<Element> ) xPathExpression.evaluate( document );
-            for ( final Element element : appPropertiesElements )
-            {
-                final List<Element> properties = element.getChildren();
-                for ( final Element property : properties )
-                {
-                    final String key = property.getAttributeValue( "key" );
-                    final String value = property.getText();
-                    if ( key != null && !key.isEmpty() && value != null && !value.isEmpty() )
-                    {
-                        LOGGER.info( () -> "migrating app-property config element '" + key + "' to setting " + PwmSetting.APP_PROPERTY_OVERRIDES.getKey() );
-                        final String newValue = key + "=" + value;
-                        List<String> existingValues = ( List<String> ) storedConfiguration.readSetting( PwmSetting.APP_PROPERTY_OVERRIDES ).toNativeObject();
-                        if ( existingValues == null )
-                        {
-                            existingValues = new ArrayList<>();
-                        }
-                        existingValues = new ArrayList<>( existingValues );
-                        existingValues.add( newValue );
-                        storedConfiguration.writeSetting( PwmSetting.APP_PROPERTY_OVERRIDES, new StringArrayValue( existingValues ), null );
-                    }
-                }
-                element.detach();
-            }
-        }
-
-        private static void updateDeprecatedSettings( final StoredConfigurationImpl storedConfiguration ) throws PwmUnrecoverableException
-        {
-            final UserIdentity actor = new UserIdentity( "UpgradeProcessor", null );
-            for ( final String profileID : storedConfiguration.profilesForSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY ) )
-            {
-                if ( !storedConfiguration.isDefaultValue( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID ) )
-                {
-                    final boolean ad2003Enabled = ( boolean ) storedConfiguration.readSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID ).toNativeObject();
-                    final StoredValue value;
-                    if ( ad2003Enabled )
-                    {
-                        value = new StringValue( ADPolicyComplexity.AD2003.toString() );
-                    }
-                    else
-                    {
-                        value = new StringValue( ADPolicyComplexity.NONE.toString() );
-                    }
-                    LOGGER.warn( "converting deprecated non-default setting " + PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY.getKey() + "/" + profileID
-                            + " to replacement setting " + PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY_LEVEL + ", value=" + value.toNativeObject().toString() );
-                    storedConfiguration.writeSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY_LEVEL, profileID, value, actor );
-                    storedConfiguration.resetSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID, actor );
-                }
-            }
-
-            for ( final String profileID : storedConfiguration.profilesForSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME ) )
-            {
-                if ( !storedConfiguration.isDefaultValue( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID ) )
-                {
-                    final boolean enforceEnabled = ( boolean ) storedConfiguration.readSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID ).toNativeObject();
-                    final StoredValue value = enforceEnabled
-                            ? new StringValue( "NONE" )
-                            : new StringValue( "ALLOW" );
-                    final ValueMetaData existingData = storedConfiguration.readSettingMetadata( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID );
-                    LOGGER.warn( "converting deprecated non-default setting "
-                            + PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME.toMenuLocationDebug(profileID,PwmConstants.DEFAULT_LOCALE) + "/" + profileID
-                            + " to replacement setting " + PwmSetting.RECOVERY_MINIMUM_PASSWORD_LIFETIME_OPTIONS.toMenuLocationDebug( profileID, PwmConstants.DEFAULT_LOCALE )
-                            + ", value=" + value.toNativeObject().toString() );
-                    final UserIdentity newActor = existingData != null && existingData.getUserIdentity() != null
-                            ? existingData.getUserIdentity()
-                            : actor;
-                    storedConfiguration.writeSetting( PwmSetting.RECOVERY_MINIMUM_PASSWORD_LIFETIME_OPTIONS, profileID, value, newActor );
-                    storedConfiguration.resetSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID, actor );
-                }
-            }
-
-            {
-                if ( !storedConfiguration.isDefaultValue( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES ) )
-                {
-                    final List<String> oldValues = ( List<String> ) storedConfiguration.readSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES ).toNativeObject();
-
-                    final List<FormConfiguration> newValues = new ArrayList<>();
-                    for ( final String attribute : oldValues )
-                    {
-                        final FormConfiguration formConfiguration = FormConfiguration.builder()
-                                .name( attribute )
-                                .labels( Collections.singletonMap( "", attribute ) )
-                                .build();
-                        newValues.add( formConfiguration );
-                    }
-
-                    final ValueMetaData existingData = storedConfiguration.readSettingMetadata( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES, null );
-                    final UserIdentity newActor = existingData != null && existingData.getUserIdentity() != null
-                            ? existingData.getUserIdentity()
-                            : actor;
-
-                    storedConfiguration.writeSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_FORM, null, new FormValue( newValues ), newActor );
-                    storedConfiguration.resetSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES, null, actor );
-                }
-            }
-        }
-    }
-
-
     public static class ConfigRecordID implements Serializable, Comparable
     {
         private RecordType recordType;

+ 9 - 2
server/src/main/java/password/pwm/ldap/search/SearchConfiguration.java

@@ -25,6 +25,7 @@ package password.pwm.ldap.search;
 import com.novell.ldapchai.provider.ChaiProvider;
 import lombok.Builder;
 import lombok.Getter;
+import password.pwm.PwmConstants;
 import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.config.value.data.UserPermission;
 import password.pwm.util.java.StringUtil;
@@ -78,9 +79,15 @@ public class SearchConfiguration implements Serializable
             builder.contexts( Collections.singletonList( permission.getLdapBase() ) );
         }
 
-        if ( !StringUtil.isEmpty( permission.getLdapProfileID() ) )
         {
-            builder.ldapProfile( permission.getLdapProfileID() );
+            final String ldapProfileID = permission.getLdapProfileID();
+            if ( !StringUtil.isEmpty( ldapProfileID ) )
+            {
+                if ( !PwmConstants.PROFILE_ID_ALL.equalsIgnoreCase( ldapProfileID ) )
+                {
+                    builder.ldapProfile( ldapProfileID );
+                }
+            }
         }
 
         return builder.build();

+ 3 - 3
server/src/main/java/password/pwm/svc/report/ReportService.java

@@ -80,7 +80,7 @@ public class ReportService implements PwmService
     private ExecutorService executorService;
 
     private UserCacheService userCacheService;
-    private ReportSettings settings = new ReportSettings();
+    private ReportSettings settings = ReportSettings.builder().build();
 
     private Queue<String> dnQueue;
 
@@ -438,7 +438,7 @@ public class ReportService implements PwmService
             resetJobStatus();
             clearWorkQueue();
 
-            final Iterator<UserIdentity> memQueue = LdapOperationsHelper.readAllUsersFromLdap(
+            final Iterator<UserIdentity> memQueue = LdapOperationsHelper.readUsersFromLdapForPermissions(
                     pwmApplication,
                     SessionLabel.REPORTING_SESSION_LABEL,
                     settings.getSearchFilter(),
@@ -507,7 +507,7 @@ public class ReportService implements PwmService
         }
 
         private void processWorkQueue( )
-                throws ChaiUnavailableException, ChaiOperationException, PwmOperationalException, PwmUnrecoverableException
+                throws PwmUnrecoverableException
         {
             LOGGER.debug( SessionLabel.REPORTING_SESSION_LABEL, () -> "beginning process to updating user cache records from ldap" );
             if ( status != STATUS.OPEN )

+ 35 - 52
server/src/main/java/password/pwm/svc/report/ReportSettings.java

@@ -22,10 +22,13 @@
 
 package password.pwm.svc.report;
 
+import lombok.Builder;
+import lombok.Value;
 import password.pwm.AppProperty;
 import password.pwm.PwmConstants;
 import password.pwm.config.Configuration;
 import password.pwm.config.PwmSetting;
+import password.pwm.config.value.data.UserPermission;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.java.JsonUtil;
 import password.pwm.util.java.TimeDuration;
@@ -37,16 +40,31 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+@Value
+@Builder
 class ReportSettings implements Serializable
 {
     private static final PwmLogger LOGGER = PwmLogger.forClass( ReportSettings.class );
 
+    @Builder.Default
     private TimeDuration maxCacheAge = TimeDuration.of( TimeDuration.DAY.asMillis() * 90, TimeDuration.Unit.MILLISECONDS );
-    private String searchFilter = null;
-    private int jobOffsetSeconds;
+
+    @Builder.Default
+    private List<UserPermission> searchFilter = Collections.emptyList();
+
+    @Builder.Default
+    private int jobOffsetSeconds = 0;
+
+    @Builder.Default
     private int maxSearchSize = 100 * 1000;
-    private List<Integer> trackDays = new ArrayList<>();
+
+    @Builder.Default
+    private List<Integer> trackDays = Collections.emptyList();
+
+    @Builder.Default
     private int reportJobThreads = 1;
+
+    @Builder.Default
     private JobIntensity reportJobIntensity = JobIntensity.LOW;
 
     public enum JobIntensity
@@ -58,29 +76,29 @@ class ReportSettings implements Serializable
 
     public static ReportSettings readSettingsFromConfig( final Configuration config )
     {
-        final ReportSettings settings = new ReportSettings();
-        settings.maxCacheAge = TimeDuration.of( config.readSettingAsLong( PwmSetting.REPORTING_MAX_CACHE_AGE ), TimeDuration.Unit.SECONDS );
-        settings.searchFilter = config.readSettingAsString( PwmSetting.REPORTING_SEARCH_FILTER );
-        settings.maxSearchSize = ( int ) config.readSettingAsLong( PwmSetting.REPORTING_MAX_QUERY_SIZE );
+        final ReportSettings.ReportSettingsBuilder builder = ReportSettings.builder();
+        builder.maxCacheAge( TimeDuration.of( config.readSettingAsLong( PwmSetting.REPORTING_MAX_CACHE_AGE ), TimeDuration.Unit.SECONDS ) );
+        builder.searchFilter( config.readSettingAsUserPermission( PwmSetting.REPORTING_USER_MATCH ) );
+        builder.maxSearchSize ( ( int ) config.readSettingAsLong( PwmSetting.REPORTING_MAX_QUERY_SIZE ) );
 
-        if ( settings.searchFilter == null || settings.searchFilter.isEmpty() )
+        if ( builder.searchFilter == null || builder.searchFilter.isEmpty() )
         {
-            settings.searchFilter = null;
+            builder.searchFilter = null;
         }
 
-        settings.jobOffsetSeconds = ( int ) config.readSettingAsLong( PwmSetting.REPORTING_JOB_TIME_OFFSET );
-        if ( settings.jobOffsetSeconds > 60 * 60 * 24 )
+        builder.jobOffsetSeconds = ( int ) config.readSettingAsLong( PwmSetting.REPORTING_JOB_TIME_OFFSET );
+        if ( builder.jobOffsetSeconds > 60 * 60 * 24 )
         {
-            settings.jobOffsetSeconds = 0;
+            builder.jobOffsetSeconds = 0;
         }
 
-        settings.trackDays = parseDayIntervalStr( config );
+        builder.trackDays( parseDayIntervalStr( config ) );
 
-        settings.reportJobThreads = Integer.parseInt( config.readAppProperty( AppProperty.REPORTING_LDAP_SEARCH_THREADS ) );
+        builder.reportJobThreads( Integer.parseInt( config.readAppProperty( AppProperty.REPORTING_LDAP_SEARCH_THREADS ) ) );
 
-        settings.reportJobIntensity = config.readSettingAsEnum( PwmSetting.REPORTING_JOB_INTENSITY, JobIntensity.class );
+        builder.reportJobIntensity( config.readSettingAsEnum( PwmSetting.REPORTING_JOB_INTENSITY, JobIntensity.class ) );
 
-        return settings;
+        return builder.build();
     }
 
     private static List<Integer> parseDayIntervalStr( final Configuration configuration )
@@ -111,42 +129,7 @@ class ReportSettings implements Serializable
         return Collections.unmodifiableList( returnValue );
     }
 
-    public TimeDuration getMaxCacheAge( )
-    {
-        return maxCacheAge;
-    }
-
-    public String getSearchFilter( )
-    {
-        return searchFilter;
-    }
-
-    public int getJobOffsetSeconds( )
-    {
-        return jobOffsetSeconds;
-    }
-
-    public int getMaxSearchSize( )
-    {
-        return maxSearchSize;
-    }
-
-    public List<Integer> getTrackDays( )
-    {
-        return trackDays;
-    }
-
-    public int getReportJobThreads( )
-    {
-        return reportJobThreads;
-    }
-
-    public JobIntensity getReportJobIntensity( )
-    {
-        return reportJobIntensity;
-    }
-
-    public String getSettingsHash( )
+    String getSettingsHash( )
             throws PwmUnrecoverableException
     {
         return SecureEngine.hash( JsonUtil.serialize( this ), PwmConstants.SETTING_CHECKSUM_HASH_METHOD );

+ 6 - 1
server/src/main/resources/password/pwm/config/PwmSetting.xml

@@ -3855,11 +3855,16 @@
             <value/>
         </default>
     </setting>
-    <setting hidden="false" key="reporting.ldap.searchFilter" level="1">
+    <setting hidden="true" key="reporting.ldap.searchFilter" level="1">
         <default>
             <value />
         </default>
     </setting>
+    <setting hidden="false" key="reporting.ldap.userMatch" level="1">
+        <default syntaxVersion="2">
+            <value><![CDATA[{"type":"ldapQuery","ldapProfileID":"all","ldapQuery":"(objectClass=*)"}]]></value>
+        </default>
+    </setting>
     <setting hidden="false" key="reporting.maxCacheAge" level="1">
         <default>
             <value>2592000</value>

+ 2 - 0
server/src/main/resources/password/pwm/i18n/PwmSetting.properties

@@ -655,6 +655,7 @@ Setting_Description_reporting.job.intensity=Control the level of intensity of a
 Setting_Description_reporting.job.timeOffset=Specify the number of seconds past midnight (GMT) when @PwmAppName@ processes the update job.  Setting this option to -1 disables the nightly job processor.
 Setting_Description_reporting.ldap.maxQuerySize=Specify the maximum number of records read during a reporting query search.  Setting this value to a larger sizes requires more Java heap memory.
 Setting_Description_reporting.ldap.searchFilter=Add an LDAP search filter @PwmAppName@ uses when running a reporting job.  If blank @PwmAppName@ auto-generates a filter based on the login query setting.
+Setting_Description_reporting.ldap.userMatch=Select users to include in the reporting job.
 Setting_Description_reporting.maxCacheAge=Specify the maximum age of a cached report record before @PwmAppName@ discards it.  @PwmAppName@ periodically purges records older than this age from the local report data cache.  @PwmAppName@ does this so that the deleted records that it deletes from the LDAP directory are eventually removed from the report cache.  The default value of 2592000 seconds is equal to 30 days.<br/><br/>Specify the value in seconds.
 Setting_Description_reporting.summary.dayValues=Specify day intervals to include in report summary data.
 Setting_Description_response.hashMethod=<p>Select the method of hashing @PwmAppName@ uses to store responses.  Storing the responses as plaintext might facilitate synchronization or migration to other systems but is not secure.</p><p>This setting only controls how @PwmAppName@ writes the responses. @PwmAppName@ can always read stored responses in other formats. @PwmAppName@ cannot convert existing responses until a user re-saves their responses. You can use the reporting engine to identify and count the hash types in use.</p>
@@ -1171,6 +1172,7 @@ Setting_Label_reporting.job.intensity=Reporting Job Intensity
 Setting_Label_reporting.job.timeOffset=Reporting Job Time Offset
 Setting_Label_reporting.ldap.maxQuerySize=Maximum LDAP Query Size
 Setting_Label_reporting.ldap.searchFilter=Reporting Search Filter
+Setting_Label_reporting.ldap.userMatch=Reporting User Match
 Setting_Label_reporting.maxCacheAge=Maximum Cache Age
 Setting_Label_reporting.summary.dayValues=Reporting Summary Day Intervals
 Setting_Label_response.hashMethod=Responses Storage Hashing Method