/*
* (C) Copyright 2010 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Anahide Tchertchian
*/
package org.nuxeo.ecm.platform.task.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.NuxeoException;
import org.nuxeo.ecm.core.api.NuxeoGroup;
import org.nuxeo.ecm.core.api.NuxeoPrincipal;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.core.test.CoreFeature;
import org.nuxeo.ecm.platform.task.Task;
import org.nuxeo.ecm.platform.task.TaskComment;
import org.nuxeo.ecm.platform.task.TaskService;
import org.nuxeo.ecm.platform.usermanager.UserManager;
import org.nuxeo.runtime.test.runner.Deploy;
import org.nuxeo.runtime.test.runner.Features;
import org.nuxeo.runtime.test.runner.FeaturesRunner;
import org.nuxeo.runtime.test.runner.LocalDeploy;
/**
* @author Anahide Tchertchian
* @author Antoine Taillefer
*/
@RunWith(FeaturesRunner.class)
@Features(CoreFeature.class)
@Deploy({ "org.nuxeo.ecm.platform.content.template", //
"org.nuxeo.ecm.directory", //
"org.nuxeo.ecm.platform.usermanager", //
"org.nuxeo.ecm.directory.types.contrib", //
"org.nuxeo.ecm.directory.sql", //
"org.nuxeo.ecm.platform.query.api", //
"org.nuxeo.ecm.platform.task.core", //
})
@LocalDeploy({ "org.nuxeo.ecm.platform.task.testing:OSGI-INF/test-sql-directories-contrib.xml", //
"org.nuxeo.ecm.platform.test:test-usermanagerimpl/directory-config.xml" })
public class TaskServiceTest {
@Inject
protected CoreFeature coreFeature;
@Inject
protected CoreSession session;
@Inject
protected TaskService taskService;
@Inject
protected UserManager userManager;
protected NuxeoPrincipal administrator;
protected NuxeoPrincipal user1;
protected NuxeoPrincipal user2;
protected NuxeoPrincipal user3;
protected NuxeoPrincipal user4;
@Before
public void setUp() {
administrator = userManager.getPrincipal(SecurityConstants.ADMINISTRATOR);
assertNotNull(administrator);
user1 = userManager.getPrincipal("myuser1");
assertNotNull(user1);
user2 = userManager.getPrincipal("myuser2");
assertNotNull(user2);
user3 = userManager.getPrincipal("myuser3");
assertNotNull(user3);
user4 = userManager.getPrincipal("myuser4");
assertNotNull(user4);
}
@Test
public void testSingleTaskWithAccept() throws Exception {
DocumentModel document = getDocument();
assertNotNull(document);
// create task as admin
List<String> actors = new ArrayList<String>();
actors.add(user1.getName());
actors.add(SecurityConstants.MEMBERS);
Calendar calendar = Calendar.getInstance();
calendar.set(2006, 6, 6);
calendar.set(Calendar.MILLISECOND, 0); // be sure to avoid Timestamp
// truncation issues.
// create one task for all actors
taskService.createTask(session, user3, document, "Test Task Name", "test type", "test process id", actors,
false, "test directive", "test comment", calendar.getTime(), null, null);
session.save();
List<Task> tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
Task task = tasks.get(0);
assertEquals("Test Task Name", task.getName());
assertEquals("test type", task.getType());
assertEquals("test process id", task.getProcessId());
List<String> pooledActorIds = task.getActors();
assertEquals(2, pooledActorIds.size());
assertTrue(pooledActorIds.contains(SecurityConstants.MEMBERS));
assertTrue(pooledActorIds.contains(user1.getName()));
List<TaskComment> comments = task.getComments();
assertEquals(1, comments.size());
TaskComment comment = comments.get(0);
assertEquals(user3.getName(), comment.getAuthor());
assertEquals("test comment", comment.getText());
assertEquals(calendar.getTime(), task.getDueDate());
// task status
assertTrue(task.isOpened());
assertFalse(task.isCancelled());
assertFalse(task.hasEnded());
assertEquals(4, task.getVariables().size());
assertEquals(document.getRepositoryName(),
task.getVariable(TaskService.VariableName.documentRepositoryName.name()));
assertEquals(document.getId(), task.getVariable(TaskService.VariableName.documentId.name()));
assertEquals("test directive", task.getVariable(TaskService.VariableName.directive.name()));
assertEquals("true", task.getVariable(TaskService.VariableName.createdFromTaskService.name()));
assertEquals(user3.getName(), task.getInitiator());
// test rights for each user
// initiator or admin can end a task
assertTrue(taskService.canEndTask(administrator, task));
assertTrue(taskService.canEndTask(user3, task));
// user 1 is in actors
assertTrue(taskService.canEndTask(user1, task));
// user 2 is in the members group
assertTrue(taskService.canEndTask(user2, task));
// user 4 is not in the members group
assertFalse(taskService.canEndTask(user4, task));
// test ending of the task
try {
taskService.acceptTask(session, user4, task, "ok i'm in");
fail("Should have raised an exception: user4 cannot end the task");
} catch (NuxeoException e) {
assertEquals("User with id 'myuser4' cannot end this task", e.getMessage());
}
// accept task
taskService.acceptTask(session, user1, task, "ok i'm in");
session.save();
// test task again
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
// ended tasks are filtered
assertEquals(0, tasks.size());
// retrieve the task another way
String taskId = task.getId();
task = getTask(taskId);
assertNotNull(task);
assertEquals("Test Task Name", task.getName());
pooledActorIds = task.getActors();
assertEquals(2, pooledActorIds.size());
assertTrue(pooledActorIds.contains(SecurityConstants.MEMBERS));
assertTrue(pooledActorIds.contains(user1.getName()));
comments = task.getComments();
assertEquals(2, comments.size());
comment = comments.get(0);
assertEquals(user3.getName(), comment.getAuthor());
assertEquals("test comment", comment.getText());
assertEquals(calendar.getTime(), task.getDueDate());
// task status
assertFalse(task.isOpened());
assertFalse(task.isCancelled());
assertTrue(task.hasEnded());
assertEquals(5, task.getVariables().size());
assertEquals(document.getRepositoryName(),
task.getVariable(TaskService.VariableName.documentRepositoryName.name()));
assertEquals(document.getId(), task.getVariable(TaskService.VariableName.documentId.name()));
assertEquals("test directive", task.getVariable(TaskService.VariableName.directive.name()));
assertEquals("true", task.getVariable(TaskService.VariableName.createdFromTaskService.name()));
assertEquals("true", task.getVariable(TaskService.VariableName.validated.name()));
}
@Test
public void testMultipleTaskWithReject() throws Exception {
DocumentModel document = getDocument();
assertNotNull(document);
// create task as admin
List<String> actors = new ArrayList<String>();
actors.add(user1.getName());
actors.add(SecurityConstants.MEMBERS);
Calendar calendar = Calendar.getInstance();
calendar.set(2006, 6, 6);
calendar.set(Calendar.MILLISECOND, 0); // be sure to avoid Timestamp
// truncation issues.
// create one task per actor
taskService.createTask(session, user3, document, "Test Task Name", actors, true, "test directive",
"test comment", calendar.getTime(), null, null);
session.save();
List<Task> tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
assertEquals(2, tasks.size());
// order is database-dependent
if (tasks.get(0).getActors().get(0).equals(SecurityConstants.MEMBERS)) {
Collections.reverse(tasks);
}
Task task1 = tasks.get(0);
assertEquals("Test Task Name", task1.getName());
List<String> pooledActorIds = task1.getActors();
assertEquals(1, pooledActorIds.size());
assertEquals(user1.getName(), pooledActorIds.get(0));
List<TaskComment> comments = task1.getComments();
assertEquals(1, comments.size());
TaskComment comment = comments.get(0);
assertEquals(user3.getName(), comment.getAuthor());
assertEquals("test comment", comment.getText());
assertEquals(calendar.getTime(), task1.getDueDate());
// task status
assertTrue(task1.isOpened());
assertFalse(task1.isCancelled());
assertFalse(task1.hasEnded());
assertEquals(4, task1.getVariables().size());
assertEquals(document.getRepositoryName(),
task1.getVariable(TaskService.VariableName.documentRepositoryName.name()));
assertEquals(document.getId(), task1.getVariable(TaskService.VariableName.documentId.name()));
assertEquals("test directive", task1.getVariable(TaskService.VariableName.directive.name()));
assertEquals("true", task1.getVariable(TaskService.VariableName.createdFromTaskService.name()));
assertEquals(user3.getName(), task1.getInitiator());
// test rights for each user
// initiator or admin can end a task
assertTrue(taskService.canEndTask(administrator, task1));
assertTrue(taskService.canEndTask(user3, task1));
// user 1 is in actors
assertTrue(taskService.canEndTask(user1, task1));
assertFalse(taskService.canEndTask(user2, task1));
assertFalse(taskService.canEndTask(user4, task1));
// test ending of the task
try {
taskService.rejectTask(session, user2, task1, "i don't agree");
fail("Should have raised an exception: user2 cannot end the task");
} catch (NuxeoException e) {
assertEquals("User with id 'myuser2' cannot end this task", e.getMessage());
}
// reject task as user1
taskService.rejectTask(session, user1, task1, "i don't agree");
session.save();
// test task again
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
// ended tasks are filtered
assertEquals(1, tasks.size());
// retrieve the task another way
final String taskId = task1.getId();
task1 = getTask(taskId);
assertNotNull(task1);
assertEquals("Test Task Name", task1.getName());
pooledActorIds = task1.getActors();
assertEquals(1, pooledActorIds.size());
assertEquals(user1.getName(), pooledActorIds.get(0));
comments = task1.getComments();
assertEquals(2, comments.size());
comment = comments.get(0);
assertEquals(user3.getName(), comment.getAuthor());
assertEquals("test comment", comment.getText());
assertEquals(calendar.getTime(), task1.getDueDate());
// task status
assertFalse(task1.isOpened());
assertFalse(task1.isCancelled());
assertTrue(task1.hasEnded());
assertEquals(5, task1.getVariables().size());
assertEquals(document.getRepositoryName(),
task1.getVariable(TaskService.VariableName.documentRepositoryName.name()));
assertEquals(document.getId(), task1.getVariable(TaskService.VariableName.documentId.name()));
assertEquals("test directive", task1.getVariable(TaskService.VariableName.directive.name()));
assertEquals("true", task1.getVariable(TaskService.VariableName.createdFromTaskService.name()));
assertEquals("false", task1.getVariable(TaskService.VariableName.validated.name()));
assertEquals(user3.getName(), task1.getInitiator());
// check second task
Task task2 = tasks.get(0);
assertEquals("Test Task Name", task2.getName());
pooledActorIds = task2.getActors();
assertEquals(1, pooledActorIds.size());
assertEquals(SecurityConstants.MEMBERS, pooledActorIds.get(0));
comments = task2.getComments();
assertEquals(1, comments.size());
comment = comments.get(0);
assertEquals(user3.getName(), comment.getAuthor());
assertEquals("test comment", comment.getText());
assertEquals(calendar.getTime(), task2.getDueDate());
// task status
assertTrue(task2.isOpened());
assertFalse(task2.isCancelled());
assertFalse(task2.hasEnded());
assertEquals(4, task2.getVariables().size());
assertEquals(document.getRepositoryName(),
task2.getVariable(TaskService.VariableName.documentRepositoryName.name()));
assertEquals(document.getId(), task2.getVariable(TaskService.VariableName.documentId.name()));
assertEquals("test directive", task2.getVariable(TaskService.VariableName.directive.name()));
assertEquals("true", task2.getVariable(TaskService.VariableName.createdFromTaskService.name()));
assertEquals(user3.getName(), task2.getInitiator());
// test rights for each user
// initiator or admin can end a task
assertTrue(taskService.canEndTask(administrator, task2));
assertTrue(taskService.canEndTask(user3, task2));
// user 1 is in actors
assertTrue(taskService.canEndTask(user1, task2));
// user 2 is in the members group
assertTrue(taskService.canEndTask(user2, task2));
// user 4 is not in the members group
assertFalse(taskService.canEndTask(user4, task2));
// test ending of the task
try {
taskService.acceptTask(session, user4, task2, "i don't agree");
fail("Should have raised an exception: user4 cannot end the task");
} catch (NuxeoException e) {
assertEquals("User with id 'myuser4' cannot end this task", e.getMessage());
}
// accept task as user1
taskService.acceptTask(session, user1, task2, "i don't agree");
session.save();
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
assertEquals(0, tasks.size());
}
/**
* Test user tasks.
*
* @throws Exception the exception
*/
@Test
public void testUserTasks() throws Exception {
DocumentModel document = getDocument();
assertNotNull(document);
// ----------------------------------------------------------------------
// Create a task assigned to user1 and check that user1 has 1 task
// assigned
// ----------------------------------------------------------------------
// set task actors
List<String> actors = new ArrayList<String>();
actors.add(user1.getName());
// create task
taskService.createTask(session, administrator, document, "Task assigned to user1", actors, false, null, null,
null, null, null);
session.save();
// get user1 tasks
List<Task> tasks = taskService.getTaskInstances(document, user1, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
Task task = tasks.get(0);
assertEquals("Task assigned to user1", task.getName());
List<String> pooledActorIds = task.getActors();
assertEquals(1, pooledActorIds.size());
assertTrue(pooledActorIds.contains(user1.getName()));
// ----------------------------------------------------------------------
// Create a task assigned to user2 and check that:
// - user2 has 1 task assigned
// - the total number of tasks is 2
// ----------------------------------------------------------------------
// set task actors
actors.clear();
actors.add(user2.getName());
// create task
taskService.createTask(session, administrator, document, "Task assigned to user2", actors, false, null, null,
null, null, null);
session.save();
// get user2 tasks
tasks = taskService.getTaskInstances(document, user2, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
task = tasks.get(0);
assertEquals("Task assigned to user2", task.getName());
pooledActorIds = task.getActors();
assertEquals(1, pooledActorIds.size());
assertTrue(pooledActorIds.contains(user2.getName()));
// get all tasks
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
assertEquals(2, tasks.size());
// ----------------------------------------------------------------------
// Create a task assigned to user3 and user4 (using
// createOneTaskPerActor) and check that:
// - user3 has 1 task assigned
// - user4 has 1 task assigned
// - the total number of tasks is 4
// ----------------------------------------------------------------------
// set task actors
actors.clear();
actors.add(user3.getName());
actors.add(user4.getName());
// create task
taskService.createTask(session, administrator, document, "Task assigned to user3 and user4", actors, true,
null, null, null, null, null);
session.save();
// get user3 tasks
tasks = taskService.getTaskInstances(document, user3, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
task = tasks.get(0);
assertEquals("Task assigned to user3 and user4", task.getName());
pooledActorIds = task.getActors();
assertEquals(1, pooledActorIds.size());
assertTrue(pooledActorIds.contains(user3.getName()));
// get user4 tasks
tasks = taskService.getTaskInstances(document, user4, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
task = tasks.get(0);
assertEquals("Task assigned to user3 and user4", task.getName());
pooledActorIds = task.getActors();
assertEquals(1, pooledActorIds.size());
assertTrue(pooledActorIds.contains(user4.getName()));
// get all tasks
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
assertEquals(4, tasks.size());
// ----------------------------------------------------------------------
// Create a task assigned to members and check that all users that are
// in the members group have this task assigned (user1, user2, user3).
// Since at this point each user has 1 task assigned,
// these users should then have 2.
// The total number of tasks should be 5.
// ----------------------------------------------------------------------
// set task actors
actors.clear();
actors.add(SecurityConstants.MEMBERS);
// create task
taskService.createTask(session, administrator, document, "Task assigned to members", actors, false, null, null,
null, null, null);
session.save();
// get user1 tasks
tasks = taskService.getTaskInstances(document, user1, session);
assertNotNull(tasks);
assertEquals(2, tasks.size());
// get user2 tasks
tasks = taskService.getTaskInstances(document, user2, session);
assertNotNull(tasks);
assertEquals(2, tasks.size());
// get user3 tasks
tasks = taskService.getTaskInstances(document, user3, session);
assertNotNull(tasks);
assertEquals(2, tasks.size());
// get user4 tasks
tasks = taskService.getTaskInstances(document, user4, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
// get all tasks
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
assertEquals(5, tasks.size());
}
/**
* Check prefixed and unprefixed names in actors list.
* <p>
* It should have no impact since the DocumentTaskProvider rebuilds a clean actors list with both prefixed and
* unprefixed names of the principal and all its groups.
*
* @throws Exception the exception
*/
@Test
public void testPrefixedUnprefixedActorNames() throws Exception {
DocumentModel document = getDocument();
assertNotNull(document);
// set task actors mixing user and groups, prefixed and unprefixed
// names
List<String> actors = new ArrayList<String>();
actors.add(user1.getName());
actors.add(NuxeoPrincipal.PREFIX + user2.getName());
actors.add(SecurityConstants.ADMINISTRATORS);
actors.add(NuxeoGroup.PREFIX + SecurityConstants.MEMBERS);
// create task
taskService.createTask(session, administrator, document,
"Task assigned to prefixed ans unprefixed users and groups", actors, true, null, null, null, null, null);
session.save();
// get user1 tasks: should have 2 since in members group
List<Task> tasks = taskService.getTaskInstances(document, user1, session);
assertNotNull(tasks);
assertEquals(2, tasks.size());
// get user2 tasks: should have 2 since in members group
tasks = taskService.getTaskInstances(document, user2, session);
assertNotNull(tasks);
assertEquals(2, tasks.size());
// get user3 tasks: should have 1 since in members group
tasks = taskService.getTaskInstances(document, user3, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
// get user4 tasks: should have 0 since not in members group
tasks = taskService.getTaskInstances(document, user4, session);
assertNotNull(tasks);
assertEquals(0, tasks.size());
// get administrator tasks: should have 1 since in administrators group
tasks = taskService.getTaskInstances(document, administrator, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
// get all tasks: should have 4 (1 per actor)
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
assertEquals(4, tasks.size());
}
/**
* Test user tasks retrieval by non-admin session.
*/
@Test
public void testUserTasksAsUser() throws Exception {
DocumentModel document = getDocument();
assertNotNull(document);
taskService.createTask(session, administrator, document, "Task assigned to user1",
Arrays.asList(user1.getName()), false, null, null, null, null, null);
session.save();
// check as admin
List<Task> tasks = taskService.getTaskInstances(document, user1, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
Task task = tasks.get(0);
assertEquals("Task assigned to user1", task.getName());
List<String> pooledActorIds = task.getActors();
assertEquals(1, pooledActorIds.size());
assertTrue(pooledActorIds.contains(user1.getName()));
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session);
assertNotNull(tasks);
assertEquals(1, tasks.size());
// check as user1
try (CoreSession session1 = coreFeature.openCoreSession(user1.getName())) {
tasks = taskService.getTaskInstances(document, user1, session1);
assertNotNull(tasks);
assertEquals(1, tasks.size());
task = tasks.get(0);
assertEquals("Task assigned to user1", task.getName());
pooledActorIds = task.getActors();
assertEquals(1, pooledActorIds.size());
assertTrue(pooledActorIds.contains(user1.getName()));
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session1);
assertNotNull(tasks);
assertEquals(1, tasks.size());
}
// check that user2 sees them if requesting the given user / all
try (CoreSession session2 = coreFeature.openCoreSession(user2.getName())) {
tasks = taskService.getTaskInstances(document, user1, session2);
assertNotNull(tasks);
assertEquals(1, tasks.size());
task = tasks.get(0);
assertEquals("Task assigned to user1", task.getName());
pooledActorIds = task.getActors();
assertEquals(1, pooledActorIds.size());
assertTrue(pooledActorIds.contains(user1.getName()));
tasks = taskService.getTaskInstances(document, (NuxeoPrincipal) null, session2);
assertNotNull(tasks);
assertEquals(1, tasks.size());
}
}
protected Task getTask(final String taskId) {
DocumentModel taskDoc = session.getDocument(new IdRef(taskId));
if (taskDoc != null) {
return taskDoc.getAdapter(Task.class);
}
return null;
}
protected DocumentModel getDocument() throws Exception {
DocumentModel model = session.createDocumentModel(session.getRootDocument().getPathAsString(), "1", "File");
DocumentModel doc = session.createDocument(model);
assertNotNull(doc);
session.saveDocument(doc);
session.save();
return doc;
}
}