Author: ilgrosso
Date: Fri Sep 19 08:58:36 2014
New Revision: 1626150

URL: http://svn.apache.org/r1626150
Log:
[SYNCOPE-135] Merge from 1_2_X

Added:
    
syncope/trunk/common/src/main/java/org/apache/syncope/common/services/SecurityQuestionService.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/common/src/main/java/org/apache/syncope/common/services/SecurityQuestionService.java
    
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/SecurityQuestionTO.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/common/src/main/java/org/apache/syncope/common/to/SecurityQuestionTO.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/SecurityQuestion.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/java/org/apache/syncope/core/persistence/beans/SecurityQuestion.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/SecurityQuestionDAO.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/java/org/apache/syncope/core/persistence/dao/SecurityQuestionDAO.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/SecurityQuestionDAOImpl.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/SecurityQuestionDAOImpl.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/SecurityQuestionController.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/java/org/apache/syncope/core/rest/controller/SecurityQuestionController.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/SecurityQuestionDataBinder.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/java/org/apache/syncope/core/rest/data/SecurityQuestionDataBinder.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/SecurityQuestionServiceImpl.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/java/org/apache/syncope/core/services/SecurityQuestionServiceImpl.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Notify.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Notify.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/PasswordReset.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/PasswordReset.java
    
syncope/trunk/core/src/main/resources/mailTemplates/confirmPasswordReset.html.vm
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/resources/mailTemplates/confirmPasswordReset.html.vm
    
syncope/trunk/core/src/main/resources/mailTemplates/confirmPasswordReset.txt.vm
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/resources/mailTemplates/confirmPasswordReset.txt.vm
    
syncope/trunk/core/src/main/resources/mailTemplates/requestPasswordReset.html.vm
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/resources/mailTemplates/requestPasswordReset.html.vm
    
syncope/trunk/core/src/main/resources/mailTemplates/requestPasswordReset.txt.vm
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/main/resources/mailTemplates/requestPasswordReset.txt.vm
    
syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/SecurityQuestionTest.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/test/java/org/apache/syncope/core/persistence/dao/SecurityQuestionTest.java
    
syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/SecurityQuestionTest.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/test/java/org/apache/syncope/core/persistence/relationships/SecurityQuestionTest.java
    
syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SecurityQuestionTestITCase.java
      - copied unchanged from r1626149, 
syncope/branches/1_2_X/core/src/test/java/org/apache/syncope/core/rest/SecurityQuestionTestITCase.java
Modified:
    syncope/trunk/   (props changed)
    
syncope/trunk/common/src/main/java/org/apache/syncope/common/mod/UserMod.java
    
syncope/trunk/common/src/main/java/org/apache/syncope/common/services/ConnectorService.java
    
syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserSelfService.java
    
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnPoolConfTO.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java
    
syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java
    
syncope/trunk/common/src/main/java/org/apache/syncope/common/types/RESTHeaders.java
    syncope/trunk/core/pom.xml
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationJob.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/UserDAO.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/UserDAOImpl.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/NotificationController.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/AbstractAttributableDataBinder.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/NotificationDataBinder.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/NotificationServiceImpl.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/SchemaServiceImpl.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/util/Encryptor.java
    
syncope/trunk/core/src/main/java/org/apache/syncope/core/util/POJOHelper.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/resources/META-INF/orm.xml
    syncope/trunk/core/src/main/resources/META-INF/orm.xml.oracle
    syncope/trunk/core/src/main/resources/META-INF/orm.xml.sqlserver
    syncope/trunk/core/src/main/resources/content.xml
    syncope/trunk/core/src/main/resources/mail.properties
    syncope/trunk/core/src/main/resources/userWorkflow.bpmn20.xml
    
syncope/trunk/core/src/test/java/org/apache/syncope/core/connid/PasswordGeneratorTest.java
    
syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/EntitlementTest.java
    
syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/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/NotificationTestITCase.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/resources/content.xml
    syncope/trunk/core/src/test/resources/mail.properties
    syncope/trunk/core/src/test/resources/userWorkflow.bpmn20.xml
    syncope/trunk/pom.xml

Propchange: syncope/trunk/
------------------------------------------------------------------------------
  Merged /syncope/branches/1_2_X:r1625932-1626149

Modified: 
syncope/trunk/common/src/main/java/org/apache/syncope/common/mod/UserMod.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/mod/UserMod.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/common/src/main/java/org/apache/syncope/common/mod/UserMod.java 
(original)
+++ 
syncope/trunk/common/src/main/java/org/apache/syncope/common/mod/UserMod.java 
Fri Sep 19 08:58:36 2014
@@ -43,6 +43,10 @@ public class UserMod extends AbstractSub
 
     private StatusMod pwdPropRequest;
 
+    private Long securityQuestion;
+
+    private String securityAnswer;
+
     public UserMod() {
         super();
 
@@ -88,6 +92,22 @@ public class UserMod extends AbstractSub
         this.pwdPropRequest = pwdPropRequest;
     }
 
+    public Long getSecurityQuestion() {
+        return securityQuestion;
+    }
+
+    public void setSecurityQuestion(final Long securityQuestion) {
+        this.securityQuestion = securityQuestion;
+    }
+
+    public String getSecurityAnswer() {
+        return securityAnswer;
+    }
+
+    public void setSecurityAnswer(final String securityAnswer) {
+        this.securityAnswer = securityAnswer;
+    }
+
     @JsonIgnore
     @Override
     public boolean isEmpty() {
@@ -96,6 +116,8 @@ public class UserMod extends AbstractSub
                 && username == null
                 && membershipsToAdd.isEmpty()
                 && membershipsToRemove.isEmpty()
-                && pwdPropRequest == null;
+                && pwdPropRequest == null
+                && securityQuestion == null
+                && securityAnswer == null;
     }
 }

Modified: 
syncope/trunk/common/src/main/java/org/apache/syncope/common/services/ConnectorService.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/services/ConnectorService.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/common/src/main/java/org/apache/syncope/common/services/ConnectorService.java
 (original)
+++ 
syncope/trunk/common/src/main/java/org/apache/syncope/common/services/ConnectorService.java
 Fri Sep 19 08:58:36 2014
@@ -155,12 +155,12 @@ public interface ConnectorService extend
      * Updates the connector instance matching the provided id.
      *
      * @param connInstanceId connector instance id to be updated
-     * @param connInstaceTO connector instance to be stored
+     * @param connInstanceTO connector instance to be stored
      */
     @PUT
     @Path("{connInstanceId}")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    void update(@NotNull @PathParam("connInstanceId") Long connInstanceId, 
@NotNull ConnInstanceTO connInstaceTO);
+    void update(@NotNull @PathParam("connInstanceId") Long connInstanceId, 
@NotNull ConnInstanceTO connInstanceTO);
 
     /**
      * Deletes the connector instance matching the provided id.
@@ -172,14 +172,14 @@ public interface ConnectorService extend
     void delete(@NotNull @PathParam("connInstanceId") Long connInstanceId);
 
     /**
-     * @param connInstaceTO connector instance to be used for connection check
+     * @param connInstanceTO connector instance to be used for connection check
      * @return true if connection could be established
      */
     @POST
     @Path("check")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    boolean check(@NotNull ConnInstanceTO connInstaceTO);
+    boolean check(@NotNull ConnInstanceTO connInstanceTO);
 
     /**
      * Reload all connector bundles and instances.

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -46,12 +46,15 @@ public interface UserSelfService extends
     /**
      * Checks whether self-registration is allowed.
      *
-     * @return <tt>Response</tt> contains special Syncope HTTP header 
indicating if user self registration is allowed
+     * @return <tt>Response</tt> contains special Syncope HTTP header 
indicating if user self registration and / or
+     * password reset is allowed
      * @see 
org.apache.syncope.common.types.RESTHeaders#SELFREGISTRATION_ALLOWED
+     * @see org.apache.syncope.common.types.RESTHeaders#PASSWORDRESET_ALLOWED
      */
     @Descriptions({
         @Description(target = DocTarget.RESPONSE,
-                value = "Contains special Syncope HTTP header indicating if 
user self registration is allowed")
+                value = "Contains special Syncope HTTP header indicating if 
user self registration "
+                + "and / or password reset is allowed")
     })
     @OPTIONS
     Response getOptions();
@@ -114,4 +117,28 @@ public interface UserSelfService extends
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     Response delete();
 
+    /**
+     * Provides answer for the security question configured for user matching 
the given username, if any.
+     * If provided anwser matches the one stored for that user, a password 
reset token is internally generated,
+     * otherwise an error is returned.
+     *
+     * @param username username for which the security answer is provided
+     * @param securityAnswer actual answer text
+     */
+    @POST
+    @Path("requestPasswordReset")
+    void requestPasswordReset(@NotNull @QueryParam("username") String 
username, String securityAnswer);
+
+    /**
+     * Reset the password value for the user matching the provided token, if 
available and still valid.
+     * If the token actually matches one of users, and if it is still valid at 
the time of submission, the matching
+     * user's password value is set as provided. The new password value will 
need anyway to comply with all relevant
+     * password policies.
+     *
+     * @param token password reset token
+     * @param password new password to be set
+     */
+    @POST
+    @Path("confirmPasswordReset")
+    void confirmPasswordReset(@NotNull @QueryParam("token") String token, 
String password);
 }

Modified: 
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnPoolConfTO.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnPoolConfTO.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnPoolConfTO.java
 (original)
+++ 
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/ConnPoolConfTO.java
 Fri Sep 19 08:58:36 2014
@@ -26,6 +26,8 @@ import org.apache.syncope.common.Abstrac
 @XmlType
 public class ConnPoolConfTO extends AbstractBaseBean {
 
+    private static final long serialVersionUID = -214360178113476623L;
+
     private Integer maxObjects;
 
     private Integer minIdle;

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=1626150&r1=1626149&r2=1626150&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 
Fri Sep 19 08:58:36 2014
@@ -58,6 +58,10 @@ public class UserTO extends AbstractSubj
 
     private Integer failedLogins;
 
+    private Long securityQuestion;
+
+    private String securityAnswer;
+
     public String getPassword() {
         return password;
     }
@@ -150,6 +154,22 @@ public class UserTO extends AbstractSubj
         this.lastLoginDate = lastLoginDate;
     }
 
+    public Long getSecurityQuestion() {
+        return securityQuestion;
+    }
+
+    public void setSecurityQuestion(final Long securityQuestion) {
+        this.securityQuestion = securityQuestion;
+    }
+
+    public String getSecurityAnswer() {
+        return securityAnswer;
+    }
+
+    public void setSecurityAnswer(final String securityAnswer) {
+        this.securityAnswer = securityAnswer;
+    }
+
     @Override
     public String toString() {
         return new ReflectionToStringBuilder(this, 
ToStringStyle.MULTI_LINE_STYLE) {

Modified: 
syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java
 (original)
+++ 
syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java
 Fri Sep 19 08:58:36 2014
@@ -28,6 +28,7 @@ public enum ClientExceptionType {
     DataIntegrityViolation(Response.Status.BAD_REQUEST),
     EntityExists(Response.Status.CONFLICT),
     GenericPersistence(Response.Status.BAD_REQUEST),
+    InvalidSecurityAnswer(Response.Status.BAD_REQUEST),
     InvalidLogger(Response.Status.BAD_REQUEST),
     InvalidConnInstance(Response.Status.BAD_REQUEST),
     InvalidConnIdConf(Response.Status.BAD_REQUEST),

Modified: 
syncope/trunk/common/src/main/java/org/apache/syncope/common/types/RESTHeaders.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/types/RESTHeaders.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/common/src/main/java/org/apache/syncope/common/types/RESTHeaders.java
 (original)
+++ 
syncope/trunk/common/src/main/java/org/apache/syncope/common/types/RESTHeaders.java
 Fri Sep 19 08:58:36 2014
@@ -39,6 +39,11 @@ public final class RESTHeaders {
     public static final String SELFREGISTRATION_ALLOWED = 
"Syncope.SelfRegistration.Allowed";
 
     /**
+     * Option key stating if user request create is allowed or not.
+     */
+    public static final String PASSWORDRESET_ALLOWED = 
"Syncope.PasswordReset.Allowed";
+
+    /**
      * Option key stating if Activiti workflow adapter is in use for users.
      */
     public static final String ACTIVITI_USER_ENABLED = 
"Syncope.Activiti.User.Enabled";

Modified: syncope/trunk/core/pom.xml
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/pom.xml?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- syncope/trunk/core/pom.xml (original)
+++ syncope/trunk/core/pom.xml Fri Sep 19 08:58:36 2014
@@ -180,7 +180,11 @@ under the License.
       <groupId>com.fasterxml.jackson.jaxrs</groupId>
       <artifactId>jackson-jaxrs-json-provider</artifactId>
     </dependency>
-
+    <dependency>
+      <groupId>com.fasterxml.jackson.module</groupId>
+      <artifactId>jackson-module-afterburner</artifactId>
+    </dependency>
+      
     <dependency>
       <groupId>org.apache.velocity</groupId>
       <artifactId>velocity</artifactId>

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationJob.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationJob.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationJob.java
 (original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationJob.java
 Fri Sep 19 08:58:36 2014
@@ -89,12 +89,7 @@ public class NotificationJob implements 
     private long maxRetries;
 
     private void init() {
-        try {
-            maxRetries = confDAO.find("notification.maxRetries", 
"0").getValues().get(0).getLongValue();
-        } catch (NumberFormatException e) {
-            LOG.error("Invalid maximum number of retries, retries disabled", 
e);
-            maxRetries = 0;
-        }
+        maxRetries = confDAO.find("notification.maxRetries", 
"0").getValues().get(0).getLongValue();
 
         if (mailSender instanceof JavaMailSenderImpl
                 && StringUtils.isNotBlank(((JavaMailSenderImpl) 
mailSender).getUsername())) {

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -39,6 +39,7 @@ import javax.persistence.JoinColumn;
 import javax.persistence.JoinTable;
 import javax.persistence.Lob;
 import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
@@ -53,6 +54,7 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.persistence.beans.AbstractSubject;
 import org.apache.syncope.core.persistence.beans.AbstractVirAttr;
 import org.apache.syncope.core.persistence.beans.ExternalResource;
+import org.apache.syncope.core.persistence.beans.SecurityQuestion;
 import org.apache.syncope.core.persistence.beans.membership.Membership;
 import org.apache.syncope.core.persistence.beans.role.SyncopeRole;
 import org.apache.syncope.core.persistence.validation.entity.SyncopeUserCheck;
@@ -154,7 +156,13 @@ public class SyncopeUser extends Abstrac
             @JoinColumn(name = "resource_name"))
     @Valid
     private Set<ExternalResource> resources;
-    
+
+    @ManyToOne(fetch = FetchType.EAGER, optional = true)
+    private SecurityQuestion securityQuestion;
+
+    @Column(nullable = true)
+    private String securityAnswer;
+
     public SyncopeUser() {
         super();
 
@@ -267,7 +275,7 @@ public class SyncopeUser extends Abstrac
         this.cipherAlgorithm = cipherAlgoritm;
     }
 
-    public void setPassword(final String password, final CipherAlgorithm 
cipherAlgoritm, final int historySize) {
+    public void setPassword(final String password, final CipherAlgorithm 
cipherAlgoritm) {
         // clear password
         this.clearPassword = password;
 
@@ -494,8 +502,8 @@ public class SyncopeUser extends Abstrac
                 res = passwordHistory.subList(size >= passwordHistory.size()
                         ? 0
                         : passwordHistory.size() - size, 
passwordHistory.size()).contains(cipherAlgorithm == null
-                                ? password
-                                : Encryptor.getInstance().encode(password, 
cipherAlgorithm));
+                                        ? password
+                                        : 
Encryptor.getInstance().encode(password, cipherAlgorithm));
             } catch (Exception e) {
                 LOG.error("Error evaluating password history", e);
             }
@@ -503,4 +511,21 @@ public class SyncopeUser extends Abstrac
 
         return res;
     }
+
+    public SecurityQuestion getSecurityQuestion() {
+        return securityQuestion;
+    }
+
+    public void setSecurityQuestion(final SecurityQuestion securityQuestion) {
+        this.securityQuestion = securityQuestion;
+    }
+
+    public String getSecurityAnswer() {
+        return securityAnswer;
+    }
+
+    public void setSecurityAnswer(final String securityAnswer) {
+        this.securityAnswer = securityAnswer;
+    }
+
 }

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/UserDAO.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/UserDAO.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/UserDAO.java
 (original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/UserDAO.java
 Fri Sep 19 08:58:36 2014
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.syncope.core.persistence.beans.ExternalResource;
+import org.apache.syncope.core.persistence.beans.SecurityQuestion;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.apache.syncope.core.persistence.beans.user.UAttrValue;
 import org.apache.syncope.core.persistence.dao.search.OrderByClause;
@@ -35,6 +36,10 @@ public interface UserDAO extends Subject
 
     SyncopeUser findByWorkflowId(String workflowId);
 
+    SyncopeUser findByToken(String token);
+
+    List<SyncopeUser> findBySecurityQuestion(SecurityQuestion 
securityQuestion);
+
     List<SyncopeUser> findByDerAttrValue(String schemaName, String value);
 
     List<SyncopeUser> findByAttrValue(String schemaName, UAttrValue attrValue);
@@ -54,4 +59,5 @@ public interface UserDAO extends Subject
     void delete(Long id);
 
     void delete(SyncopeUser user);
+
 }

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/UserDAOImpl.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/UserDAOImpl.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/UserDAOImpl.java
 (original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/UserDAOImpl.java
 Fri Sep 19 08:58:36 2014
@@ -30,6 +30,7 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.persistence.beans.AbstractAttributable;
 import org.apache.syncope.core.persistence.beans.AbstractVirAttr;
 import org.apache.syncope.core.persistence.beans.ExternalResource;
+import org.apache.syncope.core.persistence.beans.SecurityQuestion;
 import org.apache.syncope.core.persistence.beans.membership.Membership;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.apache.syncope.core.persistence.beans.user.UAttrValue;
@@ -78,7 +79,7 @@ public class UserDAOImpl extends Abstrac
     @Override
     public SyncopeUser find(final String username) {
         TypedQuery<SyncopeUser> query = entityManager.createQuery("SELECT e 
FROM " + SyncopeUser.class.getSimpleName()
-                + " e " + "WHERE e.username = :username", SyncopeUser.class);
+                + " e WHERE e.username = :username", SyncopeUser.class);
         query.setParameter("username", username);
 
         SyncopeUser result = null;
@@ -94,7 +95,7 @@ public class UserDAOImpl extends Abstrac
     @Override
     public SyncopeUser findByWorkflowId(final String workflowId) {
         TypedQuery<SyncopeUser> query = entityManager.createQuery("SELECT e 
FROM " + SyncopeUser.class.getSimpleName()
-                + " e " + "WHERE e.workflowId = :workflowId", 
SyncopeUser.class);
+                + " e WHERE e.workflowId = :workflowId", SyncopeUser.class);
         query.setParameter("workflowId", workflowId);
 
         SyncopeUser result = null;
@@ -108,6 +109,31 @@ public class UserDAOImpl extends Abstrac
     }
 
     @Override
+    public SyncopeUser findByToken(final String token) {
+        TypedQuery<SyncopeUser> query = entityManager.createQuery("SELECT e 
FROM " + SyncopeUser.class.getSimpleName()
+                + " e WHERE e.token = :token", SyncopeUser.class);
+        query.setParameter("token", token);
+
+        SyncopeUser result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No user found with token {}", token, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<SyncopeUser> findBySecurityQuestion(final SecurityQuestion 
securityQuestion) {
+        TypedQuery<SyncopeUser> query = entityManager.createQuery("SELECT e 
FROM " + SyncopeUser.class.getSimpleName()
+                + " e WHERE e.securityQuestion = :securityQuestion", 
SyncopeUser.class);
+        query.setParameter("securityQuestion", securityQuestion);
+
+        return query.getResultList();
+    }
+
+    @Override
     protected TypedQuery<AbstractAttrValue> findByAttrValueQuery(final String 
entityName) {
         return entityManager.createQuery("SELECT e FROM " + entityName + " e"
                 + " WHERE e.attribute.schema.name = :schemaName AND 
(e.stringValue IS NOT NULL"

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/NotificationController.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/NotificationController.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/NotificationController.java
 (original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/NotificationController.java
 Fri Sep 19 08:58:36 2014
@@ -66,7 +66,7 @@ public class NotificationController exte
 
     @PreAuthorize("hasRole('NOTIFICATION_CREATE')")
     public NotificationTO create(final NotificationTO notificationTO) {
-        return 
binder.getNotificationTO(notificationDAO.save(binder.createNotification(notificationTO)));
+        return 
binder.getNotificationTO(notificationDAO.save(binder.create(notificationTO)));
     }
 
     @PreAuthorize("hasRole('NOTIFICATION_UPDATE')")
@@ -77,7 +77,7 @@ public class NotificationController exte
             throw new 
NotFoundException(String.valueOf(notificationTO.getId()));
         }
 
-        binder.updateNotification(notification, notificationTO);
+        binder.update(notification, notificationTO);
         notification = notificationDAO.save(notification);
 
         return binder.getNotificationTO(notification);
@@ -87,19 +87,16 @@ public class NotificationController exte
     public NotificationTO delete(final Long notificationId) {
         Notification notification = notificationDAO.find(notificationId);
         if (notification == null) {
-            LOG.error("Could not find notificatin '" + notificationId + "'");
+            LOG.error("Could not find notification '" + notificationId + "'");
 
             throw new NotFoundException(String.valueOf(notificationId));
         }
 
-        NotificationTO notificationToDelete = 
binder.getNotificationTO(notification);
+        NotificationTO deleted = binder.getNotificationTO(notification);
         notificationDAO.delete(notificationId);
-        return notificationToDelete;
+        return deleted;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected NotificationTO resolveReference(final Method method, final 
Object... args)
             throws UnresolvedReferenceException {

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -46,6 +46,7 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.apache.syncope.core.persistence.dao.SubjectSearchDAO;
 import org.apache.syncope.core.persistence.dao.ConfDAO;
+import org.apache.syncope.core.persistence.dao.NotFoundException;
 import org.apache.syncope.core.persistence.dao.RoleDAO;
 import org.apache.syncope.core.persistence.dao.UserDAO;
 import org.apache.syncope.core.persistence.dao.search.OrderByClause;
@@ -107,6 +108,11 @@ public class UserController extends Abst
         return confDAO.find("selfRegistration.allowed", 
"false").getValues().get(0).getBooleanValue();
     }
 
+    @Transactional(readOnly = true)
+    public boolean isPasswordResetAllowed() {
+        return confDAO.find("passwordReset.allowed", 
"false").getValues().get(0).getBooleanValue();
+    }
+
     @PreAuthorize("hasRole('USER_READ')")
     public String getUsername(final Long userId) {
         return binder.getUserTO(userId).getUsername();
@@ -359,6 +365,46 @@ public class UserController extends Abst
         return savedTO;
     }
 
+    @PreAuthorize("isAnonymous() or 
hasRole(T(org.apache.syncope.common.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
+    @Transactional
+    public void requestPasswordReset(final String username, final String 
securityAnswer) {
+        if (username == null) {
+            throw new NotFoundException("Null username");
+        }
+
+        SyncopeUser user = userDAO.find(username);
+        if (user == null) {
+            throw new NotFoundException("User " + username);
+        }
+
+        if (securityAnswer == null || 
!securityAnswer.equals(user.getSecurityAnswer())) {
+            throw 
SyncopeClientException.build(ClientExceptionType.InvalidSecurityAnswer);
+        }
+
+        uwfAdapter.requestPasswordReset(user.getId());
+    }
+
+    @PreAuthorize("isAnonymous() or 
hasRole(T(org.apache.syncope.common.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
+    @Transactional
+    public void confirmPasswordReset(final String token, final String 
password) {
+        SyncopeUser user = userDAO.findByToken(token);
+        if (user == null) {
+            throw new NotFoundException("User with token " + token);
+        }
+
+        uwfAdapter.confirmPasswordReset(user.getId(), token, password);
+
+        List<PropagationTask> tasks = 
propagationManager.getUserUpdateTaskIds(user, null, null);
+        PropagationReporter propReporter =
+                
ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
+        try {
+            taskExecutor.execute(tasks, propReporter);
+        } catch (PropagationException e) {
+            LOG.error("Error propagation primary resource", e);
+            propReporter.onPrimaryResourceFailure(tasks);
+        }
+    }
+
     @PreAuthorize("isAuthenticated() "
             + "and 
not(hasRole(T(org.apache.syncope.common.SyncopeConstants).ANONYMOUS_ENTITLEMENT))")
     public UserTO deleteSelf() {
@@ -564,14 +610,11 @@ public class UserController extends Abst
         return original;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected UserTO resolveReference(final Method method, final Object... 
args) throws UnresolvedReferenceException {
         Object id = null;
 
-        if (ArrayUtils.isNotEmpty(args)) {
+        if (!"confirmPasswordReset".equals(method.getName()) && 
ArrayUtils.isNotEmpty(args)) {
             for (int i = 0; id == null && i < args.length; i++) {
                 if (args[i] instanceof Long) {
                     id = (Long) args[i];

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java
 (original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java
 Fri Sep 19 08:58:36 2014
@@ -73,7 +73,6 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.persistence.beans.user.UVirSchema;
 import org.apache.syncope.core.persistence.dao.AttrDAO;
 import org.apache.syncope.core.persistence.dao.AttrValueDAO;
-import org.apache.syncope.core.persistence.dao.ConfDAO;
 import org.apache.syncope.core.persistence.dao.DerAttrDAO;
 import org.apache.syncope.core.persistence.dao.DerSchemaDAO;
 import org.apache.syncope.core.persistence.dao.MembershipDAO;
@@ -101,9 +100,6 @@ public abstract class AbstractAttributab
     protected static final Logger LOG = 
LoggerFactory.getLogger(AbstractAttributableDataBinder.class);
 
     @Autowired
-    protected ConfDAO confDAO;
-
-    @Autowired
     protected RoleDAO roleDAO;
 
     @Autowired
@@ -215,8 +211,8 @@ public abstract class AbstractAttributab
         List<String> valuesProvided = schema.isMultivalue()
                 ? values
                 : (values.isEmpty()
-                ? Collections.<String>emptyList()
-                : Collections.singletonList(values.iterator().next()));
+                        ? Collections.<String>emptyList()
+                        : Collections.singletonList(values.iterator().next()));
 
         for (String value : valuesProvided) {
             if (value == null || value.isEmpty()) {

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/NotificationDataBinder.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/NotificationDataBinder.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/NotificationDataBinder.java
 (original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/NotificationDataBinder.java
 Fri Sep 19 08:58:36 2014
@@ -41,13 +41,13 @@ public class NotificationDataBinder {
         return result;
     }
 
-    public Notification createNotification(final NotificationTO 
notificationTO) {
+    public Notification create(final NotificationTO notificationTO) {
         Notification result = new Notification();
-        updateNotification(result, notificationTO);
+        update(result, notificationTO);
         return result;
     }
 
-    public void updateNotification(final Notification notification, final 
NotificationTO notificationTO) {
+    public void update(final Notification notification, final NotificationTO 
notificationTO) {
         BeanUtils.copyProperties(notificationTO, notification, 
IGNORE_PROPERTIES);
 
         notification.setUserAbout(notificationTO.getUserAbout());

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -30,9 +30,7 @@ import org.apache.syncope.common.mod.Use
 import org.apache.syncope.common.to.MembershipTO;
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.common.types.AttributableType;
-import org.apache.syncope.common.types.CipherAlgorithm;
 import org.apache.syncope.common.types.IntMappingType;
-import org.apache.syncope.common.types.PasswordPolicySpec;
 import org.apache.syncope.common.types.ResourceOperation;
 import org.apache.syncope.common.types.ClientExceptionType;
 import org.apache.syncope.common.util.BeanUtils;
@@ -45,7 +43,7 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.persistence.beans.AbstractMappingItem;
 import org.apache.syncope.core.persistence.beans.AbstractVirAttr;
 import org.apache.syncope.core.persistence.beans.ExternalResource;
-import org.apache.syncope.core.persistence.beans.PasswordPolicy;
+import org.apache.syncope.core.persistence.beans.SecurityQuestion;
 import org.apache.syncope.core.persistence.beans.membership.MAttr;
 import org.apache.syncope.core.persistence.beans.membership.MDerAttr;
 import org.apache.syncope.core.persistence.beans.membership.MVirAttr;
@@ -53,6 +51,7 @@ 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.NotFoundException;
+import org.apache.syncope.core.persistence.dao.SecurityQuestionDAO;
 import org.apache.syncope.core.propagation.PropagationByResource;
 import org.apache.syncope.core.rest.controller.UnauthorizedRoleException;
 import org.apache.syncope.core.util.AttributableUtil;
@@ -68,12 +67,15 @@ import org.springframework.transaction.a
 public class UserDataBinder extends AbstractAttributableDataBinder {
 
     private static final String[] IGNORE_USER_PROPERTIES = {
-        "memberships", "attrs", "derAttrs", "virAttrs", "resources"
+        "memberships", "attrs", "derAttrs", "virAttrs", "resources", 
"securityQuestion"
     };
 
     @Autowired
     private ConnObjectUtil connObjectUtil;
 
+    @Autowired
+    private SecurityQuestionDAO securityQuestionDAO;
+
     @Resource(name = "adminUser")
     private String adminUser;
 
@@ -82,6 +84,21 @@ public class UserDataBinder extends Abst
 
     private final Encryptor encryptor = Encryptor.getInstance();
 
+    private void securityChecks(final SyncopeUser user) {
+        // Allows anonymous (during self-registration) and self (during 
self-update) to read own SyncopeUser,
+        // otherwise goes thorugh security checks to see if needed role 
entitlements are owned
+        if (!EntitlementUtil.getAuthenticatedUsername().equals(anonymousUser)
+                && 
!EntitlementUtil.getAuthenticatedUsername().equals(user.getUsername())) {
+
+            Set<Long> roleIds = user.getRoleIds();
+            Set<Long> adminRoleIds = 
EntitlementUtil.getRoleIds(EntitlementUtil.getOwnedEntitlementNames());
+            roleIds.removeAll(adminRoleIds);
+            if (!roleIds.isEmpty()) {
+                throw new UnauthorizedRoleException(roleIds);
+            }
+        }
+    }
+
     @Transactional(readOnly = true)
     public SyncopeUser getUserFromId(final Long userId) {
         if (userId == null) {
@@ -93,19 +110,24 @@ public class UserDataBinder extends Abst
             throw new NotFoundException("User " + userId);
         }
 
-        // Allows anonymous (during self-registration) and self (during 
self-update) to read own SyncopeUser,
-        // otherwise goes thorugh security checks to see if needed role 
entitlements are owned
-        if (!EntitlementUtil.getAuthenticatedUsername().equals(anonymousUser)
-                && 
!EntitlementUtil.getAuthenticatedUsername().equals(user.getUsername())) {
+        securityChecks(user);
 
-            Set<Long> roleIds = user.getRoleIds();
-            Set<Long> adminRoleIds = 
EntitlementUtil.getRoleIds(EntitlementUtil.getOwnedEntitlementNames());
-            roleIds.removeAll(adminRoleIds);
-            if (!roleIds.isEmpty()) {
-                throw new UnauthorizedRoleException(roleIds);
-            }
+        return user;
+    }
+
+    @Transactional(readOnly = true)
+    public SyncopeUser getUserFromUsername(final String username) {
+        if (username == null) {
+            throw new NotFoundException("Null username");
+        }
+
+        SyncopeUser user = userDAO.find(username);
+        if (user == null) {
+            throw new NotFoundException("User " + username);
         }
 
+        securityChecks(user);
+
         return user;
     }
 
@@ -159,55 +181,11 @@ public class UserDataBinder extends Abst
         return encryptor.verify(password, user.getCipherAlgorithm(), 
user.getPassword());
     }
 
-    @Transactional(readOnly = true)
-    public SyncopeUser getUserFromUsername(final String username) {
-        if (username == null) {
-            throw new NotFoundException("Null username");
-        }
-
-        SyncopeUser user = userDAO.find(username);
-        if (user == null) {
-            throw new NotFoundException("User " + username);
-        }
-
-        Set<Long> roleIds = user.getRoleIds();
-        Set<Long> adminRoleIds = 
EntitlementUtil.getRoleIds(EntitlementUtil.getOwnedEntitlementNames());
-        roleIds.removeAll(adminRoleIds);
-
-        if (!roleIds.isEmpty()) {
-            throw new UnauthorizedRoleException(roleIds);
-        }
-
-        return user;
-    }
-
-    /**
-     * Get predefined password cipher algorithm from SyncopeConf.
-     *
-     * @return cipher algorithm.
-     */
-    private CipherAlgorithm getPredefinedCipherAlgoritm() {
-        final String algorithm = confDAO.find(
-                "password.cipher.algorithm", 
CipherAlgorithm.AES.name()).getValues().get(0).getStringValue();
-
-        try {
-            return CipherAlgorithm.valueOf(algorithm);
-        } catch (IllegalArgumentException e) {
-            throw new NotFoundException("Cipher algorithm " + algorithm);
-        }
-    }
-
     private void setPassword(final SyncopeUser user, final String password,
             final SyncopeClientCompositeException scce) {
 
-        int passwordHistorySize = 0;
-        PasswordPolicy policy = policyDAO.getGlobalPasswordPolicy();
-        if (policy != null && 
policy.getSpecification(PasswordPolicySpec.class) != null) {
-            passwordHistorySize = 
policy.getSpecification(PasswordPolicySpec.class).getHistoryLength();
-        }
-
         try {
-            user.setPassword(password, getPredefinedCipherAlgoritm(), 
passwordHistorySize);
+            user.setPassword(password, 
Encryptor.getPredefinedCipherAlgoritm());
         } catch (NotFoundException e) {
             final SyncopeClientException invalidCiperAlgorithm =
                     SyncopeClientException.build(ClientExceptionType.NotFound);
@@ -261,6 +239,15 @@ public class UserDataBinder extends Abst
 
         // set username
         user.setUsername(userTO.getUsername());
+
+        // security question / answer
+        if (userTO.getSecurityQuestion() != null) {
+            SecurityQuestion securityQuestion = 
securityQuestionDAO.find(userTO.getSecurityQuestion());
+            if (securityQuestion != null) {
+                user.setSecurityQuestion(securityQuestion);
+            }
+        }
+        user.setSecurityAnswer(userTO.getSecurityAnswer());
     }
 
     /**
@@ -304,6 +291,21 @@ public class UserDataBinder extends Abst
             }
         }
 
+        // security question / answer:
+        // userMod.getSecurityQuestion() is null => remove user security 
question and answer
+        // userMod.getSecurityQuestion() == 0 => don't change anything
+        // userMod.getSecurityQuestion() > 0 => update user security question 
and answer
+        if (userMod.getSecurityQuestion() == null) {
+            user.setSecurityQuestion(null);
+            user.setSecurityAnswer(null);
+        } else if (userMod.getSecurityQuestion() > 0) {
+            SecurityQuestion securityQuestion = 
securityQuestionDAO.find(userMod.getSecurityQuestion());
+            if (securityQuestion != null) {
+                user.setSecurityQuestion(securityQuestion);
+                user.setSecurityAnswer(userMod.getSecurityAnswer());
+            }
+        }
+
         // attributes, derived attributes, virtual attributes and resources
         propByRes.merge(fill(user, userMod, 
AttributableUtil.getInstance(AttributableType.USER), scce));
 
@@ -413,8 +415,11 @@ public class UserDataBinder extends Abst
 
         BeanUtils.copyProperties(user, userTO, IGNORE_USER_PROPERTIES);
 
-        connObjectUtil.retrieveVirAttrValues(user, 
AttributableUtil.getInstance(AttributableType.USER));
+        if (user.getSecurityQuestion() != null) {
+            userTO.setSecurityQuestion(user.getSecurityQuestion().getId());
+        }
 
+        connObjectUtil.retrieveVirAttrValues(user, 
AttributableUtil.getInstance(AttributableType.USER));
         fillTO(userTO, user.getAttrs(), user.getDerAttrs(), 
user.getVirAttrs(), user.getResources());
 
         MembershipTO membershipTO;
@@ -495,8 +500,8 @@ public class UserDataBinder extends Abst
                 ? fillVirtual(
                         membership,
                         membership.getVirAttrs() == null
-                        ? Collections.<String>emptySet()
-                        : getAttributeNames(membership.getVirAttrs()),
+                                ? Collections.<String>emptySet()
+                                : getAttributeNames(membership.getVirAttrs()),
                         vAttrsToBeUpdated,
                         
AttributableUtil.getInstance(AttributableType.MEMBERSHIP))
                 : fillVirtual(

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/NotificationServiceImpl.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/NotificationServiceImpl.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/NotificationServiceImpl.java
 (original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/NotificationServiceImpl.java
 Fri Sep 19 08:58:36 2014
@@ -38,10 +38,10 @@ public class NotificationServiceImpl ext
 
     @Override
     public Response create(final NotificationTO notificationTO) {
-        NotificationTO createdNotificationTO = 
controller.create(notificationTO);
-        URI location = 
uriInfo.getAbsolutePathBuilder().path(String.valueOf(createdNotificationTO.getId())).build();
+        NotificationTO created = controller.create(notificationTO);
+        URI location = 
uriInfo.getAbsolutePathBuilder().path(String.valueOf(created.getId())).build();
         return Response.created(location).
-                header(RESTHeaders.RESOURCE_ID, createdNotificationTO.getId()).
+                header(RESTHeaders.RESOURCE_ID, created.getId()).
                 build();
     }
 

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/SchemaServiceImpl.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/SchemaServiceImpl.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/SchemaServiceImpl.java
 (original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/services/SchemaServiceImpl.java
 Fri Sep 19 08:58:36 2014
@@ -42,11 +42,11 @@ public class SchemaServiceImpl extends A
     public <T extends AbstractSchemaTO> Response create(final AttributableType 
attrType, final SchemaType schemaType,
             final T schemaTO) {
 
-        T response = controller.create(attrType, schemaType, schemaTO);
+        T created = controller.create(attrType, schemaType, schemaTO);
 
-        URI location = 
uriInfo.getAbsolutePathBuilder().path(response.getName()).build();
+        URI location = 
uriInfo.getAbsolutePathBuilder().path(created.getName()).build();
         return Response.created(location).
-                header(RESTHeaders.RESOURCE_ID, response.getName()).
+                header(RESTHeaders.RESOURCE_ID, created.getName()).
                 build();
     }
 

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -40,6 +40,7 @@ public class UserSelfServiceImpl extends
     public Response getOptions() {
         return Response.ok().header(HttpHeaders.ALLOW, OPTIONS_ALLOW).
                 header(RESTHeaders.SELFREGISTRATION_ALLOWED, 
controller.isSelfRegistrationAllowed()).
+                header(RESTHeaders.PASSWORDRESET_ALLOWED, 
controller.isSelfRegistrationAllowed()).
                 build();
     }
 
@@ -47,7 +48,7 @@ public class UserSelfServiceImpl extends
     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");
+            sce.getElements().add("Self registration forbidden by 
configuration");
             throw sce;
         }
 
@@ -73,4 +74,26 @@ public class UserSelfServiceImpl extends
         return modificationResponse(deleted);
     }
 
+    @Override
+    public void requestPasswordReset(final String username, final String 
securityAnswer) {
+        if (!controller.isPasswordResetAllowed()) {
+            SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unauthorized);
+            sce.getElements().add("Password reset forbidden by configuration");
+            throw sce;
+        }
+
+        controller.requestPasswordReset(username, securityAnswer);
+    }
+
+    @Override
+    public void confirmPasswordReset(final String token, final String 
password) {
+        if (!controller.isPasswordResetAllowed()) {
+            SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unauthorized);
+            sce.getElements().add("Password reset forbidden by configuration");
+            throw sce;
+        }
+
+        controller.confirmPasswordReset(token, password);
+    }
+
 }

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/util/Encryptor.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/Encryptor.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/util/Encryptor.java 
(original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/util/Encryptor.java 
Fri Sep 19 08:58:36 2014
@@ -35,6 +35,8 @@ import org.apache.commons.lang3.ArrayUti
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.SyncopeConstants;
 import org.apache.syncope.common.types.CipherAlgorithm;
+import org.apache.syncope.core.persistence.dao.ConfDAO;
+import org.apache.syncope.core.persistence.dao.NotFoundException;
 import org.jasypt.commons.CommonUtils;
 import org.jasypt.digest.StandardStringDigester;
 import org.slf4j.Logger;
@@ -132,6 +134,22 @@ public final class Encryptor {
         }
     }
 
+    /**
+     * Get predefined password cipher algorithm from SyncopeConf.
+     *
+     * @return cipher algorithm.
+     */
+    public static CipherAlgorithm getPredefinedCipherAlgoritm() {
+        ConfDAO confDAO = 
ApplicationContextProvider.getApplicationContext().getBean(ConfDAO.class);
+        final String algorithm = confDAO.find(
+                "password.cipher.algorithm", 
CipherAlgorithm.AES.name()).getValues().get(0).getStringValue();
+        try {
+            return CipherAlgorithm.valueOf(algorithm);
+        } catch (IllegalArgumentException e) {
+            throw new NotFoundException("Cipher algorithm " + algorithm);
+        }
+    }
+
     public static Encryptor getInstance() {
         return getInstance(secretKey);
     }

Modified: 
syncope/trunk/core/src/main/java/org/apache/syncope/core/util/POJOHelper.java
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/POJOHelper.java?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- 
syncope/trunk/core/src/main/java/org/apache/syncope/core/util/POJOHelper.java 
(original)
+++ 
syncope/trunk/core/src/main/java/org/apache/syncope/core/util/POJOHelper.java 
Fri Sep 19 08:58:36 2014
@@ -18,9 +18,11 @@
  */
 package org.apache.syncope.core.util;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
 import org.identityconnectors.common.security.GuardedString;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.SyncToken;
@@ -46,6 +48,7 @@ public final class POJOHelper {
 
         MAPPER = new ObjectMapper();
         MAPPER.registerModule(pojoModule);
+        MAPPER.registerModule(new AfterburnerModule());
     }
 
     public static String serialize(final Object object) {

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -119,6 +119,23 @@ public abstract class AbstractUserWorkfl
         return doReactivate(user);
     }
 
+    protected abstract void doRequestPasswordReset(SyncopeUser user) throws 
WorkflowException;
+
+    @Override
+    public void requestPasswordReset(final Long userId) throws 
UnauthorizedRoleException, WorkflowException {
+        doRequestPasswordReset(dataBinder.getUserFromId(userId));
+    }
+
+    protected abstract void doConfirmPasswordReset(SyncopeUser user, String 
token, String password) 
+            throws WorkflowException;
+
+    @Override
+    public void confirmPasswordReset(final Long userId, final String token, 
final String password)
+            throws UnauthorizedRoleException, WorkflowException {
+
+        doConfirmPasswordReset(dataBinder.getUserFromId(userId), token, 
password);
+    }
+
     protected abstract void doDelete(SyncopeUser user) throws 
WorkflowException;
 
     @Override

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -30,12 +30,15 @@ import org.apache.syncope.common.to.User
 import org.apache.syncope.common.to.WorkflowFormTO;
 import org.apache.syncope.common.types.ResourceOperation;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
+import org.apache.syncope.core.persistence.dao.ConfDAO;
 import org.apache.syncope.core.persistence.dao.NotFoundException;
+import org.apache.syncope.core.persistence.dao.PolicyDAO;
 import org.apache.syncope.core.propagation.PropagationByResource;
 import org.apache.syncope.core.rest.controller.UnauthorizedRoleException;
 import org.apache.syncope.core.workflow.WorkflowDefinitionFormat;
 import org.apache.syncope.core.workflow.WorkflowException;
 import org.apache.syncope.core.workflow.WorkflowResult;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -44,7 +47,11 @@ import org.springframework.transaction.a
 @Transactional(rollbackFor = { Throwable.class })
 public class NoOpUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
 
-    public static final String ENABLED = "enabled";
+    @Autowired
+    private PolicyDAO policyDAO;
+
+    @Autowired
+    private ConfDAO confDAO;
 
     @Override
     public WorkflowResult<Map.Entry<Long, Boolean>> create(final UserTO 
userTO, final boolean disablePwdPolicyCheck,
@@ -124,9 +131,7 @@ public class NoOpUserWorkflowAdapter ext
     }
 
     @Override
-    protected WorkflowResult<Long> doSuspend(final SyncopeUser user)
-            throws WorkflowException {
-
+    protected WorkflowResult<Long> doSuspend(final SyncopeUser user) throws 
WorkflowException {
         user.setStatus("suspended");
         SyncopeUser updated = userDAO.save(user);
 
@@ -134,9 +139,7 @@ public class NoOpUserWorkflowAdapter ext
     }
 
     @Override
-    protected WorkflowResult<Long> doReactivate(final SyncopeUser user)
-            throws WorkflowException {
-
+    protected WorkflowResult<Long> doReactivate(final SyncopeUser user) throws 
WorkflowException {
         user.setStatus("active");
         SyncopeUser updated = userDAO.save(user);
 
@@ -144,9 +147,28 @@ public class NoOpUserWorkflowAdapter ext
     }
 
     @Override
-    protected void doDelete(final SyncopeUser user)
+    protected void doRequestPasswordReset(final SyncopeUser user) throws 
WorkflowException {
+        user.generateToken(
+                confDAO.find("token.length", 
"256").getValues().get(0).getLongValue().intValue(),
+                confDAO.find("token.expireTime", 
"60").getValues().get(0).getLongValue().intValue());
+        userDAO.save(user);
+    }
+
+    @Override
+    protected void doConfirmPasswordReset(final SyncopeUser user, final String 
token, final String password)
             throws WorkflowException {
 
+        if (!user.checkToken(token)) {
+            throw new WorkflowException(new IllegalArgumentException("Wrong 
token: " + token + " for " + user));
+        }
+
+        user.removeToken();
+        user.setPassword(password, user.getCipherAlgorithm());
+        userDAO.save(user);
+    }
+
+    @Override
+    protected void doDelete(final SyncopeUser user) throws WorkflowException {
         userDAO.delete(user);
     }
 

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -135,6 +135,27 @@ public interface UserWorkflowAdapter ext
     WorkflowResult<Long> reactivate(Long userId) throws 
UnauthorizedRoleException, WorkflowException;
 
     /**
+     * Request password reset for an user.
+     *
+     * @param userId user requesting password reset
+     * @throws UnauthorizedRoleException authorization exception
+     * @throws WorkflowException workflow exception
+     */
+    void requestPasswordReset(Long userId) throws UnauthorizedRoleException, 
WorkflowException;
+
+    /**
+     * Confirm password reset for an user.
+     *
+     * @param userId user confirming password reset
+     * @param token security token
+     * @param password new password value
+     * @throws UnauthorizedRoleException authorization exception
+     * @throws WorkflowException workflow exception
+     */
+    void confirmPasswordReset(Long userId, String token, String password) 
+            throws UnauthorizedRoleException, WorkflowException;
+
+    /**
      * Delete an user.
      *
      * @param userId user to be deleted

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=1626150&r1=1626149&r2=1626150&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 Sep 19 08:58:36 2014
@@ -70,6 +70,7 @@ import org.apache.syncope.core.persisten
 import 
org.apache.syncope.core.persistence.validation.attrvalue.ParsingValidationException;
 import org.apache.syncope.core.propagation.PropagationByResource;
 import org.apache.syncope.core.rest.controller.UnauthorizedRoleException;
+import org.apache.syncope.core.rest.data.UserDataBinder;
 import org.apache.syncope.core.util.EntitlementUtil;
 import org.apache.syncope.core.workflow.WorkflowDefinitionFormat;
 import org.apache.syncope.core.workflow.WorkflowException;
@@ -115,6 +116,8 @@ public class ActivitiUserWorkflowAdapter
 
     public static final String TOKEN = "token";
 
+    public static final String PASSWORD = "password";
+
     public static final String PROP_BY_RESOURCE = "propByResource";
 
     public static final String PROPAGATE_ENABLE = "propagateEnable";
@@ -127,6 +130,8 @@ public class ActivitiUserWorkflowAdapter
 
     public static final String STORE_PASSWORD = "storePassword";
 
+    public static final String EVENT = "event";
+
     @Resource(name = "adminUser")
     private String adminUser;
 
@@ -148,6 +153,9 @@ public class ActivitiUserWorkflowAdapter
     @Autowired
     private ActivitiImportUtils importUtils;
 
+    @Autowired
+    private UserDataBinder userDataBinder;
+
     @Override
     public Class<? extends WorkflowInstanceLoader> getLoaderClass() {
         return ActivitiWorkflowLoader.class;
@@ -355,9 +363,7 @@ public class ActivitiUserWorkflowAdapter
 
     @Override
     @Transactional(rollbackFor = { Throwable.class })
-    protected WorkflowResult<Long> doSuspend(final SyncopeUser user)
-            throws WorkflowException {
-
+    protected WorkflowResult<Long> doSuspend(final SyncopeUser user) throws 
WorkflowException {
         Set<String> performedTasks = doExecuteTask(user, "suspend", null);
         updateStatus(user);
         SyncopeUser updated = userDAO.save(user);
@@ -366,9 +372,7 @@ public class ActivitiUserWorkflowAdapter
     }
 
     @Override
-    protected WorkflowResult<Long> doReactivate(final SyncopeUser user)
-            throws WorkflowException {
-
+    protected WorkflowResult<Long> doReactivate(final SyncopeUser user) throws 
WorkflowException {
         Set<String> performedTasks = doExecuteTask(user, "reactivate", null);
         updateStatus(user);
 
@@ -378,9 +382,31 @@ public class ActivitiUserWorkflowAdapter
     }
 
     @Override
-    protected void doDelete(final SyncopeUser user)
+    protected void doRequestPasswordReset(final SyncopeUser user) throws 
WorkflowException {
+        Map<String, Object> variables = new HashMap<String, Object>(2);
+        variables.put(USER_TO, userDataBinder.getUserTO(user));
+        variables.put(EVENT, "requestPasswordReset");
+
+        doExecuteTask(user, "requestPasswordReset", variables);
+        userDAO.save(user);
+    }
+
+    @Override
+    protected void doConfirmPasswordReset(final SyncopeUser user, final String 
token, final String password)
             throws WorkflowException {
 
+        Map<String, Object> variables = new HashMap<String, Object>(4);
+        variables.put(TOKEN, token);
+        variables.put(PASSWORD, password);
+        variables.put(USER_TO, userDataBinder.getUserTO(user));
+        variables.put(EVENT, "confirmPasswordReset");
+
+        doExecuteTask(user, "confirmPasswordReset", variables);
+        userDAO.save(user);
+    }
+
+    @Override
+    protected void doDelete(final SyncopeUser user) throws WorkflowException {
         doExecuteTask(user, "delete", null);
 
         PropagationByResource propByRes = new PropagationByResource();

Modified: syncope/trunk/core/src/main/resources/META-INF/orm.xml
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/META-INF/orm.xml?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/META-INF/orm.xml (original)
+++ syncope/trunk/core/src/main/resources/META-INF/orm.xml Fri Sep 19 08:58:36 
2014
@@ -344,4 +344,12 @@ under the License.
       </id>
     </attributes>
   </entity>
+  <entity class="org.apache.syncope.core.persistence.beans.SecurityQuestion">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_SecurityQuestion" strategy="TABLE"/>
+        <table-generator name="SEQ_SecurityQuestion" 
pk-column-value="SEQ_SecurityQuestion" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
 </entity-mappings>

Modified: syncope/trunk/core/src/main/resources/META-INF/orm.xml.oracle
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/META-INF/orm.xml.oracle?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/META-INF/orm.xml.oracle (original)
+++ syncope/trunk/core/src/main/resources/META-INF/orm.xml.oracle Fri Sep 19 
08:58:36 2014
@@ -297,4 +297,12 @@ under the License.
       </id>
     </attributes>
   </entity>
+  <entity class="org.apache.syncope.core.persistence.beans.SecurityQuestion">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_SecurityQuestion" strategy="TABLE"/>
+        <table-generator name="SEQ_SecurityQuestion" 
pk-column-value="SEQ_SecurityQuestion" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>  
 </entity-mappings>

Modified: syncope/trunk/core/src/main/resources/META-INF/orm.xml.sqlserver
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/META-INF/orm.xml.sqlserver?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/META-INF/orm.xml.sqlserver (original)
+++ syncope/trunk/core/src/main/resources/META-INF/orm.xml.sqlserver Fri Sep 19 
08:58:36 2014
@@ -333,4 +333,12 @@ under the License.
       </id>
     </attributes>
   </entity>
+  <entity class="org.apache.syncope.core.persistence.beans.SecurityQuestion">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_SecurityQuestion" strategy="TABLE"/>
+        <table-generator name="SEQ_SecurityQuestion" 
pk-column-value="SEQ_SecurityQuestion" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>  
 </entity-mappings>

Modified: syncope/trunk/core/src/main/resources/content.xml
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/content.xml?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/content.xml (original)
+++ syncope/trunk/core/src/main/resources/content.xml Fri Sep 19 08:58:36 2014
@@ -56,10 +56,16 @@ under the License.
   <CAttr id="6" owner_id="1" schema_name="selfRegistration.allowed"/>
   <CAttrValue id="6" attribute_id="6" booleanValue="1"/>
 
+  <CSchema name="passwordReset.allowed" type="Boolean"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" 
readonly="0"/>
+  <CAttr id="7" owner_id="1" schema_name="passwordReset.allowed"/>
+  <CAttrValue id="7" attribute_id="7" booleanValue="1"/>
+
   <CSchema name="authentication.statuses" type="String"
            mandatoryCondition="true" multivalue="1" uniqueConstraint="0" 
readonly="0"/>
-  <CAttr id="7" owner_id="1" schema_name="authentication.statuses"/>
-  <CAttrValue id="7" attribute_id="7" stringValue="active"/>
+  <CAttr id="8" owner_id="1" schema_name="authentication.statuses"/>
+  <CAttrValue id="8" attribute_id="8" stringValue="created"/>
+  <CAttrValue id="9" attribute_id="8" stringValue="active"/>
 
   <!-- Save user login date upon successful authentication -->
   <CSchema name="log.lastlogindate" type="Boolean"
@@ -67,6 +73,22 @@ under the License.
   <CAttr id="10" owner_id="1" schema_name="log.lastlogindate"/>
   <CAttrValue id="10" attribute_id="10" booleanValue="1"/>
     
+  <!-- User pre-defined schemas -->
+  <USchema name="email" type="String"
+           mandatoryCondition="false" multivalue="0" uniqueConstraint="0" 
readonly="0"
+           
validatorClass="org.apache.syncope.core.persistence.validation.attrvalue.EmailAddressValidator"/>
  
+  
+  <!-- Password reset notifications -->
+  <Notification id="1" active="1" recipientAttrName="email" 
recipientAttrType="UserSchema" selfAsRecipient="1" 
+                sender="[email protected]" subject="Password Reset 
request" template="requestPasswordReset" 
+                traceLevel="FAILURES" userAbout="token!=$null"/> 
+  <Notification_events Notification_id="1" 
events="[CUSTOM]:[]:[]:[requestPasswordReset]:[SUCCESS]"/>
+  
+  <Notification id="2" active="1" recipientAttrName="email" 
recipientAttrType="UserSchema" selfAsRecipient="1" 
+                sender="[email protected]" subject="Password Reset 
successful" template="confirmPasswordReset" 
+                traceLevel="FAILURES" userAbout="token!=$null"/> 
+  <Notification_events Notification_id="2" 
events="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/>  
+  
   <!-- Authentication and authorization -->
   <Entitlement name="SCHEMA_LIST"/>
   <Entitlement name="SCHEMA_CREATE"/>
@@ -136,5 +158,10 @@ under the License.
   <Entitlement name="AUDIT_LIST"/>
   <Entitlement name="AUDIT_ENABLE"/>
   <Entitlement name="AUDIT_DISABLE"/>
+  <Entitlement name="SECURITY_QUESTION_LIST"/>
+  <Entitlement name="SECURITY_QUESTION_READ"/>
+  <Entitlement name="SECURITY_QUESTION_CREATE"/>
+  <Entitlement name="SECURITY_QUESTION_UPDATE"/>
+  <Entitlement name="SECURITY_QUESTION_DELETE"/>
 
 </dataset>

Modified: syncope/trunk/core/src/main/resources/mail.properties
URL: 
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/mail.properties?rev=1626150&r1=1626149&r2=1626150&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/mail.properties (original)
+++ syncope/trunk/core/src/main/resources/mail.properties Fri Sep 19 08:58:36 
2014
@@ -16,9 +16,9 @@
 # under the License.
 smtpHost=none.syncope.apache.org
 smtpPort=25
-smtpUser=syncope
-smtpPassword=secret
+smtpUser=
+smtpPassword=
 smtpProtocol=smtp
 smtpEncoding=UTF-8
 smtpConnectionTimeout=3000
-mailDebug=false
+mailDebug=false
\ No newline at end of file


Reply via email to