Переглянути джерело

Merge remote-tracking branch 'origin/feature/advanced-search' into feature/advanced-search

jalbr74 6 роки тому
батько
коміт
32b50e4067

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

@@ -1017,6 +1017,8 @@ public enum PwmSetting
     HELPDESK_PROFILE_QUERY_MATCH(
             "helpdesk.queryMatch", PwmSettingSyntax.USER_PERMISSION, PwmSettingCategory.HELPDESK_BASE ),
     HELPDESK_SEARCH_FORM(
+            "helpdesk.search.form", PwmSettingSyntax.FORM, PwmSettingCategory.HELPDESK_BASE ),
+    HELPDESK_SEARCH_RESULT_FORM(
             "helpdesk.result.form", PwmSettingSyntax.FORM, PwmSettingCategory.HELPDESK_BASE ),
     HELPDESK_SEARCH_FILTERS(
             "helpdesk.search.filters", PwmSettingSyntax.USER_PERMISSION, PwmSettingCategory.HELPDESK_BASE ),
@@ -1067,6 +1069,9 @@ public enum PwmSetting
             "helpdesk.setPassword.maskValue", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.HELPDESK_OPTIONS ),
     HELPDESK_ENABLE_PHOTOS(
             "helpdesk.enablePhotos", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.HELPDESK_OPTIONS ),
+    HELPDESK_ENABLE_ADVANCED_SEARCH(
+            "helpdesk.advancedSearch.enable", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.HELPDESK_OPTIONS ),
+
 
     HELPDESK_VERIFICATION_METHODS(
             "helpdesk.verificationMethods", PwmSettingSyntax.VERIFICATION_METHOD, PwmSettingCategory.HELPDESK_VERIFICATION ),

+ 5 - 16
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskClientDataBean.java

@@ -36,7 +36,6 @@ import password.pwm.http.servlet.peoplesearch.PeopleSearchClientConfigBean;
 
 import java.io.Serializable;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -76,14 +75,6 @@ public class HelpdeskClientDataBean implements Serializable
         private String label;
     }
 
-    @Value
-    @Builder
-    public static class SearchAttribute implements Serializable
-    {
-        private String id;
-        private String attribute;
-    }
-
 
     static HelpdeskClientDataBean fromConfig(
             final HelpdeskProfile helpdeskProfile,
@@ -93,7 +84,7 @@ public class HelpdeskClientDataBean implements Serializable
         final HelpdeskClientDataBean.HelpdeskClientDataBeanBuilder builder = HelpdeskClientDataBean.builder();
         {
             // search page
-            final List<FormConfiguration> searchForm = helpdeskProfile.readSettingAsForm( PwmSetting.HELPDESK_SEARCH_FORM );
+            final List<FormConfiguration> searchForm = helpdeskProfile.readSettingAsForm( PwmSetting.HELPDESK_SEARCH_RESULT_FORM );
             final Map<String, String> searchColumns = new LinkedHashMap<>();
             for ( final FormConfiguration formConfiguration : searchForm )
             {
@@ -147,13 +138,11 @@ public class HelpdeskClientDataBean implements Serializable
             builder.verificationForm( formInformations );
         }
         {
-            final List<PeopleSearchClientConfigBean.SearchAttribute> searchAttributes = Arrays.asList(
-                    PeopleSearchClientConfigBean.SearchAttribute.builder().type( FormConfiguration.Type.text ).label( "Title" ).attribute( "title" ).build(),
-                    PeopleSearchClientConfigBean.SearchAttribute.builder().type( FormConfiguration.Type.text ).label( "Given Name" ).attribute( "givenName" ).build(),
-                    PeopleSearchClientConfigBean.SearchAttribute.builder().type( FormConfiguration.Type.text ).label( "First Name" ).attribute( "sn" ).build()
-            );
+            final List<PeopleSearchClientConfigBean.SearchAttribute> searchAttributes = PeopleSearchClientConfigBean.SearchAttribute.searchAttributesFromForm(
+                    locale,
+                    helpdeskProfile.readSettingAsForm( PwmSetting.HELPDESK_SEARCH_FORM ) );
 
-                    builder.enableAdvancedSearch( true );
+                    builder.enableAdvancedSearch( helpdeskProfile.readSettingAsBoolean( PwmSetting.HELPDESK_ENABLE_ADVANCED_SEARCH ) );
                     builder.maxAdvancedSearchAttributes( 3 );
                     builder.advancedSearchAttributes( searchAttributes );
         }

+ 41 - 0
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskSearchRequestBean.java

@@ -0,0 +1,41 @@
+/*
+ * 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.http.servlet.helpdesk;
+
+import lombok.Builder;
+import lombok.Value;
+import password.pwm.http.servlet.peoplesearch.SearchRequestBean;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Value
+@Builder
+public class HelpdeskSearchRequestBean implements Serializable
+{
+    @Builder.Default
+    private SearchRequestBean.SearchMode mode = SearchRequestBean.SearchMode.simple;
+
+    private String username;
+    private List<SearchRequestBean.SearchValue> searchValues;
+}

+ 12 - 19
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskSearchResultsBean.java

@@ -22,33 +22,26 @@
 
 package password.pwm.http.servlet.helpdesk;
 
+import lombok.Builder;
+import lombok.Value;
+
 import java.io.Serializable;
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+@Value
+@Builder
 public class HelpdeskSearchResultsBean implements Serializable
 {
-    private List<Map<String, Object>> searchResults = new ArrayList<>();
+    private List<Map<String, Object>> searchResults;
     private boolean sizeExceeded;
 
-    public List<Map<String, Object>> getSearchResults( )
-    {
-        return searchResults;
-    }
-
-    public void setSearchResults( final List<Map<String, Object>> searchResults )
-    {
-        this.searchResults = searchResults;
-    }
-
-    public boolean isSizeExceeded( )
-    {
-        return sizeExceeded;
-    }
-
-    public void setSizeExceeded( final boolean sizeExceeded )
+    static HelpdeskSearchResultsBean emptyResult()
     {
-        this.sizeExceeded = sizeExceeded;
+        return HelpdeskSearchResultsBean.builder()
+            .searchResults( Collections.emptyList() )
+            .sizeExceeded( false )
+            .build();
     }
 }

+ 95 - 29
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServlet.java

@@ -59,6 +59,7 @@ import password.pwm.http.PwmRequestAttribute;
 import password.pwm.http.PwmSession;
 import password.pwm.http.servlet.AbstractPwmServlet;
 import password.pwm.http.servlet.ControlledPwmServlet;
+import password.pwm.http.servlet.peoplesearch.SearchRequestBean;
 import password.pwm.i18n.Message;
 import password.pwm.ldap.LdapOperationsHelper;
 import password.pwm.ldap.PhotoDataBean;
@@ -78,6 +79,7 @@ import password.pwm.util.PasswordData;
 import password.pwm.util.RandomPasswordGenerator;
 import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.JsonUtil;
+import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.macro.MacroMachine;
@@ -98,10 +100,10 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.time.Instant;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -425,24 +427,67 @@ public class HelpdeskServlet extends ControlledPwmServlet
     private ProcessStatus restSearchRequest(
             final PwmRequest pwmRequest
     )
-            throws ChaiUnavailableException, PwmUnrecoverableException, IOException, ServletException
+            throws PwmUnrecoverableException, IOException
     {
         final HelpdeskProfile helpdeskProfile = getHelpdeskProfile( pwmRequest );
-        final Map<String, String> valueMap = pwmRequest.readBodyAsJsonStringMap();
-        final String username = valueMap.get( "username" );
+        final HelpdeskSearchRequestBean searchRequest = JsonUtil.deserialize( pwmRequest.readRequestBodyAsString(), HelpdeskSearchRequestBean.class );
+        final HelpdeskSearchResultsBean searchResultsBean;
+
+        try
+        {
+            searchResultsBean = searchImpl( pwmRequest, helpdeskProfile, searchRequest );
+        }
+        catch ( PwmOperationalException e )
+        {
+            throw new PwmUnrecoverableException( e.getErrorInformation() );
+        }
+
+        final RestResultBean restResultBean = RestResultBean.withData( searchResultsBean );
+        pwmRequest.outputJsonResult( restResultBean );
+        return ProcessStatus.Halt;
+
+    }
+
+    private static HelpdeskSearchResultsBean searchImpl(
+            final PwmRequest pwmRequest,
+            final HelpdeskProfile helpdeskProfile,
+            final HelpdeskSearchRequestBean searchRequest
+    ) throws PwmUnrecoverableException, PwmOperationalException
+    {
 
         final boolean useProxy = helpdeskProfile.readSettingAsBoolean( PwmSetting.HELPDESK_USE_PROXY );
-        final List<FormConfiguration> searchForm = helpdeskProfile.readSettingAsForm( PwmSetting.HELPDESK_SEARCH_FORM );
+        final List<FormConfiguration> searchForm = helpdeskProfile.readSettingAsForm( PwmSetting.HELPDESK_SEARCH_RESULT_FORM );
         final int maxResults = ( int ) helpdeskProfile.readSettingAsLong( PwmSetting.HELPDESK_RESULT_LIMIT );
 
-        if ( username == null || username.isEmpty() )
+        final SearchRequestBean.SearchMode searchMode = searchRequest.getMode() == null
+                ? SearchRequestBean.SearchMode.simple
+                : searchRequest.getMode();
+
+
+
+        switch ( searchMode )
         {
-            final HelpdeskSearchResultsBean emptyResults = new HelpdeskSearchResultsBean();
-            emptyResults.setSearchResults( new ArrayList<>() );
-            emptyResults.setSizeExceeded( false );
-            final RestResultBean restResultBean = RestResultBean.withData( emptyResults );
-            pwmRequest.outputJsonResult( restResultBean );
-            return ProcessStatus.Halt;
+            case simple:
+            {
+                if ( StringUtil.isEmpty( searchRequest.getUsername() ) )
+                {
+                    return HelpdeskSearchResultsBean.emptyResult();
+                }
+            }
+            break;
+
+            case advanced:
+            {
+                if ( JavaHelper.isEmpty( searchRequest.getSearchValues() ) )
+                {
+                    return HelpdeskSearchResultsBean.emptyResult();
+                }
+            }
+            break;
+
+
+            default:
+                JavaHelper.unhandledSwitchStatement( searchMode );
         }
 
         final UserSearchEngine userSearchEngine = pwmRequest.getPwmApplication().getUserSearchEngine();
@@ -453,9 +498,7 @@ public class HelpdeskServlet extends ControlledPwmServlet
             final SearchConfiguration.SearchConfigurationBuilder builder = SearchConfiguration.builder();
             builder.contexts( helpdeskProfile.readSettingAsStringArray( PwmSetting.HELPDESK_SEARCH_BASE ) );
             builder.enableContextValidation( false );
-            builder.username( username );
             builder.enableValueEscaping( false );
-            builder.filter( HelpdeskServletUtil.getSearchFilter( pwmRequest.getConfig(), helpdeskProfile ) );
             builder.enableSplitWhitespace( true );
 
             if ( !useProxy )
@@ -465,33 +508,56 @@ public class HelpdeskServlet extends ControlledPwmServlet
                 builder.chaiProvider( getChaiUser( pwmRequest, helpdeskProfile, loggedInUser ).getChaiProvider() );
             }
 
+            switch ( searchMode )
+            {
+                case simple:
+                {
+                    builder.username( searchRequest.getUsername() );
+                    builder.filter( HelpdeskServletUtil.makeAdvancedSearchFilter( pwmRequest.getConfig(), helpdeskProfile ) );
+                }
+                break;
+
+                case advanced:
+                {
+                    final Map<FormConfiguration, String> formValues = new LinkedHashMap<>();
+                    final Map<String, String> requestSearchValues = SearchRequestBean.searchValueToMap( searchRequest.getSearchValues() );
+                    for ( final FormConfiguration formConfiguration : helpdeskProfile.readSettingAsForm( PwmSetting.HELPDESK_SEARCH_FORM ) )
+                    {
+                        final String attribute = formConfiguration.getName();
+                        final String value = requestSearchValues.get( attribute );
+                        if ( !StringUtil.isEmpty( value ) )
+                        {
+                            formValues.put( formConfiguration, value );
+                        }
+                    }
+
+                    builder.formValues( formValues );
+                    builder.filter( HelpdeskServletUtil.makeAdvancedSearchFilter( pwmRequest.getConfig(), helpdeskProfile, requestSearchValues ) );
+
+                }
+                break;
+
+
+                default:
+                    JavaHelper.unhandledSwitchStatement( searchMode );
+            }
+
             searchConfiguration = builder.build();
         }
 
 
         final UserSearchResults results;
         final boolean sizeExceeded;
-        try
         {
             final Locale locale = pwmRequest.getLocale();
             results = userSearchEngine.performMultiUserSearchFromForm( locale, searchConfiguration, maxResults, searchForm, pwmRequest.getSessionLabel() );
             sizeExceeded = results.isSizeExceeded();
         }
-        catch ( PwmOperationalException e )
-        {
-            final ErrorInformation errorInformation = e.getErrorInformation();
-            LOGGER.error( pwmRequest, errorInformation );
-            final RestResultBean restResultBean = RestResultBean.fromError( errorInformation, pwmRequest );
-            pwmRequest.outputJsonResult( restResultBean );
-            return ProcessStatus.Halt;
-        }
 
-        final HelpdeskSearchResultsBean outputData = new HelpdeskSearchResultsBean();
-        outputData.setSearchResults( results.resultsAsJsonOutput( pwmRequest.getPwmApplication(), pwmRequest.getUserInfoIfLoggedIn() ) );
-        outputData.setSizeExceeded( sizeExceeded );
-        final RestResultBean restResultBean = RestResultBean.withData( outputData );
-        pwmRequest.outputJsonResult( restResultBean );
-        return ProcessStatus.Halt;
+        return HelpdeskSearchResultsBean.builder()
+                .searchResults( results.resultsAsJsonOutput( pwmRequest.getPwmApplication(), pwmRequest.getUserInfoIfLoggedIn() ) )
+                .sizeExceeded( sizeExceeded )
+                .build();
     }
 
     @ActionHandler( action = "unlockIntruder" )

+ 51 - 2
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServletUtil.java

@@ -46,6 +46,7 @@ import password.pwm.svc.event.AuditRecordFactory;
 import password.pwm.svc.event.HelpdeskAuditRecord;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.StatisticsManager;
+import password.pwm.util.java.StringUtil;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.macro.MacroMachine;
 
@@ -58,7 +59,7 @@ class HelpdeskServletUtil
 {
     private static final PwmLogger LOGGER = PwmLogger.forClass( HelpdeskServletUtil.class );
 
-    static String getSearchFilter( final Configuration configuration, final HelpdeskProfile helpdeskProfile )
+    static String makeAdvancedSearchFilter( final Configuration configuration, final HelpdeskProfile helpdeskProfile )
     {
         final String configuredFilter = helpdeskProfile.readSettingAsString( PwmSetting.HELPDESK_SEARCH_FILTER );
         if ( configuredFilter != null && !configuredFilter.isEmpty() )
@@ -98,6 +99,54 @@ class HelpdeskServletUtil
         return filter.toString();
     }
 
+    static String makeAdvancedSearchFilter(
+            final Configuration configuration,
+            final HelpdeskProfile helpdeskProfile,
+            final Map<String, String> attributesInSearchRequest
+    )
+    {
+        final List<String> defaultObjectClasses = configuration.readSettingAsStringArray( PwmSetting.DEFAULT_OBJECT_CLASSES );
+        final List<FormConfiguration> searchAttributes = helpdeskProfile.readSettingAsForm( PwmSetting.HELPDESK_SEARCH_RESULT_FORM );
+        final StringBuilder filter = new StringBuilder();
+
+        //open AND clause for objectclasses and attributes
+        filter.append( "(&" );
+
+        for ( final String objectClass : defaultObjectClasses )
+        {
+            filter.append( "(objectClass=" ).append( objectClass ).append( ")" );
+        }
+
+        // open AND clause for attributes
+        filter.append( "(&" );
+
+        for ( final FormConfiguration formConfiguration : searchAttributes )
+        {
+            if ( formConfiguration != null && formConfiguration.getName() != null )
+            {
+                final String searchAttribute = formConfiguration.getName();
+                final String value = attributesInSearchRequest.get( searchAttribute );
+                if ( !StringUtil.isEmpty( value ) )
+                {
+                    filter.append( "(" ).append( searchAttribute ).append( "=*%" ).append( searchAttribute ).append( "%*)" );
+                }
+            }
+        }
+
+        // close OR clause
+        filter.append( ")" );
+
+        // close AND clause
+        filter.append( ")" );
+        return filter.toString();
+    }
+
+
+
+
+
+
+
     static void checkIfUserIdentityViewable(
             final PwmRequest pwmRequest,
             final HelpdeskProfile helpdeskProfile,
@@ -105,7 +154,7 @@ class HelpdeskServletUtil
     )
             throws PwmUnrecoverableException
     {
-        final String filterSetting = getSearchFilter( pwmRequest.getConfig(), helpdeskProfile );
+        final String filterSetting = makeAdvancedSearchFilter( pwmRequest.getConfig(), helpdeskProfile );
         String filterString = filterSetting.replace( PwmConstants.VALUE_REPLACEMENT_USERNAME, "*" );
         while ( filterString.contains( "**" ) )
         {

+ 3 - 51
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskVerificationStateBean.java

@@ -24,6 +24,7 @@ package password.pwm.http.servlet.helpdesk;
 
 import com.novell.ldapchai.exception.ChaiOperationException;
 import com.novell.ldapchai.exception.ChaiUnavailableException;
+import lombok.Value;
 import password.pwm.AppProperty;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
@@ -138,70 +139,21 @@ class HelpdeskVerificationStateBean implements Serializable
         return Collections.unmodifiableList( new ArrayList<>( returnRecords.values() ) );
     }
 
-
+    @Value
     static class ViewableValidationRecord implements Serializable
     {
         private Instant timestamp;
         private String profile;
         private String username;
         private String method;
-
-        ViewableValidationRecord( final Instant timestamp, final String profile, final String username, final String method )
-        {
-            this.timestamp = timestamp;
-            this.profile = profile;
-            this.username = username;
-            this.method = method;
-        }
-
-        public Instant getTimestamp( )
-        {
-            return timestamp;
-        }
-
-        public String getProfile( )
-        {
-            return profile;
-        }
-
-        public String getUsername( )
-        {
-            return username;
-        }
-
-        public String getMethod( )
-        {
-            return method;
-        }
     }
 
+    @Value
     static class HelpdeskValidationRecord implements Serializable
     {
         private Instant timestamp;
         private UserIdentity identity;
         private IdentityVerificationMethod method;
-
-        HelpdeskValidationRecord( final Instant timestamp, final UserIdentity identity, final IdentityVerificationMethod method )
-        {
-            this.timestamp = timestamp;
-            this.identity = identity;
-            this.method = method;
-        }
-
-        public Instant getTimestamp( )
-        {
-            return timestamp;
-        }
-
-        public UserIdentity getIdentity( )
-        {
-            return identity;
-        }
-
-        public IdentityVerificationMethod getMethod( )
-        {
-            return method;
-        }
     }
 
     String toClientString( final PwmApplication pwmApplication ) throws PwmUnrecoverableException

+ 25 - 20
server/src/main/java/password/pwm/http/servlet/peoplesearch/PeopleSearchClientConfigBean.java

@@ -64,6 +64,30 @@ public class PeopleSearchClientConfigBean implements Serializable
         private String label;
         private FormConfiguration.Type type;
         private Map<String, String> options;
+
+        public static List<SearchAttribute> searchAttributesFromForm(
+                final Locale locale,
+                final List<FormConfiguration> formConfigurations
+        )
+        {
+            final List<SearchAttribute> returnList = new ArrayList<>( );
+            for ( final FormConfiguration formConfiguration : formConfigurations )
+            {
+                final String attribute = formConfiguration.getName();
+                final String label = formConfiguration.getLabel( locale );
+
+                final SearchAttribute searchAttribute = SearchAttribute.builder()
+                        .attribute( attribute )
+                        .type( formConfiguration.getType() )
+                        .label( label )
+                        .options( formConfiguration.getSelectOptions() )
+                        .build();
+
+                returnList.add( searchAttribute );
+            }
+
+            return Collections.unmodifiableList( returnList );
+        }
     }
 
 
@@ -87,26 +111,7 @@ public class PeopleSearchClientConfigBean implements Serializable
         }
 
 
-        final List<SearchAttribute> searchAttributes;
-        {
-            final List<SearchAttribute> returnList = new ArrayList<>( );
-            for ( final FormConfiguration formConfiguration : peopleSearchConfiguration.getSearchForm() )
-            {
-                final String attribute = formConfiguration.getName();
-                final String label = formConfiguration.getLabel( locale );
-
-                final SearchAttribute searchAttribute = SearchAttribute.builder()
-                        .attribute( attribute )
-                        .type( formConfiguration.getType() )
-                        .label( label )
-                        .options( formConfiguration.getSelectOptions() )
-                        .build();
-
-                returnList.add( searchAttribute );
-            }
-            searchAttributes = Collections.unmodifiableList( returnList );
-        }
-
+        final List<SearchAttribute> searchAttributes = SearchAttribute.searchAttributesFromForm( locale, peopleSearchConfiguration.getSearchForm() );
 
         return PeopleSearchClientConfigBean.builder()
                 .searchColumns( searchColumns )

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/peoplesearch/SearchRequestBean.java

@@ -55,7 +55,7 @@ public class SearchRequestBean implements Serializable
         private String value;
     }
 
-    static Map<String, String> searchValueToMap( final List<SearchValue> input )
+    public static Map<String, String> searchValueToMap( final List<SearchValue> input )
     {
         final Map<String, String> returnMap = new LinkedHashMap<>();
         for ( final SearchValue searchValue : input )

+ 27 - 0
server/src/main/resources/password/pwm/config/PwmSetting.xml

@@ -3402,6 +3402,28 @@
     <setting hidden="false" key="helpdesk.filter" level="1">
         <default/>
     </setting>
+    <setting hidden="false" key="helpdesk.search.form" level="1" required="true">
+        <flag>Form_HideStandardOptions</flag>
+        <ldapPermission actor="helpdesk" access="read"/>
+        <default>
+            <value>{"name":"cn","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Username"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+            <value>{"name":"givenName","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"First Name"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+            <value>{"name":"sn","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Last Name"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+            <value>{"name":"mail","minimumLength":1,"maximumLength":64,"type":"email","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Email"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+            <value>{"name":"workforceID","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Workforce ID"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+        </default>
+        <default template="AD">
+            <value>{"name":"sAMAccountName","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Username"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+            <value>{"name":"givenName","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"First Name"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+            <value>{"name":"sn","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Last Name"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+            <value>{"name":"mail","minimumLength":1,"maximumLength":64,"type":"email","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Email"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+            <value>{"name":"userPrincipalName","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"UPN"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
+        </default>
+        <options>
+            <option value="text">text</option>
+            <option value="select">select</option>
+        </options>
+    </setting>
     <setting hidden="false" key="helpdesk.result.form" level="1" required="true">
         <flag>Form_HideOptions</flag>
         <ldapPermission actor="helpdesk" access="read"/>
@@ -3669,6 +3691,11 @@
             <value>true</value>
         </default>
     </setting>
+    <setting hidden="false" key="helpdesk.advancedSearch.enable" level="1">
+        <default>
+            <value>true</value>
+        </default>
+    </setting>
     <setting hidden="false" key="helpdesk.verificationMethods" level="1">
         <flag>Verification_HideMinimumOptional</flag>
         <default>

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

@@ -383,6 +383,7 @@ Setting_Description_guest.maxValidDays=Specify the maximum number of days before
 Setting_Description_guest.update.form=Specify the attributes and fields to update the New Guest form creation.
 Setting_Description_guest.writeAttributes=Add actions @PwmAppName@ performs after it creates a guest user.  You can use macros.
 Setting_Description_helpdesk.actions=Add actions available to the Help Desk actor.  You can use macros.
+Setting_Description_helpdesk.advancedSearch.enable=Enable advanced searching user interface.  Allows operators to specify individual attributes for searching.
 Setting_Description_helpdesk.clearOtp.button=Eanble this option to allow the Help Desk operator to clear out a user's stored one-time password settings by clicking a button.
 Setting_Description_helpdesk.clearResponses=Enable this option to allow the Help Desk operator to clear out a user's stored responses after changing the user's password.
 Setting_Description_helpdesk.clearResponses.button=Enable this option to allow the Help Desk operator to clear out a user's stored responses by clicking a button.
@@ -394,7 +395,7 @@ Setting_Description_helpdesk.enable=Enable this option to enable the Help Desk m
 Setting_Description_helpdesk.enablePhotos=Enable photos in helpdesk search screen 
 Setting_Description_helpdesk.enableUnlock=Enable this option to enable the Help Desk module users to unlock an (intruder) locked account.
 Setting_Description_helpdesk.enforcePasswordPolicy=Enable this option to require that the passwords set by Help Desk must meet the same password policy that normally constrains the user.
-Setting_Description_helpdesk.filter=Specify the LDAP search filter to query the directory.  Substitute <i>%USERNAME%</i> for user supplied user name.  If not specified, @PwmAppName@ auto calculates a search filter based on the Help Desk Search Form.<p>Examples<ul><li>Edirectory\: <code>(&(objectClass\=Person)(|((cn\=*%USERNAME%*)(uid\=*%USERNAME%*)(givenName\=*%USERNAME%*)(sn\=*%USERNAME%*))))</code></li><li>Active Directory\: <code>(&(objectClass\=Person)(|((cn\=*%USERNAME%*)(uid\=*%USERNAME%*)(sAMAccountName\=*%USERNAME%*)(userprincipalname\=*%USERNAME%*)(givenName\=*%USERNAME%*)(sn\=*%USERNAME%*))))</code></li></ul>
+Setting_Description_helpdesk.filter=Specify the LDAP search filter to query the directory.  Substitute <i>%USERNAME%</i> for user supplied user name.  If not specified, @PwmAppName@ auto calculates a search filter based on the Help Desk Search Results.<p>Examples<ul><li>Edirectory\: <code>(&(objectClass\=Person)(|((cn\=*%USERNAME%*)(uid\=*%USERNAME%*)(givenName\=*%USERNAME%*)(sn\=*%USERNAME%*))))</code></li><li>Active Directory\: <code>(&(objectClass\=Person)(|((cn\=*%USERNAME%*)(uid\=*%USERNAME%*)(sAMAccountName\=*%USERNAME%*)(userprincipalname\=*%USERNAME%*)(givenName\=*%USERNAME%*)(sn\=*%USERNAME%*))))</code></li></ul>
 Setting_Description_helpdesk.forcePwExpiration=Enable this option to force the system to expire the password for the users when the help desk operator sets a user's password.
 Setting_Description_helpdesk.idleTimeout=Specify the number of seconds after which @PwmAppName@ unauthenticates an authenticated session.   @PwmAppName@ sets the session idle timeout to this value after a user successfully accesses the Help Desk module.
 Setting_Description_helpdesk.otp.verify=Enable this option to enable the OTP Verification.
@@ -404,6 +405,7 @@ Setting_Description_helpdesk.result.form=Add the fields @PwmAppName@ shows as a
 Setting_Description_helpdesk.result.limit=Specify a limit of the results of help desk searches.
 Setting_Description_helpdesk.searchBase=Specify one or more LDAP search bases. If empty, @PwmAppName@ uses the default LDAP search base.
 Setting_Description_helpdesk.search.filters=Specify a filter to limit the help desk search.
+Setting_Description_helpdesk.search.form=Specify the attributes used in searching.
 Setting_Description_helpdesk.sendPassword=Enable this option to send the password to the user using the method selected under <code>@PwmSettingReference\:recovery.sendNewPassword.sendMethod@</code>.
 Setting_Description_helpdesk.setPassword.maskValue=Enable this option to have @PwmAppName@ mask the password for a user when they are entering it.
 Setting_Description_helpdesk.setPassword.mode=Select the mode to allow Help Desk administrators to set passwords.  (Note the logged-in user must have the proper LDAP permissions.)
@@ -889,6 +891,7 @@ Setting_Label_guest.maxValidDays=Maximum Duration of Account Validity
 Setting_Label_guest.update.form=Update Guest Form
 Setting_Label_guest.writeAttributes=Guest Creation Actions
 Setting_Label_helpdesk.actions=Help Desk Actor Actions
+Setting_Label_helpdesk.advancedSearch.enable=Enable Advanced Search
 Setting_Label_helpdesk.clearOtp.button=Enable Clear One Time Password Settings Button
 Setting_Label_helpdesk.clearResponses.button=Enable Clear Responses Button
 Setting_Label_helpdesk.clearResponses=Clear Responses on Password Set
@@ -906,10 +909,11 @@ Setting_Label_helpdesk.idleTimeout=Idle Timeout Seconds for Help Desk Users
 Setting_Label_helpdesk.otp.verify=Enable OTP Verification Button
 Setting_Label_helpdesk.profile.list=Help Desk Profile
 Setting_Label_helpdesk.queryMatch=Help Desk Profile Match
-Setting_Label_helpdesk.result.form=Help Desk Search Form
+Setting_Label_helpdesk.result.form=Help Desk Search Results
 Setting_Label_helpdesk.result.limit=Help Desk Search Result Limit
 Setting_Label_helpdesk.searchBase=LDAP Search Base
 Setting_Label_helpdesk.search.filters=Help Desk Profile Search Filter
+Setting_Label_helpdesk.search.form=Help Desk Search Attributes
 Setting_Label_helpdesk.sendPassword=Send Password to User
 Setting_Label_helpdesk.setPassword.maskValue=Mask Password Value
 Setting_Label_helpdesk.setPassword.mode=Set Password UI Mode