Merge branch 'master' of https://github.com/Alfresco/alfresco-community-repo into MNT-23926_add_sevenpass_dod_5220.22-M_ags_deletion

This commit is contained in:
Vedant Mehra
2025-03-12 13:05:29 +05:30
29 changed files with 656 additions and 565 deletions

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId> <artifactId>alfresco-community-repo-amps</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<modules> <modules>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId> <artifactId>alfresco-governance-services-community-parent</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<modules> <modules>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-automation-community-repo</artifactId> <artifactId>alfresco-governance-services-automation-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<build> <build>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId> <artifactId>alfresco-governance-services-community-parent</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<modules> <modules>

View File

@@ -1,3 +1,3 @@
SOLR6_TAG=2.0.14 SOLR6_TAG=2.0.15
POSTGRES_TAG=16.6 POSTGRES_TAG=16.6
ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8 ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8

View File

@@ -8,7 +8,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId> <artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<properties> <properties>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId> <artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<build> <build>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<modules> <modules>

View File

@@ -8,7 +8,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId> <artifactId>alfresco-community-repo-amps</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<properties> <properties>

View File

@@ -23,10 +23,6 @@ function runAction(p_params)
if (p_params.destNode.hasAspect("cm:lockable") && !p_params.destNode.hasAspect("trx:transferred")) if (p_params.destNode.hasAspect("cm:lockable") && !p_params.destNode.hasAspect("trx:transferred"))
{ {
p_params.destNode.unlock(); p_params.destNode.unlock();
if(p_params.destNode.hasAspect("gd2:editingInGoogle"))
{
p_params.destNode.removeAspect("gd2:editingInGoogle");
}
} }
var resultId = originalDoc.name, var resultId = originalDoc.name,

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<dependencies> <dependencies>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<properties> <properties>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<dependencies> <dependencies>

View File

@@ -9,6 +9,6 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId> <artifactId>alfresco-community-repo-packaging</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
</project> </project>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId> <artifactId>alfresco-community-repo-packaging</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<properties> <properties>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<modules> <modules>

View File

@@ -1,3 +1,3 @@
SOLR6_TAG=2.0.14 SOLR6_TAG=2.0.15
POSTGRES_TAG=16.6 POSTGRES_TAG=16.6
ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8 ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId> <artifactId>alfresco-community-repo-packaging</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<modules> <modules>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<organization> <organization>

View File

@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<developers> <developers>

View File

@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<developers> <developers>

View File

@@ -8,7 +8,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<properties> <properties>

View File

@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<developers> <developers>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId> <artifactId>alfresco-community-repo-packaging</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<properties> <properties>

10
pom.xml
View File

@@ -2,7 +2,7 @@
<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"> <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> <modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name> <name>Alfresco Community Repo Parent</name>
@@ -51,8 +51,8 @@
<dependency.alfresco-server-root.version>7.0.1</dependency.alfresco-server-root.version> <dependency.alfresco-server-root.version>7.0.1</dependency.alfresco-server-root.version>
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version> <dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
<dependency.activiti.version>5.23.0</dependency.activiti.version> <dependency.activiti.version>5.23.0</dependency.activiti.version>
<dependency.alfresco-transform-core.version>5.1.7-A.3</dependency.alfresco-transform-core.version> <dependency.alfresco-transform-core.version>5.1.7</dependency.alfresco-transform-core.version>
<dependency.alfresco-transform-service.version>4.1.7-A.1</dependency.alfresco-transform-service.version> <dependency.alfresco-transform-service.version>4.1.7</dependency.alfresco-transform-service.version>
<dependency.alfresco-greenmail.version>7.1</dependency.alfresco-greenmail.version> <dependency.alfresco-greenmail.version>7.1</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>1.0.2</dependency.acs-event-model.version> <dependency.acs-event-model.version>1.0.2</dependency.acs-event-model.version>
@@ -112,10 +112,10 @@
<dependency.jakarta-ee-json-api.version>2.1.3</dependency.jakarta-ee-json-api.version> <dependency.jakarta-ee-json-api.version>2.1.3</dependency.jakarta-ee-json-api.version>
<dependency.jakarta-ee-json-impl.version>1.1.7</dependency.jakarta-ee-json-impl.version> <dependency.jakarta-ee-json-impl.version>1.1.7</dependency.jakarta-ee-json-impl.version>
<dependency.jakarta-json-path.version>2.9.0</dependency.jakarta-json-path.version> <dependency.jakarta-json-path.version>2.9.0</dependency.jakarta-json-path.version>
<dependency.json-smart.version>2.5.1</dependency.json-smart.version> <dependency.json-smart.version>2.5.2</dependency.json-smart.version>
<alfresco.googledrive.version>4.1.0</alfresco.googledrive.version> <alfresco.googledrive.version>4.1.0</alfresco.googledrive.version>
<alfresco.aos-module.version>3.2.0</alfresco.aos-module.version> <alfresco.aos-module.version>3.2.0</alfresco.aos-module.version>
<alfresco.api-explorer.version>25.1.0-A1</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share --> <alfresco.api-explorer.version>25.1.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version> <alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
<license-maven-plugin.version>2.4.0</license-maven-plugin.version> <license-maven-plugin.version>2.4.0</license-maven-plugin.version>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<dependencies> <dependencies>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>25.1.0.61-SNAPSHOT</version> <version>25.1.0.70-SNAPSHOT</version>
</parent> </parent>
<dependencies> <dependencies>

View File

@@ -28,11 +28,17 @@ package org.alfresco.repo.workflow.activiti.script;
import java.util.Map; import java.util.Map;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.delegate.VariableScope; import org.activiti.engine.delegate.VariableScope;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context; import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.el.Expression; import org.activiti.engine.impl.el.Expression;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity; import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.workflow.WorkflowDeployer; import org.alfresco.repo.workflow.WorkflowDeployer;
@@ -45,13 +51,12 @@ import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.workflow.WorkflowException; import org.alfresco.service.cmr.workflow.WorkflowException;
/** /**
* Base class for execution scripts, using {@link ScriptService} as part of * Base class for execution scripts, using {@link ScriptService} as part of activiti workflow.
* activiti workflow.
* *
* @author Frederik Heremans * @author Frederik Heremans
* @since 3.4.e * @since 3.4.e
*/ */
public class ActivitiScriptBase public class ActivitiScriptBase
{ {
protected static final String PERSON_BINDING_NAME = "person"; protected static final String PERSON_BINDING_NAME = "person";
protected static final String USERHOME_BINDING_NAME = "userhome"; protected static final String USERHOME_BINDING_NAME = "userhome";
@@ -61,17 +66,19 @@ public class ActivitiScriptBase
protected Expression runAs; protected Expression runAs;
protected Expression scriptProcessor; protected Expression scriptProcessor;
private static final Logger LOGGER = LoggerFactory.getLogger(ActivitiScriptBase.class);
protected Object executeScript(String theScript, Map<String, Object> model, String scriptProcessorName, String runAsUser) protected Object executeScript(String theScript, Map<String, Object> model, String scriptProcessorName, String runAsUser)
{ {
String user = AuthenticationUtil.getFullyAuthenticatedUser(); String user = AuthenticationUtil.getFullyAuthenticatedUser();
Object scriptResult = null; Object scriptResult = null;
if (runAsUser == null && user != null) if (runAsUser == null && user != null)
{ {
// Just execute the script using the current user // Just execute the script using the current user
scriptResult = executeScript(theScript, model, scriptProcessorName); scriptResult = executeScript(theScript, model, scriptProcessorName);
} }
else else
{ {
if (runAsUser != null) if (runAsUser != null)
{ {
@@ -87,26 +94,25 @@ public class ActivitiScriptBase
} }
return scriptResult; return scriptResult;
} }
protected Object executeScriptAsUser(final String theScript, final Map<String, Object> model, final String scriptProcessorName, final String runAsUser) protected Object executeScriptAsUser(final String theScript, final Map<String, Object> model, final String scriptProcessorName, final String runAsUser)
{ {
// execute as specified runAsUser // execute as specified runAsUser
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>() return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<>() {
{
public Object doWork() throws Exception public Object doWork() throws Exception
{ {
return executeScript(theScript, model, scriptProcessorName); return executeScript(theScript, model, scriptProcessorName);
} }
}, runAsUser); }, runAsUser);
} }
protected Object executeScript(String theScript, Map<String, Object> model, String scriptProcessorName) protected Object executeScript(String theScript, Map<String, Object> model, String scriptProcessorName)
{ {
// Execute the script using the appropriate processor // Execute the script using the appropriate processor
Object scriptResult = null; Object scriptResult = null;
// Checks if current workflow is secure // Checks if current workflow is secure
boolean secure = isSecure(); boolean secure = isSecure(model);
if (scriptProcessorName != null) if (scriptProcessorName != null)
{ {
@@ -117,11 +123,11 @@ public class ActivitiScriptBase
// Use default script-processor // Use default script-processor
scriptResult = getServiceRegistry().getScriptService().executeScriptString(theScript, model, secure); scriptResult = getServiceRegistry().getScriptService().executeScriptString(theScript, model, secure);
} }
return scriptResult; return scriptResult;
} }
protected String getStringValue(Expression expression, VariableScope scope) protected String getStringValue(Expression expression, VariableScope scope)
{ {
if (expression != null) if (expression != null)
{ {
@@ -133,15 +139,15 @@ public class ActivitiScriptBase
protected ServiceRegistry getServiceRegistry() protected ServiceRegistry getServiceRegistry()
{ {
ProcessEngineConfigurationImpl config = Context.getProcessEngineConfiguration(); ProcessEngineConfigurationImpl config = Context.getProcessEngineConfiguration();
if (config != null) if (config != null)
{ {
// Fetch the registry that is injected in the activiti spring-configuration // Fetch the registry that is injected in the activiti spring-configuration
ServiceRegistry registry = (ServiceRegistry) config.getBeans().get(ActivitiConstants.SERVICE_REGISTRY_BEAN_KEY); ServiceRegistry registry = (ServiceRegistry) config.getBeans().get(ActivitiConstants.SERVICE_REGISTRY_BEAN_KEY);
if (registry == null) if (registry == null)
{ {
throw new RuntimeException( throw new RuntimeException(
"Service-registry not present in ProcessEngineConfiguration beans, expected ServiceRegistry with key" + "Service-registry not present in ProcessEngineConfiguration beans, expected ServiceRegistry with key" +
ActivitiConstants.SERVICE_REGISTRY_BEAN_KEY); ActivitiConstants.SERVICE_REGISTRY_BEAN_KEY);
} }
return registry; return registry;
} }
@@ -149,42 +155,136 @@ public class ActivitiScriptBase
} }
/** /**
* Checks whether the workflow must be considered secure or not - based on {@link DeploymentEntity} category. * Checks whether the workflow must be considered secure or not - based on {@link DeploymentEntity} category. If it is not considered secure, the workflow will be executed in sandbox context with more restrictions
* If it is not considered secure, the workflow will be executed in sandbox context with more restrictions
* *
* @return true if workflow is considered secure, false otherwise * @return true if workflow is considered secure, false otherwise
*/ */
private boolean isSecure() private boolean isSecure(Map<String, Object> model)
{
String category = getDeploymentCategory(model);
// iF The deployment category matches the condition (either internal or full access) the workflow is considered secure
return category != null && (WorkflowDeployer.CATEGORY_ALFRESCO_INTERNAL.equals(category) || WorkflowDeployer.CATEGORY_FULL_ACCESS.equals(category));
}
/**
* Gets the deployment category from the execution context. If no execution context is available, a query to obtain the deployment is performed so the category can be returned.
*
* @param model
* a map with workflow model
* @return the deployment category
*/
private String getDeploymentCategory(Map<String, Object> model)
{
String category = getDeploymentCategoryFromContext();
if (category == null)
{
String deploymentId = null;
String processDefinitionId = null;
if (model != null && model.containsKey(EXECUTION_BINDING_NAME) && model.get(EXECUTION_BINDING_NAME) instanceof ExecutionEntity)
{
ExecutionEntity executionEntity = (ExecutionEntity) model.get(EXECUTION_BINDING_NAME);
deploymentId = executionEntity.getDeploymentId();
processDefinitionId = executionEntity.getProcessDefinitionId();
}
category = getDeploymentCategoryFromQuery(deploymentId, processDefinitionId);
}
return category;
}
/**
* Obtains the deployment category from current execution context
*
* @return the category for current execution deployment, otherwise null
*/
private String getDeploymentCategoryFromContext()
{ {
String category = null; String category = null;
try try
{ {
if (Context.isExecutionContextActive()) if (Context.isExecutionContextActive())
{ {
category = Context.getExecutionContext().getDeployment().getCategory(); category = Context.getExecutionContext().getDeployment().getCategory();
} }
else
{
if (LOGGER.isDebugEnabled())
{
LOGGER.debug("No execution context available");
}
}
} }
catch (Exception e) catch (Exception e)
{ {
// No action required if (LOGGER.isDebugEnabled())
{
LOGGER.debug("Could not obtain deployment category from execution context: {}", e.getMessage());
}
} }
// If the workflow is considered secure, the deployment entity category matches the condition (either internal or full access) return category;
return category != null && (WorkflowDeployer.CATEGORY_ALFRESCO_INTERNAL.equals(category) || WorkflowDeployer.CATEGORY_FULL_ACCESS.equals(category));
} }
/** /**
* Checks that the specified 'runAs' field * Obtains the deployment category through a query
* specifies a valid username. *
* @param deploymentId
* the deployment id to obtain the category from
* @param processDefinitionId
* if no deployment id is provided, the process definition id can be used to obtain the deployment
* @return the category for the obtained deployment, otherwise null
*/ */
private void validateRunAsUser(final String runAsUser) private String getDeploymentCategoryFromQuery(String deploymentId, String processDefinitionId)
{ {
Boolean runAsExists = AuthenticationUtil.runAs(new RunAsWork<Boolean>() String category = null;
try
{ {
RepositoryService repositoryService = Context.getProcessEngineConfiguration().getRepositoryService();
if (deploymentId == null && processDefinitionId != null)
{
ProcessDefinition processDefnition = repositoryService.getProcessDefinition(processDefinitionId);
if (processDefnition != null)
{
deploymentId = processDefnition.getDeploymentId();
}
}
if (deploymentId != null)
{
DeploymentEntity deployment = (DeploymentEntity) repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
if (deployment != null)
{
category = deployment.getCategory();
}
}
}
catch (Exception e)
{
if (LOGGER.isDebugEnabled())
{
LOGGER.debug("Could not obtain deployment category through a query: {}", e.getMessage());
}
}
return category;
}
/**
* Checks that the specified 'runAs' field specifies a valid username.
*/
private void validateRunAsUser(final String runAsUser)
{
Boolean runAsExists = AuthenticationUtil.runAs(new RunAsWork<>() {
// Validate using System user to ensure sufficient permissions available to access person node. // Validate using System user to ensure sufficient permissions available to access person node.
public Boolean doWork() throws Exception @Override
public Boolean doWork() throws Exception
{ {
return getServiceRegistry().getPersonService().personExists(runAsUser); return getServiceRegistry().getPersonService().personExists(runAsUser);
} }
@@ -195,21 +295,21 @@ public class ActivitiScriptBase
throw new WorkflowException("runas user '" + runAsUser + "' does not exist."); throw new WorkflowException("runas user '" + runAsUser + "' does not exist.");
} }
} }
protected ActivitiScriptNode getPersonNode(String runAsUser) protected ActivitiScriptNode getPersonNode(String runAsUser)
{ {
String userName = null; String userName = null;
if (runAsUser != null) if (runAsUser != null)
{ {
userName = runAsUser; userName = runAsUser;
} }
else else
{ {
userName = AuthenticationUtil.getFullyAuthenticatedUser(); userName = AuthenticationUtil.getFullyAuthenticatedUser();
} }
// The "System" user is a special case, which has no person object associated with it. // The "System" user is a special case, which has no person object associated with it.
if(userName != null && !AuthenticationUtil.SYSTEM_USER_NAME.equals(userName)) if (userName != null && !AuthenticationUtil.SYSTEM_USER_NAME.equals(userName))
{ {
ServiceRegistry services = getServiceRegistry(); ServiceRegistry services = getServiceRegistry();
PersonService personService = services.getPersonService(); PersonService personService = services.getPersonService();
@@ -221,18 +321,18 @@ public class ActivitiScriptBase
} }
return null; return null;
} }
public void setScript(Expression script) public void setScript(Expression script)
{ {
this.script = script; this.script = script;
} }
public void setRunAs(Expression runAs) public void setRunAs(Expression runAs)
{ {
this.runAs = runAs; this.runAs = runAs;
} }
public void setScriptProcessor(Expression scriptProcessor) public void setScriptProcessor(Expression scriptProcessor)
{ {
this.scriptProcessor = scriptProcessor; this.scriptProcessor = scriptProcessor;
} }

View File

@@ -1,494 +1,489 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2023 Alfresco Software Limited * Copyright (C) 2005 - 2023 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.lock.mem; package org.alfresco.repo.lock.mem;
import java.util.Date; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import jakarta.transaction.NotSupportedException; import static org.junit.Assert.fail;
import jakarta.transaction.SystemException;
import jakarta.transaction.UserTransaction; import java.util.Date;
import jakarta.transaction.NotSupportedException;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import jakarta.transaction.SystemException;
import org.alfresco.service.cmr.lock.LockType; import jakarta.transaction.UserTransaction;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.transaction.TransactionService; import org.junit.Before;
import org.alfresco.util.ApplicationContextHelper; import org.junit.BeforeClass;
import org.junit.Before; import org.junit.Test;
import org.junit.BeforeClass; import org.springframework.context.ApplicationContext;
import org.junit.Test; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.ConcurrencyFailureException; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.lock.LockType;
import static org.junit.Assert.assertEquals; import org.alfresco.service.cmr.repository.NodeRef;
import static org.junit.Assert.assertNull; import org.alfresco.service.transaction.TransactionService;
import static org.junit.Assert.fail; import org.alfresco.util.ApplicationContextHelper;
/** /**
* Integration tests that check transaction related functionality of {@link LockStore} implementations. * Integration tests that check transaction related functionality of {@link LockStore} implementations.
* @author Matt Ward *
*/ * @author Matt Ward
public abstract class AbstractLockStoreTxTest<T extends LockStore> */
{ public abstract class AbstractLockStoreTxTest<T extends LockStore>
/** {
* Instance of the Class Under Test. /**
*/ * Instance of the Class Under Test.
protected T lockStore; */
protected T lockStore;
protected static ApplicationContext ctx;
protected static TransactionService transactionService; protected static ApplicationContext ctx;
protected static TransactionService transactionService;
/**
* Concrete subclasses must implement this method to provide the tests with a LockStore instance. /**
* * Concrete subclasses must implement this method to provide the tests with a LockStore instance.
* @return LockStore to test *
*/ * @return LockStore to test
protected abstract T createLockStore(); */
protected abstract T createLockStore();
@BeforeClass
public static void setUpSpringContext() @BeforeClass
{ public static void setUpSpringContext()
ctx = ApplicationContextHelper.getApplicationContext(); {
transactionService = (TransactionService) ctx.getBean("TransactionService"); ctx = ApplicationContextHelper.getApplicationContext();
} transactionService = (TransactionService) ctx.getBean("TransactionService");
}
@Before
public void setUpLockStore() @Before
{ public void setUpLockStore()
lockStore = createLockStore(); {
} lockStore = createLockStore();
}
/**
* <ul> /**
* <li>Start outer txn</li> * <ul>
* <li>Modify lock in outer txn</li> * <li>Start outer txn</li>
* <li>Start inner txn</li> * <li>Modify lock in outer txn</li>
* <li>Modify lock in inner txn</li> * <li>Start inner txn</li>
* </ul> * <li>Modify lock in inner txn</li>
* Inner transaction should fail while outer succeeds * </ul>
*/ * Inner transaction should fail while outer succeeds
@Test */
public void testRepeatableRead_01() throws Exception @Test
{ public void testRepeatableRead_01() throws Exception
{
}
}
@Test
public void testRepeatableReadsInTransaction() throws NotSupportedException, SystemException @Test
{ public void testRepeatableReadsInTransaction() throws NotSupportedException, SystemException
final TransactionService txService = (TransactionService) ctx.getBean("TransactionService"); {
UserTransaction txA = txService.getUserTransaction(); final TransactionService txService = (TransactionService) ctx.getBean("TransactionService");
UserTransaction txA = txService.getUserTransaction();
final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1");
final NodeRef nodeRef2 = new NodeRef("workspace://SpacesStore/UUID-2"); final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1");
Date now = new Date(); final NodeRef nodeRef2 = new NodeRef("workspace://SpacesStore/UUID-2");
Date expires = new Date(now.getTime() + 180000); Date now = new Date();
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK, Date expires = new Date(now.getTime() + 180000);
"jbloggs", expires, Lifetime.EPHEMERAL, null); final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"jbloggs", expires, Lifetime.EPHEMERAL, null);
Thread txB = new Thread("TxB") Thread txB = new Thread("TxB") {
{ @Override
@Override public void run()
public void run() {
{ Object main = AbstractLockStoreTxTest.this;
Object main = AbstractLockStoreTxTest.this; UserTransaction tx = txService.getUserTransaction();
UserTransaction tx = txService.getUserTransaction(); try
try {
{ tx.begin();
tx.begin(); try
try {
{ // txB read lock state
// txB read lock state LockState lockState = lockStore.get(nodeRef);
LockState lockState = lockStore.get(nodeRef); assertEquals("jbloggs", lockState.getOwner());
assertEquals("jbloggs", lockState.getOwner()); assertEquals(Lifetime.EPHEMERAL, lockState.getLifetime());
assertEquals(Lifetime.EPHEMERAL, lockState.getLifetime());
// Wait, while txA changes the lock state
// Wait, while txA changes the lock state passControl(this, main);
passControl(this, main);
// assert txB still sees state A
// assert txB still sees state A lockState = lockStore.get(nodeRef);
lockState = lockStore.get(nodeRef); assertEquals("jbloggs", lockState.getOwner());
assertEquals("jbloggs", lockState.getOwner());
// Wait, while txA checks whether it can see lock for nodeRef2 (though it doesn't exist yet)
// Wait, while txA checks whether it can see lock for nodeRef2 (though it doesn't exist yet) passControl(this, main);
passControl(this, main);
// txB sets a value, already seen as non-existent lock by txA
// txB sets a value, already seen as non-existent lock by txA lockStore.set(nodeRef2, LockState.createLock(nodeRef2, LockType.WRITE_LOCK,
lockStore.set(nodeRef2, LockState.createLock(nodeRef2, LockType.WRITE_LOCK, "csmith", null, Lifetime.EPHEMERAL, null));
"csmith", null, Lifetime.EPHEMERAL, null)); }
} finally
finally {
{ tx.rollback();
tx.rollback(); }
} }
} catch (Throwable e)
catch (Throwable e) {
{ throw new RuntimeException("Error in transaction B", e);
throw new RuntimeException("Error in transaction B", e); }
} finally
finally {
{ // Stop 'main' from waiting
// Stop 'main' from waiting synchronized (main)
synchronized(main) {
{ main.notifyAll();
main.notifyAll(); }
} }
} }
} };
};
txA.begin();
txA.begin(); try
try {
{ // txA set lock state 1
// txA set lock state 1 lockStore.set(nodeRef, lockState1);
lockStore.set(nodeRef, lockState1);
// Perform a read, that we know will retrieve a null value (and null will be cached for this transaction)
// Wait while txB reads and checks the LockState assertNull("nodeRef2 LockState", lockStore.get(nodeRef2));
txB.setDaemon(true);
txB.start(); // Wait while txB reads and checks the LockState
passControl(this, txB); txB.setDaemon(true);
txB.start();
// txA set different lock state passControl(this, txB);
AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner needed to change lock.
final LockState lockState2 = LockState.createWithOwner(lockState1, "another"); // txA set different lock state
lockStore.set(nodeRef, lockState2); AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner needed to change lock.
final LockState lockState2 = LockState.createWithOwner(lockState1, "another");
// Wait while txB reads/checks the LockState again for nodeRef lockStore.set(nodeRef, lockState2);
passControl(this, txB);
// Wait while txB reads/checks the LockState again for nodeRef
// Another update passControl(this, txB);
AuthenticationUtil.setFullyAuthenticatedUser("another"); // Current lock owner needed to change lock.
final LockState lockState3 = LockState.createWithOwner(lockState2, "bsmith"); // Another update
lockStore.set(nodeRef, lockState3); AuthenticationUtil.setFullyAuthenticatedUser("another"); // Current lock owner needed to change lock.
// Check we can see the update. final LockState lockState3 = LockState.createWithOwner(lockState2, "bsmith");
assertEquals("bsmith", lockStore.get(nodeRef).getOwner()); lockStore.set(nodeRef, lockState3);
// Check we can see the update.
// Perform a read, that we know will retrieve a null value assertEquals("bsmith", lockStore.get(nodeRef).getOwner());
assertNull("nodeRef2 LockState", lockStore.get(nodeRef2));
// Wait while txB populates the store with a value for nodeRef2
// Wait while txB populates the store with a value for nodeRef2 passControl(this, txB);
passControl(this, txB);
// Perform the read again - update should not be visible in this transaction (was already cached)
// Perform the read again - update should not be visible in this transaction assertNull("nodeRef2 LockState", lockStore.get(nodeRef2));
assertNull("nodeRef2 LockState", lockStore.get(nodeRef2)); }
} finally
finally {
{ txA.rollback();
txA.rollback(); }
} }
}
protected void passControl(Object from, Object to)
protected void passControl(Object from, Object to) {
{ synchronized (to)
synchronized(to) {
{ to.notifyAll();
to.notifyAll(); }
} synchronized (from)
synchronized(from) {
{ try
try {
{ // TODO: wait should be called in a loop with repeated wait condition check,
// TODO: wait should be called in a loop with repeated wait condition check, // but what's the condition we're waiting on?
// but what's the condition we're waiting on? from.wait(10000);
from.wait(10000); }
} catch (InterruptedException error)
catch (InterruptedException error) {
{ throw new RuntimeException(error);
throw new RuntimeException(error); }
} }
} }
}
@Test
@Test public void testCannotSetLockWhenChangedByAnotherTx() throws NotSupportedException, SystemException
public void testCannotSetLockWhenChangedByAnotherTx() throws NotSupportedException, SystemException {
{ final TransactionService txService = (TransactionService) ctx.getBean("TransactionService");
final TransactionService txService = (TransactionService) ctx.getBean("TransactionService"); UserTransaction txA = txService.getUserTransaction();
UserTransaction txA = txService.getUserTransaction(); final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1");
final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1"); Date now = new Date();
Date now = new Date(); Date expires = new Date(now.getTime() + 180000);
Date expires = new Date(now.getTime() + 180000); final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK, "jbloggs", expires, Lifetime.EPHEMERAL, null);
"jbloggs", expires, Lifetime.EPHEMERAL, null);
Thread txB = new Thread("TxB") {
@Override
Thread txB = new Thread("TxB") public void run()
{ {
@Override Object main = AbstractLockStoreTxTest.this;
public void run() UserTransaction tx = txService.getUserTransaction();
{ try
Object main = AbstractLockStoreTxTest.this; {
UserTransaction tx = txService.getUserTransaction(); tx.begin();
try try
{ {
tx.begin(); // txB read lock state
try LockState lockState = lockStore.get(nodeRef);
{ assertEquals("jbloggs", lockState.getOwner());
// txB read lock state assertEquals(Lifetime.EPHEMERAL, lockState.getLifetime());
LockState lockState = lockStore.get(nodeRef);
assertEquals("jbloggs", lockState.getOwner()); // Wait, while txA changes the lock state
assertEquals(Lifetime.EPHEMERAL, lockState.getLifetime()); passControl(this, main);
// Wait, while txA changes the lock state try
passControl(this, main); {
// Attempt to change the lock state for a NodeRef should fail
try // when it has been modified by another tx since this tx last inspected it.
{ AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner
// Attempt to change the lock state for a NodeRef should fail lockStore.set(nodeRef, LockState.createLock(nodeRef, LockType.WRITE_LOCK,
// when it has been modified by another tx since this tx last inspected it. "csmith", null, Lifetime.EPHEMERAL, null));
AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner fail("Exception should have been thrown but was not.");
lockStore.set(nodeRef, LockState.createLock(nodeRef, LockType.WRITE_LOCK, }
"csmith", null, Lifetime.EPHEMERAL, null)); catch (ConcurrencyFailureException e)
fail("Exception should have been thrown but was not."); {
} // Good!
catch (ConcurrencyFailureException e) }
{ }
// Good! finally
} {
} tx.rollback();
finally }
{ }
tx.rollback(); catch (Throwable e)
} {
} throw new RuntimeException("Error in transaction B", e);
catch (Throwable e) }
{ finally
throw new RuntimeException("Error in transaction B", e); {
} // Stop 'main' from waiting
finally synchronized (main)
{ {
// Stop 'main' from waiting main.notifyAll();
synchronized(main) }
{ }
main.notifyAll(); }
} };
}
} txA.begin();
}; try
{
txA.begin(); // txA set lock state 1
try lockStore.set(nodeRef, lockState1);
{
// txA set lock state 1 // Wait while txB reads and checks the LockState
lockStore.set(nodeRef, lockState1); txB.setDaemon(true);
txB.start();
// Wait while txB reads and checks the LockState passControl(this, txB);
txB.setDaemon(true);
txB.start(); // txA set different lock state
passControl(this, txB); AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner needed to change lock.
final LockState lockState2 = LockState.createWithOwner(lockState1, "another");
// txA set different lock state lockStore.set(nodeRef, lockState2);
AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner needed to change lock.
final LockState lockState2 = LockState.createWithOwner(lockState1, "another"); // Wait while txB attempts to modify the lock info
lockStore.set(nodeRef, lockState2); passControl(this, txB);
// Wait while txB attempts to modify the lock info // Lock shouldn't have changed since this tx updated it.
passControl(this, txB); assertEquals(lockState2, lockStore.get(nodeRef));
}
// Lock shouldn't have changed since this tx updated it. finally
assertEquals(lockState2, lockStore.get(nodeRef)); {
} txA.rollback();
finally }
{ }
txA.rollback();
} @Test
} public void testCanChangeLockIfLatestValueIsHeldEvenIfAlreadyChangedByAnotherTx() throws NotSupportedException, SystemException
{
@Test final TransactionService txService = (TransactionService) ctx.getBean("TransactionService");
public void testCanChangeLockIfLatestValueIsHeldEvenIfAlreadyChangedByAnotherTx() throws NotSupportedException, SystemException UserTransaction txA = txService.getUserTransaction();
{ final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1");
final TransactionService txService = (TransactionService) ctx.getBean("TransactionService"); final Date now = new Date();
UserTransaction txA = txService.getUserTransaction(); Date expired = new Date(now.getTime() - 180000);
final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1"); final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
final Date now = new Date(); "jbloggs", expired, Lifetime.EPHEMERAL, null);
Date expired = new Date(now.getTime() - 180000);
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK, final LockState lockState2 = LockState.createWithOwner(lockState1, "another");
"jbloggs", expired, Lifetime.EPHEMERAL, null);
Thread txB = new Thread("TxB") {
final LockState lockState2 = LockState.createWithOwner(lockState1, "another"); @Override
public void run()
Thread txB = new Thread("TxB") {
{ Object main = AbstractLockStoreTxTest.this;
@Override UserTransaction tx = txService.getUserTransaction();
public void run() try
{ {
Object main = AbstractLockStoreTxTest.this; tx.begin();
UserTransaction tx = txService.getUserTransaction(); try
try {
{ AuthenticationUtil.setFullyAuthenticatedUser("new-user");
tx.begin();
try // txB read lock state
{ LockState readLockState = lockStore.get(nodeRef);
AuthenticationUtil.setFullyAuthenticatedUser("new-user"); assertEquals(lockState2, readLockState);
// txB read lock state // Set new value, even though txA has already set new values
LockState readLockState = lockStore.get(nodeRef); // (but not since this tx's initial read)
assertEquals(lockState2, readLockState); Date expiresFuture = new Date(now.getTime() + 180000);
final LockState newUserLockState = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
// Set new value, even though txA has already set new values "new-user", expiresFuture, Lifetime.EPHEMERAL, null);
// (but not since this tx's initial read) lockStore.set(nodeRef, newUserLockState);
Date expiresFuture = new Date(now.getTime() + 180000);
final LockState newUserLockState = LockState.createLock(nodeRef, LockType.WRITE_LOCK, // Read
"new-user", expiresFuture, Lifetime.EPHEMERAL, null); assertEquals(newUserLockState, lockStore.get(nodeRef));
lockStore.set(nodeRef, newUserLockState); }
finally
// Read {
assertEquals(newUserLockState, lockStore.get(nodeRef)); tx.rollback();
} }
finally }
{ catch (Throwable e)
tx.rollback(); {
} throw new RuntimeException("Error in transaction B", e);
} }
catch (Throwable e) finally
{ {
throw new RuntimeException("Error in transaction B", e); // Stop 'main' from waiting
} synchronized (main)
finally {
{ main.notifyAll();
// Stop 'main' from waiting }
synchronized(main) }
{ }
main.notifyAll(); };
}
} txA.begin();
} try
}; {
AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner needed to change lock.
txA.begin();
try // txA set lock state 1
{ lockStore.set(nodeRef, lockState1);
AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner needed to change lock. assertEquals(lockState1, lockStore.get(nodeRef));
// txA set lock state 1 // txA set different lock state
lockStore.set(nodeRef, lockState1); lockStore.set(nodeRef, lockState2);
assertEquals(lockState1, lockStore.get(nodeRef)); assertEquals(lockState2, lockStore.get(nodeRef));
// txA set different lock state // Wait while txB modifies the lock info
lockStore.set(nodeRef, lockState2); txB.setDaemon(true);
assertEquals(lockState2, lockStore.get(nodeRef)); txB.start();
passControl(this, txB);
// Wait while txB modifies the lock info
txB.setDaemon(true); // This tx should still see the same state, though it has been changed by txB.
txB.start(); assertEquals(lockState2, lockStore.get(nodeRef));
passControl(this, txB); }
finally
// This tx should still see the same state, though it has been changed by txB. {
assertEquals(lockState2, lockStore.get(nodeRef)); txA.rollback();
} }
finally }
{
txA.rollback(); @Test
} public void testNotOnlyCurrentLockOwnerCanChangeInfo() throws NotSupportedException, SystemException
} {
final TransactionService txService = (TransactionService) ctx.getBean("TransactionService");
UserTransaction txA = txService.getUserTransaction();
@Test final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1");
public void testNotOnlyCurrentLockOwnerCanChangeInfo() throws NotSupportedException, SystemException Date now = new Date();
{ Date expires = new Date(now.getTime() + 180000);
final TransactionService txService = (TransactionService) ctx.getBean("TransactionService"); final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
UserTransaction txA = txService.getUserTransaction(); "jbloggs", expires, Lifetime.EPHEMERAL, null);
final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1");
Date now = new Date(); txA.begin();
Date expires = new Date(now.getTime() + 180000); try
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK, {
"jbloggs", expires, Lifetime.EPHEMERAL, null); AuthenticationUtil.setFullyAuthenticatedUser("jbloggs");
txA.begin(); // Set initial lock state
try lockStore.set(nodeRef, lockState1);
{
AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Set different lock state
// Current lock owner is still authenticated (jbloggs)
// Set initial lock state final LockState lockState2 = LockState.createWithOwner(lockState1, "csmith");
lockStore.set(nodeRef, lockState1); lockStore.set(nodeRef, lockState2);
// Set different lock state // Check update
// Current lock owner is still authenticated (jbloggs) assertEquals(lockState2, lockStore.get(nodeRef));
final LockState lockState2 = LockState.createWithOwner(lockState1, "csmith");
lockStore.set(nodeRef, lockState2); // Incorrect lock owner - this shouldn't fail. See ACE-2181
final LockState lockState3 = LockState.createWithOwner(lockState1, "dsmithers");
// Check update
assertEquals(lockState2, lockStore.get(nodeRef)); lockStore.set(nodeRef, lockState3);
// Incorrect lock owner - this shouldn't fail. See ACE-2181 // Check update.
final LockState lockState3 = LockState.createWithOwner(lockState1, "dsmithers"); assertEquals(lockState3, lockStore.get(nodeRef));
}
lockStore.set(nodeRef, lockState3); finally
{
// Check update. txA.rollback();
assertEquals(lockState3, lockStore.get(nodeRef)); }
} }
finally
{ @Test
txA.rollback(); public void testOtherUserCanChangeLockInfoOnceExpired() throws NotSupportedException, SystemException
} {
} final TransactionService txService = (TransactionService) ctx.getBean("TransactionService");
UserTransaction txA = txService.getUserTransaction();
@Test final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1");
public void testOtherUserCanChangeLockInfoOnceExpired() throws NotSupportedException, SystemException Date now = new Date();
{ Date expired = new Date(now.getTime() - 900);
final TransactionService txService = (TransactionService) ctx.getBean("TransactionService"); final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
UserTransaction txA = txService.getUserTransaction(); "jbloggs", expired, Lifetime.EPHEMERAL, null);
final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/UUID-1");
Date now = new Date(); txA.begin();
Date expired = new Date(now.getTime() - 900); try
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK, {
"jbloggs", expired, Lifetime.EPHEMERAL, null); AuthenticationUtil.setFullyAuthenticatedUser("jbloggs");
txA.begin(); // Set initial lock state
try lockStore.set(nodeRef, lockState1);
{
AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Set different lock state
AuthenticationUtil.setFullyAuthenticatedUser("csmith");
// Set initial lock state Date expiresFuture = new Date(now.getTime() + 180000);
lockStore.set(nodeRef, lockState1); final LockState lockState2 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"csmith", expiresFuture, Lifetime.EPHEMERAL, null);
// Set different lock state lockStore.set(nodeRef, lockState2);
AuthenticationUtil.setFullyAuthenticatedUser("csmith");
Date expiresFuture = new Date(now.getTime() + 180000); // Updated, since lock had expired.
final LockState lockState2 = LockState.createLock(nodeRef, LockType.WRITE_LOCK, assertEquals(lockState2, lockStore.get(nodeRef));
"csmith", expiresFuture, Lifetime.EPHEMERAL, null);
lockStore.set(nodeRef, lockState2); // Incorrect lock owner - this shouldn't fail
// LockStore does not check for lock owning
// Updated, since lock had expired. // and is owned by csmith.
assertEquals(lockState2, lockStore.get(nodeRef)); AuthenticationUtil.setFullyAuthenticatedUser("dsmithers");
final LockState lockState3 = LockState.createWithOwner(lockState2, "dsmithers");
// Incorrect lock owner - this shouldn't fail
// LockStore does not check for lock owning lockStore.set(nodeRef, lockState3);
// and is owned by csmith.
AuthenticationUtil.setFullyAuthenticatedUser("dsmithers"); // Check update.
final LockState lockState3 = LockState.createWithOwner(lockState2, "dsmithers"); assertEquals(lockState3, lockStore.get(nodeRef));
}
lockStore.set(nodeRef, lockState3); finally
{
// Check update. txA.rollback();
assertEquals(lockState3, lockStore.get(nodeRef)); }
} }
finally }
{
txA.rollback();
}
}
}