You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by an...@apache.org on 2014/07/11 15:53:09 UTC

svn commit: r1609715 [1/2] - in /syncope/trunk: ./ common/src/main/java/org/apache/syncope/common/services/ common/src/main/java/org/apache/syncope/common/types/ common/src/main/java/org/apache/syncope/common/util/ console/src/main/java/org/apache/sync...

Author: andreapatricelli
Date: Fri Jul 11 13:53:08 2014
New Revision: 1609715

URL: http://svn.apache.org/r1609715
Log:
merge from branch 1_2_X

Modified:
    syncope/trunk/   (props changed)
    syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserSelfService.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/types/PasswordPolicySpec.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/util/AttributableOperations.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.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/UserSelfModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserDetailsPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserSelfRestClient.java
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_it.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_pt_BR.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.html
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_it.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_pt_BR.properties
    syncope/trunk/console/src/test/java/org/apache/syncope/console/UserTestITCase.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/validation/entity/SyncopeUserValidator.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractSubjectController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.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/services/UserSelfServiceImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.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/UserSelfTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirAttrTestITCase.java
    syncope/trunk/core/src/test/resources/content.xml

Propchange: syncope/trunk/
------------------------------------------------------------------------------
  Merged /syncope/branches/1_2_X:r1608412-1609714

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserSelfService.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserSelfService.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserSelfService.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserSelfService.java Fri Jul 11 13:53:08 2014
@@ -21,12 +21,14 @@ package org.apache.syncope.common.servic
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.OPTIONS;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.cxf.jaxrs.model.wadl.Description;
@@ -67,6 +69,7 @@ public interface UserSelfService extends
      * Self-registration for new user.
      *
      * @param userTO user to be created
+     * @param storePassword whether password shall be stored internally
      * @return <tt>Response</tt> object featuring <tt>Location</tt> header of self-registered user as well as the user
      * itself - {@link UserTO} as <tt>Entity</tt>
      */
@@ -78,7 +81,8 @@ public interface UserSelfService extends
     @POST
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    Response create(@NotNull UserTO userTO);
+    Response create(@NotNull UserTO userTO,
+            @DefaultValue("true") @QueryParam("storePassword") boolean storePassword);
 
     /**
      * Self-updates user.

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java Fri Jul 11 13:53:08 2014
@@ -199,6 +199,7 @@ public interface UserService extends JAX
      * Creates a new user.
      *
      * @param userTO user to be created
+     * @param storePassword whether password shall be stored internally
      * @return <tt>Response</tt> object featuring <tt>Location</tt> header of created user as well as the user itself
      * enriched with propagation status information - {@link UserTO} as <tt>Entity</tt>
      */
@@ -210,7 +211,8 @@ public interface UserService extends JAX
     @POST
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    Response create(@NotNull UserTO userTO);
+    Response create(@NotNull UserTO userTO,
+            @DefaultValue("true") @QueryParam("storePassword") boolean storePassword);
 
     /**
      * Updates user matching the provided userId.

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/types/PasswordPolicySpec.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/types/PasswordPolicySpec.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/types/PasswordPolicySpec.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/types/PasswordPolicySpec.java Fri Jul 11 13:53:08 2014
@@ -143,6 +143,11 @@ public class PasswordPolicySpec extends 
     private boolean mustntEndWithAlpha;
 
     /**
+     * Specify if password shall not be stored internally.
+     */
+    private boolean allowNullPassword;
+
+    /**
      * Substrings not permitted as prefix.
      */
     private List<String> prefixesNotPermitted;
@@ -351,4 +356,12 @@ public class PasswordPolicySpec extends 
     public void setHistoryLength(final int historyLength) {
         this.historyLength = historyLength;
     }
+
+    public boolean isAllowNullPassword() {
+        return allowNullPassword;
+    }
+
+    public void setAllowNullPassword(final boolean allowNullPassword) {
+        this.allowNullPassword = allowNullPassword;
+    }
 }

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/util/AttributableOperations.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/util/AttributableOperations.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/util/AttributableOperations.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/util/AttributableOperations.java Fri Jul 11 13:53:08 2014
@@ -224,7 +224,8 @@ public final class AttributableOperation
         diff(updated, original, result, incremental);
 
         // 1. password
-        if (original.getPassword() != null && !original.getPassword().equals(updated.getPassword())) {
+        if (updated.getPassword() != null && (original.getPassword() == null || !original.getPassword().
+                equals(updated.getPassword()))) {
             result.setPassword(updated.getPassword());
         }
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java Fri Jul 11 13:53:08 2014
@@ -81,7 +81,7 @@ public class EditUserModalPage extends U
         final UserTO updatedUserTO = (UserTO) form.getModelObject();
 
         if (updatedUserTO.getId() == 0) {
-            userTO = userRestClient.create(updatedUserTO);
+            userTO = userRestClient.create(updatedUserTO, storePassword.getModelObject());
         } else {
             final UserMod userMod = AttributableOperations.diff(updatedUserTO, initialUserTO);
 

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=1609715&r1=1609714&r2=1609715&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 Fri Jul 11 13:53:08 2014
@@ -26,6 +26,7 @@ import org.apache.syncope.console.pages.
 import org.apache.syncope.console.pages.panels.ResourcesPanel;
 import org.apache.syncope.console.pages.panels.UserDetailsPanel;
 import org.apache.syncope.console.pages.panels.VirtualAttributesPanel;
+import org.apache.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
@@ -66,6 +67,8 @@ public abstract class UserModalPage exte
 
     private final boolean resetPassword;
 
+    protected final AjaxCheckBoxPanel storePassword;
+
     public UserModalPage(final PageReference callerPageRef, final ModalWindow window, final UserTO userTO,
             final Mode mode, final boolean resetPassword) {
 
@@ -80,6 +83,9 @@ public abstract class UserModalPage exte
         fragment = new Fragment("userModalFrag", "userModalEditFrag", this);
         fragment.setOutputMarkupId(true);
         add(fragment);
+
+        storePassword = new AjaxCheckBoxPanel("storePassword", "storePassword",
+                new Model<Boolean>(Boolean.TRUE));
     }
 
     public UserTO getUserTO() {
@@ -116,6 +122,18 @@ public abstract class UserModalPage exte
         //--------------------------------
 
         //--------------------------------
+        // Store password internally checkbox
+        //--------------------------------
+        final Fragment storePwdFragment = new Fragment("storePwdFrag", "storePwdCheck", form);
+        storePwdFragment.setOutputMarkupId(true);
+        final Label storePasswordLabel = new Label("storePasswordLabel", new ResourceModel("storePassword"));
+        storePwdFragment.add(storePasswordLabel);
+        storePwdFragment.add(storePassword);
+        form.add(userTO.getId() == 0 && mode != Mode.TEMPLATE ? storePwdFragment : new Fragment("storePwdFrag",
+                "emptyFragment", form));
+        //--------------------------------
+
+        //--------------------------------
         // Attributes panel
         //--------------------------------
         form.add(new AttributesPanel("attrs", userTO, form, mode == Mode.TEMPLATE));

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserSelfModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserSelfModalPage.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserSelfModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserSelfModalPage.java Fri Jul 11 13:53:08 2014
@@ -23,6 +23,7 @@ import org.apache.syncope.common.mod.Use
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.common.util.AttributableOperations;
 import org.apache.syncope.console.rest.UserSelfRestClient;
+import org.apache.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
@@ -53,7 +54,7 @@ public class UserSelfModalPage extends U
         final UserTO updatedUserTO = (UserTO) form.getModelObject();
 
         if (updatedUserTO.getId() == 0) {
-            restClient.create(updatedUserTO);
+            restClient.create(updatedUserTO, storePassword.getModelObject());
         } else {
             final UserMod userMod = AttributableOperations.diff(updatedUserTO, initialUserTO);
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserDetailsPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserDetailsPanel.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserDetailsPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserDetailsPanel.java Fri Jul 11 13:53:08 2014
@@ -20,6 +20,8 @@ package org.apache.syncope.console.pages
 
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.console.commons.JexlHelpUtil;
+import org.apache.syncope.console.pages.UserModalPage;
+import org.apache.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel;
 import org.apache.syncope.console.wicket.markup.html.form.AjaxPasswordFieldPanel;
 import org.apache.syncope.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.console.wicket.markup.html.form.FieldPanel;
@@ -89,14 +91,12 @@ public class UserDetailsPanel extends Pa
 
             password = new AjaxPasswordFieldPanel("password", "password",
                     new PropertyModel<String>(userTO, "password"));
-            password.setRequired(userTO.getId() == 0);
             ((PasswordTextField) password.getField()).setResetPassword(resetPassword);
 
             confirmPassword = new AjaxPasswordFieldPanel("confirmPassword", "confirmPassword", new Model<String>());
             if (!resetPassword) {
                 confirmPassword.getField().setModelObject(userTO.getPassword());
             }
-            confirmPassword.setRequired(userTO.getId() == 0);
             ((PasswordTextField) confirmPassword.getField()).setResetPassword(resetPassword);
 
             form.add(new EqualPasswordInputValidator(password.getField(), confirmPassword.getField()));

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java Fri Jul 11 13:53:08 2014
@@ -58,8 +58,8 @@ public class UserRestClient extends Abst
         return getService(UserService.class).list(page, size, toOrderBy(sort)).getResult();
     }
 
-    public UserTO create(final UserTO userTO) {
-        Response response = getService(UserService.class).create(userTO);
+    public UserTO create(final UserTO userTO, final boolean storePassword) {
+        Response response = getService(UserService.class).create(userTO, storePassword);
         return response.readEntity(UserTO.class);
     }
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserSelfRestClient.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserSelfRestClient.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserSelfRestClient.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserSelfRestClient.java Fri Jul 11 13:53:08 2014
@@ -47,8 +47,8 @@ public class UserSelfRestClient extends 
         return getService(UserSelfService.class).read();
     }
 
-    public void create(final UserTO userTO) {
-        getService(UserSelfService.class).create(userTO);
+    public void create(final UserTO userTO, final boolean storePassword) {
+        getService(UserSelfService.class).create(userTO, storePassword);
     }
 
     public void update(final UserMod userMod) {

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage.properties
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage.properties?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage.properties Fri Jul 11 13:53:08 2014
@@ -50,6 +50,7 @@ mustEndWithNonAlpha=Must end with non al
 mustEndWithAlpha=Must end with alphanumeric character
 mustntEndWithNonAlpha=Mustn't end with non alphanumeric character
 mustntEndWithAlpha=Mustn't end with alphanumeric character
+allowNullPassword=Password may be not stored internally
 #-----------------------------
 
 #-----------------------------

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_it.properties
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_it.properties?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_it.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_it.properties Fri Jul 11 13:53:08 2014
@@ -48,6 +48,7 @@ mustEndWithNonAlpha=Deve terminare con u
 mustEndWithAlpha=Deve terminare con un carattere alfanumerico
 mustntEndWithNonAlpha=Non deve terminare con un carattere non alfanumerico
 mustntEndWithAlpha=Non deve terminare con un carattere alfanumerico
+allowNullPassword=La password pu\u00f2 non essere memorizzata internamente
 #-----------------------------
 
 #-----------------------------

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_pt_BR.properties
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_pt_BR.properties?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_pt_BR.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/PolicyModalPage_pt_BR.properties Fri Jul 11 13:53:08 2014
@@ -50,6 +50,7 @@ mustEndWithNonAlpha=Precisa terminar com
 mustEndWithAlpha=Precisa terminar com um caractere alfanum\u00e9rico
 mustntEndWithNonAlpha=N\u00e3o deve terminar com um caractere n\u00e3o alfanum\u00e9rico
 mustntEndWithAlpha=N\u00e3o precisa terminar com um caracter alfanum\u00e9rico
+allowNullPassword=A senha n\u00e3o pode ser armazenado internamente
 #-----------------------------
 
 #-----------------------------

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.html
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.html?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.html (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.html Fri Jul 11 13:53:08 2014
@@ -40,6 +40,19 @@ under the License.
             </ul>
             <div id="tabs-1">
               <span wicket:id="details">[user details]</span>
+              <span wicket:id="storePwdFrag">[storePwdFrag]</span>
+              <wicket:fragment wicket:id="storePwdCheck">
+                <div class="tablerow alt">
+                  <div class="tablecolumn_label short_dynamicsize">
+                    <span wicket:id="storePasswordLabel">[storePasswordLabel]</span>
+                  </div>
+                  <div class="tablecolumn_field medium_dynamicsize">
+                    <span wicket:id="storePassword">[storePassword]</span>
+                  </div>
+                </div>
+              </wicket:fragment>
+              <wicket:fragment wicket:id="emptyFragment">
+              </wicket:fragment>
               <div wicket:id="pwdChangeInfo" style="margin-top: 25px;">[pwdChangeInfo]</div>
               <span wicket:id="statuspanel">[Status Panel]</span>
               <span wicket:id="accountinformation">[Account Information]</span>

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.properties
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.properties?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage.properties Fri Jul 11 13:53:08 2014
@@ -48,3 +48,5 @@ virAttrValue=Virtual value
 addAttributeBtn=Add
 new=New
 pwdChangeInfo=If provided, the password will be changed on the following resources.
+
+storePassword=Store password internally

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_it.properties
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_it.properties?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_it.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_it.properties Fri Jul 11 13:53:08 2014
@@ -49,3 +49,5 @@ addAttributeBtn=Aggiungi
 
 new=Nuovo
 pwdChangeInfo=Se inserita, la password verr\u00e0 cambiata sulle seguenti risorse.
+
+storePassword=Salva la password internamente

Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_pt_BR.properties
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_pt_BR.properties?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_pt_BR.properties (original)
+++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/UserModalPage_pt_BR.properties Fri Jul 11 13:53:08 2014
@@ -48,3 +48,5 @@ virAttrValue=Valor Virtual
 addAttributeBtn=Adicionar
 new=Novo
 pwdChangeInfo=Se provida, a senha ser\u00e1 alterada nos seguintes recursos
+
+storePassword=Salvar senha internamente

Modified: syncope/trunk/console/src/test/java/org/apache/syncope/console/UserTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/test/java/org/apache/syncope/console/UserTestITCase.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/console/src/test/java/org/apache/syncope/console/UserTestITCase.java (original)
+++ syncope/trunk/console/src/test/java/org/apache/syncope/console/UserTestITCase.java Fri Jul 11 13:53:08 2014
@@ -37,6 +37,8 @@ public class UserTestITCase extends Abst
         selenium.waitForCondition("selenium.isElementPresent("
                 + "\"//span[contains(text(),'Attributes')]\");", "30000");
 
+        selenium.click("//div/form/div[3]/div[1]/span[2]/div/div[2]/span");
+        
         selenium.click("//div[@id='tabs']/ul/li[2]/a/span");
         selenium.click("//div[@id='tabs']/ul/li[3]/a/span");
         selenium.click("//div[@id='tabs']/ul/li[4]/a/span");

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=1609715&r1=1609714&r2=1609715&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 Fri Jul 11 13:53:08 2014
@@ -72,7 +72,7 @@ public class SyncopeUser extends Abstrac
     @Id
     private Long id;
 
-    @NotNull(message = "Blank password")
+    @Column(nullable = true)
     private String password;
 
     @Transient
@@ -154,7 +154,7 @@ public class SyncopeUser extends Abstrac
             @JoinColumn(name = "resource_name"))
     @Valid
     private Set<ExternalResource> resources;
-
+    
     public SyncopeUser() {
         super();
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java Fri Jul 11 13:53:08 2014
@@ -67,42 +67,40 @@ public class SyncopeUserValidator extend
         // ------------------------------
         LOG.debug("Password Policy enforcement");
 
-        if (user.getClearPassword() != null) {
-            try {
-                int maxPPSpecHistory = 0;
-                for (Policy policy : getPasswordPolicies(user)) {
-                    // evaluate policy
-                    final PasswordPolicySpec ppSpec = evaluator.evaluate(policy, user);
-                    // enforce policy
-                    ppEnforcer.enforce(ppSpec, policy.getType(), user.getClearPassword());
-
-                    if (ppSpec.getHistoryLength() > maxPPSpecHistory) {
-                        maxPPSpecHistory = ppSpec.getHistoryLength();
-                    }
-                }
+        try {
+            int maxPPSpecHistory = 0;
+            for (Policy policy : getPasswordPolicies(user)) {
+                // evaluate policy
+                final PasswordPolicySpec ppSpec = evaluator.evaluate(policy, user);
+                // enforce policy
+                ppEnforcer.enforce(ppSpec, policy.getType(), user);
 
-                // update user's password history with encrypted password
-                if (maxPPSpecHistory > 0 && user.getPassword() != null) {
-                    user.getPasswordHistory().add(user.getPassword());
-                }
-                // keep only the last maxPPSpecHistory items in user's password history
-                if (maxPPSpecHistory < user.getPasswordHistory().size()) {
-                    for (int i = 0; i < user.getPasswordHistory().size() - maxPPSpecHistory; i++) {
-                        user.getPasswordHistory().remove(i);
-                    }
+                if (ppSpec.getHistoryLength() > maxPPSpecHistory) {
+                    maxPPSpecHistory = ppSpec.getHistoryLength();
                 }
-            } catch (Exception e) {
-                LOG.debug("Invalid password");
+            }
 
-                context.buildConstraintViolationWithTemplate(
-                        getTemplate(EntityViolationType.InvalidPassword, e.getMessage())).
-                        addPropertyNode("password").addConstraintViolation();
-
-                return false;
-            } finally {
-                // password has been validated, let's remove its clear version
-                user.removeClearPassword();
+            // update user's password history with encrypted password
+            if (maxPPSpecHistory > 0 && user.getPassword() != null) {
+                user.getPasswordHistory().add(user.getPassword());
+            }
+            // keep only the last maxPPSpecHistory items in user's password history
+            if (maxPPSpecHistory < user.getPasswordHistory().size()) {
+                for (int i = 0; i < user.getPasswordHistory().size() - maxPPSpecHistory; i++) {
+                    user.getPasswordHistory().remove(i);
+                }
             }
+        } catch (Exception e) {
+            LOG.debug("Invalid password");
+
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidPassword, e.getMessage())).
+                    addPropertyNode("password").addConstraintViolation();
+
+            return false;
+        } finally {
+            // password has been validated, let's remove its clear version
+            user.removeClearPassword();
         }
         // ------------------------------
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java Fri Jul 11 13:53:08 2014
@@ -20,133 +20,139 @@ package org.apache.syncope.core.policy;
 
 import org.apache.syncope.common.types.PasswordPolicySpec;
 import org.apache.syncope.common.types.PolicyType;
+import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.springframework.stereotype.Component;
 
 @Component
-public class PasswordPolicyEnforcer extends PolicyEnforcer<PasswordPolicySpec, String> {
+public class PasswordPolicyEnforcer extends PolicyEnforcer<PasswordPolicySpec, SyncopeUser> {
 
     /* (non-Javadoc)
-	 * @see org.apache.syncope.core.policy.PasswordPolicyEnforcer#enforce(org.apache.syncope.common.types.PasswordPolicySpec, org.apache.syncope.common.types.PolicyType, java.lang.String)
-	 */
-	@Override
-    public void enforce(final PasswordPolicySpec policy, final PolicyType type, final String password)
+     * @see
+     * org.apache.syncope.core.policy.PasswordPolicyEnforcer#enforce(org.apache.syncope.common.types.PasswordPolicySpec,
+     * org.apache.syncope.common.types.PolicyType, java.lang.String)
+     */
+    @Override
+    public void enforce(final PasswordPolicySpec policy, final PolicyType type, final SyncopeUser user)
             throws PasswordPolicyException, PolicyEnforceException {
 
-        if (password == null) {
-            throw new PolicyEnforceException("Invalid password");
-        }
+        final String clearPassword = user.getClearPassword();
+        final String password = user.getPassword();
 
         if (policy == null) {
             throw new PolicyEnforceException("Invalid policy");
         }
 
-        // check length
-        if (policy.getMinLength() > 0 && policy.getMinLength() > password.length()) {
-            throw new PasswordPolicyException("Password too short");
-        }
+        if (password == null && !policy.isAllowNullPassword()) {
+            throw new PolicyEnforceException("Password must not be null and must be stored internally");
+        } else if (password != null && clearPassword != null) {
+            // check length
+            if (policy.getMinLength() > 0 && policy.getMinLength() > clearPassword.length()) {
+                throw new PasswordPolicyException("Password too short");
+            }
 
-        if (policy.getMaxLength() > 0 && policy.getMaxLength() < password.length()) {
-            throw new PasswordPolicyException("Password too long");
-        }
+            if (policy.getMaxLength() > 0 && policy.getMaxLength() < clearPassword.length()) {
+                throw new PasswordPolicyException("Password too long");
+            }
 
-        // check words not permitted
-        for (String word : policy.getWordsNotPermitted()) {
-            if (password.contains(word)) {
-                throw new PasswordPolicyException("Used word(s) not permitted");
+            // check words not permitted
+            for (String word : policy.getWordsNotPermitted()) {
+                if (clearPassword.contains(word)) {
+                    throw new PasswordPolicyException("Used word(s) not permitted");
+                }
             }
-        }
 
-        // check digits occurrence
-        if (policy.isDigitRequired() && !checkForDigit(password)) {
-            throw new PasswordPolicyException("Password must contain digit(s)");
-        }
+            // check digits occurrence
+            if (policy.isDigitRequired() && !checkForDigit(clearPassword)) {
+                throw new PasswordPolicyException("Password must contain digit(s)");
+            }
 
-        // check lowercase alphabetic characters occurrence
-        if (policy.isLowercaseRequired() && !checkForLowercase(password)) {
-            throw new PasswordPolicyException("Password must contain lowercase alphabetic character(s)");
-        }
+            // check lowercase alphabetic characters occurrence
+            if (policy.isLowercaseRequired() && !checkForLowercase(clearPassword)) {
+                throw new PasswordPolicyException("Password must contain lowercase alphabetic character(s)");
+            }
 
-        // check uppercase alphabetic characters occurrence
-        if (policy.isUppercaseRequired() && !checkForUppercase(password)) {
-            throw new PasswordPolicyException("Password must contain uppercase alphabetic character(s)");
-        }
+            // check uppercase alphabetic characters occurrence
+            if (policy.isUppercaseRequired() && !checkForUppercase(clearPassword)) {
+                throw new PasswordPolicyException("Password must contain uppercase alphabetic character(s)");
+            }
 
-        // check prefix
-        for (String prefix : policy.getPrefixesNotPermitted()) {
-            if (password.startsWith(prefix)) {
-                throw new PasswordPolicyException("Prefix not permitted");
+            // check prefix
+            for (String prefix : policy.getPrefixesNotPermitted()) {
+                if (clearPassword.startsWith(prefix)) {
+                    throw new PasswordPolicyException("Prefix not permitted");
+                }
             }
-        }
 
-        // check suffix
-        for (String suffix : policy.getSuffixesNotPermitted()) {
-            if (password.endsWith(suffix)) {
-                throw new PasswordPolicyException("Suffix not permitted");
+            // check suffix
+            for (String suffix : policy.getSuffixesNotPermitted()) {
+                if (clearPassword.endsWith(suffix)) {
+                    throw new PasswordPolicyException("Suffix not permitted");
+                }
             }
-        }
 
-        // check digit first occurrence
-        if (policy.isMustStartWithDigit() && !checkForFirstDigit(password)) {
-            throw new PasswordPolicyException("Password must start with a digit");
-        }
+            // check digit first occurrence
+            if (policy.isMustStartWithDigit() && !checkForFirstDigit(clearPassword)) {
+                throw new PasswordPolicyException("Password must start with a digit");
+            }
 
-        if (policy.isMustntStartWithDigit() && checkForFirstDigit(password)) {
-            throw new PasswordPolicyException("Password mustn't start with a digit");
-        }
+            if (policy.isMustntStartWithDigit() && checkForFirstDigit(clearPassword)) {
+                throw new PasswordPolicyException("Password mustn't start with a digit");
+            }
 
-        // check digit last occurrence
-        if (policy.isMustEndWithDigit() && !checkForLastDigit(password)) {
-            throw new PasswordPolicyException("Password must end with a digit");
-        }
+            // check digit last occurrence
+            if (policy.isMustEndWithDigit() && !checkForLastDigit(clearPassword)) {
+                throw new PasswordPolicyException("Password must end with a digit");
+            }
 
-        if (policy.isMustntEndWithDigit() && checkForLastDigit(password)) {
-            throw new PasswordPolicyException("Password mustn't end with a digit");
-        }
+            if (policy.isMustntEndWithDigit() && checkForLastDigit(clearPassword)) {
+                throw new PasswordPolicyException("Password mustn't end with a digit");
+            }
 
-        // check alphanumeric characters occurence
-        if (policy.isAlphanumericRequired() && !checkForAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password must contain alphanumeric character(s)");
-        }
+            // check alphanumeric characters occurence
+            if (policy.isAlphanumericRequired() && !checkForAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password must contain alphanumeric character(s)");
+            }
 
-        // check non alphanumeric characters occurence
-        if (policy.isNonAlphanumericRequired() && !checkForNonAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password must contain non-alphanumeric character(s)");
-        }
+            // check non alphanumeric characters occurence
+            if (policy.isNonAlphanumericRequired() && !checkForNonAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password must contain non-alphanumeric character(s)");
+            }
 
-        // check alphanumeric character first occurrence
-        if (policy.isMustStartWithAlpha() && !checkForFirstAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password must start with an alphanumeric character");
-        }
+            // check alphanumeric character first occurrence
+            if (policy.isMustStartWithAlpha() && !checkForFirstAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password must start with an alphanumeric character");
+            }
 
-        if (policy.isMustntStartWithAlpha() && checkForFirstAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password mustn't start with an alphanumeric character");
-        }
+            if (policy.isMustntStartWithAlpha() && checkForFirstAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password mustn't start with an alphanumeric character");
+            }
 
-        // check alphanumeric character last occurrence
-        if (policy.isMustEndWithAlpha() && !checkForLastAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password must end with an alphanumeric character");
-        }
+            // check alphanumeric character last occurrence
+            if (policy.isMustEndWithAlpha() && !checkForLastAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password must end with an alphanumeric character");
+            }
 
-        if (policy.isMustntEndWithAlpha() && checkForLastAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password mustn't end with an alphanumeric character");
-        }
+            if (policy.isMustntEndWithAlpha() && checkForLastAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password mustn't end with an alphanumeric character");
+            }
 
-        // check non alphanumeric character first occurrence
-        if (policy.isMustStartWithNonAlpha() && !checkForFirstNonAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password must start with a non-alphanumeric character");
-        }
+            // check non alphanumeric character first occurrence
+            if (policy.isMustStartWithNonAlpha() && !checkForFirstNonAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password must start with a non-alphanumeric character");
+            }
 
-        if (policy.isMustntStartWithNonAlpha() && checkForFirstNonAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password mustn't start with a non-alphanumeric character");
-        }
+            if (policy.isMustntStartWithNonAlpha() && checkForFirstNonAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password mustn't start with a non-alphanumeric character");
+            }
 
-        // check non alphanumeric character last occurrence
-        if (policy.isMustEndWithNonAlpha() && !checkForLastNonAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password must end with a non-alphanumeric character");
-        }
+            // check non alphanumeric character last occurrence
+            if (policy.isMustEndWithNonAlpha() && !checkForLastNonAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password must end with a non-alphanumeric character");
+            }
 
-        if (policy.isMustntEndWithNonAlpha() && checkForLastNonAlphanumeric(password)) {
-            throw new PasswordPolicyException("Password mustn't end with a non-alphanumeric character");
+            if (policy.isMustntEndWithNonAlpha() && checkForLastNonAlphanumeric(clearPassword)) {
+                throw new PasswordPolicyException("Password mustn't end with a non-alphanumeric character");
+            }
         }
     }
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractSubjectController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractSubjectController.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractSubjectController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractSubjectController.java Fri Jul 11 13:53:08 2014
@@ -31,8 +31,6 @@ public abstract class AbstractSubjectCon
 
     public abstract int count();
 
-    public abstract T create(T attributableTO);
-
     public abstract T update(V attributableMod);
 
     public abstract T delete(Long id);

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java Fri Jul 11 13:53:08 2014
@@ -223,7 +223,6 @@ public class RoleController extends Abst
     }
 
     @PreAuthorize("hasRole('ROLE_CREATE')")
-    @Override
     public RoleTO create(final RoleTO roleTO) {
         // Check that this operation is allowed to be performed by caller
         Set<Long> allowedRoleIds = EntitlementUtil.getRoleIds(EntitlementUtil.getOwnedEntitlementNames());

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java Fri Jul 11 13:53:08 2014
@@ -180,13 +180,12 @@ public class UserController extends Abst
     }
 
     @PreAuthorize("isAnonymous() or hasRole(T(org.apache.syncope.common.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
-    public UserTO createSelf(final UserTO userTO) {
-        return doCreate(userTO);
+    public UserTO createSelf(final UserTO userTO, final boolean storePassword) {
+        return doCreate(userTO, storePassword);
     }
 
     @PreAuthorize("hasRole('USER_CREATE')")
-    @Override
-    public UserTO create(final UserTO userTO) {
+    public UserTO create(final UserTO userTO, final boolean storePassword) {
         Set<Long> requestRoleIds = new HashSet<Long>(userTO.getMemberships().size());
         for (MembershipTO membership : userTO.getMemberships()) {
             requestRoleIds.add(membership.getRoleId());
@@ -197,10 +196,10 @@ public class UserController extends Abst
             throw new UnauthorizedRoleException(requestRoleIds);
         }
 
-        return doCreate(userTO);
+        return doCreate(userTO, storePassword);
     }
 
-    protected UserTO doCreate(final UserTO userTO) {
+    protected UserTO doCreate(final UserTO userTO, final boolean storePassword) {
         // Attributable transformation (if configured)
         UserTO actual = attrTransformer.transform(userTO);
         LOG.debug("Transformed: {}", actual);
@@ -208,7 +207,7 @@ public class UserController extends Abst
         /*
          * Actual operations: workflow, propagation, notification
          */
-        WorkflowResult<Map.Entry<Long, Boolean>> created = uwfAdapter.create(actual);
+        WorkflowResult<Map.Entry<Long, Boolean>> created = uwfAdapter.create(actual, storePassword);
 
         List<PropagationTask> tasks = propagationManager.getUserCreateTaskIds(
                 created, actual.getPassword(), actual.getVirAttrs(), actual.getMemberships());

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=1609715&r1=1609714&r2=1609715&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 Fri Jul 11 13:53:08 2014
@@ -218,7 +218,7 @@ public class UserDataBinder extends Abst
         }
     }
 
-    public void create(final SyncopeUser user, final UserTO userTO) {
+    public void create(final SyncopeUser user, final UserTO userTO, final boolean storePassword) {
         SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
 
         // memberships
@@ -253,8 +253,8 @@ public class UserDataBinder extends Abst
         fill(user, userTO, AttributableUtil.getInstance(AttributableType.USER), scce);
 
         // set password
-        if (StringUtils.isBlank(userTO.getPassword())) {
-            LOG.error("No password provided");
+        if (StringUtils.isBlank(userTO.getPassword()) || !storePassword) {
+            LOG.debug("Password was not provided or not required to be stored");
         } else {
             setPassword(user, userTO.getPassword(), scce);
         }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java Fri Jul 11 13:53:08 2014
@@ -44,14 +44,14 @@ public class UserSelfServiceImpl extends
     }
 
     @Override
-    public Response create(final UserTO userTO) {
+    public Response create(final UserTO userTO, final boolean storePassword) {
         if (!controller.isSelfRegistrationAllowed()) {
             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unauthorized);
             sce.getElements().add("SelfRegistration forbidden by configuration");
             throw sce;
         }
 
-        UserTO created = controller.createSelf(userTO);
+        UserTO created = controller.createSelf(userTO, storePassword);
         return createResponse(created.getId(), created);
     }
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java Fri Jul 11 13:53:08 2014
@@ -62,8 +62,8 @@ public class UserServiceImpl extends Abs
     }
 
     @Override
-    public Response create(final UserTO userTO) {
-        UserTO created = controller.create(userTO);
+    public Response create(final UserTO userTO, final boolean storePassword) {
+        UserTO created = controller.create(userTO, storePassword);
         return createResponse(created.getId(), created);
     }
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java Fri Jul 11 13:53:08 2014
@@ -81,7 +81,7 @@ public class UserSyncResultHandler exten
 
         Boolean enabled = syncUtilities.readEnabled(delta.getObject(), profile.getSyncTask());
         WorkflowResult<Map.Entry<Long, Boolean>> created =
-                uwfAdapter.create(userTO, true, enabled);
+                uwfAdapter.create(userTO, true, enabled, true);
 
         List<PropagationTask> tasks = propagationManager.getUserCreateTaskIds(created,
                 userTO.getPassword(), userTO.getVirAttrs(),

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java Fri Jul 11 13:53:08 2014
@@ -351,8 +351,6 @@ public final class MappingUtil {
                             passwordAttrValue = passwordGenerator.generate(user);
                         } catch (InvalidPasswordPolicySpecException e) {
                             LOG.error("Could not generate policy-compliant random password for {}", user, e);
-
-                            passwordAttrValue = SecureRandomUtil.generateRandomPassword(16);
                         }
                     }
                 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java Fri Jul 11 13:53:08 2014
@@ -62,10 +62,10 @@ public abstract class AbstractUserWorkfl
     }
 
     @Override
-    public WorkflowResult<Entry<Long, Boolean>> create(final UserTO userTO)
+    public WorkflowResult<Entry<Long, Boolean>> create(final UserTO userTO, final boolean storePassword)
             throws UnauthorizedRoleException, WorkflowException {
 
-        return create(userTO, false);
+        return create(userTO, false, storePassword);
     }
 
     protected abstract WorkflowResult<Long> doActivate(SyncopeUser user, String token) throws WorkflowException;

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java Fri Jul 11 13:53:08 2014
@@ -47,19 +47,19 @@ public class NoOpUserWorkflowAdapter ext
     public static final String ENABLED = "enabled";
 
     @Override
-    public WorkflowResult<Map.Entry<Long, Boolean>> create(final UserTO userTO, final boolean disablePwdPolicyCheck)
+    public WorkflowResult<Map.Entry<Long, Boolean>> create(final UserTO userTO, final boolean disablePwdPolicyCheck,
+            final boolean storePassword)
             throws WorkflowException {
 
-        return create(userTO, disablePwdPolicyCheck, null);
+        return create(userTO, disablePwdPolicyCheck, null, storePassword);
     }
 
     @Override
     public WorkflowResult<Map.Entry<Long, Boolean>> create(final UserTO userTO, final boolean disablePwdPolicyCheck,
-            final Boolean enabled)
-            throws WorkflowException {
+            final Boolean enabled, final boolean storePassword) throws WorkflowException {
 
         SyncopeUser user = new SyncopeUser();
-        dataBinder.create(user, userTO);
+        dataBinder.create(user, userTO, storePassword);
 
         // this will make SyncopeUserValidator not to consider password policies at all
         if (disablePwdPolicyCheck) {

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java Fri Jul 11 13:53:08 2014
@@ -36,23 +36,26 @@ public interface UserWorkflowAdapter ext
      * Create an user.
      *
      * @param userTO user to be created and wether to propagate it as active
+     * @param storePassword whether password shall be stored into the internal storage
      * @return user just created
      * @throws UnauthorizedRoleException authorization exception
      * @throws WorkflowException workflow exception
      */
-    WorkflowResult<Map.Entry<Long, Boolean>> create(UserTO userTO) throws UnauthorizedRoleException, WorkflowException;
+    WorkflowResult<Map.Entry<Long, Boolean>> create(UserTO userTO, boolean storePassword) throws
+            UnauthorizedRoleException, WorkflowException;
 
     /**
      * Create an user, optionally disabling password policy check.
      *
      * @param userTO user to be created and wether to propagate it as active
      * @param disablePwdPolicyCheck disable password policy check?
+     * @param storePassword whether password shall be stored into the internal storage
      * @return user just created
      * @throws UnauthorizedRoleException authorization exception
      * @throws WorkflowException workflow exception
      */
-    WorkflowResult<Map.Entry<Long, Boolean>> create(UserTO userTO, boolean disablePwdPolicyCheck)
-            throws UnauthorizedRoleException, WorkflowException;
+    WorkflowResult<Map.Entry<Long, Boolean>> create(UserTO userTO, boolean disablePwdPolicyCheck,
+            boolean storePassword) throws UnauthorizedRoleException, WorkflowException;
 
     /**
      * Create an user, optionally disabling password policy check.
@@ -60,12 +63,13 @@ public interface UserWorkflowAdapter ext
      * @param userTO user to be created and wether to propagate it as active
      * @param disablePwdPolicyCheck disable password policy check?
      * @param enabled specify true/false to force active/supended status
+     * @param storePassword whether password shall be stored into the internal storage
      * @return user just created
      * @throws UnauthorizedRoleException authorization exception
      * @throws WorkflowException workflow exception
      */
-    WorkflowResult<Map.Entry<Long, Boolean>> create(UserTO userTO, boolean disablePwdPolicyCheck, final Boolean enabled)
-            throws UnauthorizedRoleException, WorkflowException;
+    WorkflowResult<Map.Entry<Long, Boolean>> create(UserTO userTO, boolean disablePwdPolicyCheck, final Boolean enabled,
+            boolean storePassword) throws UnauthorizedRoleException, WorkflowException;
 
     /**
      * Execute a task on an user.

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java Fri Jul 11 13:53:08 2014
@@ -124,6 +124,8 @@ public class ActivitiUserWorkflowAdapter
     public static final String TASK_IS_FORM = "taskIsForm";
 
     public static final String MODEL_DATA_JSON_MODEL = "model";
+    
+    public static final String STORE_PASSWORD = "storePassword";
 
     @Resource(name = "adminUser")
     private String adminUser;
@@ -225,21 +227,21 @@ public class ActivitiUserWorkflowAdapter
     }
 
     @Override
-    public WorkflowResult<Map.Entry<Long, Boolean>> create(final UserTO userTO, final boolean disablePwdPolicyCheck)
-            throws WorkflowException {
+    public WorkflowResult<Map.Entry<Long, Boolean>> create(final UserTO userTO, final boolean disablePwdPolicyCheck,
+            final boolean storePassword) throws WorkflowException {
 
-        return create(userTO, disablePwdPolicyCheck, null);
+        return create(userTO, disablePwdPolicyCheck, null, storePassword);
     }
 
     @Override
     public WorkflowResult<Map.Entry<Long, Boolean>> create(final UserTO userTO, final boolean disablePwdPolicyCheck,
-            final Boolean enabled)
-            throws WorkflowException {
+            final Boolean enabled, final boolean storePassword) throws WorkflowException {
 
         final Map<String, Object> variables = new HashMap<String, Object>();
         variables.put(WF_EXECUTOR, EntitlementUtil.getAuthenticatedUsername());
         variables.put(USER_TO, userTO);
         variables.put(ENABLED, enabled);
+        variables.put(STORE_PASSWORD, storePassword);
 
         ProcessInstance processInstance = null;
         try {
@@ -264,7 +266,7 @@ public class ActivitiUserWorkflowAdapter
 
         updateStatus(user);
         user = userDAO.save(user);
-
+        
         Boolean propagateEnable = (Boolean) runtimeService.getVariable(
                 processInstance.getProcessInstanceId(), PROPAGATE_ENABLE);
         if (propagateEnable == null) {

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java Fri Jul 11 13:53:08 2014
@@ -34,10 +34,11 @@ public class Create extends AbstractActi
     @Override
     protected void doExecute(final String executionId) {
         UserTO userTO = (UserTO) runtimeService.getVariable(executionId, ActivitiUserWorkflowAdapter.USER_TO);
-
+        Boolean storePassword = (Boolean) runtimeService.getVariable(executionId,
+                ActivitiUserWorkflowAdapter.STORE_PASSWORD);
         // create and set workflow id
         SyncopeUser user = new SyncopeUser();
-        dataBinder.create(user, userTO);
+        dataBinder.create(user, userTO, storePassword == null ? true : storePassword);
         user.setWorkflowId(executionId);
 
         // report SyncopeUser as result

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java Fri Jul 11 13:53:08 2014
@@ -239,7 +239,7 @@ public class NotificationTest {
         membershipTO.setRoleId(7);
         userTO.getMemberships().add(membershipTO);
 
-        userController.create(userTO);
+        userController.create(userTO, true);
 
         // 3. force Quartz job execution and verify e-mail
         notificationJob.execute(null);
@@ -296,7 +296,7 @@ public class NotificationTest {
         membershipTO.setRoleId(7);
         userTO.getMemberships().add(membershipTO);
 
-        userController.create(userTO);
+        userController.create(userTO, true);
 
         // 3. force Quartz job execution and verify e-mail
         notificationJob.execute(null);
@@ -349,7 +349,7 @@ public class NotificationTest {
         membershipTO.setRoleId(7);
         userTO.getMemberships().add(membershipTO);
 
-        userController.create(userTO);
+        userController.create(userTO, true);
 
         // 3. force Quartz job execution and verify e-mail
         notificationJob.execute(null);
@@ -399,7 +399,7 @@ public class NotificationTest {
         membershipTO.setRoleId(7);
         userTO.getMemberships().add(membershipTO);
 
-        userController.create(userTO);
+        userController.create(userTO, true);
 
         // 3. Set number of retries
         CAttr maxRetries = confDAO.find("notification.maxRetries", "5");
@@ -470,7 +470,7 @@ public class NotificationTest {
         membershipTO.setRoleId(7);
         userTO.getMemberships().add(membershipTO);
 
-        userController.create(userTO);
+        userController.create(userTO, true);
 
         // 3. force Quartz job execution and verify e-mail
         notificationJob.execute(null);
@@ -531,7 +531,7 @@ public class NotificationTest {
         membershipTO.setRoleId(7);
         userTO.getMemberships().add(membershipTO);
 
-        userController.create(userTO);
+        userController.create(userTO, true);
 
         // 3. force Quartz job execution
         notificationJob.execute(null);

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java Fri Jul 11 13:53:08 2014
@@ -189,4 +189,21 @@ public class UserTest extends AbstractDA
         assertNotNull(actual);
     }
 
+    @Test
+    public void issueSYNCOPE391() {
+        SyncopeUser user = new SyncopeUser();
+        user.setUsername("username");
+        user.setPassword(null, CipherAlgorithm.AES, 0);
+
+        SyncopeUser actual = null;
+        Throwable t = null;
+        try {
+            actual = userDAO.save(user);
+        } catch (InvalidEntityException e) {
+            t = e;
+        }
+        assertNull(t);
+        assertNull(user.getPassword());
+        assertNotNull(actual);
+    }
 }

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java Fri Jul 11 13:53:08 2014
@@ -174,7 +174,7 @@ public abstract class AbstractTest {
 
     @Autowired
     protected DataSource testDataSource;
-
+    
     @BeforeClass
     public static void securitySetup() {
         InputStream propStream = null;
@@ -241,7 +241,11 @@ public abstract class AbstractTest {
     }
 
     protected UserTO createUser(final UserTO userTO) {
-        Response response = userService.create(userTO);
+        return createUser(userTO, true);
+    }
+    
+    protected UserTO createUser(final UserTO userTO, final boolean storePassword) {
+        Response response = userService.create(userTO, storePassword);
         if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
             Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
             if (ex != null) {

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=1609715&r1=1609714&r2=1609715&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 Fri Jul 11 13:53:08 2014
@@ -361,7 +361,7 @@ public class AuthenticationTestITCase ex
         membershipTO.setRoleId(1L);
         role1User.getMemberships().add(membershipTO);
 
-        Response response = userService2.create(role1User);
+        Response response = userService2.create(role1User, true);
         assertNotNull(response);
         role1User = response.readEntity(UserTO.class);
         assertNotNull(role1User);

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java?rev=1609715&r1=1609714&r2=1609715&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java Fri Jul 11 13:53:08 2014
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.core.rest;
 
-import static org.apache.syncope.core.rest.UserTestITCase.getUniqueSampleTO;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -68,7 +67,7 @@ public class UserSelfTestITCase extends 
 
         // 1. self-registration as admin: failure
         try {
-            userSelfService.create(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org"));
+            userSelfService.create(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org"), true);
             fail();
         } catch (AccessControlException e) {
             assertNotNull(e);
@@ -77,7 +76,7 @@ public class UserSelfTestITCase extends 
         // 2. self-registration as anonymous: works
         SyncopeClient anonClient = clientFactory.createAnonymous();
         UserTO self = anonClient.getService(UserSelfService.class).
-                create(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org")).
+                create(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org"), true).
                 readEntity(UserTO.class);
         assertNotNull(self);
         assertEquals("createApproval", self.getStatus());
@@ -96,7 +95,7 @@ public class UserSelfTestITCase extends 
 
         SyncopeClient anonClient = clientFactory.createAnonymous();
         userTO = anonClient.getService(UserSelfService.class).
-                create(userTO).
+                create(userTO, true).
                 readEntity(UserTO.class);
         assertNotNull(userTO);
         assertEquals("createApproval", userTO.getStatus());
@@ -242,9 +241,9 @@ public class UserSelfTestITCase extends 
         SyncopeClient anonClient = clientFactory.createAnonymous();
         UserSelfService noContentService = anonClient.prefer(UserSelfService.class, Preference.RETURN_NO_CONTENT);
 
-        UserTO user = getUniqueSampleTO("nocontent-anonymous@syncope.apache.org");
+        UserTO user = UserTestITCase.getUniqueSampleTO("nocontent-anonymous@syncope.apache.org");
 
-        Response response = noContentService.create(user);
+        Response response = noContentService.create(user, true);
         assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
         assertEquals(Preference.RETURN_NO_CONTENT.toString(), response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED));
         assertEquals(StringUtils.EMPTY, IOUtils.toString((InputStream) response.getEntity()));

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=1609715&r1=1609714&r2=1609715&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 Fri Jul 11 13:53:08 2014
@@ -1185,7 +1185,7 @@ public class UserTestITCase extends Abst
 
         UserTO user = getUniqueSampleTO("nocontent@syncope.apache.org");
 
-        Response response = noContentService.create(user);
+        Response response = noContentService.create(user, true);
         assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
         assertEquals(Preference.RETURN_NO_CONTENT.toString(), response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED));
         assertEquals(StringUtils.EMPTY, IOUtils.toString((InputStream) response.getEntity()));
@@ -2129,19 +2129,10 @@ public class UserTestITCase extends Abst
 
     @Test
     public void issueSYNCOPE435() {
-        // 1. try to create user without password - fail
+        // 1. create user without password
         UserTO userTO = getUniqueSampleTO("syncope435@syncope.apache.org");
         userTO.setPassword(null);
-
-        try {
-            createUser(userTO);
-            fail();
-        } catch (SyncopeClientException e) {
-            assertEquals(ClientExceptionType.InvalidSyncopeUser, e.getType());
-        }
-
-        userTO.setPassword("password123");
-        userTO = createUser(userTO);
+        userTO = createUser(userTO, false);
         assertNotNull(userTO);
 
         // 2. try to update user by subscribing a resource - works but propagation is not even attempted
@@ -2157,7 +2148,8 @@ public class UserTestITCase extends Abst
 
     @Test
     public void ifMatch() {
-        UserTO userTO = userService.create(getUniqueSampleTO("ifmatch@syncope.apache.org")).readEntity(UserTO.class);
+        UserTO userTO = userService.create(getUniqueSampleTO("ifmatch@syncope.apache.org"), true).
+                readEntity(UserTO.class);
         assertNotNull(userTO);
         assertNotNull(userTO.getId());
 
@@ -2367,4 +2359,108 @@ public class UserTestITCase extends Abst
         resourceTO.setRandomPwdIfNotProvided(true);
         resourceService.update(RESOURCE_NAME_LDAP, resourceTO);
     }
+
+    @Test
+    public void issueSYNCOPE391() {
+        // 1. create user on Syncope with null password
+        UserTO userTO = getUniqueSampleTO("syncope391@syncope.apache.org");
+        userTO.setPassword(null);
+
+        userTO = createUser(userTO, false);
+        assertNotNull(userTO);
+        assertNull(userTO.getPassword());
+
+        // 2. create existing user on csv and check that password on Syncope is null and that password on resource
+        // doesn't change
+        userTO = new UserTO();
+        userTO.setPassword(null);
+        userTO.setUsername("syncope391@syncope.apache.org");
+        userTO.getAttrs().add(attributeTO("fullname", "fullname"));
+        userTO.getAttrs().add(attributeTO("firstname", "nome0"));
+        userTO.getAttrs().add(attributeTO("surname", "cognome0"));
+        userTO.getAttrs().add(attributeTO("userId", "syncope391@syncope.apache.org"));
+        userTO.getAttrs().add(attributeTO("email", "syncope391@syncope.apache.org"));
+        userTO.getDerAttrs().add(attributeTO("csvuserid", null));
+
+        userTO.getResources().add(RESOURCE_NAME_CSV);
+        userTO = createUser(userTO, false);
+        assertNotNull(userTO);
+
+        ConnObjectTO connObjectTO =
+                resourceService.getConnectorObject(RESOURCE_NAME_CSV, SubjectType.USER, userTO.getId());
+        assertNotNull(connObjectTO);
+
+        // check if password has not changed
+        assertEquals("password0", connObjectTO.getAttrMap().
+                get(OperationalAttributes.PASSWORD_NAME).getValues().get(0));
+        assertNull(userTO.getPassword());
+
+        // 3. create user with not null password and propagate onto resource-csv, specify not to save password on
+        // Syncope local storage
+        userTO = getUniqueSampleTO("syncope391@syncope.apache.org");
+        userTO.setPassword("passwordTESTNULL");
+        userTO.getDerAttrs().clear();
+        userTO.getVirAttrs().clear();
+        userTO.getDerAttrs().add(attributeTO("csvuserid", null));
+
+        userTO.getResources().add(RESOURCE_NAME_CSV);
+        userTO = createUser(userTO, false);
+        assertNotNull(userTO);
+
+        connObjectTO =
+                resourceService.getConnectorObject(RESOURCE_NAME_CSV, SubjectType.USER, userTO.getId());
+        assertNotNull(connObjectTO);
+
+        // check if password has been propagated and that saved userTO's password is null
+        assertEquals("passwordTESTNULL", connObjectTO.getAttrMap().
+                get(OperationalAttributes.PASSWORD_NAME).getValues().get(0));
+        assertNull(userTO.getPassword());
+
+        // 4. create user and propagate password on resource-csv and on Syncope local storage
+        userTO = getUniqueSampleTO("syncope391@syncope.apache.org");
+        userTO.setPassword("passwordTESTNULL");
+        userTO.getDerAttrs().clear();
+        userTO.getVirAttrs().clear();
+        userTO.getDerAttrs().add(attributeTO("csvuserid", null));
+
+        userTO.getResources().add(RESOURCE_NAME_CSV);
+        // storePassword true by default
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
+
+        connObjectTO =
+                resourceService.getConnectorObject(RESOURCE_NAME_CSV, SubjectType.USER, userTO.getId());
+        assertNotNull(connObjectTO);
+
+        // check if password has been correctly propagated on Syncope and resource-csv as usual
+        assertEquals("passwordTESTNULL", connObjectTO.getAttrMap().
+                get(OperationalAttributes.PASSWORD_NAME).getValues().get(0));
+        assertNotNull(userTO.getPassword());
+
+        // 4. add password policy to resource with passwordNotStore to false --> must store password
+        ResourceTO csv = resourceService.read(RESOURCE_NAME_CSV);
+        assertNotNull(csv);
+        try {
+            csv.setPasswordPolicy(4L);
+            resourceService.update(RESOURCE_NAME_CSV, csv);
+            csv = resourceService.read(RESOURCE_NAME_CSV);
+
+            userTO = getUniqueSampleTO("syncope391@syncope.apache.org");
+            userTO.setPassword(null);
+            userTO.getDerAttrs().clear();
+            userTO.getVirAttrs().clear();
+            userTO.getDerAttrs().add(attributeTO("csvuserid", null));
+
+            userTO.getResources().add(RESOURCE_NAME_CSV);
+            createUser(userTO, false);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidSyncopeUser, e.getType());
+            assertTrue(e.getMessage().contains("Password must not be null and must be stored internally"));
+        } finally {
+            // resource csv with null password policy
+            csv.setPasswordPolicy(null);
+            resourceService.update(RESOURCE_NAME_CSV, csv);
+        }
+    }
 }