You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by sm...@apache.org on 2014/11/11 21:35:34 UTC

[24/27] directory-fortress-commander git commit: change package structure and names, pom improvements, license

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/UserPage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/UserPage.java b/src/main/java/org/apache/directory/fortress/web/UserPage.java
new file mode 100644
index 0000000..8bb5157
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/UserPage.java
@@ -0,0 +1,74 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.web;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.directory.fortress.web.panel.Displayable;
+import org.apache.directory.fortress.web.panel.InfoPanel;
+import org.apache.directory.fortress.web.panel.NavPanel;
+import org.apache.directory.fortress.web.panel.UserDetailPanel;
+import org.apache.directory.fortress.web.panel.UserListPanel;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ */
+public class UserPage extends FortressWebBasePage
+{
+
+    public UserPage()
+    {
+        add(new Label(GlobalIds.PAGE_HEADER, "User Administration"));
+        WebMarkupContainer container = new WebMarkupContainer(GlobalIds.LAYOUT);
+        FourWaySplitter splitter = new FourWaySplitter();
+        splitter.addBorderLayout(container);
+
+        // Add the four necessary panels for Commander Page: 1. Nav,, 2. List, 3. Info, 4. Detail.
+        // Nav and info are generic and work across all entities, the others are specific to this entity type.
+
+        // 1. Nav Panel:
+        NavPanel navPanel = new NavPanel(GlobalIds.NAVPANEL);
+        container.add(navPanel);
+
+        // 2. List Panel:
+        container.add(new AjaxLazyLoadPanel("userlistpanel")
+        {
+          @Override
+          public Component getLazyLoadComponent(String id)
+          {
+               return new UserListPanel(id);
+          }
+        });
+
+        // 3. Info Panel:
+        InfoPanel infoPanel = new InfoPanel( GlobalIds.INFOPANEL );
+        Displayable display = infoPanel.getDisplay();
+        container.add(infoPanel);
+
+        // 4. Detail Panel:
+        UserDetailPanel userDetail = new UserDetailPanel("userdetailpanel", display );
+        container.add(userDetail);
+
+        this.add(container);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/overview.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/overview.html b/src/main/java/org/apache/directory/fortress/web/overview.html
new file mode 100755
index 0000000..4108161
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/overview.html
@@ -0,0 +1,59 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License.
+-->
+<html>
+   <head>
+      <title>Overview of the org.apache.directory.fortress.web component</title>
+   </head>
+   <body>
+       Fortress Web is a web application that interface with <A HREF="https://symas.com/javadocs/fortress/">Fortress</A> and a directory server like <A HREF="http://www.openldap.org/">OpenLDAP</A> or <A HREF="http://directory.apache.org/apacheds/">ApacheDS</A>.
+
+       <h2>What technologies are in use?</h2>
+
+       Fortress Web was built using established <A HREF="http://www.opensource.org/">Open Source</A> technologies including
+       <A HREF="http://wicket.apache.org//">Apache Wicket</A> (Web UI framework), <A HREF="http://www.springsource.org/">Spring Framework</A> (glue), <A HREF="http://maven.apache.org/">Maven</A> (dependencies)
+       and runs inside any reasonably compliant Java Servlets container.
+
+       Access control decisions are enforced using <A HREF="https://symas.com/javadocs/sentry/">Fortress Realm</A> which itself
+       uses declarative <A HREF="http://docs.oracle.com/javaee/5/tutorial/doc/bnbwk.html">Java EE Security</A> and <A HREF="http://static.springsource.org/spring-security/site/">Spring Security</A> policy hooks that are wired to
+       connect back to the <A HREF="https://symas.com/javadocs/fortress/org/openldap/fortress/rbac/package-summary.html">Fortress Core</A> <A HREF="http://en.wikipedia.org/wiki/Role-based_access_control">RBAC</A> component.
+
+       Fine-grained access control decisions are enforced using <A HREF="https://symas.com/javadocs/fortress/org/openldap/fortress/DelAccessMgr.html">Fortress ARBAC delegated access management.</A>
+
+       Commander server-side is a <a href="http://java.sun.com/developer/technicalArticles/tools/webapps_1/">Java Web program</a> artifact and is wholly dependent on <A HREF="http://www.jts.us/iamfortress/javadocs/api/index.html">Fortress</A>
+       but also needs a <A HREF="http://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol">V3 compliant LDAP</A> server like OpenLDAP.  For more information on installing and setting up OpenLDAP check out
+       <A HREF="http://directory.apache.org/fortress/quick-start/apacheds/apacheds.html">Fortress ApacheDS Quickstart</A>
+
+       <h2>What can Fortress Web do?</h2>
+
+       Contained within this application are Web pages to perform ANSI RBAC administration along with IETF password policies and viewing the security audit trail and history of changes.
+
+      <h2>What are the conditions of use?</h2>
+      <p>
+          This software development kit is open source, thus free to use and distribute via the <a href="http://www.apache.org/licenses/">Apache License, Version 2.0</a>.
+          It was developed and tested on open systems like <a href="http://www.ubuntu.com/">Ubuntu</a> and <a href="http://www.centos.org/">Centos</a> and was helped along
+          by the following open source products:
+       <ol>
+           <li><a href="http://www.openldap.org/project/">The OpenLDAP Project</a></li>
+           <li><a href="http://www.apache.org/">The Apache Software Foundation</a></li>
+           <li><a href="http://www.eigenbase.org/">The Eigenbase Project</a></li>
+           <li><a href="http://ehcache.org/">Ehcache</a></li>
+       </ol>
+      </p>
+   </body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/AuditAuthzDetailPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/AuditAuthzDetailPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/AuditAuthzDetailPanel.java
new file mode 100644
index 0000000..fc00627
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/AuditAuthzDetailPanel.java
@@ -0,0 +1,144 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.core.*;
+import org.apache.directory.fortress.core.rbac.AuthZ;
+import org.apache.directory.fortress.core.rbac.User;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ * Date: 8/6/13
+ */
+public class AuditAuthzDetailPanel extends FormComponentPanel
+{
+    @SpringBean
+    private AuditMgr auditMgr;
+    @SpringBean
+    private ReviewMgr reviewMgr;
+    private static final Logger LOG = Logger.getLogger(AuditAuthzDetailPanel.class.getName());
+    private Form detailForm;
+    private Displayable display;
+    private UserAuditDetailPanel userPanel;
+
+    public Form getForm()
+    {
+        return this.detailForm;
+    }
+
+    public AuditAuthzDetailPanel( String id, Displayable display )
+    {
+        super(id);
+        this.auditMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        this.reviewMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        this.detailForm = new AuditAuthzDetailForm(GlobalIds.DETAIL_FIELDS, new CompoundPropertyModel<AuthZ>(new AuthZ()));
+        this.display = display;
+        add( detailForm );
+    }
+
+    public class AuditAuthzDetailForm extends Form
+    {
+        private Component component;
+
+        public AuditAuthzDetailForm(String id, final IModel<AuthZ> model)
+        {
+            super(id, model);
+            add( new Label( GlobalIds.REQ_RESULT ) );
+            add(  new Label( GlobalIds.REQ_START ) );
+            add( new Label( GlobalIds.REQ_ATTR ) );
+            add( new Label( GlobalIds.REQ_ATTRS_ONLY ) );
+            add( new Label( GlobalIds.REQ_DEREF_ALIASES ) );
+            userPanel = new UserAuditDetailPanel( GlobalIds.USERAUDITDETAILPANEL, new CompoundPropertyModel<User>(new User()) );
+            add( userPanel );
+            setOutputMarkupId( true );
+        }
+
+        @Override
+        public void onEvent(final IEvent<?> event)
+        {
+            if (event.getPayload() instanceof SelectModelEvent )
+            {
+                SelectModelEvent modelEvent = (SelectModelEvent) event.getPayload();
+                AuthZ authZ = (AuthZ) modelEvent.getEntity();
+                this.setModelObject(authZ);
+                String msg = "AuthZ: " + authZ.getReqAuthzID() + " has been selected";
+                LOG.debug( ".onEvent SelectModelEvent: " + authZ.getReqAuthzID() );
+                GlobalUtils.getAuthZPerm(authZ.getReqDN() );
+                display.setMessage(msg);
+                component = detailForm;
+
+            }
+            else if (event.getPayload() instanceof AjaxRequestTarget)
+            {
+                // only add the form to ajax target if something has changed...
+                if (component != null)
+                {
+                    AjaxRequestTarget target = ((AjaxRequestTarget) event.getPayload());
+                    LOG.debug( ".onEvent AjaxRequestTarget: " + target.toString() );
+                    target.add(component);
+                    component = null;
+                }
+                display.display((AjaxRequestTarget) event.getPayload());
+            }
+        }
+
+        @Override
+        protected void onBeforeRender()
+        {
+            if ( getModel() != null )
+            {
+                User user = null;
+                // necessary to push the 'changed' model down into the aggregated panel:
+                AuthZ authZ = (AuthZ)detailForm.getModelObject();
+                if( VUtil.isNotNullOrEmpty( authZ.getReqAuthzID() ))
+                {
+                    user = GlobalUtils.getUser(reviewMgr, authZ.getReqAuthzID());
+                }
+                if(user == null)
+                {
+                    user = new User();
+                }
+                IModel<User> userModel = new CompoundPropertyModel<User>(user);
+                userPanel.setDefaultModel( userModel );
+            }
+            else
+            {
+                LOG.info( ".onBeforeRender null model object" );
+            }
+            super.onBeforeRender();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/AuditAuthzListPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/AuditAuthzListPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/AuditAuthzListPanel.java
new file mode 100644
index 0000000..ff21e3d
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/AuditAuthzListPanel.java
@@ -0,0 +1,525 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import com.googlecode.wicket.kendo.ui.form.datetime.DatePicker;
+import com.inmethod.grid.IGridColumn;
+import com.inmethod.grid.SizeUnit;
+import com.inmethod.grid.column.PropertyColumn;
+import com.inmethod.grid.treegrid.TreeGrid;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.CheckBox;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.directory.fortress.web.AuditAuthzListModel;
+import org.apache.directory.fortress.web.AuditAuthzPage;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.SecureIndicatingAjaxButton;
+import org.apache.directory.fortress.web.SecureIndicatingAjaxLink;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.directory.fortress.core.rbac.AuthZ;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.Model;
+import org.apache.directory.fortress.core.rbac.Permission;
+import org.apache.directory.fortress.core.rbac.User;
+import org.apache.directory.fortress.core.rbac.UserAudit;
+import org.apache.directory.fortress.core.util.attr.AttrHelper;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ * Date: 8/6/13
+ */
+public class AuditAuthzListPanel extends FormComponentPanel
+{
+    private static final Logger LOG = Logger.getLogger(AuditAuthzListPanel.class.getName());
+    private Form listForm;
+    private DefaultTreeModel treeModel;
+    private DefaultMutableTreeNode node;
+    private TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String> grid;
+    private DefaultMutableTreeNode rootNode;
+    private TextField userFld;
+    private TextField objFld;
+    private TextField opFld;
+    protected DatePicker beginDateDP;
+    protected DatePicker endDateDP;
+    private Permission permission;
+    private IModel<AuditAuthzListModel> pageModel;
+
+    public AuditAuthzListPanel(String id, UserAudit userAudit )
+    {
+        super(id);
+        init( userAudit );
+    }
+
+    private void init( UserAudit userAudit )
+    {
+        pageModel = new AuditAuthzListModel(userAudit, GlobalUtils.getRbacSession( this ) );
+        setDefaultModel(pageModel);
+        createAndLoadGrid();
+        this.listForm = new Form("authzform");
+        this.listForm.addOrReplace(grid);
+        this.listForm.setModel( new CompoundPropertyModel<UserAudit>( userAudit ) );
+        addEditFields();
+        addButtons();
+        add(this.listForm);
+    }
+
+    private void addEditFields()
+    {
+        userFld = new TextField(GlobalIds.USER_ID);
+        userFld.setOutputMarkupId( true );
+        AjaxFormComponentUpdatingBehavior ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( userFld );
+          }
+        };
+        userFld.add( ajaxUpdater );
+        this.listForm.add(userFld);
+        addUserSearchModal();
+
+        objFld = new TextField( GlobalIds.OBJ_NAME );
+        objFld.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( objFld );
+          }
+        };
+        objFld.add( ajaxUpdater );
+        this.listForm.add( objFld );
+
+        opFld = new TextField( GlobalIds.OP_NAME );
+        opFld.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( opFld );
+          }
+        };
+        opFld.add( ajaxUpdater );
+        this.listForm.add( opFld );
+
+        final CheckBox isAdminCB = new CheckBox( GlobalIds.ADMIN );
+        isAdminCB.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( isAdminCB );
+          }
+        };
+        isAdminCB.add( ajaxUpdater );
+        isAdminCB.setRequired( false );
+        this.listForm.add( isAdminCB );
+        addPermSearchModal();
+
+        final CheckBox failedOnlyCB = new CheckBox( GlobalIds.FAILED_ONLY );
+        failedOnlyCB.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( failedOnlyCB );
+          }
+        };
+        failedOnlyCB.add( ajaxUpdater );
+        failedOnlyCB.setRequired( false );
+        this.listForm.add( failedOnlyCB );
+
+        // TODO: fortress auditMgr authz search doesn't work with this flag:
+        failedOnlyCB.setEnabled( false );
+
+        // Begin Date
+        beginDateDP = new DatePicker(GlobalIds.BEGIN_DATE);
+        beginDateDP.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( beginDateDP );
+          }
+        };
+        beginDateDP.add( ajaxUpdater );
+        beginDateDP.setRequired( false );
+        this.listForm.add( beginDateDP );
+
+        // End Date
+        endDateDP = new DatePicker(GlobalIds.END_DATE);
+        endDateDP.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( endDateDP );
+          }
+        };
+        endDateDP.add( ajaxUpdater );
+        endDateDP.setRequired( false );
+        this.listForm.add( endDateDP );
+    }
+
+    private void addButtons()
+    {
+        this.listForm.add(new SecureIndicatingAjaxButton( GlobalIds.SEARCH, GlobalIds.AUDIT_MGR, GlobalIds.GET_USER_AUTHZS )
+        {
+            @Override
+            protected void onSubmit(AjaxRequestTarget target, Form form)
+            {
+                LOG.debug( ".search onSubmit" );
+                UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                if(!VUtil.isNotNullOrEmpty(userAudit.getUserId()))
+                {
+                    userAudit.setUserId( "" );
+                }
+                if(permission != null)
+                {
+                    userAudit.setDn( permission.getDn() );
+                }
+                setResponsePage( new AuditAuthzPage( userAudit ) );
+            }
+
+            @Override
+            public void onError(AjaxRequestTarget target, Form form)
+            {
+                LOG.warn( ".search.onError" );
+                throw new RuntimeException( "error submitting form" );
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        });
+        this.listForm.add(new AjaxSubmitLink(GlobalIds.CLEAR)
+        {
+            @Override
+            protected void onSubmit(AjaxRequestTarget target, Form form)
+            {
+                setResponsePage( new AuditAuthzPage( new UserAudit() ) );
+            }
+
+            @Override
+            public void onError(AjaxRequestTarget target, Form form)
+            {
+                LOG.warn("AuditAuthzListPanel.clear.onError");
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        });
+    }
+
+    private void createAndLoadGrid()
+    {
+        List<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>> columns =
+            new ArrayList<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>>();
+        PropertyColumn reqStart = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Timestamp"), "userObject.reqStart");
+        reqStart.setInitialSize(200);
+        columns.add(reqStart);
+
+        PropertyColumn requAuthzId = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("User ID"), "userObject.reqAuthzID");
+        requAuthzId.setInitialSize(200);
+        columns.add(requAuthzId);
+
+        PropertyColumn reqAttr = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Object Name"), "userObject.reqAttr");
+        reqAttr.setInitialSize(300);
+        columns.add(reqAttr);
+
+        PropertyColumn reqDerefAliases = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Object ID"), "userObject.reqDerefAliases");
+        reqDerefAliases.setInitialSize(100);
+        columns.add(reqDerefAliases);
+
+        PropertyColumn reqAttrsOnly = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Operation"), "userObject.reqAttrsOnly");
+        reqAttrsOnly.setInitialSize(120);
+        columns.add(reqAttrsOnly);
+
+        PropertyColumn reqResult = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Result"), "userObject.reqResult");
+        reqResult.setInitialSize(80);
+        columns.add(reqResult);
+
+        List<AuthZ> authZs = (List<AuthZ>) getDefaultModel().getObject();
+        treeModel = createTreeModel(authZs);
+        grid = new TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String>("authztreegrid", treeModel, columns)
+        {
+            @Override
+            public void selectItem(IModel itemModel, boolean selected)
+            {
+                node = (DefaultMutableTreeNode) itemModel.getObject();
+                if(!node.isRoot())
+                {
+                    AuthZ authZ = (AuthZ) node.getUserObject();
+                    LOG.debug( "TreeGrid.addGrid.selectItem selected authZ =" + authZ.getReqAuthzID() );
+                    if (super.isItemSelected(itemModel))
+                    {
+                        LOG.debug( "TreeGrid.addGrid.selectItem item is selected" );
+                        super.selectItem(itemModel, false);
+                    }
+                    else
+                    {
+                        super.selectItem(itemModel, true);
+                        SelectModelEvent.send(getPage(), this, authZ);
+                    }
+                }
+            }
+        };
+
+        grid.setContentHeight(50, SizeUnit.EM);
+        grid.setAllowSelectMultiple(false);
+        grid.setClickRowToSelect(true);
+        grid.setClickRowToDeselect(false);
+        grid.setSelectToEdit(false);
+        // expand the root node
+        grid.getTreeState().expandNode((TreeNode) treeModel.getRoot());
+        grid.setOutputMarkupId(true);
+    }
+
+    private void addUserSearchModal()
+    {
+        final ModalWindow usersModalWindow;
+        listForm.add( usersModalWindow = new ModalWindow( "usersearchmodal" ) );
+        final UserSearchModalPanel userSearchModalPanel = new UserSearchModalPanel( usersModalWindow.getContentId(), usersModalWindow );
+        usersModalWindow.setContent( userSearchModalPanel );
+        usersModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                User userSelection = userSearchModalPanel.getUserSelection();
+                if ( userSelection != null )
+                {
+                    LOG.debug( "modal selected:" + userSelection.getUserId() );
+                    UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                    userAudit.setUserId( userSelection.getUserId() );
+                    target.add( userFld );
+                }
+            }
+        } );
+        listForm.add( new SecureIndicatingAjaxLink( "userAssignLinkLbl", GlobalIds.REVIEW_MGR, GlobalIds.FIND_USERS )
+        {
+            public void onClick( AjaxRequestTarget target )
+            {
+                UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                String msg = "clicked on users search";
+                msg += "userSelection: " + userAudit.getUserId();
+                userSearchModalPanel.setSearchVal( userAudit.getUserId() );
+                LOG.debug( msg );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                usersModalWindow.show( target );
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+        usersModalWindow.setTitle( "User Search Modal" );
+        usersModalWindow.setInitialWidth( 1000 );
+        usersModalWindow.setInitialHeight( 700 );
+        usersModalWindow.setCookieName( "user-search-modal" );
+    }
+
+    private void addPermSearchModal()
+    {
+        final ModalWindow permsModalWindow;
+        UserAudit userAudit = (UserAudit)listForm.getModelObject();
+        listForm.add( permsModalWindow = new ModalWindow( "permsearchmodal" ) );
+        final PermSearchModalPanel permSearchModalPanel = new PermSearchModalPanel( permsModalWindow.getContentId(), permsModalWindow, userAudit.isAdmin() );
+        permsModalWindow.setContent( permSearchModalPanel );
+        permsModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                Permission permSelection = permSearchModalPanel.getSelection();
+                if ( permSelection != null )
+                {
+                    UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                    LOG.debug( "modal selected:" + permSelection.getAbstractName() );
+                    permission = permSelection;
+                    userAudit.setObjName( permSelection.getObjName() );
+                    userAudit.setOpName( permSelection.getOpName() );
+                    target.add( objFld );
+                    target.add( opFld );
+                }
+            }
+        } );
+        listForm.add( new SecureIndicatingAjaxLink( "permLinkLbl", GlobalIds.REVIEW_MGR, GlobalIds.FIND_PERMISSIONS )
+        {
+            public void onClick( AjaxRequestTarget target )
+            {
+                UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                String msg = "clicked on perms search";
+                msg += "permSelection: " + permission;
+                permSearchModalPanel.setSearchVal( userAudit.getObjName() );
+                permSearchModalPanel.setAdmin( userAudit.isAdmin() );
+                LOG.debug( msg );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                permsModalWindow.show( target );
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+        String title;
+        if(userAudit.isAdmin())
+            title = "Admin Permission Search Modal";
+        else
+            title = "RBAC Permission Search Modal";
+
+        permsModalWindow.setTitle( title );
+        permsModalWindow.setInitialWidth( 650 );
+        permsModalWindow.setInitialHeight( 450 );
+        permsModalWindow.setCookieName( "perm-search-modal" );
+    }
+
+    private DefaultTreeModel createTreeModel(List<AuthZ> authZs)
+    {
+        DefaultTreeModel model;
+        AuthZ root = new AuthZ();
+        //root.setReqStart( "Authorizations" );
+        rootNode = new DefaultMutableTreeNode(root);
+        model = new DefaultTreeModel(rootNode);
+        if (authZs == null)
+            LOG.debug("no Authorizations found");
+        else
+        {
+            LOG.debug("AuthZ found:" + authZs.size());
+            info("Loading " + authZs.size() + " objects into list panel");
+            loadTree( authZs );
+        }
+        return model;
+    }
+
+    private void loadTree(List<AuthZ> authZs)
+    {
+        for (AuthZ authZ : authZs)
+        {
+            Date start = null;
+            try
+            {
+                start = AttrHelper.decodeGeneralizedTime( authZ.getReqStart() );
+            }
+            catch (ParseException pe)
+            {
+                LOG.warn( "ParseException=" + pe.getMessage() );
+            }
+            if(start != null)
+            {
+                SimpleDateFormat formatter = new SimpleDateFormat( GlobalIds.AUDIT_TIMESTAMP_FORMAT );
+                String formattedDate = formatter.format(start);
+                authZ.setReqStart( formattedDate );
+            }
+            authZ.setReqResult( GlobalIds.FAILURE );
+/*
+            TODO: On RC40 - Replace above line with the following:
+            if(VUtil.isNotNullOrEmpty( authZ.getReqAssertion() ) && (authZ.getReqAssertion().equals( org.apache.directory.fortress.core.GlobalIds.AUTH_Z_FAILED_VALUE ) ) )
+            {
+                authZ.setReqResult( GlobalIds.FAILURE );
+            }
+            else
+            {
+                authZ.setReqResult( GlobalIds.SUCCESS );
+            }
+*/
+            authZ.setReqAuthzID( GlobalUtils.getAuthZId( authZ.getReqAuthzID() ) );
+            GlobalUtils.mapAuthZPerm( authZ );
+            rootNode.add(new DefaultMutableTreeNode(authZ));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/AuditBindDetailPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/AuditBindDetailPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/AuditBindDetailPanel.java
new file mode 100644
index 0000000..1ad04d9
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/AuditBindDetailPanel.java
@@ -0,0 +1,141 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.core.*;
+import org.apache.directory.fortress.core.rbac.Bind;
+import org.apache.directory.fortress.core.rbac.User;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ * Date: 8/11/13
+ */
+public class AuditBindDetailPanel extends FormComponentPanel
+{
+    @SpringBean
+    private AuditMgr auditMgr;
+    @SpringBean
+    private ReviewMgr reviewMgr;
+    private static final Logger LOG = Logger.getLogger(AuditBindDetailPanel.class.getName());
+    private Form detailForm;
+    private Displayable display;
+    private UserAuditDetailPanel userPanel;
+
+    public Form getForm()
+    {
+        return this.detailForm;
+    }
+
+    public AuditBindDetailPanel( String id, Displayable display )
+    {
+        super(id);
+        this.auditMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        this.reviewMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        this.detailForm = new AuditBindDetailForm( GlobalIds.DETAIL_FIELDS, new CompoundPropertyModel<Bind>(new Bind()));
+        this.display = display;
+        add( detailForm );
+    }
+
+    public class AuditBindDetailForm extends Form
+    {
+        private Component component;
+
+        public AuditBindDetailForm(String id, final IModel<Bind> model)
+        {
+            super(id, model);
+            add( new Label( GlobalIds.REQ_DN ) );
+            add( new Label( GlobalIds.REQ_RESULT ) );
+            add(  new Label( GlobalIds.REQ_START ) );
+            userPanel = new UserAuditDetailPanel( GlobalIds.USERAUDITDETAILPANEL, new CompoundPropertyModel<User>(new User()) );
+            add( userPanel );
+            setOutputMarkupId( true );
+        }
+
+        @Override
+        public void onEvent(final IEvent<?> event)
+        {
+            if (event.getPayload() instanceof SelectModelEvent )
+            {
+                SelectModelEvent modelEvent = (SelectModelEvent) event.getPayload();
+                Bind bind = (Bind) modelEvent.getEntity();
+                this.setModelObject(bind);
+                String msg = "Bind: " + bind.getReqDN() + " has been selected";
+                LOG.debug( ".onEvent SelectModelEvent: " + bind.getReqDN() );
+                display.setMessage(msg);
+                component = detailForm;
+
+            }
+            else if (event.getPayload() instanceof AjaxRequestTarget)
+            {
+                // only add the form to ajax target if something has changed...
+                if (component != null)
+                {
+                    AjaxRequestTarget target = ((AjaxRequestTarget) event.getPayload());
+                    LOG.debug( ".onEvent AjaxRequestTarget: " + target.toString() );
+                    target.add(component);
+                    component = null;
+                }
+                display.display((AjaxRequestTarget) event.getPayload());
+            }
+        }
+
+        @Override
+        protected void onBeforeRender()
+        {
+            if ( getModel() != null )
+            {
+                User user = null;
+                // necessary to push the 'changed' model down into the aggregated panel:
+                Bind bind = (Bind)detailForm.getModelObject();
+                if( VUtil.isNotNullOrEmpty( bind.getReqDN() ))
+                {
+                    user = GlobalUtils.getUser(reviewMgr, bind.getReqDN());
+                }
+                if(user == null)
+                {
+                    user = new User();
+                }
+                IModel<User> userModel = new CompoundPropertyModel<User>(user);
+                userPanel.setDefaultModel( userModel );
+            }
+            else
+            {
+                LOG.info( ".onBeforeRender null model object" );
+            }
+            super.onBeforeRender();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/AuditBindListPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/AuditBindListPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/AuditBindListPanel.java
new file mode 100644
index 0000000..87457b3
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/AuditBindListPanel.java
@@ -0,0 +1,387 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import com.googlecode.wicket.kendo.ui.form.datetime.DatePicker;
+import com.inmethod.grid.IGridColumn;
+import com.inmethod.grid.SizeUnit;
+import com.inmethod.grid.column.PropertyColumn;
+import com.inmethod.grid.treegrid.TreeGrid;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.CheckBox;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.directory.fortress.web.AuditBindListModel;
+import org.apache.directory.fortress.web.AuditBindPage;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.SecureIndicatingAjaxButton;
+import org.apache.directory.fortress.web.SecureIndicatingAjaxLink;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.Model;
+import org.apache.directory.fortress.core.rbac.Bind;
+import org.apache.directory.fortress.core.rbac.User;
+import org.apache.directory.fortress.core.rbac.UserAudit;
+import org.apache.directory.fortress.core.util.attr.AttrHelper;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ * Date: 8/11/13
+ */
+public class AuditBindListPanel extends FormComponentPanel
+{
+    private static final Logger LOG = Logger.getLogger(AuditBindListPanel.class.getName());
+    private Form listForm;
+    private DefaultTreeModel treeModel;
+    private DefaultMutableTreeNode node;
+    private TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String> grid;
+    private DefaultMutableTreeNode rootNode;
+    private TextField userFld;
+    protected DatePicker beginDateDP;
+    protected DatePicker endDateDP;
+    private IModel<AuditBindListModel> pageModel;
+
+    public AuditBindListPanel(String id, UserAudit userAudit )
+    {
+        super( id );
+        init( userAudit );
+    }
+
+    private void init( UserAudit userAudit )
+    {
+        pageModel = new AuditBindListModel(userAudit, GlobalUtils.getRbacSession( this ) );
+        setDefaultModel(pageModel);
+        createAndLoadGrid();
+        this.listForm = new Form("bindform");
+        this.listForm.addOrReplace(grid);
+        this.listForm.setModel( new CompoundPropertyModel<UserAudit>( userAudit ) );
+        addEditFields();
+        addButtons();
+        add(this.listForm);
+    }
+
+    private void addEditFields()
+    {
+        userFld = new TextField(GlobalIds.USER_ID);
+        userFld.setOutputMarkupId( true );
+        AjaxFormComponentUpdatingBehavior ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( userFld );
+          }
+        };
+        userFld.add( ajaxUpdater );
+        this.listForm.add(userFld);
+        addUserSearchModal();
+
+        final CheckBox failedOnlyCB = new CheckBox( GlobalIds.FAILED_ONLY );
+        failedOnlyCB.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( failedOnlyCB );
+          }
+        };
+        failedOnlyCB.add( ajaxUpdater );
+        failedOnlyCB.setRequired( false );
+        this.listForm.add( failedOnlyCB );
+
+        // Begin Date
+        beginDateDP = new DatePicker(GlobalIds.BEGIN_DATE);
+        beginDateDP.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( beginDateDP );
+          }
+        };
+        beginDateDP.add( ajaxUpdater );
+        beginDateDP.setRequired( false );
+        this.listForm.add( beginDateDP );
+
+        // End Date
+        endDateDP = new DatePicker(GlobalIds.END_DATE);
+        endDateDP.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( endDateDP );
+          }
+        };
+        endDateDP.add( ajaxUpdater );
+        endDateDP.setRequired( false );
+        this.listForm.add( endDateDP );
+    }
+
+    private void addButtons()
+    {
+        this.listForm.add(new SecureIndicatingAjaxButton( GlobalIds.SEARCH, GlobalIds.AUDIT_MGR, GlobalIds.GET_USER_BINDS )
+        {
+            @Override
+            protected void onSubmit(AjaxRequestTarget target, Form form)
+            {
+                LOG.debug( ".search onSubmit" );
+                UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                if(!VUtil.isNotNullOrEmpty(userAudit.getUserId()))
+                {
+                    userAudit.setUserId( "" );
+                }
+                setResponsePage( new AuditBindPage( userAudit ) );
+            }
+
+            @Override
+            public void onError(AjaxRequestTarget target, Form form)
+            {
+                LOG.warn( ".search.onError" );
+                throw new RuntimeException( "error submitting form" );
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        });
+        this.listForm.add(new AjaxSubmitLink(GlobalIds.CLEAR)
+        {
+            @Override
+            protected void onSubmit(AjaxRequestTarget target, Form form)
+            {
+                setResponsePage( new AuditBindPage( new UserAudit() ) );
+            }
+
+            @Override
+            public void onError(AjaxRequestTarget target, Form form)
+            {
+                LOG.warn("AuditBindListPanel.clear.onError");
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        });
+    }
+
+    private void createAndLoadGrid()
+    {
+        List<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>> columns =
+            new ArrayList<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>>();
+        PropertyColumn reqStart = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Timestamp"), "userObject.reqStart");
+        reqStart.setInitialSize(200);
+        columns.add(reqStart);
+
+        PropertyColumn requAuthzId = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("User ID"), "userObject.reqDN");
+        requAuthzId.setInitialSize(200);
+        columns.add(requAuthzId);
+
+        PropertyColumn reqResult = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Result"), "userObject.reqResult");
+        reqResult.setInitialSize(80);
+        columns.add(reqResult);
+
+        List<Bind> binds = (List<Bind>) getDefaultModel().getObject();
+        treeModel = createTreeModel(binds);
+        grid = new TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String>("bindtreegrid", treeModel, columns)
+        {
+            @Override
+            public void selectItem(IModel itemModel, boolean selected)
+            {
+                node = (DefaultMutableTreeNode) itemModel.getObject();
+                if(!node.isRoot())
+                {
+                    Bind bind = (Bind) node.getUserObject();
+                    LOG.debug( "TreeGrid.addGrid.selectItem selected bind =" + bind.getReqDN() );
+                    if (super.isItemSelected(itemModel))
+                    {
+                        LOG.debug( "TreeGrid.addGrid.selectItem item is selected" );
+                        super.selectItem(itemModel, false);
+                    }
+                    else
+                    {
+                        super.selectItem(itemModel, true);
+                        SelectModelEvent.send(getPage(), this, bind);
+                    }
+                }
+            }
+        };
+        grid.setContentHeight(50, SizeUnit.EM);
+        grid.setAllowSelectMultiple(false);
+        grid.setClickRowToSelect(true);
+        grid.setClickRowToDeselect(false);
+        grid.setSelectToEdit(false);
+        // expand the root node
+        grid.getTreeState().expandNode((TreeNode) treeModel.getRoot());
+        grid.setOutputMarkupId(true);
+    }
+
+    private void addUserSearchModal()
+    {
+        final ModalWindow usersModalWindow;
+        listForm.add( usersModalWindow = new ModalWindow( "usersearchmodal" ) );
+        final UserSearchModalPanel userSearchModalPanel = new UserSearchModalPanel( usersModalWindow.getContentId(), usersModalWindow );
+        usersModalWindow.setContent( userSearchModalPanel );
+        usersModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                User userSelection = userSearchModalPanel.getUserSelection();
+                if ( userSelection != null )
+                {
+                    LOG.debug( "modal selected:" + userSelection.getUserId() );
+                    UserAudit userAudit = ( UserAudit ) listForm.getModelObject();
+                    userAudit.setUserId( userSelection.getUserId() );
+                    target.add( userFld );
+                }
+            }
+        } );
+        listForm.add( new SecureIndicatingAjaxLink( "userAssignLinkLbl", GlobalIds.REVIEW_MGR, GlobalIds.FIND_USERS )
+        {
+            public void onClick( AjaxRequestTarget target )
+            {
+                UserAudit userAudit = ( UserAudit ) listForm.getModelObject();
+                String msg = "clicked on users search";
+                msg += "userSelection: " + userAudit.getUserId();
+                userSearchModalPanel.setSearchVal( userAudit.getUserId() );
+                LOG.debug( msg );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                usersModalWindow.show( target );
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+        usersModalWindow.setTitle( "User Search Modal" );
+        usersModalWindow.setInitialWidth( 1000 );
+        usersModalWindow.setInitialHeight( 700 );
+        usersModalWindow.setCookieName( "user-search-modal" );
+    }
+
+    private DefaultTreeModel createTreeModel(List<Bind> binds)
+    {
+        DefaultTreeModel model;
+        Bind root = new Bind();
+        //root.setReqAuthzID( "Authentications" );
+        rootNode = new DefaultMutableTreeNode(root);
+        model = new DefaultTreeModel(rootNode);
+        if (binds == null)
+            LOG.debug("no Authentications found");
+        else
+        {
+            LOG.debug("Binds found:" + binds.size());
+            info("Loading " + binds.size() + " objects into list panel");
+            loadTree( binds );
+        }
+        return model;
+    }
+
+    private void loadTree(List<Bind> binds)
+    {
+        for (Bind bind : binds)
+        {
+            Date start = null;
+            try
+            {
+                start = AttrHelper.decodeGeneralizedTime( bind.getReqStart() );
+            }
+            catch (ParseException pe)
+            {
+                LOG.warn( "ParseException=" + pe.getMessage() );
+            }
+            if(start != null)
+            {
+                SimpleDateFormat formatter = new SimpleDateFormat( GlobalIds.AUDIT_TIMESTAMP_FORMAT );
+                String formattedDate = formatter.format(start);
+                bind.setReqStart( formattedDate );
+            }
+            if(bind.getReqResult().equals( GlobalIds.BIND_SUCCESS_CODE ))
+            {
+                bind.setReqResult( GlobalIds.SUCCESS );
+            }
+            else
+            {
+                bind.setReqResult( GlobalIds.FAILURE );
+            }
+            bind.setReqDN( GlobalUtils.getAuthZId( bind.getReqDN() ) );
+            rootNode.add(new DefaultMutableTreeNode(bind));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/AuditModDetailPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/AuditModDetailPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/AuditModDetailPanel.java
new file mode 100644
index 0000000..da1de81
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/AuditModDetailPanel.java
@@ -0,0 +1,253 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import com.googlecode.wicket.jquery.core.Options;
+import com.googlecode.wicket.kendo.ui.datatable.DataTable;
+import com.googlecode.wicket.kendo.ui.datatable.column.IColumn;
+import com.googlecode.wicket.kendo.ui.datatable.column.PropertyColumn;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.markup.repeater.data.IDataProvider;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.directory.fortress.core.AuditMgr;
+import org.apache.directory.fortress.core.ReviewMgr;
+import org.apache.directory.fortress.core.rbac.Mod;
+import org.apache.directory.fortress.core.rbac.User;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ *          Date: 8/6/13
+ */
+public class AuditModDetailPanel extends FormComponentPanel
+{
+    public static final int MOD_OFFSET = 3;
+    public static final int ROWS = 5;
+    @SpringBean
+    private AuditMgr auditMgr;
+    @SpringBean
+    private ReviewMgr reviewMgr;
+    private static final Logger LOG = Logger.getLogger( AuditModDetailPanel.class.getName() );
+    private Form detailForm;
+    private Displayable display;
+    private UserAuditDetailPanel userPanel;
+
+    public Form getForm()
+    {
+        return this.detailForm;
+    }
+
+    public AuditModDetailPanel( String id, Displayable display )
+    {
+        super( id );
+        this.auditMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        this.reviewMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        this.detailForm = new AuditAuthzDetailForm( GlobalIds.DETAIL_FIELDS, new CompoundPropertyModel<Mod>( new Mod() ) );
+        this.display = display;
+        add( detailForm );
+    }
+
+    public class AuditAuthzDetailForm extends Form
+    {
+        private Component component;
+        private String ftModifier;
+        private String ftModCode;
+        private String ftModId;
+        private String userId;
+        private byte[] modPhoto;
+        private DataTable<RequestMod> table;
+        private List<IColumn> columns;
+        private Options options;
+
+        public AuditAuthzDetailForm( String id, final IModel<Mod> model )
+        {
+            super( id, model );
+            add( new Label( GlobalIds.FT_MOD_ID, new PropertyModel<String>( this, GlobalIds.FT_MOD_ID ) ) );
+            add( new Label( GlobalIds.FT_MOD_CODE, new PropertyModel<String>( this, GlobalIds.FT_MOD_CODE ) ) );
+            // DataTable //
+            columns = newColumnList();
+            options = new Options();
+            options.set( "height", 240 );
+            options.set( "pageable", "{ pageSizes: [ 5, 10, 15, 20 ] }" );
+            //table2 = new DataTable("modstable", columns, createDataProvider( null ), ROWS, options);
+
+            table = new DataTable<RequestMod>( "modstable", columns, createDataProvider( null ), ROWS, options );
+            table.setOutputMarkupId( true );
+            add( table );
+            add( new Label( "reqType" ) );
+            add( new Label( GlobalIds.REQ_DN ) );
+            add( new Label( GlobalIds.REQ_START ) );
+            userPanel = new UserAuditDetailPanel( GlobalIds.USERAUDITDETAILPANEL, new CompoundPropertyModel<User>( new User()
+            ) );
+            add( userPanel );
+            setOutputMarkupId( true );
+        }
+
+        @Override
+        public void onEvent( final IEvent<?> event )
+        {
+            if ( event.getPayload() instanceof SelectModelEvent )
+            {
+                SelectModelEvent modelEvent = ( SelectModelEvent ) event.getPayload();
+                Mod mod = ( Mod ) modelEvent.getEntity();
+                this.setModelObject(mod);
+                String msg = "Mod: " + mod.getReqAuthzID() + " has been selected";
+                LOG.debug( ".onEvent SelectModelEvent: " + mod.getReqAuthzID() );
+                List<RequestMod> modifications = parseRequestMods( mod.getReqMod() );
+                table = new DataTable<RequestMod>( "modstable", columns, createDataProvider( modifications ), ROWS,
+                    options );
+                User user = null;
+                // necessary to push the 'changed' model down into the aggregated panel:
+                int indx = modifications.indexOf( new RequestMod( GlobalIds.FT_MODIFIER ) );
+                if ( indx != -1 )
+                {
+                    ftModifier = modifications.get( indx ).getValue();
+                    if ( VUtil.isNotNullOrEmpty( ftModifier ) )
+                    {
+                        user = GlobalUtils.getUserByInternalId( reviewMgr, ftModifier );
+                        userId = user.getUserId();
+                    }
+                }
+                indx = modifications.indexOf( new RequestMod( GlobalIds.FT_MOD_CODE ) );
+                if ( indx != -1 )
+                {
+                    ftModCode = modifications.get( indx ).getValue();
+                }
+                indx = modifications.indexOf( new RequestMod( GlobalIds.FT_MOD_ID ) );
+                if ( indx != -1 )
+                {
+                    ftModId = modifications.get( indx ).getValue();
+                }
+
+                if ( user == null )
+                {
+                    user = new User();
+                }
+                IModel<User> userModel = new CompoundPropertyModel<User>( user );
+                userPanel.setDefaultModel( userModel );
+
+                addOrReplace( table );
+                display.setMessage( msg );
+                component = detailForm;
+            }
+            else if ( event.getPayload() instanceof AjaxRequestTarget )
+            {
+                // only add the form to ajax target if something has changed...
+                if ( component != null )
+                {
+                    AjaxRequestTarget target = ( ( AjaxRequestTarget ) event.getPayload() );
+                    LOG.debug( ".onEvent AjaxRequestTarget: " + target.toString() );
+                    target.add( component );
+                    component = null;
+                }
+                display.display( ( AjaxRequestTarget ) event.getPayload() );
+            }
+        }
+
+        private List<RequestMod> parseRequestMods( List<String> mods )
+        {
+            List<RequestMod> results = new ArrayList<RequestMod>();
+            if ( VUtil.isNotNullOrEmpty( mods ) )
+            {
+                Mod mod = ( Mod ) detailForm.getModelObject();
+                if ( mod != null && VUtil.isNotNullOrEmpty( mod.getReqMod() ) )
+                {
+                    int ctr = 1;
+                    for ( String szMod : mod.getReqMod() )
+                    {
+                        int indx = szMod.indexOf( ':' );
+                        if ( indx != -1 )
+                        {
+                            String szName = szMod.substring( 0, indx );
+                            String szValue = "";
+                            // ensure value not blank:
+                            if ( szMod.length() > indx + MOD_OFFSET && !szName.equalsIgnoreCase( GlobalIds.JPEGPHOTO ) )
+                            {
+                                szValue = szMod.substring( indx + MOD_OFFSET );
+                            }
+                            RequestMod requestMod = new RequestMod( ctr++, szName, szValue );
+                            char type = szMod.charAt( indx + 1 );
+                            if ( type == '=' )
+                            {
+                                requestMod.setType( RequestMod.TYPE.UPDATE );
+                            }
+                            else if ( type == '+' )
+                            {
+                                requestMod.setType( RequestMod.TYPE.ADD );
+                            }
+                            else if ( type == '-' )
+                            {
+                                requestMod.setType( RequestMod.TYPE.DELETE );
+                            }
+                            else
+                            {
+                                requestMod.setType( RequestMod.TYPE.UNKNOWN );
+                            }
+                            results.add( requestMod );
+                        }
+                    }
+                }
+            }
+            return results;
+        }
+    }
+
+    private IDataProvider<RequestMod> createDataProvider( List<RequestMod> mods )
+    {
+        ListDataProvider<RequestMod> results;
+        if ( VUtil.isNotNullOrEmpty( mods ) )
+        {
+            results = new ListDataProvider<RequestMod>( mods );
+        }
+        else
+        {
+            results = new ListDataProvider<RequestMod>( new ArrayList<RequestMod>() );
+        }
+        return results;
+    }
+
+    private List<IColumn> newColumnList()
+    {
+        List<IColumn> columns = new ArrayList<IColumn>();
+        columns.add( new PropertyColumn( "#", "index", 30 ) );
+        columns.add( new PropertyColumn( "Op", "type", 50 ) );
+        columns.add( new PropertyColumn( "Name", "name", 80 ) );
+        columns.add( new PropertyColumn( "Value", "value", 200 ) );
+        return columns;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/AuditModListPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/AuditModListPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/AuditModListPanel.java
new file mode 100644
index 0000000..3aff1fa
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/AuditModListPanel.java
@@ -0,0 +1,458 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import com.googlecode.wicket.kendo.ui.form.datetime.DatePicker;
+import com.inmethod.grid.IGridColumn;
+import com.inmethod.grid.SizeUnit;
+import com.inmethod.grid.column.PropertyColumn;
+import com.inmethod.grid.treegrid.TreeGrid;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.directory.fortress.web.AuditModListModel;
+import org.apache.directory.fortress.web.AuditModPage;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.SecureIndicatingAjaxButton;
+import org.apache.directory.fortress.web.SecureIndicatingAjaxLink;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.Model;
+import org.apache.directory.fortress.core.rbac.Mod;
+import org.apache.directory.fortress.core.rbac.Permission;
+import org.apache.directory.fortress.core.rbac.User;
+import org.apache.directory.fortress.core.rbac.UserAudit;
+import org.apache.directory.fortress.core.util.attr.AttrHelper;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ * Date: 8/6/13
+ */
+public class AuditModListPanel extends FormComponentPanel
+{
+    private static final Logger LOG = Logger.getLogger(AuditModListPanel.class.getName());
+    private Form listForm;
+    private DefaultTreeModel treeModel;
+    private DefaultMutableTreeNode node;
+    private TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String> grid;
+    private DefaultMutableTreeNode rootNode;
+    private TextField userFld;
+    private TextField objFld;
+    private TextField opFld;
+    protected DatePicker beginDateDP;
+    protected DatePicker endDateDP;
+    private Permission permission;
+    private IModel<AuditModListModel> pageModel;
+
+    public AuditModListPanel(String id, UserAudit userAudit )
+    {
+        super(id);
+        init( userAudit );
+    }
+
+    private void init( UserAudit userAudit )
+    {
+        pageModel = new AuditModListModel(userAudit, GlobalUtils.getRbacSession( this ) );
+        setDefaultModel(pageModel);
+        createAndLoadGrid();
+        this.listForm = new Form( "modform" );
+        this.listForm.addOrReplace(grid);
+        this.listForm.setModel( new CompoundPropertyModel<UserAudit>( userAudit ) );
+        addFormFields();
+        addButtons();
+        add(this.listForm);
+    }
+
+    private void addFormFields()
+    {
+        userFld = new TextField(GlobalIds.USER_ID);
+        userFld.setOutputMarkupId( true );
+        AjaxFormComponentUpdatingBehavior ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( userFld );
+          }
+        };
+        userFld.add( ajaxUpdater );
+        this.listForm.add(userFld);
+        addUserSearchModal();
+
+        objFld = new TextField(GlobalIds.OBJ_NAME );
+        objFld.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( objFld );
+          }
+        };
+        objFld.add( ajaxUpdater );
+        this.listForm.add( objFld );
+
+        opFld = new TextField(GlobalIds.OP_NAME);
+        opFld.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( opFld );
+          }
+        };
+        opFld.add( ajaxUpdater );
+        this.listForm.add( opFld );
+        addPermSearchModal();
+
+        // Begin Date
+        beginDateDP = new DatePicker(GlobalIds.BEGIN_DATE);
+        beginDateDP.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( beginDateDP );
+          }
+        };
+        beginDateDP.add( ajaxUpdater );
+        beginDateDP.setRequired( false );
+        this.listForm.add( beginDateDP );
+
+        // End Date
+        endDateDP = new DatePicker(GlobalIds.END_DATE);
+        endDateDP.setOutputMarkupId( true );
+        ajaxUpdater = new AjaxFormComponentUpdatingBehavior( GlobalIds.ONBLUR )
+        {
+          @Override
+          protected void onUpdate(final AjaxRequestTarget target)
+          {
+              target.add( endDateDP );
+          }
+        };
+        endDateDP.add( ajaxUpdater );
+        endDateDP.setRequired( false );
+        this.listForm.add( endDateDP );
+    }
+
+    private void addButtons()
+    {
+        this.listForm.add(new SecureIndicatingAjaxButton( GlobalIds.SEARCH, GlobalIds.AUDIT_MGR, "searchAdminMods" )
+        {
+            @Override
+            protected void onSubmit(AjaxRequestTarget target, Form form)
+            {
+                LOG.debug( ".search onSubmit" );
+                UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                if(!VUtil.isNotNullOrEmpty(userAudit.getUserId()))
+                {
+                    userAudit.setUserId( "" );
+                }
+                if(permission != null)
+                {
+                    userAudit.setDn( permission.getDn() );
+                }
+                setResponsePage( new AuditModPage( userAudit ) );
+            }
+
+            @Override
+            public void onError(AjaxRequestTarget target, Form form)
+            {
+                LOG.warn( ".search.onError" );
+                throw new RuntimeException( "error submitting form" );
+            }
+
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        });
+        this.listForm.add(new AjaxSubmitLink(GlobalIds.CLEAR)
+        {
+            @Override
+            protected void onSubmit(AjaxRequestTarget target, Form form)
+            {
+                setResponsePage( new AuditModPage( new UserAudit() ) );
+            }
+
+            @Override
+            public void onError(AjaxRequestTarget target, Form form)
+            {
+                LOG.warn("AuditModListPanel.clear.onError");
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        });
+    }
+
+    private void createAndLoadGrid()
+    {
+        List<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>> columns =
+            new ArrayList<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>>();
+        PropertyColumn reqStart = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Timestamp"), "userObject.reqStart");
+        reqStart.setInitialSize(200);
+        columns.add(reqStart);
+        PropertyColumn reqAttr = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("LDAP Operation"), "userObject.reqType");
+        reqAttr.setInitialSize(150);
+        columns.add(reqAttr);
+
+        PropertyColumn reqAttrsOnly = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Target Location"), "userObject.reqDN");
+        reqAttrsOnly.setInitialSize(500);
+        columns.add(reqAttrsOnly);
+
+        List<Mod> mods = (List<Mod>) getDefaultModel().getObject();
+        treeModel = createTreeModel(mods);
+        grid = new TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String>("modtreegrid", treeModel, columns)
+        {
+            @Override
+            public void selectItem(IModel itemModel, boolean selected)
+            {
+                node = (DefaultMutableTreeNode) itemModel.getObject();
+                if(!node.isRoot())
+                {
+                    Mod mod = (Mod) node.getUserObject();
+                    LOG.debug( "TreeGrid.addGrid.selectItem selected mod =" + mod.getReqAuthzID() );
+                    if (super.isItemSelected(itemModel))
+                    {
+                        LOG.debug( "TreeGrid.addGrid.selectItem item is selected" );
+                        super.selectItem(itemModel, false);
+                    }
+                    else
+                    {
+                        super.selectItem(itemModel, true);
+                        SelectModelEvent.send(getPage(), this, mod);
+                    }
+                }
+            }
+        };
+
+        grid.setContentHeight(50, SizeUnit.EM);
+        grid.setAllowSelectMultiple(false);
+        grid.setClickRowToSelect(true);
+        grid.setClickRowToDeselect(false);
+        grid.setSelectToEdit(false);
+        // expand the root node
+        grid.getTreeState().expandNode((TreeNode) treeModel.getRoot());
+        grid.setOutputMarkupId(true);
+    }
+
+    private void addUserSearchModal()
+    {
+        final ModalWindow usersModalWindow;
+        listForm.add( usersModalWindow = new ModalWindow( "usersearchmodal" ) );
+        final UserSearchModalPanel userSearchModalPanel = new UserSearchModalPanel( usersModalWindow.getContentId(), usersModalWindow );
+        usersModalWindow.setContent( userSearchModalPanel );
+        usersModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                User userSelection = userSearchModalPanel.getUserSelection();
+                if ( userSelection != null )
+                {
+                    LOG.debug( "modal selected:" + userSelection.getUserId() );
+                    UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                    userAudit.setUserId( userSelection.getUserId() );
+                    userAudit.setInternalUserId( userSelection.getInternalId() );
+                    target.add( userFld );
+                }
+            }
+        } );
+        listForm.add( new SecureIndicatingAjaxLink( "userAssignLinkLbl", GlobalIds.REVIEW_MGR, GlobalIds.FIND_USERS )
+        {
+            public void onClick( AjaxRequestTarget target )
+            {
+                UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                String msg = "clicked on users search";
+                msg += "userSelection: " + userAudit.getUserId();
+                userSearchModalPanel.setSearchVal( userAudit.getUserId() );
+                LOG.debug( msg );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                usersModalWindow.show( target );
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+        usersModalWindow.setTitle( "User Search Modal" );
+        usersModalWindow.setInitialWidth( 1000 );
+        usersModalWindow.setInitialHeight( 700 );
+        usersModalWindow.setCookieName( "user-search-modal" );
+    }
+
+    private void addPermSearchModal()
+    {
+        final ModalWindow permsModalWindow;
+        listForm.add( permsModalWindow = new ModalWindow( "permsearchmodal" ) );
+        final PermSearchModalPanel permSearchModalPanel = new PermSearchModalPanel( permsModalWindow.getContentId(), permsModalWindow, true );
+        permsModalWindow.setContent( permSearchModalPanel );
+        permsModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                Permission permSelection = permSearchModalPanel.getSelection();
+                if ( permSelection != null )
+                {
+                    UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                    LOG.debug( "modal selected:" + permSelection.getAbstractName() );
+                    permission = permSelection;
+                    userAudit.setObjName( permSelection.getObjName() );
+                    userAudit.setOpName( permSelection.getOpName() );
+                    target.add( objFld );
+                    target.add( opFld );
+                }
+            }
+        } );
+        listForm.add( new SecureIndicatingAjaxLink( "permLinkLbl", GlobalIds.REVIEW_MGR, GlobalIds.FIND_PERMISSIONS )
+        {
+            public void onClick( AjaxRequestTarget target )
+            {
+                UserAudit userAudit = (UserAudit)listForm.getModelObject();
+                String msg = "clicked on perms search";
+                msg += "permSelection: " + permission;
+                permSearchModalPanel.setSearchVal( userAudit.getOpName() );
+                permSearchModalPanel.setAdmin( true );
+                LOG.debug( msg );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                permsModalWindow.show( target );
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+        permsModalWindow.setTitle( "Admin Permission Search Modal" );
+        permsModalWindow.setInitialWidth( 650 );
+        permsModalWindow.setInitialHeight( 450 );
+        permsModalWindow.setCookieName( "perm-search-modal" );
+    }
+
+    private DefaultTreeModel createTreeModel(List<Mod> mods)
+    {
+        DefaultTreeModel model;
+        Mod root = new Mod();
+        //root.setReqAuthzID( "Modifications" );
+        rootNode = new DefaultMutableTreeNode(root);
+        model = new DefaultTreeModel(rootNode);
+        if (mods == null)
+            LOG.debug("no Modifications found");
+        else
+        {
+            LOG.debug("AuthZ found:" + mods.size());
+            info("Loading " + mods.size() + " objects into list panel");
+            loadTree( mods );
+        }
+        return model;
+    }
+
+    private void loadTree(List<Mod> mods)
+    {
+        for (Mod mod : mods)
+        {
+            Date start = null;
+            try
+            {
+                start = AttrHelper.decodeGeneralizedTime( mod.getReqStart() );
+            }
+            catch (ParseException pe)
+            {
+                LOG.warn( "ParseException=" + pe.getMessage() );
+            }
+            if(start != null)
+            {
+                SimpleDateFormat formatter = new SimpleDateFormat( GlobalIds.AUDIT_TIMESTAMP_FORMAT );
+                String formattedDate = formatter.format(start);
+                mod.setReqStart( formattedDate );
+            }
+            rootNode.add(new DefaultMutableTreeNode(mod));
+        }
+    }
+}