Просмотр исходного кода

Merge remote-tracking branch 'origin/master' into ng-helpdesk

# Conflicts:
#	server/src/main/webapp/public/resources/style.css
jalbr74 7 лет назад
Родитель
Сommit
91c80f4755

+ 64 - 1
server/src/main/java/password/pwm/health/ConfigurationChecker.java

@@ -30,6 +30,7 @@ import password.pwm.bean.SessionLabel;
 import password.pwm.config.Configuration;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSettingSyntax;
+import password.pwm.config.StoredValue;
 import password.pwm.config.option.DataStorageMethod;
 import password.pwm.config.option.MessageSendMethod;
 import password.pwm.config.profile.ForgottenPasswordProfile;
@@ -37,11 +38,13 @@ import password.pwm.config.profile.HelpdeskProfile;
 import password.pwm.config.profile.LdapProfile;
 import password.pwm.config.profile.NewUserProfile;
 import password.pwm.config.profile.PwmPasswordPolicy;
+import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.error.PwmException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.i18n.Config;
 import password.pwm.util.LocaleHelper;
 import password.pwm.util.PasswordData;
+import password.pwm.util.java.StringUtil;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.operations.PasswordUtility;
 
@@ -273,7 +276,8 @@ public class ConfigurationChecker implements HealthChecker
             VerifyPasswordPolicyConfigs.class,
             VerifyResponseLdapAttribute.class,
             VerifyDbConfiguredIfNeeded.class,
-            VerifyIfDeprecatedSendMethodValuesUsed.class
+            VerifyIfDeprecatedSendMethodValuesUsed.class,
+            VerifyIfDeprecatedJsFormOptionUsed.class
     ) );
 
     static class VerifyResponseLdapAttribute implements ConfigHealthCheck
@@ -365,6 +369,65 @@ public class ConfigurationChecker implements HealthChecker
         }
     }
 
+    static class VerifyIfDeprecatedJsFormOptionUsed implements ConfigHealthCheck
+    {
+        @Override
+        public List<HealthRecord> healthCheck( final Configuration config, final Locale locale )
+        {
+            final List<HealthRecord> records = new ArrayList<>();
+
+            for ( final PwmSetting loopSetting : PwmSetting.values() )
+            {
+                if ( loopSetting.getSyntax() == PwmSettingSyntax.FORM )
+                {
+                    if ( loopSetting.getCategory().hasProfiles() )
+                    {
+                        try
+                        {
+                            final List<String> profiles = config.getStoredConfiguration().profilesForSetting( loopSetting );
+                            for ( final String profile : profiles )
+                            {
+                                final StoredValue storedValue = config.getStoredConfiguration().readSetting( loopSetting, profile );
+                                final List<FormConfiguration> forms = (List<FormConfiguration>) storedValue.toNativeObject();
+                                for ( final FormConfiguration form : forms )
+                                {
+                                    if ( !StringUtil.isEmpty( form.getJavascript() ) )
+                                    {
+                                        records.add( HealthRecord.forMessage(
+                                                HealthMessage.Config_DeprecatedJSForm,
+                                                loopSetting.toMenuLocationDebug( profile, locale ),
+                                                PwmSetting.DISPLAY_CUSTOM_JAVASCRIPT.toMenuLocationDebug( null, locale )
+                                        ) );
+                                    }
+                                }
+                            }
+                        }
+                        catch ( PwmUnrecoverableException e )
+                        {
+                            LOGGER.error( "unexpected error examining profiles for deprecated form  js option check: " + e.getMessage() );
+                        }
+                    }
+                    else
+                    {
+                        final List<FormConfiguration> forms = config.readSettingAsForm( loopSetting );
+                        for ( final FormConfiguration form : forms )
+                        {
+                            if ( !StringUtil.isEmpty( form.getJavascript() ) )
+                            {
+                                records.add( HealthRecord.forMessage(
+                                        HealthMessage.Config_DeprecatedJSForm,
+                                        loopSetting.toMenuLocationDebug( null, locale ),
+                                        PwmSetting.DISPLAY_CUSTOM_JAVASCRIPT.toMenuLocationDebug( null, locale )
+                                ) );
+                            }
+                        }
+                    }
+                }
+            }
+            return records;
+        }
+    }
+
     static class VerifyIfDeprecatedSendMethodValuesUsed implements ConfigHealthCheck
     {
         @Override

+ 1 - 0
server/src/main/java/password/pwm/health/HealthMessage.java

@@ -69,6 +69,7 @@ public enum HealthMessage
     Config_NoRecoveryEnabled( HealthStatus.CAUTION, HealthTopic.Configuration ),
     Config_Certificate( HealthStatus.WARN, HealthTopic.Configuration ),
     Config_InvalidSendMethod( HealthStatus.CAUTION, HealthTopic.Configuration ),
+    Config_DeprecatedJSForm( HealthStatus.CONFIG, HealthTopic.Configuration ),
     LDAP_VendorsNotSame( HealthStatus.CONFIG, HealthTopic.LDAP ),
     LDAP_OK( HealthStatus.GOOD, HealthTopic.LDAP ),
     LDAP_RecentlyUnreachable( HealthStatus.CAUTION, HealthTopic.LDAP ),

+ 23 - 28
server/src/main/java/password/pwm/http/servlet/admin/AdminServlet.java

@@ -48,10 +48,8 @@ import password.pwm.http.servlet.ControlledPwmServlet;
 import password.pwm.http.servlet.PwmServletDefinition;
 import password.pwm.i18n.Message;
 import password.pwm.ldap.search.UserSearchEngine;
+import password.pwm.svc.event.AuditEvent;
 import password.pwm.svc.event.AuditRecord;
-import password.pwm.svc.event.HelpdeskAuditRecord;
-import password.pwm.svc.event.SystemAuditRecord;
-import password.pwm.svc.event.UserAuditRecord;
 import password.pwm.svc.intruder.RecordType;
 import password.pwm.svc.report.ReportColumnFilter;
 import password.pwm.svc.report.ReportCsvUtility;
@@ -62,6 +60,7 @@ import password.pwm.util.java.ClosableIterator;
 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.localdb.LocalDBException;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.reports.ReportUtils;
@@ -75,6 +74,7 @@ import java.io.OutputStream;
 import java.io.Writer;
 import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadInfo;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -84,6 +84,7 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
 
 @WebServlet(
         name = "AdminServlet",
@@ -437,38 +438,32 @@ public class AdminServlet extends ControlledPwmServlet
 
     @ActionHandler( action = "auditData" )
     private ProcessStatus restAuditDataHandler( final PwmRequest pwmRequest )
-            throws ChaiUnavailableException, PwmUnrecoverableException, IOException
+            throws PwmUnrecoverableException, IOException
     {
-        final int max = readMaxParameter( pwmRequest, 1000, 10 * 1000 );
-        final ArrayList<UserAuditRecord> userRecords = new ArrayList<>();
-        final ArrayList<HelpdeskAuditRecord> helpdeskRecords = new ArrayList<>();
-        final ArrayList<SystemAuditRecord> systemRecords = new ArrayList<>();
+        final Instant startTime = Instant.now();
+        final TimeDuration maxSearchTime = new TimeDuration( 10, TimeUnit.SECONDS );
+        final int max = readMaxParameter( pwmRequest, 100, 10 * 1000 );
+        final AuditEvent.Type auditDataType = AuditEvent.Type.valueOf( pwmRequest.readParameterAsString( "type", AuditEvent.Type.USER.name() ) );
+        final ArrayList<AuditRecord> records = new ArrayList<>();
         final Iterator<AuditRecord> iterator = pwmRequest.getPwmApplication().getAuditManager().readVault();
-        int counter = 0;
-        while ( iterator.hasNext() && counter <= max )
+
+        while (
+                iterator.hasNext()
+                        && records.size() < max
+                        && TimeDuration.fromCurrent( startTime ).isShorterThan( maxSearchTime )
+                )
         {
             final AuditRecord loopRecord = iterator.next();
-            counter++;
-            if ( loopRecord instanceof SystemAuditRecord )
+            if ( auditDataType == loopRecord.getType() )
             {
-                systemRecords.add( ( SystemAuditRecord ) loopRecord );
-            }
-            else if ( loopRecord instanceof HelpdeskAuditRecord )
-            {
-                helpdeskRecords.add( ( HelpdeskAuditRecord ) loopRecord );
-            }
-            else if ( loopRecord instanceof UserAuditRecord )
-            {
-                userRecords.add( ( UserAuditRecord ) loopRecord );
+                records.add( loopRecord );
             }
         }
-        final HashMap<String, List> outputMap = new HashMap<>();
-        outputMap.put( "user", userRecords );
-        outputMap.put( "helpdesk", helpdeskRecords );
-        outputMap.put( "system", systemRecords );
 
-        final RestResultBean restResultBean = RestResultBean.withData( outputMap );
-        LOGGER.debug( pwmRequest.getPwmSession(), "output " + counter + " audit records." );
+        final HashMap<String, Object> resultData = new HashMap<>( Collections.singletonMap( "records", records ) );
+
+        final RestResultBean restResultBean = RestResultBean.withData( resultData );
+        LOGGER.debug( pwmRequest.getPwmSession(), "output " + records.size() + " audit records." );
         pwmRequest.outputJsonResult( restResultBean );
         return ProcessStatus.Halt;
     }
@@ -640,7 +635,7 @@ public class AdminServlet extends ControlledPwmServlet
             throws PwmUnrecoverableException
     {
         final String stringMax = pwmRequest.readParameterAsString( "maximum", String.valueOf( defaultValue ) );
-        return Math.max( Integer.parseInt( stringMax ), maxValue );
+        return Math.min( Integer.parseInt( stringMax ), maxValue );
     }
 
     public enum Page

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/admin/AppDashboardData.java

@@ -480,7 +480,7 @@ public class AppDashboardData implements Serializable
             javaInfo.add( new DisplayElement(
                     "sessionAverageSize",
                     DisplayElement.Type.string,
-                    "Estimated Session Total Size",
+                    "Estimated Session Average Size",
                     debugInfoMap.get( SessionTrackService.DebugKey.HttpSessionAvgSize )
             ) );
         }

+ 4 - 1
server/src/main/java/password/pwm/svc/event/SyslogAuditService.java

@@ -298,7 +298,10 @@ public class SyslogAuditService
     public void close( )
     {
         final SyslogIF syslogIF = syslogInstance;
-        syslogIF.shutdown();
+        if ( syslogIF != null )
+        {
+            syslogIF.shutdown();
+        }
         workQueueProcessor.close();
         syslogInstance = null;
     }

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

@@ -1049,6 +1049,10 @@
         </default>
     </setting>
     <setting hidden="false" key="password.policy.maximumLength" level="1" required="true">
+        <properties>
+            <property key="Minimum">0</property>
+            <property key="Maximum">10000</property>
+        </properties>
         <default>
             <value>64</value>
         </default>

+ 1 - 1
server/src/main/resources/password/pwm/i18n/Config.properties

@@ -161,7 +161,7 @@ Tooltip_FormOptions_LinkLabel=Label to be displayed that tells where the link wi
 Tooltip_FormOptions_LinkURL=Full url that you want to go to when the link is selected.
 Tooltip_Form_ShowInNewWindow=Choose if the link will e opened in a new browser window
 Tooltip_FormOptions_Placeholder=Placeholder text to display in the form field with the field is not populated with a value.
-Tooltip_FormOptions_Javascript=Javascript to be added to the browser.
+Tooltip_FormOptions_Javascript=Javascript to be added to the browser.  This option is depreciated.  Use 'Settings -> User Interface -> Look & Feel -> Embedded JavaScript' instead.
 Tooltip_FormOptions_MultiValue=Display multiple values of the attribute.
 VerificationMethodDetail_PREVIOUS_AUTH=This method is passed when a user has previously authenticated using their browser.  There is no user interaction or display associated with this method.
 VerificationMethodDetail_ATTRIBUTES=User will be prompted for LDAP attribute values defined by the setting @PwmSettingReference:challenge.requiredAttributes@.

+ 1 - 0
server/src/main/resources/password/pwm/i18n/Health.properties

@@ -58,6 +58,7 @@ HealthMessage_Config_UserPermissionValidity=User Permission configuration for se
 HealthMessage_Config_DNValueValidity=LDAP DN configuration setting %1% issue: %2%.  This may cause unexpected issues.
 HealthMessage_Config_Certificate=Certificate for setting %1% issue: %2%
 HealthMessage_Config_InvalidSendMethod=The send method '%1%' is no longer available for setting %2%.  Please modify the configuration to use an alternate value.
+HealthMessage_Config_DeprecatedJSForm=The javascript form option in the form setting %1% has been deprecated and will be removed in a future version.  Use the setting %2% instead.
 HealthMessage_LDAP_VendorsNotSame=LDAP directories of different vendor types are in use.  This configuration may cause undesirable side effects and is not supported.  %1%
 HealthMessage_LDAP_Ad_History_Asn_Missing=%1% is enabled, but the server at %2% does not support this feature.  Check to be sure it is upgraded to Windows Server 2008 R2 SP1 or greater.  Password changes against this server may fail until this is resolved.
 HealthMessage_LDAP_RecentlyUnreachable=LDAP profile %1% was recently unavailable (%2% ago at %3%): %4%

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

@@ -512,15 +512,15 @@ Setting_Description_password.policy.allowNumeric=Enable this option to allow num
 Setting_Description_password.policy.allowSpecial=Enable this option to allow special (non alpha-numeric) characters in the password.
 Setting_Description_password.policy.caseSensitivity=Enable this option to control if the password is case sensitive.  In most cases, @PwmAppName@ can read this from the directory, but in some cases, the system cannot correctly read this value, so you can override it here.
 Setting_Description_password.policy.changeMessage=Specify a message @PwmAppName@ displays to the users during password changes.  Might include HTML markup.  You can override this setting by adding a change password message read as part of an LDAP password policy.
-Setting_Description_password.policy.charGroup.minimumMatch=Specify tthe number of regular expression matches defined in the setting <code>@PwmSettingReference\:password.policy.charGroup.regExValues@</code>.
+Setting_Description_password.policy.charGroup.minimumMatch=Specify the number of regular expression matches defined in the setting <code>@PwmSettingReference\:password.policy.charGroup.regExValues@</code>.
 Setting_Description_password.policy.charGroup.regExValues=Add an LDAP filter that contains a list of regular expression character matches.  Along with the setting <code>@PwmSettingReference\:password.policy.charGroup.minimumMatch@</code>, this setting allows creating a complex list of requirements that the user only needs to partially match.  For example, you can use this type of policy to replicate the Active Directory "3 out of 5" rules, but with more flexibility and customization.
 Setting_Description_password.policy.checkWordlist=Enable this option to check the password against the configured Word List.
 Setting_Description_password.policy.disallowCurrent=Enable this option to prohibit the current password from being used as a new password.  Note: @PwmAppName@ can only enforce this if the login method permits the user's password to be known.
 Setting_Description_password.policy.disallowedAttributes=Specify a list of attributes not allowed to be used as passwords.  For a given user, @PwmAppName@ reads the values and does not permit the users to use it as part of the password value.  This check is case-insensitive.  Note: Specifying a number after the attribute name restricts how many consecutive characters @PwmAppName@ disallows in the value (For example: "Language:4" means the password cannot contain: "Engl", "ngli", "glis", or "lish", for English speaking users).
-Setting_Description_password.policy.disallowedValues=Speciy a case insensitive list of values @PwmAppName@ does not allow the users to use as passwords.
+Setting_Description_password.policy.disallowedValues=Specify a case insensitive list of values @PwmAppName@ does not allow the users to use as passwords.
 Setting_Description_password.policy.maximumAlpha=Specify the maximum amount of alphabetic characters required.  A value of zero disables this check.
-Setting_Description_password.policy.maximumConsecutive=Speicfy the maximum amount of characters in a sequence such as <b>0123456789</b> or <b>abcdefghijk</b>.  @PwmAppName@ defines a more specific character sequence by the unicode character order of each character after it converts the entire value to lowercase.   A value of 0 disables this check.
-Setting_Description_password.policy.maximumLength=Specify the maximum length of the password.  A value of zero disables this check.
+Setting_Description_password.policy.maximumConsecutive=Specify the maximum amount of characters in a sequence such as <b>0123456789</b> or <b>abcdefghijk</b>.  @PwmAppName@ defines a more specific character sequence by the unicode character order of each character after it converts the entire value to lowercase.   A value of 0 disables this check.
+Setting_Description_password.policy.maximumLength=Specify the maximum length of the password.  A value of zero disables this check.  Although you can set this limit to large values, the LDAP directory being used may have fixed limitations on the supported password length.
 Setting_Description_password.policy.maximumLowerCase=Specify the maximum amount of lowercase characters required.  A value of zero disables this check.
 Setting_Description_password.policy.maximumNonAlpha=Specify the maximum amount of non-alphabetic characters required.  A value of zero disables this check.
 Setting_Description_password.policy.maximumNumeric=Specify the maximum amount of numeric characters required (if the password policy allows numeric).  A value of zero disables this check.

+ 2 - 12
server/src/main/webapp/WEB-INF/jsp/accountinformation.jsp

@@ -42,7 +42,7 @@
     </jsp:include>
     <div id="centerbody">
         <div id="page-content-title" style="display: none;"><pwm:display key="Title_UserInformation" displayIfMissing="true"/></div>
-        <div class="tab-container" style="width: 100%; height: 100%;" data-dojo-props="doLayout: false">
+        <div class="tab-container" style="width: 100%; height: 100%;">
             <input name="tabs" type="radio" id="tab-1" checked="checked" class="input"/>
             <label for="tab-1" class="label"><pwm:display key="Title_UserInformation"/></label>
             <div class="tab-content-pane" id="UserInformation" title="<pwm:display key="Title_UserInformation"/>" class="tabContent">
@@ -55,7 +55,7 @@
             </div>
             <% if (!JavaHelper.isEmpty(accountInformationBean.getFormData())) { %>
             <input name="tabs" type="radio" id="tab-2" class="input"/>
-            <label for="tab-2" class="label"><%=Display.Title_UserData.toString()%></label>
+            <label for="tab-2" class="label"><pwm:display key="Title_UserData"/></label>
             <div class="tab-content-pane" id="UserData" title="<pwm:display key="<%=Display.Title_UserData.toString()%>"/>" class="tabContent">
                 <div style="max-height: 400px; overflow: auto;">
                     <table class="nomargin">
@@ -126,16 +126,6 @@
     </div>
     <div class="push"></div>
 </div>
-<pwm:script>
-    <script type="text/javascript">
-        PWM_GLOBAL['startupFunctions'].push(function(){
-            require(["dojo/parser","dijit/layout/TabContainer","dijit/layout/ContentPane"],function(dojoParser){
-                dojoParser.parse();
-            });
-        });
-    </script>
-</pwm:script>
-<link rel="stylesheet" type="text/css" href="<pwm:url url='/public/resources/tab-container.css' addContext="true"/>"/>
 <jsp:include page="/WEB-INF/jsp/fragment/footer.jsp"/>
 </body>
 </html>                   

+ 114 - 109
server/src/main/webapp/WEB-INF/jsp/admin-activity.jsp

@@ -49,20 +49,22 @@
     }
 </style>
 <div id="wrapper">
-    <% final String PageName = JspUtility.localizedString(pageContext,"Title_UserActivity",Admin.class);%>
+        <% final String PageName = JspUtility.localizedString(pageContext,"Title_UserActivity",Admin.class);%>
     <jsp:include page="/WEB-INF/jsp/fragment/header-body.jsp" flush="true" >
         <jsp:param name="pwm.PageName" value="<%=PageName%>"/>
     </jsp:include>
     <div id="centerbody" class="wide">
         <div id="page-content-title"><pwm:display key="Title_UserActivity" bundle="Admin"/></div>
         <%@ include file="fragment/admin-nav.jsp" %>
-        <div data-dojo-type="dijit/layout/TabContainer" style="width: 100%; height: 100%;" data-dojo-props="doLayout: false, persist: true">
-            <div id="ActiveWebSessions" data-dojo-type="dijit/layout/ContentPane" title="<pwm:display key="Title_Sessions" bundle="Admin"/>" class="tabContent">
+        <div id="ActivityTabContainer" class="tab-container" style="width: 100%; height: 100%;">
+            <input name="tabs" type="radio" id="tab-1" checked="checked" class="input"/>
+            <label for="tab-1" class="label"><pwm:display key="Title_Sessions" bundle="Admin"/></label>
+            <div id="SessionsTab" class="tab-content-pane" title="<pwm:display key="Title_Sessions" bundle="Admin"/>" >
+
                 <div id="activeSessionGrid" class="analysisGrid">
                 </div>
                 <div style="text-align: center">
-                    <input name="maxResults" id="maxActiveSessionResults" value="1000" data-dojo-type="dijit/form/NumberSpinner" style="width: 70px"
-                           data-dojo-props="constraints:{min:10,max:10000000,pattern:'#'},smallDelta:100"/>
+                    <input name="maxResults" id="maxActiveSessionResults" value="1000" type="number" min="10" max="10000000" style="width: 70px"/>
                     Rows
                     <button class="btn" type="button" id="button-activeSessionRefresh">
                         <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-refresh">&nbsp;</span></pwm:if>
@@ -77,126 +79,129 @@
                             });
                         </script>
                     </pwm:script>
-
                 </div>
             </div>
+            <input name="tabs" type="radio" id="tab-2" class="input"/>
+            <label for="tab-2" class="label"><pwm:display key="Title_Intruders" bundle="Admin"/></label>
+            <div id="IntrudersTab" class="tab-content-pane" title="<pwm:display key="Title_Intruders" bundle="Admin"/>">
+                <div class="tab-container" style="width: 100%; height: 100%;">
+                    <% boolean checked = true; %>
+                    <% for (final RecordType recordType : RecordType.values()) { %>
+                    <% final String titleName = LocaleHelper.getLocalizedMessage(activity_pwmRequest.getLocale(),"IntruderRecordType_" + recordType.toString(), activity_pwmRequest.getConfig(), Admin.class); %>
+                    <input name="intruder_tabs" type="radio" id="tab-2.<%=recordType%>" <%=checked?"checked=\"checked\"":""%> class="input"/>
+                    <label for="tab-2.<%=recordType%>" class="label"><%=titleName%></label>
+                    <div class="tab-content-pane" title="<%=titleName%>">
 
-
-            <div data-dojo-type="dijit/layout/TabContainer" title="<pwm:display key="Title_Intruders" bundle="Admin"/>" style="width: 100%; height: 100%;" data-dojo-props="doLayout: false, persist: true">
-            <% for (final RecordType recordType : RecordType.values()) { %>
-            <% final String titleName = LocaleHelper.getLocalizedMessage(activity_pwmRequest.getLocale(),"IntruderRecordType_" + recordType.toString(), activity_pwmRequest.getConfig(), Admin.class); %>
-            <div id="Intruders<%=titleName%>" data-dojo-type="dijit/layout/ContentPane" title="<%=titleName%>" class="tabContent">
-                <div id="<%=recordType%>_Grid" class="analysisGrid">
+                            <div id="<%=recordType%>_Grid" class="analysisGrid">
+                            </div>
+                    </div>
+                    <% checked = false; %>
+                    <% } %>
+                    <div class="tab-end"></div>
                 </div>
             </div>
-            <% } %>
-            </div>
+            <input name="tabs" type="radio" id="tab-3" class="input"/>
+            <label for="tab-3" class="label" id="audit_tab_label"><pwm:display key="Title_Audit" bundle="Admin"/></label>
+            <div id="AuditTab" class="tab-content-pane" title="<pwm:display key="Title_Audit" bundle="Admin"/>">
+                <div class="tab-container" style="width: 100%; height: 100%;">
 
-            <div data-dojo-type="dijit/layout/TabContainer" title="<pwm:display key="Title_Audit" bundle="Admin"/>" style="width: 100%; height: 100%;" data-dojo-props="doLayout: false, persist: true">
-            <div id="AuditUser" data-dojo-type="dijit/layout/ContentPane" title="<pwm:display key="Title_AuditUsers" bundle="Admin"/>" class="tabContent">
-                <div id="auditUserGrid" class="analysisGrid">
-                </div>
-                <div style="text-align: center">
-                    <input name="maxAuditUserResults" id="maxAuditUserResults" value="1000" data-dojo-type="dijit/form/NumberSpinner" style="width: 70px"
-                           data-dojo-props="constraints:{min:10,max:10000000,pattern:'#'},smallDelta:100"/>
-                    Rows
-                    <button class="btn" type="button" id="button-refreshAuditUser">
-                        <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-refresh">&nbsp;</span></pwm:if>
-                        <pwm:display key="Button_Refresh" bundle="Admin"/>
-                    </button>
-                    <form action="<pwm:current-url/>" method="post" enctype="application/x-www-form-urlencoded">
-                        <button type="submit" class="btn">
-                            <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-download"></span></pwm:if>
-                            <pwm:display key="Button_DownloadCSV" bundle="Admin"/>
-                        </button>
-                        <input type="hidden" name="processAction" value="downloadAuditLogCsv"/>
-                        <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
-                    </form>
-                </div>
-            </div>
-            <div id="AuditHelpdesk" data-dojo-type="dijit/layout/ContentPane" title="<pwm:display key="Title_AuditHelpdesk" bundle="Admin"/>" class="tabContent">
-                <div id="auditHelpdeskGrid" class="analysisGrid">
-                </div>
-                <div style="text-align: center">
-                    <input name="maxAuditHelpdeskResults" id="maxAuditHelpdeskResults" value="1000" data-dojo-type="dijit/form/NumberSpinner" style="width: 70px"
-                           data-dojo-props="constraints:{min:10,max:10000000,pattern:'#'},smallDelta:100"/>
-                    Rows
-                    <button class="btn" type="button" id="button-refreshHelpdeskUser">
-                        <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-refresh">&nbsp;</span></pwm:if>
-                        <pwm:display key="Button_Refresh" bundle="Admin"/>
-                    </button>
-                    <form action="<pwm:current-url/>" method="post" enctype="application/x-www-form-urlencoded">
-                        <button type="submit" class="btn">
-                            <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-download"></span></pwm:if>
-                            <pwm:display key="Button_DownloadCSV" bundle="Admin"/>
-                        </button>
-                        <input type="hidden" name="processAction" value="downloadAuditLogCsv"/>
-                        <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
-                    </form>
-                </div>
-            </div>
-            <div id="AuditSystem" data-dojo-type="dijit/layout/ContentPane" title="<pwm:display key="Title_AuditSystem" bundle="Admin"/>" class="tabContent">
-                <div id="auditSystemGrid" class="analysisGrid">
-                </div>
-                <div style="text-align: center">
-                    <input name="maxAuditSystemResults" id="maxAuditSystemResults" value="1000" data-dojo-type="dijit/form/NumberSpinner" style="width: 70px"
-                           data-dojo-props="constraints:{min:10,max:10000000,pattern:'#'},smallDelta:100"/>
-                    Rows
-                    <button class="btn" type="button" id="button-refreshSystemAudit">
-                        <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-refresh">&nbsp;</span></pwm:if>
-                        <pwm:display key="Button_Refresh" bundle="Admin"/>
-                    </button>
-                    <form action="<pwm:current-url/>" method="post" enctype="application/x-www-form-urlencoded">
-                        <button type="submit" class="btn">
-                            <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-download"></span></pwm:if>
-                            <pwm:display key="Button_DownloadCSV" bundle="Admin"/>
-                        </button>
-                        <input type="hidden" name="processAction" value="downloadAuditLogCsv"/>
-                        <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
-                    </form>
+                    <input name="audit_tabs" type="radio" id="tab-3.1" checked="checked" class="input"/>
+                    <label for="tab-3.1" class="label"><pwm:display key="Title_AuditUsers" bundle="Admin"/></label>
+                    <div class="tab-content-pane" title="<pwm:display key="Title_AuditUsers" bundle="Admin"/>" class="tabContent">
+
+                        <div id="auditUserGrid" class="analysisGrid">
+                        </div>
+
+                        <div style="text-align: center">
+                            <input name="maxAuditUserResults" id="maxAuditUserResults" value="100" type="number" min="10" max="10000000" style="width: 70px"/>
+                            Rows
+                            <button class="btn" type="button" id="button-refreshAuditUser">
+                                <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-refresh">&nbsp;</span></pwm:if>
+                                <pwm:display key="Button_Refresh" bundle="Admin"/>
+                            </button>
+                            <form action="<pwm:current-url/>" method="post" enctype="application/x-www-form-urlencoded">
+                                <button type="submit" class="btn">
+                                    <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-download"></span></pwm:if>
+                                    <pwm:display key="Button_DownloadCSV" bundle="Admin"/>
+                                </button>
+                                <input type="hidden" name="processAction" value="downloadAuditLogCsv"/>
+                                <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
+                            </form>
+                        </div>
+                    </div>
+                    <input name="audit_tabs" type="radio" id="tab-3.2" class="input"/>
+                    <label for="tab-3.2" class="label"><pwm:display key="Title_AuditHelpdesk" bundle="Admin"/></label>
+                    <div class="tab-content-pane" title="<pwm:display key="Title_AuditHelpdesk" bundle="Admin"/>" class="tabContent">
+                        <div id="auditHelpdeskGrid" class="analysisGrid">
+                        </div>
+                        <div style="text-align: center">
+                            <input name="maxAuditHelpdeskResults" id="maxAuditHelpdeskResults" value="100" type="number" min="10" max="10000000" style="width: 70px"/>
+                            Rows
+                            <button class="btn" type="button" id="button-refreshHelpdeskUser">
+                                <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-refresh">&nbsp;</span></pwm:if>
+                                <pwm:display key="Button_Refresh" bundle="Admin"/>
+                            </button>
+                            <form action="<pwm:current-url/>" method="post" enctype="application/x-www-form-urlencoded">
+                                <button type="submit" class="btn">
+                                    <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-download"></span></pwm:if>
+                                    <pwm:display key="Button_DownloadCSV" bundle="Admin"/>
+                                </button>
+                                <input type="hidden" name="processAction" value="downloadAuditLogCsv"/>
+                                <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
+                            </form>
+                        </div>
+                    </div>
+                    <input name="audit_tabs" type="radio" id="tab-3.3" class="input"/>
+                    <label for="tab-3.3" class="label"><pwm:display key="Title_AuditSystem" bundle="Admin"/></label>
+                    <div class="tab-content-pane" title="<pwm:display key="Title_AuditSystem" bundle="Admin"/>" class="tabContent">
+                        <div id="auditSystemGrid" class="analysisGrid">
+                        </div>
+                        <div style="text-align: center">
+                            <input name="maxAuditSystemResults" id="maxAuditSystemResults" value="100" type="number" min="10" max="10000000" style="width: 70px"/>
+                            Rows
+                            <button class="btn" type="button" id="button-refreshSystemAudit">
+                                <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-refresh">&nbsp;</span></pwm:if>
+                                <pwm:display key="Button_Refresh" bundle="Admin"/>
+                            </button>
+                            <form action="<pwm:current-url/>" method="post" enctype="application/x-www-form-urlencoded">
+                                <button type="submit" class="btn">
+                                    <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-download"></span></pwm:if>
+                                    <pwm:display key="Button_DownloadCSV" bundle="Admin"/>
+                                </button>
+                                <input type="hidden" name="processAction" value="downloadAuditLogCsv"/>
+                                <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
+                            </form>
+                        </div>
+                    </div>
+                    <div class="tab-end"></div>
                 </div>
             </div>
-            </div>
-        </div>
-        <br/>
-        <%--
-        <div style="text-align: center">
-            <input name="maxResults" id="maxIntruderGridResults" value="1000" data-dojo-type="dijit/form/NumberSpinner" style="width: 70px"
-                   data-dojo-props="constraints:{min:10,max:10000000,pattern:'#'},smallDelta:100"/>
-            Rows
-            <button class="btn" type="button" onclick="PWM_ADMIN.refreshIntruderGrid()">
-                <pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-refresh">&nbsp;</span></pwm:if>
-                <pwm:display key="Button_Refresh" bundle="Admin"/>
-            </button>
+            <div class="tab-end"></div>
         </div>
-        --%>
+        <div class="push"></div>
     </div>
-    <div class="push"></div>
-</div>
-<pwm:script>
+    <pwm:script>
     <script type="text/javascript">
         PWM_GLOBAL['startupFunctions'].push(function(){
-            require(["dojo/parser","dojo/ready","dijit/layout/TabContainer","dijit/layout/ContentPane","dijit/Dialog","dijit/form/NumberSpinner"],function(dojoParser,ready){
-                dojoParser.parse(PWM_MAIN.getObject('centerbody'));
-                PWM_ADMIN.initIntrudersGrid();
-                PWM_ADMIN.initActiveSessionGrid();
-                PWM_ADMIN.initAuditGrid();
-
+            PWM_MAIN.addEventHandler('audit_tab_label','click',function(){
+            });
 
+            PWM_ADMIN.initAuditGrid();
+            PWM_ADMIN.initActiveSessionGrid();
+            PWM_ADMIN.initIntrudersGrid();
 
-                PWM_MAIN.addEventHandler('button-refreshAuditUser','click',function(){
-                    PWM_ADMIN.refreshAuditGridData(PWM_MAIN.getObject('maxAuditUserResults').value);
-                });
-                PWM_MAIN.addEventHandler('button-refreshHelpdeskUser','click',function(){
-                    PWM_ADMIN.refreshAuditGridData(PWM_MAIN.getObject('maxAuditHelpdeskResults').value);
-                });
-                PWM_MAIN.addEventHandler('button-refreshSystemAudit','click',function(){
-                    PWM_ADMIN.refreshAuditGridData(PWM_MAIN.getObject('maxAuditSystemResults').value);
-                });
+            PWM_MAIN.addEventHandler('button-refreshAuditUser','click',function(){
+                PWM_ADMIN.refreshAuditGridData(PWM_MAIN.getObject('maxAuditUserResults').value,'USER');
+            });
+            PWM_MAIN.addEventHandler('button-refreshHelpdeskUser','click',function(){
+                PWM_ADMIN.refreshAuditGridData(PWM_MAIN.getObject('maxAuditHelpdeskResults').value,'HELPDESK');
+            });
+            PWM_MAIN.addEventHandler('button-refreshSystemAudit','click',function(){
+                PWM_ADMIN.refreshAuditGridData(PWM_MAIN.getObject('maxAuditSystemResults').value,'SYSTEM');
             });
         });
     </script>
-</pwm:script>
-<%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
+    </pwm:script>
+    <%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
 </body>
 </html>

+ 5 - 8
server/src/main/webapp/WEB-INF/jsp/admin-analysis.jsp

@@ -63,10 +63,10 @@
     <div id="centerbody" class="wide">
         <div id="page-content-title"><pwm:display key="Title_DataAnalysis" bundle="Admin"/></div>
         <%@ include file="fragment/admin-nav.jsp" %>
-        <div class="tab-container" style="width: 100%; height: 100%;"  data-dojo-props="doLayout: false, persist: true" id="analysis-topLevelTab">
+        <div class="tab-container" style="width: 100%; height: 100%;" id="analysis-topLevelTab">
             <input name="tabs" type="radio" id="tab-1" checked="checked" class="input"/>
             <label for="tab-1" class="label"><pwm:display key="Title_DirectoryReporting" bundle="Admin"/></label>
-            <div class="tab-content-pane" style="width: 100%; height: 100%;" data-dojo-props="doLayout: false, persist: true" title="<pwm:display key="Title_DirectoryReporting" bundle="Admin"/>">
+            <div class="tab-content-pane" style="width: 100%; height: 100%;" title="<pwm:display key="Title_DirectoryReporting" bundle="Admin"/>">
                 <div class="tab-container" style="width: 100%; height: 100%;">
                     <input name="dr_tabs" type="radio" id="tab-1.1" checked="checked" class="input"/>
                     <label for="tab-1.1" class="label"><pwm:display key="Title_ReportEngineStatus" bundle="Admin"/></label>
@@ -169,7 +169,7 @@
 
             <input name="tabs" type="radio" id="tab-2" class="input"/>
             <label for="tab-2" class="label"><pwm:display key="Title_EventStatistics" bundle="Admin"/></label>
-            <div class="tab-content-pane" style="width: 100%; height: 100%;" data-dojo-props="doLayout: false, persist: true" title="<pwm:display key="Title_EventStatistics" bundle="Admin"/>">
+            <div class="tab-content-pane" style="width: 100%; height: 100%;" title="<pwm:display key="Title_EventStatistics" bundle="Admin"/>">
                 <div class="tab-container" style="width: 100%; height: 100%;">
                     <input name="es_tabs" type="radio" id="tab-2.1" checked="checked" class="input"/>
                     <label for="tab-2.1" class="label"><pwm:display key="Title_RawStatistics" bundle="Admin"/></label>
@@ -181,7 +181,7 @@
                                         <form action="<pwm:current-url/>" method="GET" enctype="application/x-www-form-urlencoded"
                                               name="statsUpdateForm" id="statsUpdateForm">
                                             <select name="statsPeriodSelect"
-                                                    style="width: 350px;" data-dojo-props="maxHeight: -1">
+                                                    style="width: 350px;">
                                                 <option value="<%=StatisticsManager.KEY_CUMULATIVE%>" <%= StatisticsManager.KEY_CUMULATIVE.equals(statsPeriodSelect) ? "selected=\"selected\"" : "" %>>
                                                     since installation - <%= JavaHelper.toIsoDate(analysis_pwmRequest.getPwmApplication().getInstallTime()) %>
                                                 </option>
@@ -253,7 +253,6 @@
                 </div>
             </div>
 
-            <div class="tab-end"></div>
         </div>
     </div>
     <div class="push"></div>
@@ -269,8 +268,7 @@
 
 
         PWM_GLOBAL['startupFunctions'].push(function(){
-            require(["dojo","dojo/query","dojo/parser","dijit/registry","dojo/ready","dijit/layout/TabContainer","dijit/layout/ContentPane"],function(dojo,query,dojoParser,registry,ready){
-                dojoParser.parse('centerbody');
+            require(["dojo","dojo/query"],function(dojo,query){
                 PWM_MAIN.JSLibrary.setValueOfSelectElement('statsChartSelect','<%=Statistic.PASSWORD_CHANGES%>');
 
                 setTimeout(function(){
@@ -308,7 +306,6 @@
     </script>
 </pwm:script>
 <% JspUtility.setFlag(pageContext, PwmRequestFlag.HIDE_LOCALE); %>
-<link rel="stylesheet" type="text/css" href="<pwm:url url='/public/resources/tab-container.css' addContext="true"/>"/>
 <%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
 </body>
 </html>

+ 37 - 39
server/src/main/webapp/WEB-INF/jsp/admin-dashboard.jsp

@@ -55,7 +55,7 @@
     <div id="centerbody">
         <div id="page-content-title"><pwm:display key="Title_Dashboard" bundle="Admin"/></div>
         <%@ include file="fragment/admin-nav.jsp" %>
-        <div id="DashboardTabContainer" class="tab-container" style="width: 100%; height: 100%;" data-dojo-props="doLayout: false, persist: true">
+        <div id="DashboardTabContainer" class="tab-container" style="width: 100%; height: 100%;">
             <input name="tabs" type="radio" id="tab-1" checked="checked" class="input"/>
             <label for="tab-1" class="label">Status</label>
             <div id="StatusTab" class="tab-content-pane" title="Status" >
@@ -109,7 +109,7 @@
                     <% } %>
                     <% } %>
                 </table>
-                <div class="tab-container" style="margin-top: 15px;" data-dojo-props="doLayout: false, persist: true">
+                <div class="tab-container" style="margin-top: 15px;">
                     <input name="status_tabs" type="radio" id="tab-1.1" checked="checked" class="input"/>
                     <label for="tab-1.1" class="label">Last Minute</label>
                     <div class="tab-content-pane" title="Last Minute" class="tabContent">
@@ -242,6 +242,7 @@
             <input name="tabs" type="radio" id="tab-4" class="input"/>
             <label for="tab-4" class="label">Services</label>
             <div id="ServicesTab" class="tab-content-pane" title="Services">
+                <div style="max-height: 600px; overflow: auto;">
                 <table class="nomargin">
                     <tr>
                         <th style="font-weight:bold;">
@@ -289,6 +290,7 @@
                     </tr>
                     <% } %>
                 </table>
+                </div>
             </div>
 
             <input name="tabs" type="radio" id="tab-5" class="input"/>
@@ -304,32 +306,32 @@
                 </div>
                 <br/>
                 <div style="max-height: 400px; overflow: auto;">
-                <% if (!JavaHelper.isEmpty(appDashboardData.getLocalDbSizes())) { %>
-                <table class="nomargin">
-                    <tr>
-                        <td class="key">
-                            Name
-                        </td>
-                        <td class="key" style="text-align: left">
-                            Record Count
-                        </td>
-                    </tr>
-                    <% for (final Map.Entry<LocalDB.DB,String> entry : appDashboardData.getLocalDbSizes().entrySet()) { %>
-                    <tr>
-                        <td style="text-align: right">
-                            <%= entry.getKey() %>
-                        </td>
-                        <td>
-                            <%= entry.getValue() %>
-                        </td>
-                    </tr>
+                    <% if (!JavaHelper.isEmpty(appDashboardData.getLocalDbSizes())) { %>
+                    <table class="nomargin">
+                        <tr>
+                            <td class="key">
+                                Name
+                            </td>
+                            <td class="key" style="text-align: left">
+                                Record Count
+                            </td>
+                        </tr>
+                        <% for (final Map.Entry<LocalDB.DB,String> entry : appDashboardData.getLocalDbSizes().entrySet()) { %>
+                        <tr>
+                            <td style="text-align: right">
+                                <%= entry.getKey() %>
+                            </td>
+                            <td>
+                                <%= entry.getValue() %>
+                            </td>
+                        </tr>
+                        <% } %>
+                    </table>
+                    <% } else { %>
+                    <div class="noborder" style="text-align:center; width:100%;">
+                        <a style="cursor: pointer" id="button-showLocalDBCounts">Show LocalDB record counts</a> (may be slow to load)
+                    </div>
                     <% } %>
-                </table>
-                <% } else { %>
-                <div class="noborder" style="text-align:center; width:100%;">
-                    <a style="cursor: pointer" id="button-showLocalDBCounts">Show LocalDB record counts</a> (may be slow to load)
-                </div>
-                <% } %>
                 </div>
             </div>
 
@@ -449,21 +451,18 @@
 <pwm:script>
     <script type="text/javascript">
         PWM_GLOBAL['startupFunctions'].push(function(){
-            require(["dojo/parser","dijit/layout/TabContainer","dijit/layout/ContentPane"],function(dojoParser){
-                dojoParser.parse();
-                PWM_ADMIN.showStatChart('PASSWORD_CHANGES',14,'statsChart',{refreshTime:11*1000});
-                PWM_ADMIN.showAppHealth('healthBody', {showRefresh:true,showTimestamp:true});
+            PWM_ADMIN.showStatChart('PASSWORD_CHANGES',14,'statsChart',{refreshTime:11*1000});
+            PWM_ADMIN.showAppHealth('healthBody', {showRefresh:true,showTimestamp:true});
 
-                PWM_MAIN.addEventHandler('button-showLocalDBCounts','click',function(){
-                    PWM_MAIN.showWaitDialog({loadFunction:function(){
+            PWM_MAIN.addEventHandler('button-showLocalDBCounts','click',function(){
+                PWM_MAIN.showWaitDialog({loadFunction:function(){
                         PWM_MAIN.goto('dashboard?showLocalDBCounts=true');
                     }})
-                });
-                PWM_MAIN.addEventHandler('button-showThreadDetails','click',function(){
-                    PWM_MAIN.showWaitDialog({loadFunction:function(){
+            });
+            PWM_MAIN.addEventHandler('button-showThreadDetails','click',function(){
+                PWM_MAIN.showWaitDialog({loadFunction:function(){
                         PWM_MAIN.goto('dashboard?showThreadDetails=true');
                     }})
-                });
             });
             <% for (final AppDashboardData.ServiceData loopService : appDashboardData.getServices()) { %>
             <% if (!JavaHelper.isEmpty(loopService.getDebugData())) { %>
@@ -471,7 +470,7 @@
                 var tableText = '<table>';
                 <% for (final Map.Entry<String,String> entry : loopService.getDebugData().entrySet()) { %>
                 tableText += '<tr><td><%=StringUtil.escapeJS(entry.getKey())%></td>'
-                + '<td><%=StringUtil.escapeJS(entry.getValue())%></td></tr>';
+                    + '<td><%=StringUtil.escapeJS(entry.getValue())%></td></tr>';
                 <% } %>
                 tableText += '</table>';
                 PWM_MAIN.showDialog({title:'Debug Properties',text:tableText});
@@ -482,7 +481,6 @@
     </script>
 </pwm:script>
 
-<link rel="stylesheet" type="text/css" href="<pwm:url url='/public/resources/tab-container.css' addContext="true"/>"/>
 <%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
 <pwm:script-ref url="/public/resources/js/admin.js"/>
 </body>

+ 1 - 13
server/src/main/webapp/WEB-INF/jsp/setupotpsecret.jsp

@@ -55,7 +55,7 @@
         <div id="page-content-title"><pwm:display key="Title_SetupOtpSecret" displayIfMissing="true"/></div>
         <p><pwm:display key="Display_SetupOtpSecret"/></p>
         <%@ include file="fragment/message.jsp" %>
-        <div class="tab-container" data-dojo-props="doLayout: false, persist: true">
+        <div class="tab-container">
             <input name="tabs" type="radio" id="tab-1" checked="checked" class="input"/>
             <label for="tab-1" class="label"><pwm:display key="Display_SetupOtp_Android_Title"/></label>
             <div class="tab-content-pane" title="<pwm:display key="Display_SetupOtp_Android_Title"/>">
@@ -126,20 +126,8 @@
     </div>
     <div class="push"></div>
 </div>
-<pwm:script>
-    <script type="text/javascript">
-        PWM_GLOBAL['startupFunctions'].push(function(){
-            require(["dojo/parser","dojo/ready","dijit/layout/TabContainer","dijit/layout/ContentPane"],function(dojoParser,ready){
-                ready(function(){
-                    dojoParser.parse();
-                });
-            });
-        });
-    </script>
-</pwm:script>
 <pwm:script-ref url="/public/resources/js/responses.js"/>
 <pwm:script-ref url="/public/resources/js/otpsecret.js"/>
-<link rel="stylesheet" type="text/css" href="<pwm:url url='/public/resources/tab-container.css' addContext="true"/>"/>
 <%@ include file="fragment/footer.jsp" %>
 </body>
 </html>

+ 131 - 158
server/src/main/webapp/public/resources/js/admin.js

@@ -114,30 +114,30 @@ PWM_ADMIN.initAdminNavMenu = function() {
 };
 
 PWM_ADMIN.reportDataHeaders = function() {
-    return {
-        "username":PWM_ADMIN.showString("Field_Report_Username"),
-        "userDN":PWM_ADMIN.showString("Field_Report_UserDN"),
-        "ldapProfile":PWM_ADMIN.showString("Field_Report_LDAP_Profile"),
-        "email":PWM_ADMIN.showString("Field_Report_Email"),
-        "userGUID":PWM_ADMIN.showString("Field_Report_UserGuid"),
-        "accountExpirationTime":PWM_ADMIN.showString("Field_Report_AccountExpireTime"),
-        "passwordExpirationTime":PWM_ADMIN.showString("Field_Report_PwdExpireTime"),
-        "passwordChangeTime":PWM_ADMIN.showString("Field_Report_PwdChangeTime"),
-        "responseSetTime":PWM_ADMIN.showString("Field_Report_ResponseSaveTime"),
-        "lastLoginTime":PWM_ADMIN.showString("Field_Report_LastLogin"),
-        "hasResponses":PWM_ADMIN.showString("Field_Report_HasResponses"),
-        "hasHelpdeskResponses":PWM_ADMIN.showString("Field_Report_HasHelpdeskResponses"),
-        "responseStorageMethod":PWM_ADMIN.showString("Field_Report_ResponseStorageMethod"),
-        "responseFormatType":PWM_ADMIN.showString("Field_Report_ResponseFormatType"),
-        "passwordStatusExpired":PWM_ADMIN.showString("Field_Report_PwdExpired"),
-        "passwordStatusPreExpired":PWM_ADMIN.showString("Field_Report_PwdPreExpired"),
-        "passwordStatusViolatesPolicy":PWM_ADMIN.showString("Field_Report_PwdViolatesPolicy"),
-        "passwordStatusWarnPeriod":PWM_ADMIN.showString("Field_Report_PwdWarnPeriod"),
-        "requiresPasswordUpdate":PWM_ADMIN.showString("Field_Report_RequiresPasswordUpdate"),
-        "requiresResponseUpdate":PWM_ADMIN.showString("Field_Report_RequiresResponseUpdate"),
-        "requiresProfileUpdate":PWM_ADMIN.showString("Field_Report_RequiresProfileUpdate"),
-        "cacheTimestamp":PWM_ADMIN.showString("Field_Report_RecordCacheTime")
-    };
+    return [
+        {field:"username",label:PWM_ADMIN.showString("Field_Report_Username")},
+        {field:"userDN",label:PWM_ADMIN.showString("Field_Report_UserDN"),hidden:true},
+        {field:"ldapProfile",label:PWM_ADMIN.showString("Field_Report_LDAP_Profile"),hidden:true},
+        {field:"email",label:PWM_ADMIN.showString("Field_Report_Email"),hidden:true},
+        {field:"userGUID",label:PWM_ADMIN.showString("Field_Report_UserGuid"),hidden:true},
+        {field:"accountExpirationTime",label:PWM_ADMIN.showString("Field_Report_AccountExpireTime")},
+        {field:"passwordExpirationTime",label:PWM_ADMIN.showString("Field_Report_PwdExpireTime")},
+        {field:"passwordChangeTime",label:PWM_ADMIN.showString("Field_Report_PwdChangeTime")},
+        {field:"responseSetTime",label:PWM_ADMIN.showString("Field_Report_ResponseSaveTime")},
+        {field:"lastLoginTime",label:PWM_ADMIN.showString("Field_Report_LastLogin")},
+        {field:"hasResponses",label:PWM_ADMIN.showString("Field_Report_HasResponses")},
+        {field:"hasHelpdeskResponses",label:PWM_ADMIN.showString("Field_Report_HasHelpdeskResponses"),hidden:true},
+        {field:"responseStorageMethod",label:PWM_ADMIN.showString("Field_Report_ResponseStorageMethod"),hidden:true},
+        {field:"responseFormatType",label:PWM_ADMIN.showString("Field_Report_ResponseFormatType"),hidden:true},
+        {field:"passwordStatusExpired",label:PWM_ADMIN.showString("Field_Report_PwdExpired"),hidden:true},
+        {field:"passwordStatusPreExpired",label:PWM_ADMIN.showString("Field_Report_PwdPreExpired"),hidden:true},
+        {field:"passwordStatusViolatesPolicy",label:PWM_ADMIN.showString("Field_Report_PwdViolatesPolicy"),hidden:true},
+        {field:"passwordStatusWarnPeriod",label:PWM_ADMIN.showString("Field_Report_PwdWarnPeriod"),hidden:true},
+        {field:"requiresPasswordUpdate",label:PWM_ADMIN.showString("Field_Report_RequiresPasswordUpdate")},
+        {field:"requiresResponseUpdate",label:PWM_ADMIN.showString("Field_Report_RequiresResponseUpdate")},
+        {field:"requiresProfileUpdate",label:PWM_ADMIN.showString("Field_Report_RequiresProfileUpdate")},
+        {field:"cacheTimestamp",label:PWM_ADMIN.showString("Field_Report_RecordCacheTime"),hidden:true}
+    ];
 };
 
 PWM_ADMIN.initReportDataGrid=function() {
@@ -153,20 +153,6 @@ PWM_ADMIN.initReportDataGrid=function() {
             // Now, create an instance of our custom grid
             PWM_VAR['reportGrid'] = new CustomGrid({columns: columnHeaders}, "grid");
 
-            // unclick superfluous fields
-            PWM_MAIN.getObject('grid-hider-menu-check-cacheTimestamp').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-ldapProfile').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-email').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-userGUID').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-responseStorageMethod').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-responseFormatType').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-userDN').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-hasHelpdeskResponses').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-passwordStatusExpired').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-passwordStatusPreExpired').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-passwordStatusViolatesPolicy').click();
-            PWM_MAIN.getObject('grid-hider-menu-check-passwordStatusWarnPeriod').click();
-
             PWM_VAR['reportGrid'].on(".dgrid-row:click", function(evt){
                 PWM_ADMIN.detailView(evt, PWM_ADMIN.reportDataHeaders(), PWM_VAR['reportGrid']);
             });
@@ -280,36 +266,36 @@ PWM_ADMIN.reportAction=function(action) {
     confirmText = PWM_ADMIN.showString('Confirm_Report_' + action);
     actionText = PWM_ADMIN.showString('Display_Report_Action_' + action);
     PWM_MAIN.showConfirmDialog({text:confirmText,okAction:function(){
-        PWM_MAIN.showWaitDialog({title:PWM_MAIN.showString('Display_PleaseWait'),text:actionText,loadFunction:function(){
-            var url = PWM_GLOBAL['url-context'] + "/private/admin";
-            url = PWM_MAIN.addParamToUrl(url, 'processAction','reportCommand');
-            url = PWM_MAIN.addParamToUrl(url, 'command',action);
-            PWM_MAIN.ajaxRequest(url,function(){
-                setTimeout(function(){
-                    PWM_ADMIN.refreshReportDataStatus();
-                    PWM_ADMIN.refreshReportDataSummary();
-                    PWM_MAIN.closeWaitDialog();
-                },7500);
-            });
+            PWM_MAIN.showWaitDialog({title:PWM_MAIN.showString('Display_PleaseWait'),text:actionText,loadFunction:function(){
+                    var url = PWM_GLOBAL['url-context'] + "/private/admin";
+                    url = PWM_MAIN.addParamToUrl(url, 'processAction','reportCommand');
+                    url = PWM_MAIN.addParamToUrl(url, 'command',action);
+                    PWM_MAIN.ajaxRequest(url,function(){
+                        setTimeout(function(){
+                            PWM_ADMIN.refreshReportDataStatus();
+                            PWM_ADMIN.refreshReportDataSummary();
+                            PWM_MAIN.closeWaitDialog();
+                        },7500);
+                    });
+                }});
         }});
-    }});
 };
 
 PWM_ADMIN.webSessionHeaders = function() {
-    return {
-        "userID":PWM_ADMIN.showString('Field_Session_UserID'),
-        "ldapProfile":PWM_ADMIN.showString('Field_Session_LdapProfile'),
-        "userDN":PWM_ADMIN.showString('Field_Session_UserDN'),
-        "createTime":PWM_ADMIN.showString('Field_Session_CreateTime'),
-        "lastTime":PWM_ADMIN.showString('Field_Session_LastTime'),
-        "label":PWM_ADMIN.showString('Field_Session_Label'),
-        "idle":PWM_ADMIN.showString('Field_Session_Idle'),
-        "locale":PWM_ADMIN.showString('Field_Session_Locale'),
-        "srcAddress":PWM_ADMIN.showString('Field_Session_SrcAddress'),
-        "srcHost":PWM_ADMIN.showString('Field_Session_SrcHost'),
-        "lastUrl":PWM_ADMIN.showString('Field_Session_LastURL'),
-        "intruderAttempts":PWM_ADMIN.showString('Field_Session_IntruderAttempts')
-    };
+    return [
+        {field:"userID",label:PWM_ADMIN.showString('Field_Session_UserID')},
+        {field:"ldapProfile",label:PWM_ADMIN.showString('Field_Session_LdapProfile')},
+        {field:"userDN",label:PWM_ADMIN.showString('Field_Session_UserDN'),hidden:true},
+        {field:"createTime",label:PWM_ADMIN.showString('Field_Session_CreateTime')},
+        {field:"lastTime",label:PWM_ADMIN.showString('Field_Session_LastTime')},
+        {field:"label",label:PWM_ADMIN.showString('Field_Session_Label')},
+        {field:"idle",label:PWM_ADMIN.showString('Field_Session_Idle')},
+        {field:"locale",label:PWM_ADMIN.showString('Field_Session_Locale'),hidden:true},
+        {field:"srcAddress",label:PWM_ADMIN.showString('Field_Session_SrcAddress')},
+        {field:"srcHost",label:PWM_ADMIN.showString('Field_Session_SrcHost'),hidden:true},
+        {field:"lastUrl",label:PWM_ADMIN.showString('Field_Session_LastURL'),hidden:true},
+        {field:"intruderAttempts",label:PWM_ADMIN.showString('Field_Session_IntruderAttempts'),hidden:true}
+    ];
 };
 
 PWM_ADMIN.initActiveSessionGrid=function() {
@@ -327,14 +313,6 @@ PWM_ADMIN.initActiveSessionGrid=function() {
                 columns: columnHeaders
             }, "activeSessionGrid");
 
-            // unclick superfluous fields
-            PWM_MAIN.getObject('activeSessionGrid-hider-menu-check-label').click();
-            PWM_MAIN.getObject('activeSessionGrid-hider-menu-check-userDN').click();
-            PWM_MAIN.getObject('activeSessionGrid-hider-menu-check-srcHost').click();
-            PWM_MAIN.getObject('activeSessionGrid-hider-menu-check-locale').click();
-            PWM_MAIN.getObject('activeSessionGrid-hider-menu-check-lastUrl').click();
-            PWM_MAIN.getObject('activeSessionGrid-hider-menu-check-intruderAttempts').click();
-
             PWM_ADMIN.refreshActiveSessionGrid();
 
             PWM_VAR['activeSessionsGrid'].on(".dgrid-row:click", function(evt){
@@ -358,12 +336,12 @@ PWM_ADMIN.refreshActiveSessionGrid=function() {
 };
 
 PWM_ADMIN.intruderHeaders = function(){
-    return {
-        "subject":PWM_ADMIN.showString('Field_Intruder_Subject'),
-        "timestamp":PWM_ADMIN.showString('Field_Intruder_Timestamp'),
-        "count":PWM_ADMIN.showString('Field_Intruder_Count'),
-        "status":PWM_ADMIN.showString('Field_Intruder_Status')
-    };
+    return [
+        {field:"subject",label:PWM_ADMIN.showString('Field_Intruder_Subject')},
+        {field:"timestamp",label:PWM_ADMIN.showString('Field_Intruder_Timestamp')},
+        {field:"count",label:PWM_ADMIN.showString('Field_Intruder_Count')},
+        {field:"status",label:PWM_ADMIN.showString('Field_Intruder_Status')}
+    ];
 };
 
 
@@ -417,47 +395,55 @@ PWM_ADMIN.refreshIntruderGrid=function() {
 };
 
 PWM_ADMIN.auditUserHeaders = function() {
-    return {
-        "timestamp": PWM_ADMIN.showString('Field_Audit_Timestamp'),
-        "perpetratorID": PWM_ADMIN.showString('Field_Audit_PerpetratorID'),
-        "perpetratorDN": PWM_ADMIN.showString('Field_Audit_PerpetratorDN'),
-        "perpetratorLdapProfile": PWM_ADMIN.showString('Field_Audit_PerpetratorLdapProfile'),
-        "eventCode": PWM_ADMIN.showString('Field_Audit_EventCode'),
-        "message": PWM_ADMIN.showString('Field_Audit_Message'),
-        "sourceAddress": PWM_ADMIN.showString('Field_Audit_SourceAddress'),
-        "sourceHost": PWM_ADMIN.showString('Field_Audit_SourceHost'),
-        "guid": PWM_ADMIN.showString('Field_Audit_GUID'),
-        "narrative": PWM_ADMIN.showString('Field_Audit_Narrative')
-    };
+    return [
+        {field:"timestamp",label:PWM_ADMIN.showString('Field_Audit_Timestamp')},
+        {field:"perpetratorID",label:PWM_ADMIN.showString('Field_Audit_PerpetratorID')},
+        {field:"perpetratorDN",label:PWM_ADMIN.showString('Field_Audit_PerpetratorDN'),hidden:true},
+        {field:"perpetratorLdapProfile",label:PWM_ADMIN.showString('Field_Audit_PerpetratorLdapProfile'),hidden:true},
+        {field:"eventCode",label:PWM_ADMIN.showString('Field_Audit_EventCode')},
+        {field:"message",label:PWM_ADMIN.showString('Field_Audit_Message'),hidden:true},
+        {field:"sourceAddress",label:PWM_ADMIN.showString('Field_Audit_SourceAddress')},
+        {field:"sourceHost",label:PWM_ADMIN.showString('Field_Audit_SourceHost'),hidden:true},
+        {field:"guid",label:PWM_ADMIN.showString('Field_Audit_GUID'),hidden:true},
+        {field:"narrative",label:PWM_ADMIN.showString('Field_Audit_Narrative')}
+    ];
 };
 
 PWM_ADMIN.auditHelpdeskHeaders = function() {
-    return {
-        "timestamp": PWM_ADMIN.showString('Field_Audit_Timestamp'),
-        "perpetratorID": PWM_ADMIN.showString('Field_Audit_PerpetratorID'),
-        "perpetratorDN": PWM_ADMIN.showString('Field_Audit_PerpetratorDN'),
-        "perpetratorLdapProfile": PWM_ADMIN.showString('Field_Audit_PerpetratorLdapProfile'),
-        "eventCode": PWM_ADMIN.showString('Field_Audit_EventCode'),
-        "message": PWM_ADMIN.showString('Field_Audit_Message'),
-        "targetID": PWM_ADMIN.showString('Field_Audit_TargetID'),
-        "targetDN": PWM_ADMIN.showString('Field_Audit_TargetDN'),
-        "targetLdapProfile": PWM_ADMIN.showString('Field_Audit_TargetLdapProfile'),
-        "sourceAddress": PWM_ADMIN.showString('Field_Audit_SourceAddress'),
-        "sourceHost": PWM_ADMIN.showString('Field_Audit_SourceHost'),
-        "guid": PWM_ADMIN.showString('Field_Audit_GUID'),
-        "narrative": PWM_ADMIN.showString('Field_Audit_Narrative')
-    };
+    return [
+        {field:"timestamp",label:PWM_ADMIN.showString('Field_Audit_Timestamp')},
+        {field:"perpetratorID",label:PWM_ADMIN.showString('Field_Audit_PerpetratorID')},
+        {field:"perpetratorDN",label:PWM_ADMIN.showString('Field_Audit_PerpetratorDN'),hidden:true},
+        {field:"perpetratorLdapProfile",label:PWM_ADMIN.showString('Field_Audit_PerpetratorLdapProfile'),hidden:true},
+        {field:"eventCode",label:PWM_ADMIN.showString('Field_Audit_EventCode')},
+        {field:"message",label:PWM_ADMIN.showString('Field_Audit_Message'),hidden:true},
+        {field:"targetID",label:PWM_ADMIN.showString('Field_Audit_TargetID')},
+        {field:"targetDN",label:PWM_ADMIN.showString('Field_Audit_TargetDN')},
+        {field:"targetLdapProfile",label:PWM_ADMIN.showString('Field_Audit_TargetLdapProfile')},
+        {field:"sourceAddress",label:PWM_ADMIN.showString('Field_Audit_SourceAddress')},
+        {field:"sourceHost",label:PWM_ADMIN.showString('Field_Audit_SourceHost'),hidden:true},
+        {field:"guid",label:PWM_ADMIN.showString('Field_Audit_GUID'),hidden:true},
+        {field:"narrative",label:PWM_ADMIN.showString('Field_Audit_Narrative'),hidden:true}
+    ];
 };
 
 PWM_ADMIN.auditSystemHeaders = function() {
-    return {
-        "timestamp":PWM_ADMIN.showString('Field_Audit_Timestamp'),
-        "eventCode":PWM_ADMIN.showString('Field_Audit_EventCode'),
-        "message":PWM_ADMIN.showString('Field_Audit_Message'),
-        "instance":PWM_ADMIN.showString('Field_Audit_Instance'),
-        "guid":PWM_ADMIN.showString('Field_Audit_GUID'),
-        "narrative":PWM_ADMIN.showString('Field_Audit_Narrative')
-    };
+    return [
+        {field:"timestamp",label:PWM_ADMIN.showString('Field_Audit_Timestamp')},
+        {field:"eventCode",label:PWM_ADMIN.showString('Field_Audit_EventCode')},
+        {field:"message",label:PWM_ADMIN.showString('Field_Audit_Message')},
+        {field:"instance",label:PWM_ADMIN.showString('Field_Audit_Instance'),hidden:true},
+        {field:"guid",label:PWM_ADMIN.showString('Field_Audit_GUID'),hidden:true},
+        {field:"narrative",label:PWM_ADMIN.showString('Field_Audit_Narrative'),hidden:true}
+    ];
+};
+
+PWM_ADMIN.makeGrid = function() {
+    require(["dojo","dojo/_base/declare", "dgrid/Grid", "dgrid/Keyboard", "dgrid/Selection", "dgrid/extensions/ColumnResizer", "dgrid/extensions/ColumnReorder", "dgrid/extensions/ColumnHider", "dgrid/extensions/DijitRegistry"],
+        function(dojo, declare, Grid, Keyboard, Selection, ColumnResizer, ColumnReorder, ColumnHider, DijitRegistry){
+            return declare([ Grid, Keyboard, Selection, ColumnResizer, ColumnReorder, ColumnHider, DijitRegistry ]);
+        }
+    );
 };
 
 PWM_ADMIN.initAuditGrid=function() {
@@ -471,27 +457,9 @@ PWM_ADMIN.initAuditGrid=function() {
             PWM_VAR['auditSystemGrid'] = new CustomGrid({columns: PWM_ADMIN.auditSystemHeaders()}, "auditSystemGrid");
             PWM_VAR['auditHelpdeskGrid'] = new CustomGrid({columns: PWM_ADMIN.auditHelpdeskHeaders()}, "auditHelpdeskGrid");
 
-            // unclick superfluous fields
-            PWM_MAIN.getObject('auditUserGrid-hider-menu-check-perpetratorDN').click();
-            PWM_MAIN.getObject('auditUserGrid-hider-menu-check-perpetratorLdapProfile').click();
-            PWM_MAIN.getObject('auditUserGrid-hider-menu-check-message').click();
-            PWM_MAIN.getObject('auditUserGrid-hider-menu-check-sourceHost').click();
-            PWM_MAIN.getObject('auditUserGrid-hider-menu-check-guid').click();
-            PWM_MAIN.getObject('auditUserGrid-hider-menu-check-narrative').click();
-
-            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-perpetratorDN').click();
-            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-perpetratorLdapProfile').click();
-            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-message').click();
-            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-targetDN').click();
-            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-targetLdapProfile').click();
-            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-sourceHost').click();
-            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-guid').click();
-            PWM_MAIN.getObject('auditHelpdeskGrid-hider-menu-check-narrative').click();
-
-            PWM_MAIN.getObject('auditSystemGrid-hider-menu-check-instance').click();
-            PWM_MAIN.getObject('auditSystemGrid-hider-menu-check-guid').click();
-            PWM_MAIN.getObject('auditSystemGrid-hider-menu-check-narrative').click();
-            PWM_ADMIN.refreshAuditGridData();
+            PWM_ADMIN.refreshAuditGridData(undefined,'USER');
+            PWM_ADMIN.refreshAuditGridData(undefined,'HELPDESK');
+            PWM_ADMIN.refreshAuditGridData(undefined,'SYSTEM');
 
             PWM_VAR['auditUserGrid'].on(".dgrid-row:click", function(evt){
                 PWM_ADMIN.detailView(evt, PWM_ADMIN.auditUserHeaders(), PWM_VAR['auditUserGrid']);
@@ -505,28 +473,32 @@ PWM_ADMIN.initAuditGrid=function() {
         });
 };
 
-PWM_ADMIN.refreshAuditGridData=function(maximum) {
-    PWM_VAR['auditUserGrid'].refresh();
-    PWM_VAR['auditHelpdeskGrid'].refresh();
-    PWM_VAR['auditSystemGrid'].refresh();
-    if (!maximum) {
-        maximum = 1000;
+PWM_ADMIN.refreshAuditGridData=function(maximum,type) {
+    switch (type) {
+        case 'USER':
+            var grid = PWM_VAR['auditUserGrid'];
+            break;
+
+        case 'HELPDESK':
+            var grid = PWM_VAR['auditHelpdeskGrid'];
+            break;
+
+        case 'SYSTEM':
+            var grid = PWM_VAR['auditSystemGrid'];
+            break;
     }
-    var url = PWM_MAIN.addParamToUrl(window.location.href,"processAction", "auditData");
-    url = PWM_MAIN.addParamToUrl(url,'maximum',maximum);
-    var loadFunction = function(data) {
-        PWM_VAR['auditUserGrid'].renderArray(data['data']['user']);
-        PWM_VAR['auditUserGrid'].set("sort", { attribute : 'timestamp', ascending: false, descending: true });
-        PWM_VAR['auditUserGrid'].resize();
 
-        PWM_VAR['auditHelpdeskGrid'].renderArray(data['data']['helpdesk']);
-        PWM_VAR['auditHelpdeskGrid'].set("sort", { attribute : 'timestamp', ascending: false, descending: true });
-        PWM_VAR['auditHelpdeskGrid'].resize();
+    grid.refresh();
 
-        PWM_VAR['auditSystemGrid'].renderArray(data['data']['system']);
-        PWM_VAR['auditSystemGrid'].set("sort", { attribute : 'timestamp', ascending: false, descending: true });
-        PWM_VAR['auditSystemGrid'].resize();
+    if (!maximum) {
+        maximum = 100;
+    }
 
+    var url = PWM_MAIN.addParamToUrl(window.location.href, "processAction", "auditData");
+    url = PWM_MAIN.addParamToUrl(url,'maximum',maximum);
+    url = PWM_MAIN.addParamToUrl(url,'type',type);
+    var loadFunction = function(data) {
+        grid.renderArray(data['data']['records']);
     };
     PWM_MAIN.ajaxRequest(url,loadFunction,{method:'GET'});
 };
@@ -768,8 +740,9 @@ PWM_ADMIN.detailView = function(evt, headers, grid){
     var postExecuteFunctions = [];
     for (var item in headers) {
         (function(key){
-            var value = key in row.data ? row.data[key] : '';
-            var label = headers[key];
+            var field = headers[key]['field'];
+            var label = headers[key]['label'];
+            var value = field in row.data ? row.data[field] : '';
             var id = "record-detail-" + key;
             text += '<tr><td class="key">' + label + '</td>';
             text += '<td><span id="' + id + '" style="max-height: 200px; overflow: auto; max-width: 400px" class="timestamp">';
@@ -788,10 +761,10 @@ PWM_ADMIN.detailView = function(evt, headers, grid){
     }
     text += '</table>';
     PWM_MAIN.showDialog({title:"Record Detail",text:text,showClose:true,allowMove:true,loadFunction:function(){
-        for (var i = 0; i < postExecuteFunctions.length; i++) {
-            postExecuteFunctions[i]();
-        }
-    }});
+            for (var i = 0; i < postExecuteFunctions.length; i++) {
+                postExecuteFunctions[i]();
+            }
+        }});
 };
 
 PWM_ADMIN.showString=function (key, options) {

+ 1 - 1
server/src/main/webapp/public/resources/js/configeditor-settings.js

@@ -862,7 +862,7 @@ FormTableHandler.showOptionsDialog = function(keyName, iteration) {
         }
         bodyText += '<td id="' + inputID + '-label-placeholder" class="key" title="' + PWM_CONFIG.showString('Tooltip_FormOptions_Placeholder') + '">Placeholder</td><td><input type="text" class="configStringInput" style="width:300px" id="' + inputID + 'placeholder' + '"/></td>';
         bodyText += '</tr><tr>';
-        bodyText += '<td id="' + inputID + '-label-js" class="key" title="' + PWM_CONFIG.showString('Tooltip_FormOptions_Javascript') + '">JavaScript</td><td><input type="text" class="configStringInput" style="width:300px" id="' + inputID + 'javascript' + '"/></td>';
+        bodyText += '<td id="' + inputID + '-label-js" class="key" title="' + PWM_CONFIG.showString('Tooltip_FormOptions_Javascript') + '">JavaScript (Depreciated)</td><td><input type="text" class="configStringInput" style="width:300px" id="' + inputID + 'javascript' + '"/></td>';
         bodyText += '</tr><tr>';
         if (currentValue['type'] === 'select') {
             bodyText += '<td class="key">Select Options</td><td><button id="' + inputID + 'editOptionsButton"><span class="btn-icon pwm-icon pwm-icon-list-ul"/> Edit</button></td>';

+ 97 - 0
server/src/main/webapp/public/resources/style.css

@@ -1525,6 +1525,9 @@ html[dir="rtl"] .message.message-error .errorDetail {
     white-space: nowrap;
 }
 
+/*** TABS ****/
+
+
 /*Change these values for the tab highlight color:*/
 .tab-container > .label:hover {
     color: #2D2D2D;
@@ -1533,6 +1536,100 @@ html[dir="rtl"] .message.message-error .errorDetail {
     border-right-color: #2D2D2D;
 }
 
+
+.tab-container * {
+    box-sizing: border-box;
+}
+
+.tab-container {
+    display: flex;
+    flex-wrap: wrap;
+    position: relative;
+}
+
+.input {
+    position: absolute;
+    opacity: 0;
+}
+
+.tab-container > .label {
+    background: #f6f9f8;
+    border: 1px solid #dae1e1;
+    border-bottom: transparent;
+    border-radius: 4px 4px 0 0;
+    color: #7f7f7f;
+    cursor: pointer;
+    font-size: 15px;
+    height: 31px;
+    margin-left: 5px;
+    padding: 6px 12px;
+    transition: background 0.1s, color 0.1s;
+    width: 100%;
+}
+
+.tab-container > .label:active {
+    /*background: #ccc;*/
+}
+
+.tab-container > .input:focus + .label {
+    z-index: 1;
+}
+
+.tab-container > .input:checked + .label {
+    background: #fff;
+    border: 1px solid #6a6f71;
+    border-bottom-color: transparent;
+    color: #000;
+    position: relative;
+    z-index: 100;
+}
+
+.tab-container > .input:checked + .label::after {
+    content: "";
+    background: #fff;
+    bottom: -3px;
+    height: 3px;
+    left: 0;
+    position: absolute;
+    right: 0;
+}
+
+@media (min-width: 600px) {
+    .tab-container > .label {
+        width: auto;
+    }
+}
+
+.tab-content-pane {
+    background: #fff;
+    display: none;
+    padding: 20px 30px 30px;
+    width: 100%;
+}
+
+@media (min-width: 600px) {
+    .tab-content-pane {
+        order: 99;
+    }
+}
+
+.input:checked + .label + .tab-content-pane {
+    display: block;
+}
+
+.tab-container > .tab-end {
+    border-bottom: 1px solid #6a6f71;
+    left: 0;
+    width: 100%;
+}
+
+/*This targets only IE*/
+@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
+    .tab-container > .tab-end {
+        height: 7px;
+    }
+}
+
 table.ias-table, table.ias-table td {
     border: none;
 }

+ 0 - 114
server/src/main/webapp/public/resources/tab-container.css

@@ -1,114 +0,0 @@
-/*
- * 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
- */
-
-.tab-container * {
-    box-sizing: border-box;
-}
-
-.tab-container {
-    display: flex;
-    flex-wrap: wrap;
-    position: relative;
-}
-
-.input {
-    position: absolute;
-    opacity: 0;
-}
-
-.tab-container > .label {
-    background: #f6f9f8;
-    border: 1px solid #dae1e1;
-    border-bottom: transparent;
-    border-radius: 4px 4px 0 0;
-    color: #7f7f7f;
-    cursor: pointer;
-    font-size: 15px;
-    height: 31px;
-    margin-left: 5px;
-    padding: 6px 12px;
-    transition: background 0.1s, color 0.1s;
-    width: 100%;
-}
-
-.tab-container > .label:active {
-    /*background: #ccc;*/
-}
-
-.tab-container > .input:focus + .label {
-    z-index: 1;
-}
-
-.tab-container > .input:checked + .label {
-    background: #fff;
-    border: 1px solid #6a6f71;
-    border-bottom-color: transparent;
-    color: #000;
-    position: relative;
-    z-index: 100;
-}
-
-.tab-container > .input:checked + .label::after {
-    content: "";
-    background: #fff;
-    bottom: -3px;
-    height: 3px;
-    left: 0;
-    position: absolute;
-    right: 0;
-}
-
-@media (min-width: 600px) {
-    .tab-container > .label {
-        width: auto;
-    }
-}
-
-.tab-content-pane {
-    background: #fff;
-    display: none;
-    padding: 20px 30px 30px;
-    width: 100%;
-}
-
-@media (min-width: 600px) {
-    .tab-content-pane {
-        order: 99;
-    }
-}
-
-.input:checked + .label + .tab-content-pane {
-    display: block;
-}
-
-.tab-container > .tab-end {
-    border-bottom: 1px solid #6a6f71;
-    left: 0;
-    width: 100%;
-}
-
-/*This targets only IE*/
-@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
-    .tab-container > .tab-end {
-        height: 7px;
-    }
-}

+ 23 - 0
server/src/main/webapp/public/resources/themes/pwm/style.css

@@ -164,3 +164,26 @@ h3 {
     border: 1px solid transparent;
     box-shadow: 0 0 0 0 white, 0 0 0 0 white, 9px 0 12px -4px #B2B1B9, -9px 0 12px -4px #B2B1B9;
 }
+
+.tab-container > .tab-end {
+    border-bottom: 1px solid #E8E1F6;
+}
+
+.tab-container > .input:checked + .label {
+    border: 1px solid #E8E1F6;
+    color: #808080;
+}
+
+.tab-container > .label {
+    font-size: 14px;
+    height: 25px;
+    padding-top: 3px;
+}
+
+.tab-container > .label:hover {
+    color: #808080;
+    border-top-color: #E8E1F6;
+    border-left-color: #E8E1F6;
+    border-right-color: #E8E1F6;
+}
+