You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2013/07/25 11:25:10 UTC

svn commit: r1506859 [1/2] - in /syncope/trunk: common/src/main/java/org/apache/syncope/common/to/ console/ console/src/main/java/org/apache/syncope/console/ console/src/main/java/org/apache/syncope/console/pages/ console/src/main/java/org/apache/synco...

Author: fmartelli
Date: Thu Jul 25 09:25:09 2013
New Revision: 1506859

URL: http://svn.apache.org/r1506859
Log:
Provided creator, lastModifier, creationDate and lastChangeDate for attributables and resources - see SYNCOPE-15

Added:
    syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractSysInfoTO.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SysInfoPanel.java
      - copied, changed from r1506478, syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.html
      - copied, changed from r1506478, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.properties
      - copied, changed from r1506478, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_it.properties
      - copied, changed from r1506478, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel_it.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_pt_BR.properties
      - copied, changed from r1506478, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel_pt_BR.properties
    syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractSysInfo.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/util/SysInfoListener.java
Modified:
    syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnObjectTO.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTaskTO.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ResourceTO.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java
    syncope/trunk/console/pom.xml
    syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Logout.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RolePanel.java
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/MembershipModalPage.html
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/ResourceModalPage.html
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/RolePanel.html
    syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/ExternalResource.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/UserRequest.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/user/SyncopeUser.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/MembershipDAOImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/ResourceDataBinder.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/util/JexlUtil.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/DerAttrTest.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/AttrTest.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
    syncope/trunk/core/src/test/resources/content.xml

Added: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractSysInfoTO.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractSysInfoTO.java?rev=1506859&view=auto
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractSysInfoTO.java (added)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractSysInfoTO.java Thu Jul 25 09:25:09 2013
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013 The Apache Software Foundation.
+ *
+ * Licensed 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.syncope.common.to;
+
+import java.util.Date;
+import org.apache.syncope.common.AbstractBaseBean;
+
+/**
+ * Abstract wrapper for common system information.
+ */
+public class AbstractSysInfoTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -930797879027642457L;
+
+    /**
+     * Username of the user that has created this profile.
+     * <p>
+     * Cannot be used a reference to an existing user for two main reasons: the creator can be the user <tt>admin</tt>;
+     * the creator could have been removed.
+     */
+    private String creator;
+
+    /**
+     * Creation date.
+     */
+    private Date creationDate;
+
+    /**
+     * Username of the user that has performed the last modification to this profile.
+     * <p>
+     * This field cannot be null: at creation time it have to be initialized with the creator username.
+     * <p>
+     * The modifier can be the user itself whether the last performed change has been a self-modification.
+     * <p>
+     * Cannot be used a reference to an existing user for two main reasons: the modifier can be the user <tt>admin</tt>;
+     * the modifier could have been removed.
+     */
+    private String lastModifier;
+
+    /**
+     * Last change date.
+     * <p>
+     * This field cannot be null: at creation time it has to be initialized with <tt>creationDate</tt> field value.
+     */
+    private Date lastChangeDate;
+
+    public String getCreator() {
+        return creator;
+    }
+
+    public void setCreator(final String creator) {
+        this.creator = creator;
+    }
+
+    public Date getCreationDate() {
+        return creationDate;
+    }
+
+    public void setCreationDate(final Date creationDate) {
+        this.creationDate = creationDate;
+    }
+
+    public String getLastModifier() {
+        return lastModifier;
+    }
+
+    public void setLastModifier(final String lastModifier) {
+        this.lastModifier = lastModifier;
+    }
+
+    public Date getLastChangeDate() {
+        return lastChangeDate;
+    }
+
+    public void setLastChangeDate(final Date lastChangeDate) {
+        this.lastChangeDate = lastChangeDate;
+    }
+}

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnObjectTO.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnObjectTO.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnObjectTO.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnObjectTO.java Thu Jul 25 09:25:09 2013
@@ -29,11 +29,10 @@ import javax.xml.bind.annotation.XmlElem
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.AbstractBaseBean;
 
 @XmlRootElement(name = "connObject")
 @XmlType
-public class ConnObjectTO extends AbstractBaseBean {
+public class ConnObjectTO extends AbstractSysInfoTO {
 
     private static final long serialVersionUID = 5139554911265442497L;
 

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTaskTO.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTaskTO.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTaskTO.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTaskTO.java Thu Jul 25 09:25:09 2013
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.common.to;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -50,6 +51,7 @@ public class NotificationTaskTO extends 
 
     @XmlElementWrapper(name = "recipients")
     @XmlElement(name = "recipient")
+    @JsonProperty("recipients")
     public Set<String> getRecipients() {
         return recipients;
     }

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ResourceTO.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ResourceTO.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ResourceTO.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ResourceTO.java Thu Jul 25 09:25:09 2013
@@ -25,14 +25,13 @@ import javax.xml.bind.annotation.XmlElem
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.AbstractBaseBean;
 import org.apache.syncope.common.types.ConnConfProperty;
 import org.apache.syncope.common.types.PropagationMode;
 import org.apache.syncope.common.types.TraceLevel;
 
 @XmlRootElement(name = "resource")
 @XmlType
-public class ResourceTO extends AbstractBaseBean {
+public class ResourceTO extends AbstractSysInfoTO {
 
     private static final long serialVersionUID = -9193551354041698963L;
 

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java Thu Jul 25 09:25:09 2013
@@ -54,8 +54,6 @@ public class UserTO extends AbstractAttr
 
     private Date lastLoginDate;
 
-    private Date creationDate;
-
     private Date changePwdDate;
 
     private Integer failedLogins;
@@ -150,10 +148,6 @@ public class UserTO extends AbstractAttr
         return changePwdDate;
     }
 
-    public Date getCreationDate() {
-        return creationDate;
-    }
-
     public Integer getFailedLogins() {
         return failedLogins;
     }
@@ -166,10 +160,6 @@ public class UserTO extends AbstractAttr
         this.changePwdDate = changePwdDate;
     }
 
-    public void setCreationDate(final Date creationDate) {
-        this.creationDate = creationDate;
-    }
-
     public void setFailedLogins(final Integer failedLogins) {
         this.failedLogins = failedLogins;
     }

Modified: syncope/trunk/console/pom.xml
URL: http://svn.apache.org/viewvc/syncope/trunk/console/pom.xml?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/pom.xml (original)
+++ syncope/trunk/console/pom.xml Thu Jul 25 09:25:09 2013
@@ -240,8 +240,7 @@ under the License.
               <cargo.tomcat.ajp.port>${cargo.tomcat.ajp.port}</cargo.tomcat.ajp.port>
               <cargo.rmi.port>${cargo.rmi.port}</cargo.rmi.port>
 
-              <!--<cargo.jvmargs>-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n</cargo.jvmargs>-->
-              <cargo.jvmargs>-noverify ${javaagent} -Drebel.spring_plugin=false -Xms512m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=1024m</cargo.jvmargs>
+              <cargo.jvmargs>-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -noverify ${javaagent} -Drebel.spring_plugin=false -Xms512m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=1024m</cargo.jvmargs>
             </properties>
             <configfiles>
               <configfile>

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java Thu Jul 25 09:25:09 2013
@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.rest.RestClientFactoryBean;
 import org.apache.wicket.Session;
 import org.apache.wicket.authroles.authorization.strategies.role.Roles;
@@ -74,10 +75,17 @@ public class SyncopeSession extends WebS
 
     @SuppressWarnings("unchecked")
     public <T> T getService(final Class<T> service, final String username, final String password) {
-        if (!restServices.containsKey(service)) {
-            restServices.put(service, restClientFactory.createServiceInstance(service, username, password));
+        T res;
+        if (restServices.containsKey(service)) {
+            res = (T) restServices.get(service);
+        } else {
+            res = restClientFactory.createServiceInstance(service, username, password);
+            if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
+                restServices.put(service, restClientFactory.createServiceInstance(service, username, password));
+            }
         }
-        return (T) restServices.get(service);
+
+        return res;
     }
 
     public String getUsername() {

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Logout.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Logout.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Logout.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Logout.java Thu Jul 25 09:25:09 2013
@@ -32,7 +32,7 @@ public class Logout extends BasePage {
         super(parameters);
 
         SyncopeSession.get().invalidate();
-
+        
         setResponsePage(getApplication().getHomePage());
     }
 }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java Thu Jul 25 09:25:09 2013
@@ -22,6 +22,7 @@ import org.apache.syncope.common.to.Memb
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.console.pages.panels.AttributesPanel;
 import org.apache.syncope.console.pages.panels.DerivedAttributesPanel;
+import org.apache.syncope.console.pages.panels.SysInfoPanel;
 import org.apache.syncope.console.pages.panels.VirtualAttributesPanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -90,6 +91,7 @@ public class MembershipModalPage extends
         // Attributes panel
         //--------------------------------
         form.add(new AttributesPanel("attributes", membershipTO, form, templateMode));
+        form.add(new SysInfoPanel("systeminformation", membershipTO));
         //--------------------------------
 
         //--------------------------------

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java Thu Jul 25 09:25:09 2013
@@ -27,6 +27,7 @@ import org.apache.syncope.console.pages.
 import org.apache.syncope.console.pages.panels.ResourceDetailsPanel;
 import org.apache.syncope.console.pages.panels.ResourceMappingPanel;
 import org.apache.syncope.console.pages.panels.ResourceSecurityPanel;
+import org.apache.syncope.console.pages.panels.SysInfoPanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
@@ -67,6 +68,8 @@ public class ResourceModalPage extends B
         //--------------------------------
         form.add(new ResourceDetailsPanel("details", resourceTO,
                 resourceRestClient.getPropagationActionsClasses(), createFlag));
+        
+        form.add(new SysInfoPanel("systeminformation", resourceTO));
         //--------------------------------
 
         //--------------------------------

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java Thu Jul 25 09:25:09 2013
@@ -372,7 +372,7 @@ public class Todo extends BasePage {
         @Override
         public Iterator<WorkflowFormTO> iterator(final long first, final long count) {
 
-            List<WorkflowFormTO> list = approvalRestClient.getForms();
+            final List<WorkflowFormTO> list = approvalRestClient.getForms();
 
             Collections.sort(list, comparator);
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java Thu Jul 25 09:25:09 2013
@@ -135,8 +135,7 @@ public abstract class UserModalPage exte
         //--------------------------------
         // Resources panel
         //--------------------------------
-        form.add(new ResourcesPanel.Builder("resources")
-                .attributableTO(userTO).statusPanel(null).build());
+        form.add(new ResourcesPanel.Builder("resources").attributableTO(userTO).statusPanel(null).build());
         //--------------------------------
 
         //--------------------------------

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java Thu Jul 25 09:25:09 2013
@@ -22,63 +22,48 @@ import org.apache.syncope.common.to.Abst
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.console.SyncopeSession;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.Model;
 
-public class AccountInformationPanel extends Panel {
+public class AccountInformationPanel extends SysInfoPanel {
 
     private static final long serialVersionUID = 4228064224811390808L;
 
     public <T extends AbstractAttributableTO> AccountInformationPanel(final String id, final UserTO userTO) {
-
-        super(id);
-
-        // ------------------------
-        // Creation date
-        // ------------------------
-        add(new Label("creationDate", new Model(userTO.getCreationDate() != null
-                ? SyncopeSession.get().getDateFormat().format(userTO.getCreationDate())
-                : "")));
-        // ------------------------
+        super(id, userTO);
 
         // ------------------------
         // Change password date
         // ------------------------
         add(new Label("changePwdDate", new Model(userTO.getChangePwdDate() != null
-                ? SyncopeSession.get().getDateFormat().format(userTO.getChangePwdDate())
-                : "")));
+                ? SyncopeSession.get().getDateFormat().format(userTO.getChangePwdDate()) : "")));
         // ------------------------
 
         // ------------------------
         // Last login date
         // ------------------------
         add(new Label("lastLoginDate", new Model(userTO.getLastLoginDate() != null
-                ? SyncopeSession.get().getDateFormat().format(userTO.getLastLoginDate())
-                : "")));
+                ? SyncopeSession.get().getDateFormat().format(userTO.getLastLoginDate()) : "")));
         // ------------------------
 
         // ------------------------
         // Failed logins
         // ------------------------
         add(new Label("failedLogins", new Model(userTO.getFailedLogins() != null
-                ? userTO.getFailedLogins()
-                : "")));
+                ? userTO.getFailedLogins() : "")));
         // ------------------------
 
         // ------------------------
         // Token
         // ------------------------
         add(new Label("token", new Model(userTO.getToken() != null
-                ? userTO.getToken()
-                : "")));
+                ? userTO.getToken() : "")));
         // ------------------------
 
         // ------------------------
         // Token expire time
         // ------------------------
         add(new Label("tokenExpireTime", new Model(userTO.getTokenExpireTime() != null
-                ? userTO.getTokenExpireTime()
-                : "")));
+                ? userTO.getTokenExpireTime() : "")));
         // ------------------------
     }
 }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RolePanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RolePanel.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RolePanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RolePanel.java Thu Jul 25 09:25:09 2013
@@ -114,6 +114,8 @@ public class RolePanel extends Panel {
             this.add(statusPanel);
         }
 
+        this.add(new SysInfoPanel("systeminformation", builder.roleTO));
+
         //--------------------------------
         // Attributes panel
         this.add(new AttributesPanel(

Copied: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SysInfoPanel.java (from r1506478, syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java)
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SysInfoPanel.java?p2=syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SysInfoPanel.java&p1=syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java&r1=1506478&r2=1506859&rev=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AccountInformationPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SysInfoPanel.java Thu Jul 25 09:25:09 2013
@@ -19,66 +19,49 @@
 package org.apache.syncope.console.pages.panels;
 
 import org.apache.syncope.common.to.AbstractAttributableTO;
-import org.apache.syncope.common.to.UserTO;
+import org.apache.syncope.common.to.AbstractSysInfoTO;
 import org.apache.syncope.console.SyncopeSession;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.Model;
 
-public class AccountInformationPanel extends Panel {
+public class SysInfoPanel extends Panel {
 
-    private static final long serialVersionUID = 4228064224811390808L;
+    private static final long serialVersionUID = 4228064224811390809L;
 
-    public <T extends AbstractAttributableTO> AccountInformationPanel(final String id, final UserTO userTO) {
+    public <T extends AbstractAttributableTO> SysInfoPanel(
+            final String id, final AbstractSysInfoTO sysInfoTO) {
 
         super(id);
 
         // ------------------------
         // Creation date
         // ------------------------
-        add(new Label("creationDate", new Model(userTO.getCreationDate() != null
-                ? SyncopeSession.get().getDateFormat().format(userTO.getCreationDate())
-                : "")));
+        add(new Label("creationDate", new Model<String>(sysInfoTO.getCreationDate() != null
+                ? SyncopeSession.get().getDateFormat().format(sysInfoTO.getCreationDate()) : "")));
         // ------------------------
 
         // ------------------------
-        // Change password date
+        // Last change date
         // ------------------------
-        add(new Label("changePwdDate", new Model(userTO.getChangePwdDate() != null
-                ? SyncopeSession.get().getDateFormat().format(userTO.getChangePwdDate())
-                : "")));
+        add(new Label("lastChangeDate", new Model<String>(sysInfoTO.getLastChangeDate() != null
+                ? SyncopeSession.get().getDateFormat().format(sysInfoTO.getCreationDate()) : "")));
         // ------------------------
 
-        // ------------------------
-        // Last login date
-        // ------------------------
-        add(new Label("lastLoginDate", new Model(userTO.getLastLoginDate() != null
-                ? SyncopeSession.get().getDateFormat().format(userTO.getLastLoginDate())
-                : "")));
-        // ------------------------
 
         // ------------------------
-        // Failed logins
+        // Creator
         // ------------------------
-        add(new Label("failedLogins", new Model(userTO.getFailedLogins() != null
-                ? userTO.getFailedLogins()
-                : "")));
+        add(new Label("creator", new Model<String>(sysInfoTO.getCreator() != null
+                ? sysInfoTO.getCreator() : "")));
         // ------------------------
 
         // ------------------------
-        // Token
+        // Last modifier
         // ------------------------
-        add(new Label("token", new Model(userTO.getToken() != null
-                ? userTO.getToken()
-                : "")));
+        add(new Label("lastModifier", new Model<String>(sysInfoTO.getLastModifier() != null
+                ? sysInfoTO.getLastModifier() : "")));
         // ------------------------
 
-        // ------------------------
-        // Token expire time
-        // ------------------------
-        add(new Label("tokenExpireTime", new Model(userTO.getTokenExpireTime() != null
-                ? userTO.getTokenExpireTime()
-                : "")));
-        // ------------------------
     }
 }

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/MembershipModalPage.html
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/MembershipModalPage.html?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/MembershipModalPage.html (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/MembershipModalPage.html Thu Jul 25 09:25:09 2013
@@ -28,6 +28,7 @@ under the License.
     <div id="tabs-1">
       <div id="formtable">
         <span wicket:id="attributes">[membership attributes]</span>
+        <span wicket:id="systeminformation">[System Information]</span>
       </div>
 
       <script type="text/javascript">

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/ResourceModalPage.html
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/ResourceModalPage.html?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/ResourceModalPage.html (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/ResourceModalPage.html Thu Jul 25 09:25:09 2013
@@ -34,6 +34,7 @@ under the License.
           </ul>
           <div id="resource">
             <span wicket:id="details">[details]</span>
+            <span wicket:id="systeminformation">[System Information]</span>
           </div>
           <div id="umapping">
             <span wicket:id="umapping">[umapping]</span>

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html Thu Jul 25 09:25:09 2013
@@ -17,98 +17,51 @@ specific language governing permissions 
 under the License.
 -->
 <html>
-    <wicket:head>
-        <style>
-            div.information{
-                margin-top: 30px; 
-                border: 1px solid #DDDDDD; 
-                font-size: 8px;
-                color: #555555;
-                display: inline-table; 
-                width: 100%; 
-                clear: both; 
-                float:none;
-            }
+  <wicket:extend>
 
-            div.infolabel{
-                margin-left: 5px; 
-                float:left; 
-                width: 150px;
-                font-weight: bold
-            }
-
-            div.infoleft{
-                float:left; 
-                display: inline-table; 
-                width: 50%
-            }
-
-            div.inforight{ 
-                display: inline-table; 
-                width: 50%
-            }
-
-            div.inforow{
-                display: inline-table;
-                width: 100%
-            }
-        </style>
-    </wicket:head>
-    <wicket:panel>
-        <div class="information">
-            <div class="infoleft">
-                <div class="infolabel"> 
-                    <wicket:message key="creationDate"/>:
-                </div>
-                <div>
-                    <span wicket:id="creationDate" />
-                </div>
-            </div>
-
-            <div class="inforight">
-                <div class="infolabel">
-                    <wicket:message key="lastLoginDate"/>:
-                </div>
-                <div>
-                    <span wicket:id="lastLoginDate" />
-                </div>
-            </div>
-
-            <div class="infoleft">
-                <div class="infolabel">
-                    <wicket:message key="changePwdDate"/>:
-                </div>
-                <div>
-                    <span wicket:id="changePwdDate" />
-                </div>
-            </div>
-
-            <div class="inforight">
-                <div class="infolabel">
-                    <wicket:message key="failedLogins"/>:
-                </div>
-                <div>
-                    <span wicket:id="failedLogins" />
-                </div>
-            </div>
-
-            <div class="inforow">
-                <div class="infolabel">
-                    <wicket:message key="token"/>:
-                </div>
-                <div>
-                    <span wicket:id="token" />
-                </div>
-            </div>
-
-            <div class="inforow">
-                <div class="infolabel">
-                    <wicket:message key="tokenExpireTime"/>
-                </div>
-                <div>
-                    <span wicket:id="tokenExpireTime" />
-                </div>
-            </div>
-        </div>
-    </wicket:panel>
+    <div class="infoleft">
+      <div class="infolabel">
+        <wicket:message key="lastLoginDate"/>:
+      </div>
+      <div>
+        <span wicket:id="lastLoginDate" />
+      </div>
+    </div>
+
+    <div class="inforight">
+      <div class="infolabel">
+        <wicket:message key="failedLogins"/>:
+      </div>
+      <div>
+        <span wicket:id="failedLogins" />
+      </div>
+    </div>
+
+    <div class="infoleft">
+      <div class="infolabel">
+        <wicket:message key="changePwdDate"/>:
+      </div>
+      <div>
+        <span wicket:id="changePwdDate" />
+      </div>
+    </div>
+
+    <div class="inforight">
+      <div class="infolabel">
+        <wicket:message key="tokenExpireTime"/>
+      </div>
+      <div>
+        <span wicket:id="tokenExpireTime" />
+      </div>
+    </div>
+
+    <div class="inforow">
+      <div class="infolabel">
+        <wicket:message key="token"/>:
+      </div>
+      <div>
+        <span wicket:id="token" />
+      </div>
+    </div>
+  </wicket:extend>
 </html>

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties Thu Jul 25 09:25:09 2013
@@ -14,7 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-creationDate=Creation Date
 changePwdDate=Last Change Password Date
 lastLoginDate=Last Login Data
 failedLogins=Subsequent Failed Logins

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/RolePanel.html
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/RolePanel.html?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/RolePanel.html (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/RolePanel.html Thu Jul 25 09:25:09 2013
@@ -22,6 +22,7 @@ under the License.
     <div id="tabs-1">
       <span wicket:id="details">[role details]</span>
       <span wicket:id="statuspanel">[Status Panel]</span>
+      <span wicket:id="systeminformation">[System Information]</span>
     </div>
 
     <div id="tabs-2">

Copied: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.html (from r1506478, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html)
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.html?p2=syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.html&p1=syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html&r1=1506478&r2=1506859&rev=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.html (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.html Thu Jul 25 09:25:09 2013
@@ -17,98 +17,82 @@ specific language governing permissions 
 under the License.
 -->
 <html>
-    <wicket:head>
-        <style>
-            div.information{
-                margin-top: 30px; 
-                border: 1px solid #DDDDDD; 
-                font-size: 8px;
-                color: #555555;
-                display: inline-table; 
-                width: 100%; 
-                clear: both; 
-                float:none;
-            }
-
-            div.infolabel{
-                margin-left: 5px; 
-                float:left; 
-                width: 150px;
-                font-weight: bold
-            }
-
-            div.infoleft{
-                float:left; 
-                display: inline-table; 
-                width: 50%
-            }
-
-            div.inforight{ 
-                display: inline-table; 
-                width: 50%
-            }
-
-            div.inforow{
-                display: inline-table;
-                width: 100%
-            }
-        </style>
-    </wicket:head>
-    <wicket:panel>
-        <div class="information">
-            <div class="infoleft">
-                <div class="infolabel"> 
-                    <wicket:message key="creationDate"/>:
-                </div>
-                <div>
-                    <span wicket:id="creationDate" />
-                </div>
-            </div>
-
-            <div class="inforight">
-                <div class="infolabel">
-                    <wicket:message key="lastLoginDate"/>:
-                </div>
-                <div>
-                    <span wicket:id="lastLoginDate" />
-                </div>
-            </div>
-
-            <div class="infoleft">
-                <div class="infolabel">
-                    <wicket:message key="changePwdDate"/>:
-                </div>
-                <div>
-                    <span wicket:id="changePwdDate" />
-                </div>
-            </div>
-
-            <div class="inforight">
-                <div class="infolabel">
-                    <wicket:message key="failedLogins"/>:
-                </div>
-                <div>
-                    <span wicket:id="failedLogins" />
-                </div>
-            </div>
-
-            <div class="inforow">
-                <div class="infolabel">
-                    <wicket:message key="token"/>:
-                </div>
-                <div>
-                    <span wicket:id="token" />
-                </div>
-            </div>
-
-            <div class="inforow">
-                <div class="infolabel">
-                    <wicket:message key="tokenExpireTime"/>
-                </div>
-                <div>
-                    <span wicket:id="tokenExpireTime" />
-                </div>
-            </div>
+  <wicket:head>
+    <style>
+      div.information{
+        margin-top: 30px; 
+        border: 1px solid #DDDDDD; 
+        font-size: 8px;
+        color: #555555;
+        display: inline-table; 
+        width: 100%; 
+        clear: both; 
+        float:none;
+      }
+
+      div.infolabel{
+        margin-left: 5px; 
+        float:left; 
+        width: 150px;
+        font-weight: bold
+      }
+
+      div.infoleft{
+        float:left; 
+        display: inline-table; 
+        width: 50%
+      }
+
+      div.inforight{ 
+        display: inline-table; 
+        width: 50%
+      }
+
+      div.inforow{
+        display: inline-table;
+        width: 100%
+      }
+    </style>
+  </wicket:head>
+  <wicket:panel>
+    <div class="information">
+      <div class="infoleft">
+        <div class="infolabel"> 
+          <wicket:message key="creationDate"/>:
         </div>
-    </wicket:panel>
+        <div>
+          <span wicket:id="creationDate" />
+        </div>
+      </div>
+
+      <div class="inforight">
+        <div class="infolabel">
+          <wicket:message key="lastChangeDate"/>:
+        </div>
+        <div>
+          <span wicket:id="lastChangeDate" />
+        </div>
+      </div>
+
+      <div class="infoleft">
+        <div class="infolabel">
+          <wicket:message key="creator"/>:
+        </div>
+        <div>
+          <span wicket:id="creator" />
+        </div>
+      </div>
+
+      <div class="inforight">
+        <div class="infolabel">
+          <wicket:message key="lastModifier"/>:
+        </div>
+        <div>
+          <span wicket:id="lastModifier" />
+        </div>
+      </div>
+
+      <wicket:child />
+    </div>
+  </wicket:panel>
 </html>

Copied: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.properties (from r1506478, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties)
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.properties?p2=syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.properties&p1=syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties&r1=1506478&r2=1506859&rev=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel.properties Thu Jul 25 09:25:09 2013
@@ -15,9 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 creationDate=Creation Date
-changePwdDate=Last Change Password Date
-lastLoginDate=Last Login Data
-failedLogins=Subsequent Failed Logins
-token=Token
-tokenExpireTime=Token Expire Time
-confirmPassword=Password (confirm)
+creator=Creator
+lastChangeDate=Last change date
+lastModifier=Last modifier

Copied: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_it.properties (from r1506478, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel_it.properties)
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_it.properties?p2=syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_it.properties&p1=syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel_it.properties&r1=1506478&r2=1506859&rev=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel_it.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_it.properties Thu Jul 25 09:25:09 2013
@@ -15,9 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 creationDate=Data Di Creazione
-changePwdDate=Data Ultimo Cambio Password
-lastLoginDate=Data Di Ultimo Login
-failedLogins=Login Consecutivi Falliti
-token=Token
-tokenExpireTime=Scadenza Token
-confirmPassword=Password (conferma)
+creator=Creatore
+lastChangeDate=Data Di Ultima Modifica
+lastModifier=Ultimo Modificatore

Copied: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_pt_BR.properties (from r1506478, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel_pt_BR.properties)
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_pt_BR.properties?p2=syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_pt_BR.properties&p1=syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel_pt_BR.properties&r1=1506478&r2=1506859&rev=1506859&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AccountInformationPanel_pt_BR.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/SysInfoPanel_pt_BR.properties Thu Jul 25 09:25:09 2013
@@ -14,10 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-creationDate=Data de Cria\u00E7\u00E3o
-changePwdDate=Data da \u00DAltima Troca de Senha
-lastLoginDate=Data do \u00DAltimo Login
-failedLogins=Falhas Subsequentes de Logins 
-token=Token
-tokenExpireTime=Tempo de Expira\u00E7\u00E3o do Token
-confirmPassword=Senha (confirmar)
+creationDate=Data de Cria\u00e7\u00e3o
+creator=Criador
+lastChangeDate=Data De \u00daltima Altera\u00e7\u00e3o
+lastModifier=\u00daltima Modificador

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java Thu Jul 25 09:25:09 2013
@@ -25,7 +25,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-public abstract class AbstractAttributable extends AbstractBaseBean {
+public abstract class AbstractAttributable extends AbstractSysInfo {
 
     private static final long serialVersionUID = -4801685541488201119L;
 

Added: syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractSysInfo.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractSysInfo.java?rev=1506859&view=auto
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractSysInfo.java (added)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractSysInfo.java Thu Jul 25 09:25:09 2013
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 The Apache Software Foundation.
+ *
+ * Licensed 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.syncope.core.persistence.beans;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import org.apache.syncope.core.util.SysInfoListener;
+
+/**
+ * Abstract wrapper for common system information.
+ */
+@MappedSuperclass
+@EntityListeners(value = SysInfoListener.class)
+public abstract class AbstractSysInfo extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -4801685541488201219L;
+
+    /**
+     * Username of the user that has created this profile.
+     * <p>
+     * Cannot be used a reference to an existing user for two main reasons: the creator can be the user <tt>admin</tt>;
+     * the creator could have been removed.
+     */
+    @Column(nullable = false)
+    private String creator;
+
+    /**
+     * Creation date.
+     */
+    @Column(nullable = false)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date creationDate;
+
+    /**
+     * Username of the user that has performed the last modification to this profile.
+     * <p>
+     * This field cannot be null: at creation time it have to be initialized with the creator username.
+     * <p>
+     * The modifier can be the user itself whether the last performed change has been a self-modification.
+     * <p>
+     * Cannot be used a reference to an existing user for two main reasons: the modifier can be the user <tt>admin</tt>;
+     * the modifier could have been removed.
+     */
+    @Column(nullable = false)
+    private String lastModifier;
+
+    /**
+     * Last change date.
+     * <p>
+     * This field cannot be null: at creation time it has to be initialized with <tt>creationDate</tt> field value.
+     */
+    @Column(nullable = false)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date lastChangeDate;
+
+    public String getCreator() {
+        return creator;
+    }
+
+    public void setCreator(final String creator) {
+        this.creator = creator;
+    }
+
+    public Date getCreationDate() {
+        return creationDate == null ? null : new Date(creationDate.getTime());
+    }
+
+    public void setCreationDate(final Date creationDate) {
+        this.creationDate = creationDate == null ? null : new Date(creationDate.getTime());
+    }
+
+    public String getLastModifier() {
+        return lastModifier;
+    }
+
+    public void setLastModifier(final String lastModifier) {
+        this.lastModifier = lastModifier;
+    }
+
+    public Date getLastChangeDate() {
+        return lastChangeDate == null ? creationDate : lastChangeDate;
+    }
+
+    public void setLastChangeDate(final Date lastChangeDate) {
+        this.lastChangeDate = lastChangeDate == null ? null : new Date(lastChangeDate.getTime());
+    }
+}

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/ExternalResource.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/ExternalResource.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/ExternalResource.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/ExternalResource.java Thu Jul 25 09:25:09 2013
@@ -50,7 +50,7 @@ import org.identityconnectors.framework.
  */
 @Entity
 @ExternalResourceCheck
-public class ExternalResource extends AbstractBaseBean {
+public class ExternalResource extends AbstractSysInfo {
 
     private static final long serialVersionUID = -6937712883512073278L;
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/UserRequest.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/UserRequest.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/UserRequest.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/UserRequest.java Thu Jul 25 09:25:09 2013
@@ -60,7 +60,7 @@ public class UserRequest extends Abstrac
     public UserTO getUserTO() {
         return type != UserRequestType.CREATE
                 ? null
-                : XMLSerializer.<UserTO> deserialize(payload);
+                : XMLSerializer.<UserTO>deserialize(payload);
     }
 
     public void setUserTO(final UserTO userTO) {
@@ -71,7 +71,7 @@ public class UserRequest extends Abstrac
     public UserMod getUserMod() {
         return type != UserRequestType.UPDATE
                 ? null
-                : XMLSerializer.<UserMod> deserialize(payload);
+                : XMLSerializer.<UserMod>deserialize(payload);
     }
 
     public void setUserMod(final UserMod userMod) {

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/user/SyncopeUser.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/user/SyncopeUser.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/user/SyncopeUser.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/user/SyncopeUser.java Thu Jul 25 09:25:09 2013
@@ -59,6 +59,9 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.util.PasswordEncoder;
 import org.apache.syncope.core.util.SecureRandomUtil;
 
+/**
+ * Syncope user bean.
+ */
 @Entity
 @Cacheable
 @SyncopeUserCheck
@@ -130,13 +133,6 @@ public class SyncopeUser extends Abstrac
     private Date lastLoginDate;
 
     /**
-     * Creation date.
-     */
-    @NotNull
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date creationDate;
-
-    /**
      * Change password date.
      */
     @Column(nullable = true)
@@ -449,18 +445,6 @@ public class SyncopeUser extends Abstrac
                 : new Date(changePwdDate.getTime());
     }
 
-    public Date getCreationDate() {
-        return creationDate == null
-                ? null
-                : new Date(creationDate.getTime());
-    }
-
-    public void setCreationDate(final Date creationDate) {
-        this.creationDate = creationDate == null
-                ? null
-                : new Date(creationDate.getTime());
-    }
-
     public Integer getFailedLogins() {
         return failedLogins == null ? 0 : failedLogins;
     }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/MembershipDAOImpl.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/MembershipDAOImpl.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/MembershipDAOImpl.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/MembershipDAOImpl.java Thu Jul 25 09:25:09 2013
@@ -26,7 +26,6 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.persistence.beans.role.SyncopeRole;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.apache.syncope.core.persistence.dao.MembershipDAO;
-import org.apache.syncope.core.persistence.dao.RoleDAO;
 import org.apache.syncope.core.persistence.dao.UserDAO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
@@ -37,9 +36,6 @@ public class MembershipDAOImpl extends A
     @Autowired
     private UserDAO userDAO;
 
-    @Autowired
-    private RoleDAO roleDAO;
-
     @Override
     public Membership find(final Long id) {
         return entityManager.find(Membership.class, id);

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/ResourceDataBinder.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/ResourceDataBinder.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/ResourceDataBinder.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/ResourceDataBinder.java Thu Jul 25 09:25:09 2013
@@ -285,6 +285,12 @@ public class ResourceDataBinder {
 
         ResourceTO resourceTO = new ResourceTO();
 
+        // set sys info
+        resourceTO.setCreator(resource.getCreator());
+        resourceTO.setCreationDate(resource.getCreationDate());
+        resourceTO.setLastModifier(resource.getLastModifier());
+        resourceTO.setLastChangeDate(resource.getLastChangeDate());
+
         // set the resource name
         resourceTO.setName(resource.getName());
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java Thu Jul 25 09:25:09 2013
@@ -288,6 +288,13 @@ public class RoleDataBinder extends Abst
         connObjectUtil.retrieveVirAttrValues(role, AttributableUtil.getInstance(AttributableType.ROLE));
 
         RoleTO roleTO = new RoleTO();
+
+        // set sys info
+        roleTO.setCreator(role.getCreator());
+        roleTO.setCreationDate(role.getCreationDate());
+        roleTO.setLastModifier(role.getLastModifier());
+        roleTO.setLastChangeDate(role.getLastChangeDate());
+
         roleTO.setId(role.getId());
         roleTO.setName(role.getName());
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java Thu Jul 25 09:25:09 2013
@@ -225,9 +225,6 @@ public class UserDataBinder extends Abst
 
         // set username
         user.setUsername(userTO.getUsername());
-
-        // set creation date (at execution time)
-        user.setCreationDate(new Date());
     }
 
     /**
@@ -388,6 +385,13 @@ public class UserDataBinder extends Abst
         MembershipTO membershipTO;
         for (Membership membership : user.getMemberships()) {
             membershipTO = new MembershipTO();
+
+            // set sys info
+            membershipTO.setCreator(membership.getCreator());
+            membershipTO.setCreationDate(membership.getCreationDate());
+            membershipTO.setLastModifier(membership.getLastModifier());
+            membershipTO.setLastChangeDate(membership.getLastChangeDate());
+
             membershipTO.setId(membership.getId());
             membershipTO.setRoleId(membership.getSyncopeRole().getId());
             membershipTO.setRoleName(membership.getSyncopeRole().getName());

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/util/JexlUtil.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/JexlUtil.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/util/JexlUtil.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/util/JexlUtil.java Thu Jul 25 09:25:09 2013
@@ -18,7 +18,11 @@
  */
 package org.apache.syncope.core.util;
 
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
@@ -50,7 +54,7 @@ public class JexlUtil {
      */
     private static final Logger LOG = LoggerFactory.getLogger(JexlUtil.class);
 
-    private static final String[] IGNORE_FIELDS = {"password", "clearPassword", "serialVersionUID"};
+    private static final String[] IGNORE_FIELDS = {"password", "clearPassword", "serialVersionUID", "class"};
 
     @Autowired
     private JexlEngine jexlEngine;
@@ -89,34 +93,45 @@ public class JexlUtil {
     }
 
     public JexlContext addFieldsToContext(final Object attributable, final JexlContext jexlContext) {
-        JexlContext context = jexlContext == null
-                ? new MapContext()
-                : jexlContext;
+        JexlContext context = jexlContext == null ? new MapContext() : jexlContext;
 
-        final Field[] fields = attributable.getClass().getDeclaredFields();
-        for (int i = 0; i < fields.length; i++) {
-            try {
-                Field field = fields[i];
-                field.setAccessible(true);
-                final String fieldName = field.getName();
-                if ((!field.isSynthetic()) && (!fieldName.startsWith("pc"))
-                        && (!ArrayUtils.contains(IGNORE_FIELDS, fieldName))
-                        && (!Iterable.class.isAssignableFrom(field.getType()))
-                        && (!field.getType().isArray())) {
-
-                    final Object fieldValue = field.get(attributable);
-
-                    context.set(fieldName, fieldValue == null
-                            ? ""
-                            : (field.getType().equals(Date.class)
-                            ? DataFormat.format((Date) fieldValue, false)
-                            : fieldValue));
+        try {
+            for (PropertyDescriptor desc : Introspector.getBeanInfo(attributable.getClass()).getPropertyDescriptors()) {
+                final Class<?> type = desc.getPropertyType();
+                final String fieldName = desc.getName();
 
-                    LOG.debug("Add field {} with value {}", fieldName, fieldValue);
+                if ((!fieldName.startsWith("pc"))
+                        && (!ArrayUtils.contains(IGNORE_FIELDS, fieldName))
+                        && (!Iterable.class.isAssignableFrom(type))
+                        && (!type.isArray())) {
+                    try {
+                        final Method getter = desc.getReadMethod();
+
+                        final Object fieldValue;
+
+                        if (getter == null) {
+                            final Field field = attributable.getClass().getDeclaredField(fieldName);
+                            field.setAccessible(true);
+                            fieldValue = field.get(attributable);
+                        } else {
+                            fieldValue = getter.invoke(attributable);
+                        }
+
+                        context.set(fieldName, fieldValue == null
+                                ? ""
+                                : (type.equals(Date.class)
+                                ? DataFormat.format((Date) fieldValue, false)
+                                : fieldValue));
+
+                        LOG.debug("Add field {} with value {}", fieldName, fieldValue);
+
+                    } catch (Exception iae) {
+                        LOG.error("Reading '{}' value error", fieldName, iae);
+                    }
                 }
-            } catch (Exception e) {
-                LOG.error("Reading class attributes error", e);
             }
+        } catch (IntrospectionException ie) {
+            LOG.error("Reading class attributes error", ie);
         }
 
         return context;

Added: syncope/trunk/core/src/main/java/org/apache/syncope/core/util/SysInfoListener.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/SysInfoListener.java?rev=1506859&view=auto
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/util/SysInfoListener.java (added)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/util/SysInfoListener.java Thu Jul 25 09:25:09 2013
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 The Apache Software Foundation.
+ *
+ * Licensed 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.syncope.core.util;
+
+import java.util.Date;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import org.apache.syncope.core.persistence.beans.AbstractSysInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SysInfoListener {
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(SysInfoListener.class);
+
+    @PrePersist
+    @PreUpdate
+    public void setSysInfo(final AbstractSysInfo entity) {
+        try {
+            final String username = EntitlementUtil.getAuthenticatedUsername();
+            LOG.debug("Set system properties for '{}'", entity);
+
+            final Date now = new Date();
+
+            if (entity.getCreationDate() == null) {
+                LOG.debug("Set creation date '{}' and creator '{}' for '{}'", new Object[] {now, username, entity});
+                entity.setCreationDate(now);
+                entity.setCreator(username);
+            }
+
+            LOG.debug("Set last change date '{}' and modifier '{}' for '{}'", new Object[] {now, username, entity});
+            entity.setLastModifier(username);
+            entity.setLastChangeDate(now);
+        } catch (Exception e) {
+            // In case of exception, do not trace create/update event info: maybe it's an internal management action.
+            // See SyncopeAuthenticationProvider for instance.
+            LOG.info("Unauthenticated user action: no system property to be update");
+        }
+    }
+}

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/DerAttrTest.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/DerAttrTest.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/DerAttrTest.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/DerAttrTest.java Thu Jul 25 09:25:09 2013
@@ -192,7 +192,7 @@ public class DerAttrTest extends Abstrac
         assertNotNull(value);
         assertFalse(value.isEmpty());
         assertTrue(value.startsWith("active - vivaldi - 2010-10-20"));
-        assertTrue(value.endsWith("[]"));
+        assertTrue(value.endsWith("[0]"));
     }
 
     @Test

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/AttrTest.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/AttrTest.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/AttrTest.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/AttrTest.java Thu Jul 25 09:25:09 2013
@@ -157,6 +157,6 @@ public class AttrTest extends AbstractDA
         assertNotNull(value);
         assertFalse(value.isEmpty());
         assertTrue(value.startsWith("vivaldi - 2010-10-20"));
-        assertTrue(value.endsWith("[]"));
+        assertTrue(value.endsWith("[0]"));
     }
 }

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java Thu Jul 25 09:25:09 2013
@@ -24,7 +24,6 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.net.Authenticator;
 import java.security.AccessControlException;
 import java.util.HashSet;
 import java.util.List;
@@ -32,7 +31,6 @@ import java.util.Set;
 
 import javax.ws.rs.core.Response;
 
-import org.apache.cxf.transport.http.CXFAuthenticator;
 import org.apache.syncope.common.search.AttributeCond;
 import org.apache.syncope.common.search.NodeCond;
 import org.apache.syncope.common.services.InvalidSearchConditionException;

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java Thu Jul 25 09:25:09 2013
@@ -291,6 +291,12 @@ public class RoleTestITCase extends Abst
         // 1. read role as admin
         RoleTO roleTO = roleService.read(7L);
 
+        // issue SYNCOPE-15
+        assertNotNull(roleTO.getCreationDate());
+        assertNotNull(roleTO.getLastChangeDate());
+        assertEquals("admin", roleTO.getCreator());
+        assertEquals("admin", roleTO.getLastModifier());
+
         // 2. prepare update
         RoleMod roleMod = new RoleMod();
         roleMod.setId(roleTO.getId());
@@ -313,6 +319,13 @@ public class RoleTestITCase extends Abst
 
         roleTO = roleService3.update(roleMod.getId(), roleMod);
         assertEquals("Managing Director", roleTO.getName());
+
+        // issue SYNCOPE-15
+        assertNotNull(roleTO.getCreationDate());
+        assertNotNull(roleTO.getLastChangeDate());
+        assertEquals("admin", roleTO.getCreator());
+        assertEquals("puccini", roleTO.getLastModifier());
+        assertTrue(roleTO.getCreationDate().before(roleTO.getLastChangeDate()));
     }
 
     /**

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java?rev=1506859&r1=1506858&r2=1506859&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java Thu Jul 25 09:25:09 2013
@@ -418,6 +418,14 @@ public class UserTestITCase extends Abst
         UserTO newUserTO = createUser(userTO);
 
         assertNotNull(newUserTO);
+
+        // issue SYNCOPE-15
+        assertNotNull(newUserTO.getCreationDate());
+        assertNotNull(newUserTO.getCreator());
+        assertNotNull(newUserTO.getLastChangeDate());
+        assertNotNull(newUserTO.getLastModifier());
+        assertEquals(newUserTO.getCreationDate(), newUserTO.getLastChangeDate());
+
         assertFalse(newUserTO.getAttributes().contains(attrWithInvalidSchemaTO));
 
         // check for changePwdDate
@@ -452,8 +460,7 @@ public class UserTestITCase extends Abst
         assertEquals(maxTaskExecutions, taskTO.getExecutions().size());
 
         // 3. verify password
-        UserService userService1 = createServiceInstance(UserService.class, newUserTO.getUsername(),
-                "password123");
+        UserService userService1 = createServiceInstance(UserService.class, newUserTO.getUsername(), "password123");
         try {
             UserTO user = userService1.readSelf();
             assertNotNull(user);
@@ -461,8 +468,7 @@ public class UserTestITCase extends Abst
             fail("Credentials should be valid and not cause AccessControlException");
         }
 
-        UserService userService2 = createServiceInstance(UserService.class, newUserTO.getUsername(),
-                "passwordXX");
+        UserService userService2 = createServiceInstance(UserService.class, newUserTO.getUsername(), "passwordXX");
         try {
             userService2.readSelf();
             fail("Credentials are invalid, thus request should raise AccessControlException");
@@ -877,6 +883,13 @@ public class UserTestITCase extends Abst
         userTO = userService.update(userMod.getId(), userMod);
         assertNotNull(userTO);
 
+        // issue SYNCOPE-15
+        assertNotNull(userTO.getCreationDate());
+        assertNotNull(userTO.getCreator());
+        assertNotNull(userTO.getLastChangeDate());
+        assertNotNull(userTO.getLastModifier());
+        assertTrue(userTO.getCreationDate().before(userTO.getLastChangeDate()));
+
         SyncopeUser passwordTestUser = new SyncopeUser();
         passwordTestUser.setPassword("new2Password", CipherAlgorithm.SHA1, 0);
         assertEquals(passwordTestUser.getPassword(), userTO.getPassword());
@@ -1822,7 +1835,7 @@ public class UserTestITCase extends Abst
         userTO.getResources().clear();
         userTO.addResource(RESOURCE_NAME_TESTDB);
         userTO.addResource("resource-testdb2");
-        
+
         userTO = createUser(userTO);
         assertNotNull(userTO);
         assertTrue(userTO.getResources().contains(RESOURCE_NAME_TESTDB));