How to retrieve a task candidate groups

Hi,
I’m developing a web app embedding the Flowable engine using external forms and external identity/group management.

Upon submission of my custom form for a task, I would like to perform an authorization check over the user roles (retrieved externally), which should match any of the candidate groups specified for the task.

Anyway, I couldn’t find a way, having a task Id, to retrieve such information about the task definition inside the process.

Any idea?

Thanks, ciao.
Roberto

Hi Roberto,

There is an example how to check candidate groups:
org.flowable.examples.bpmn.usertask.taskcandidate.TaskCandidateTest
in flowable source.

Or you can use listener to test post complete conditions:
org.flowable.examples.bpmn.tasklistener.TaskListenerTest

Regards
Martin

Hi Martin,
looking at the test case you mention, I tried this kind of implementation:

	public boolean canUserSubmitTask(String taskId, List<String> userGroups)
        throws ProcessException {
	
        return processEngine.getTaskService().createTaskQuery()
            .taskId(taskId)
            .taskCandidateGroupIn(userGroups)
            .list()
            .size() == 1;
    }

Anyway, it looks like, once a task has been claimed by some user, the candidate groups list is cleared, so the query above returns no items.

I was expecting this and this is why I was asking about accessing a kind of “task definition” as opposed to the “task instance” object: I guess the list of candidate groups is kept in something like a task definition, regardless of who claimed any particular task instance.

To clarify the scenario, since I’m developing custom forms to submit any task, the taskId is sent as a form parameter.
I wish to avoid a user hacking the POST request and submitting a form changing the taskId with a different one.
When processing the form parameters on the server, I’d like to perform an authorizaiton check on the user’s roles matching the task candidate groups.
Another option could be to just check that the user name matches the task claimer, but this would prevent cases when the task must be completed by a different user in case of emergency (without first claiming the task).

Does this make sense and do you have any other idea?

BTW, I really like Flowable!

Thanks again, ciao.
Roberto

Hi Roberto,

I did a small test:

    task = taskService.newTask();
    task.setName("test");
    taskService.saveTask(task);
    taskService.addCandidateGroup(task.getId(), "sales");
    taskService.addCandidateUser(task.getId(), "kermit");

    assertNotNull(taskService.createTaskQuery().taskCandidateGroup("sales").singleResult());
    assertNotNull(taskService.createTaskQuery().taskCandidateUser("kermit").singleResult());

    taskService.claim(task.getId(), "kermit");

    assertNull(taskService.createTaskQuery().taskCandidateGroup("sales").singleResult());

    taskService.unclaim(task.getId());

    assertNotNull(taskService.createTaskQuery().taskCandidateGroup("sales").singleResult());

When a task is claimed, it indicates that user works on the task and another user cannot complete it. When the task unclaimed it appears in the candidate groups query again.

If you want to have another query behaviour the easiest way is to implement custom or native query
http://www.flowable.org/docs/userguide/index.html#advanced.custom.sql.queries
http://www.flowable.org/docs/userguide/index.html#queryAPI

Regards
Martin

Hi Martin,
OK, then I’ll drop the scenario where a user can submit another user’s claimed task: she’ll first need to claim the task for herself.

It comes out the following code works well to perform an uthorization check under such conditions:

@Override
public boolean canUserSubmitTask(String taskId, String userName, List<String> userGroups)
    throws ProcessException {
	
    Task t = processEngine.getTaskService().createTaskQuery()
        .taskId(taskId)
        .singleResult();
	
    return (t.getAssignee() != null && t.getAssignee().equals(userName)) ||
        processEngine.getTaskService().createTaskQuery()
            .taskId(taskId)
            .taskCandidateGroupIn(userGroups)
            .list()
            .size() == 1;
}

Thanks for your help.

Ciao,
Roberto