@@ -0,0 +1,39 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">

<id>build-amp-file</id>
<formats>
<format>amp</format>
</formats>


<includeBaseDirectory>false</includeBaseDirectory>

<files>
<!-- Filter module.properties and put at top level in the AMP -->
<file>
<source>src/main/resources/alfresco/module/resetPassword/module.properties</source>
<filtered>true</filtered>
</file>
</files>

<fileSets>
<fileSet>
<directory>src/main/config</directory>
<outputDirectory>config</outputDirectory>
<filtered>false</filtered>
</fileSet>
</fileSets>

<!-- Include the project artifact (JAR) in the /lib directory in the AMP, and any 3rd party libraries (JARs)
used by the customization.
-->
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>

</assembly>
@@ -0,0 +1,29 @@
<?xml version='1.0' encoding='utf-8'?>

<Context>
<Resources className="org.apache.catalina.webresources.StandardRoot">
<PreResources className="org.apache.catalina.webresources.DirResourceSet"
base="/usr/local/tomcat/webapps/alfresco/development/classes"
webAppMount="/WEB-INF/classes"/>
<JarResources className="org.apache.catalina.webresources.DirResourceSet"
base="/usr/local/tomcat/webapps/alfresco/development/lib"
webAppMount="/WEB-INF/lib"/>
</Resources>

<!-- Uncomment in $CATALINA_BASE/conf/[enginename]/[hostname]/alfresco.xml to define your own datasource. Add value attributes to each of the environment tags below to define your environment settings. -->
<!-- Resource defaultTransactionIsolation="-1" defaultAutoCommit="false" maxActive="100" initialSize="10" password="alfresco" username="alfresco" url="jdbc:mysql:///alfresco" driverClassName="org.gjt.mm.mysql.Driver" type="javax.sql.DataSource" auth="Container" name="jdbc/dataSource"/-->
<Environment override="false" type="java.lang.Boolean" name="properties/startup.enable"
description="A flag that globally enables or disables startup of the major Alfresco subsystems."
value="true"/>
<Environment override="false" type="java.lang.String" name="properties/dir.root"
description="The filesystem directory below which content and index data is stored. Should be on a shared disk if this is a clustered installation."/>
<Environment override="false" type="java.lang.String" name="properties/hibernate.dialect"
description="The fully qualified name of a org.hibernate.dialect.Dialect subclass that allows Hibernate to generate SQL optimized for a particular relational database. Choose from org.hibernate.dialect.DerbyDialect, org.hibernate.dialect.MySQLInnoDBDialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect, org.hibernate.dialect.PostgreSQLDialect"/>
<Environment override="false" type="java.lang.String" name="properties/hibernate.query.substitutions"
description="Mapping from tokens in Hibernate queries to SQL tokens. For PostgreSQL, set this to &quot;true TRUE, false FALSE&quot;."/>
<Environment override="false" type="java.lang.Boolean" name="properties/hibernate.jdbc.use_get_generated_keys"
description="Enable use of JDBC3 PreparedStatement.getGeneratedKeys() to retrieve natively generated keys after insert. Requires JDBC3+ driver. Set to false if your driver has problems with the Hibernate identifier generators. By default, tries to determine the driver capabilities using connection metadata."/>
<Environment override="false" type="java.lang.String" name="properties/hibernate.default_schema"
description="Qualify unqualified table names with the given schema/tablespace in generated SQL. It may be necessary to set this when the target database has more than one schema."/>
</Context>

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>resetpassword</artifactId>
<groupId>com.flex-solution</groupId>
<version>1.2.0.RC1</version>
</parent>

<artifactId>reset-password-repo</artifactId>
<version>1.2.0.RC1</version>
<name>Reset Password Repo AMP</name>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>content-services-community</artifactId>
<version>6.2.0-ga</version>
<scope>provided</scope>
<type>pom</type>
</dependency>
</dependencies>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/config</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>

<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeScope>provided</excludeScope>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>build-amp-file</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>

<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>amp.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.alfresco.maven.plugin</groupId>
<artifactId>alfresco-maven-plugin</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

</project>
Empty file.
@@ -51,7 +51,7 @@
<p>we received a request for password change
at ${shareUrl}</p>
<br/><a href="${shareUrl}/page/changePassWF?userToken=${userToken}&taskId=${taskId}&token=${token}">Go to
<br/><a href="${shareUrl}/page/changePassWF?token=${token}">Go to
this link</a> to set your new password.
The link will be active for 24 hours.</p>
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -9,7 +9,7 @@

import java.util.List;

public class EmailHelper extends BaseScopableProcessorExtension{
public class EmailHelper extends BaseScopableProcessorExtension {

private ServiceRegistry services;
private Repository repositoryHelper;
File renamed without changes.
@@ -0,0 +1,38 @@
package com.flexsolution.resetpassword.util;

import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCrypt;

import java.util.Properties;
import java.util.UUID;


public class TokenGenerator extends BaseScopableProcessorExtension {
private static final String SALT_KEY = "fs.passreset.salt";
private static final Logger logger = LoggerFactory.getLogger(TokenGenerator.class);

private Properties globalProps;

public String genToken (String userName) {
String salt = globalProps.getProperty(SALT_KEY);
if(salt == null || salt.equals("")) {
logger.error("Property fs.passreset.salt is missing");
throw new AlfrescoRuntimeException("Reset Password addon is not configured");
}
String token = BCrypt.hashpw(userName, salt).substring(salt.length());
return token + UUID.randomUUID().toString().substring(0, 14);
}

public String getHashFromToken (String token) {
return token.substring(0, token.length() - 14);
}

public void setGlobalProps (Properties globalProps) {
this.globalProps = globalProps;
}
}


@@ -0,0 +1,89 @@
package com.flexsolution.resetpassword.util;

import org.activiti.engine.HistoryService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.repo.workflow.activiti.ActivitiConstants;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.util.Pair;
import org.apache.log4j.Logger;

import java.util.List;

public class WorkflowHelper {

private static WorkflowService workflowService;

private static Logger logger = Logger.getLogger(WorkflowHelper.class);

private static HistoryService activitiHistoryService;

public static void cancelPreviousWorkflows(final String userName) {

Pair<String, String> userTenant = AuthenticationUtil.getUserTenant(userName);

final String tenantDomain = userTenant.getSecond();

TenantUtil.runAsUserTenant(new TenantUtil.TenantRunAsWork<Object>() {
@Override
public Object doWork() throws Exception {

List<WorkflowTask> workflowTasks = getTasksInProgress(userName);

if(logger.isDebugEnabled()) {
logger.debug("Found workflow tasks = " + workflowTasks.size());
}

for (WorkflowTask task : workflowTasks) {
if (logger.isDebugEnabled()) {
logger.debug("Current task: " + task.getName());
}

if ("fs-reset:review".equals(task.getName())) {
if (logger.isDebugEnabled()) {
logger.debug("Try to end task " + task.toString());
}
workflowService.cancelWorkflow(task.getPath().getInstance().getId());
}
}
return null;
}
}, userName, tenantDomain);
}

public static List<HistoricTaskInstance> getResetPassTasksByUserTokenAcrossTenants (String token){
HistoricTaskInstanceQuery query = activitiHistoryService.createHistoricTaskInstanceQuery()
.includeProcessVariables()
.unfinished()
.processVariableValueEquals("fs-reset:token", token);

return query.list();
}

private static List<WorkflowTask> getTasksInProgress(String userName) {

WorkflowTaskQuery query = new WorkflowTaskQuery();
query.setEngineId(ActivitiConstants.ENGINE_ID);
query.setTaskState(WorkflowTaskState.IN_PROGRESS);
query.setActorId(userName);

if (logger.isDebugEnabled()) {
logger.debug("Try to delete workflows...");
}

return workflowService.queryTasks(query, true);
}

public void setWorkflowService(WorkflowService workflowService) {
WorkflowHelper.workflowService = workflowService;
}

public void setActivitiHistoryService (HistoryService activitiHistoryService) {
WorkflowHelper.activitiHistoryService = activitiHistoryService;
}
}
@@ -0,0 +1,125 @@
package com.flexsolution.resetpassword.webscripts;

import com.flexsolution.resetpassword.util.TokenGenerator;
import com.flexsolution.resetpassword.util.WorkflowHelper;
import org.activiti.engine.history.HistoricTaskInstance;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.repo.workflow.activiti.ActivitiConstants;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.extensions.surf.util.Content;
import org.springframework.extensions.webscripts.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class ApplyChangedPasswordPost extends DeclarativeWebScript {

public static final String NEW_PAS = "new-password";
public static final String NEW_PAS_CONFIRM = "new-password-confirm";
public static final String TOKEN = "userToken";


private WorkflowService workflowService;
private MutableAuthenticationService authenticationService;
private TokenGenerator tokenGenerator;

private static final Logger logger = LoggerFactory.getLogger(ApplyChangedPasswordPost.class);

@Override
protected Map<String, Object> executeImpl (WebScriptRequest req, Status status, Cache cache) {

final Map<String, String> data = getDataFromRequest(req);

String pass = data.get(NEW_PAS);
String confirmPass = data.get(NEW_PAS_CONFIRM);

if(!Objects.equals(pass, confirmPass)) {
logger.error("Password and confirm password are not equal");
throw new AlfrescoRuntimeException("Password and confirm password are not equal");
}

String incomingToken = data.get(TOKEN);
List<HistoricTaskInstance> candidateTasks = WorkflowHelper.getResetPassTasksByUserTokenAcrossTenants(incomingToken);

if(candidateTasks.isEmpty()) {
logger.error("Invalid 'change password' request received. Process by token={} does not exist or has been finished", incomingToken);
throw new AlfrescoRuntimeException("Request to change password is not valid");
}
if(candidateTasks.size() != 1) {
logger.error("Found more than one process by token={}", incomingToken);
throw new AlfrescoRuntimeException("Request to change password is not valid");
}
final HistoricTaskInstance historicTaskInstance = candidateTasks.get(0);

String assignee = historicTaskInstance.getAssignee();
String hashForCurrentAssignee = tokenGenerator.getHashFromToken(tokenGenerator.genToken(assignee));

if(!hashForCurrentAssignee.equals(tokenGenerator.getHashFromToken(incomingToken))) {
logger.error("Invalid 'change password' request received. Token={} is not valid for user {}", incomingToken, assignee);
throw new AlfrescoRuntimeException("Request to change password is not valid");
}

String tenant_domain = (String) historicTaskInstance.getProcessVariables().get(ActivitiConstants.VAR_TENANT_DOMAIN);

if(tenant_domain == null) {
tenant_domain = "";
}

// clear context - to avoid MT concurrency issue (causing domain mismatch)
AuthenticationUtil.clearCurrentSecurityContext();

TenantUtil.runAsSystemTenant(new TenantUtil.TenantRunAsWork<Object>() {

@Override
public Object doWork () throws Exception {
String activitiTaskId = "activiti$" + historicTaskInstance.getId();
authenticationService.setAuthentication(assignee, pass.toCharArray());
workflowService.endTask(activitiTaskId, null);
return null;
}
}, tenant_domain);

return new HashMap<String, Object>() {{
put("message", "OK");
}};
}

private Map<String, String> getDataFromRequest (WebScriptRequest req) {

HashMap<String, String> result = new HashMap<>();
Content content = req.getContent();

try {
JSONObject jsonObject = new JSONObject(content.getContent());

result.put(TOKEN, jsonObject.getString(TOKEN));
result.put(NEW_PAS, jsonObject.getString(NEW_PAS));
result.put(NEW_PAS_CONFIRM, jsonObject.getString(NEW_PAS_CONFIRM));

} catch (Exception e) {
logger.error(e.getMessage());
throw new WebScriptException("Failed to get data from request. Please, contact system administrator");
}
return result;
}

public void setWorkflowService (WorkflowService workflowService) {
this.workflowService = workflowService;
}

public void setAuthenticationService (MutableAuthenticationService authenticationService) {
this.authenticationService = authenticationService;
}

public void setTokenGenerator (TokenGenerator tokenGenerator) {
this.tokenGenerator = tokenGenerator;
}
}
@@ -0,0 +1,214 @@
package com.flexsolution.resetpassword.webscripts;

import com.flexsolution.resetpassword.util.WorkflowHelper;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.TenantContextHolder;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.repository.*;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.extensions.surf.util.Content;
import org.springframework.extensions.webscripts.*;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ResetPasswordPost extends DeclarativeWebScript {

@Autowired
private ContentService contentService;

@Autowired
private NodeService nodeService;

@Autowired
private Repository repository;

@Autowired
private SearchService searchService;

@Autowired
private NamespaceService namespaceService;

private WorkflowService workflowService;
private PersonService personService;

private static final String RESET_PASS_EMAIL_TEMPLATE_XPATH = "app:dictionary/app:email_templates/cm:workflownotification/cm:reset-password.ftl";
private static final String WORKFLOW_NOTIFICATION_XPATH = "app:dictionary/app:email_templates/cm:workflownotification";

private static final String RESET_PASS_FILE_NAME = "reset-password.ftl";

private static final Logger logger = LoggerFactory.getLogger(ResetPasswordPost.class);

@Override
public Map<String, Object> executeImpl (WebScriptRequest req, Status status, Cache cache) {

final String userName = getUserNameFromRequest(req);

// clear context - to avoid MT concurrency issue (causing domain mismatch)
AuthenticationUtil.clearCurrentSecurityContext();

final String tenantDomain = AuthenticationUtil.getUserTenant(userName).getSecond();

createEmailTemplateIfNotExists(tenantDomain);

TenantContextHolder.setTenantDomain(tenantDomain);
AuthenticationUtil.setRunAsUser(userName);

NodeRef user = getUserByUserName(userName);

WorkflowHelper.cancelPreviousWorkflows(userName);

logger.debug("Try to start workflow with user " + userName);

startWorkFlow(user);

logger.debug("Workflow has been started");

return null;
}

private void createEmailTemplateIfNotExists (String tenantDomain) {
AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>() {
@Override
public Object doWork () throws Exception {
if(!emailTemplateExists(tenantDomain)) {
addEmailTemplate(tenantDomain);
}
return null;
}
});
}

private boolean emailTemplateExists (String tenantDomain) {

TenantContextHolder.setTenantDomain(tenantDomain);

NodeRef companyHome = repository.getCompanyHome();

List<NodeRef> emailTemplateFiles = searchService.selectNodes(companyHome, RESET_PASS_EMAIL_TEMPLATE_XPATH, null, namespaceService, false);

return !emailTemplateFiles.isEmpty();
}

private void addEmailTemplate (String tenantDomain) {

TenantContextHolder.setTenantDomain(tenantDomain);

NodeRef companyHome = repository.getCompanyHome();

List<NodeRef> workflowNotificationFolder = searchService.selectNodes(companyHome, WORKFLOW_NOTIFICATION_XPATH, null, namespaceService, false);

Map<QName, Serializable> properties = new HashMap<>();
properties.put(ContentModel.PROP_NAME, RESET_PASS_FILE_NAME);

ChildAssociationRef newEmailTemplateCreated = nodeService.createNode(workflowNotificationFolder.get(0),
ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(RESET_PASS_FILE_NAME)),
ContentModel.TYPE_CONTENT,
properties);
ContentWriter invWriter = contentService.getWriter(newEmailTemplateCreated.getChildRef(), ContentModel.PROP_CONTENT, true);

String adminTenant = "";

TenantContextHolder.setTenantDomain(adminTenant);

companyHome = repository.getCompanyHome();

List<NodeRef> emailTemplateFiles = searchService.selectNodes(companyHome, RESET_PASS_EMAIL_TEMPLATE_XPATH, null, namespaceService, false);

NodeRef emailTemplate = emailTemplateFiles.get(0);

ContentReader reader = contentService.getReader(emailTemplate, ContentModel.PROP_CONTENT);

TenantContextHolder.setTenantDomain(tenantDomain);

invWriter.putContent(reader);

}

private void startWorkFlow (final NodeRef user) {

WorkflowDefinition workflowDefinition = workflowService.getDefinitionByName("activiti$resetPasswordFlex");

if(workflowDefinition == null) {
logger.error("Workflow definition is not found activiti$resetPasswordFlex");
throw new WebScriptException(500, "Sorry. Internal error. Try later");
}

Map<QName, Serializable> param = new HashMap<>();

logger.debug("Try to set assignee");

param.put(WorkflowModel.ASSOC_ASSIGNEE, user);

logger.debug("Assignee: {}", param.get(WorkflowModel.ASSOC_ASSIGNEE));

logger.debug("Try to set description");

param.put(WorkflowModel.PROP_DESCRIPTION, "Request to change password");

logger.debug("Try to set owner");

param.put(ContentModel.PROP_OWNER, AuthenticationUtil.getAdminUserName());

logger.debug("Try to start workflow...");

workflowService.startWorkflow(workflowDefinition.getId(), param);
}

private NodeRef getUserByUserName (final String userName) {

return AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<NodeRef>() {
@Override
public NodeRef doWork () throws Exception {
NodeRef user = personService.getPersonOrNull(userName);
if(user == null) {
logger.error("Failed to find user with username={}", userName);
throw new WebScriptException(404, "error.userNotFound");
}
return user;
}
});
}

private String getUserNameFromRequest (WebScriptRequest request) {
Content content = request.getContent();

String userName;

try {
JSONObject jsonObject = new JSONObject(content.getContent());

userName = jsonObject.getString("userName");

} catch (JSONException | IOException e) {
logger.error(e.getMessage());
throw new WebScriptException(500, "Sorry. Internal error. Try later");
}

return userName;
}

public void setWorkflowService (WorkflowService workflowService) {
this.workflowService = workflowService;
}

public void setPersonService (PersonService personService) {
this.personService = personService;
}
}
@@ -0,0 +1,54 @@
package com.flexsolution.resetpassword.webscripts;

import com.flexsolution.resetpassword.util.WorkflowHelper;
import org.activiti.engine.history.HistoricTaskInstance;
import org.alfresco.error.AlfrescoRuntimeException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.extensions.surf.util.Content;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TaskIsCompletePost extends DeclarativeWebScript {

private static final Logger logger = LoggerFactory.getLogger(TaskIsCompletePost.class);

@Override
protected Map<String, Object> executeImpl (WebScriptRequest req, Status status, Cache cache) {

try {
Content content = req.getContent();
final JSONObject jsonObject = new JSONObject(content.getContent());
final String resetPasswordToken = jsonObject.getString("token");

if(resetPasswordToken == null) {
logger.error("Invalid 'change password' request received. User token is null");
throw new AlfrescoRuntimeException("Request to change password is not valid");
}

List<HistoricTaskInstance> cnadidateTasks = WorkflowHelper.getResetPassTasksByUserTokenAcrossTenants(resetPasswordToken);

if(cnadidateTasks.isEmpty()) {
logger.error("Invalid 'change password' request received. Process by token={} does not exist or has been finished", resetPasswordToken);
throw new AlfrescoRuntimeException("Request to change password is not valid");
}
if(cnadidateTasks.size() != 1) {
logger.error("Found more than one process by token={}", resetPasswordToken);
throw new AlfrescoRuntimeException("Request to change password is not valid");
}
return new HashMap<String, Object>(){{
put("message", "OK");
}};
} catch (Exception e) {
logger.error(e.getMessage());
throw new AlfrescoRuntimeException("Failed to retrieve data from json");
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -15,8 +15,7 @@
sourceRef='start'
targetRef='review'/>

<userTask id="review" name="Review"
activiti:formKey="fs-reset:review" activiti:assignee="${bpm_assignee.properties.userName}">
<userTask id="review" name="Review" activiti:formKey="fs-reset:review" activiti:assignee="${bpm_assignee.properties.userName}">
<extensionElements>

<activiti:taskListener event="create"
@@ -29,16 +28,6 @@
</activiti:field>
</activiti:taskListener>

<activiti:taskListener event="complete"
class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string><![CDATA[<import resource="classpath:alfresco/extension/workflow/js/reset-password.js">
var obj = new ResetPassword();
sudo.asTenant(bpm_assignee.properties.userName, obj.reviewComplete, obj);
]]></activiti:string>
</activiti:field>
</activiti:taskListener>

</extensionElements>
</userTask>

@@ -10,32 +10,15 @@ var ResetPassword = function () {
this._sendEmail("reset-password.ftl", bpm_assignee.properties.email, {})
};

this.reviewComplete = function () {

var pass = task.getVariable("fs-reset_password");
pass2 = task.getVariable("fs-reset_confirmPass");

if (!isValid(pass, pass2)) {
throw "Confirm password does not match password or password length too short";
}

var password = task.getVariableLocal("fs-reset_password"),
userName = bpm_assignee.properties.userName;

passwordService.setPassword(userName, password);
};

this._sendEmail = function (templateName, to) {


try {
var template = emailHelper.getLocalizedEmailTemplate("app:dictionary/app:email_templates/cm:workflownotification/cm:" + templateName);
} catch (e) {
throw e.javaException.getMessage();
}

var mail = actions.create("mail");
var currentToken = token.genToken();
var currentToken = token.genToken(bpm_assignee.properties.userName);

mail.parameters.template = template;
mail.parameters.to = to;
@@ -56,12 +39,10 @@ var ResetPassword = function () {

this.prepareTemplateProps = function (assignee, task, currentToken) {
var templateProps = {};
templateProps["userToken"] = assignee.properties["userName"];
templateProps["assignee"] = {
firstname: assignee.properties["firstName"],
lastname: assignee.properties["lastName"]
};
templateProps["taskId"] = "activiti$" + task.id;
templateProps["token"] = currentToken;
return templateProps;
}
@@ -29,15 +29,6 @@
<title>Review</title>
<parent>bpm:workflowTask</parent>
<properties>
<property name="fs-reset:password">
<type>d:text</type>
<mandatory>true</mandatory>
</property>
<property name="fs-reset:confirmPass">
<type>d:text</type>
<mandatory>true</mandatory>
</property>

<property name="fs-reset:token">
<type>d:text</type>
<mandatory>true</mandatory>
@@ -0,0 +1,4 @@
alfresco.host=localhost
share.host=localhost

fs.passreset.salt=$2a$11$sGL4KAlXWsxR3ysNL8HOmu
File renamed without changes.
@@ -17,13 +17,12 @@
<property name="extensionName">
<value>token</value>
</property>
<property name="globalProps" ref="global-properties"/>
</bean>

<bean class="com.flexsolution.resetpassword.util.WorkflowHelper">
<property name="workflowService" ref="WorkflowService"/>
<property name="searchService" ref="SearchService"/>
<property name="repository" ref="repositoryHelper"/>
<property name="nodeService" ref="NodeService"/>
<property name="activitiHistoryService" ref="activitiHistoryService"/>
</bean>


@@ -8,11 +8,12 @@
</bean>

<bean id="webscript.com.flex-solution.taskIsComplete.taskIsComplete.post" parent="webscript" class="com.flexsolution.resetpassword.webscripts.TaskIsCompletePost">
<property name="workflowService" ref="WorkflowService"/>
</bean>

<bean id="webscript.com.flex-solution.applyChangedPassword.applyChangedPassword.post" parent="webscript" class="com.flexsolution.resetpassword.webscripts.ApplyChangedPasswordPost">
<property name="workflowService" ref="WorkflowService"/>
<property name="authenticationService" ref="AuthenticationService" />
<property name="tokenGenerator" ref="genToken" />
</bean>

</beans>
File renamed without changes.
@@ -0,0 +1,12 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- This is filtered by Maven at build time, so that module name is single sourced. -->
<import resource="classpath:alfresco/module/resetPassword/context/*-context.xml" />

<context:component-scan base-package="com.flexsolution"/>

</beans>
@@ -0,0 +1,4 @@
module.id=${project.artifactId}
module.title=${project.name}
module.description=${project.description}
module.version=${project.version}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

30 pom.xml
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.flex-solution</groupId>
<artifactId>resetpassword</artifactId>
<version>1.2.0.RC1</version>
<name>all in one</name>
<packaging>pom</packaging>


<repositories>
<repository>
<id>alfresco-public</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>alfresco-public</id>
<name>Alfresco</name>
<url>http://artifacts.alfresco.com/nexus/content/repositories/releases</url>
</pluginRepository>
</pluginRepositories>

<modules>
<module>alfresco-resetpassword</module>
<module>share-resetpassword</module>
</modules>
</project>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading