Is there any way to restrict, which user can start a process?
Because I was playing with the UI modeler and created an app, with 2 groups, but anyone that can log in in to the workflow task, can start any process I have delpoyed.
We don’t support it yet from the task app, but this could be implemented if there’s request from the community. Please raise a Github issue so it can be tracked.
Well today I was seeing some code and the interaction between the flowable 6 modeler app and flowable 6 modeler rest app.
I know now how its working the integration, but I need a little help.
Im going to implement a field for a property called “potential starter”,
so the first step is to add a property value to the shape in Oryx editor,
any clue in how to achieve this? , because the code of Orix editor is really huge.
I want to add the porperty to the start shape, after that I will work with the backend for generate the xml directives that you posted at the link and save the data.
It starts with changing the stencilset_bpmn,json file in the flowable-ui-modeler-logic module (src/main/resource). You can add the “potential starter” property in that JSON definition and add the property to Diagram element (because it’s a property of the process element not the start event in BPMN XML). Nothing needs to be changed in Oryx for this.
Then you would to change the flowable-json-converter module to read the new JSON property and translate it into the candidateStarterUsers and candidateStarterGroups on the Process element in the flowable-bpmn-model module. The translation to BPMN XML is already implemented for these properties.
I already make the changes in the stencilset_bpmn,json the result is the next:
{
“name” : “process_potentialstarter”,
“properties” : [ {
“id” : “process_potentialstarter”,
“type” : “String”,
“title” : “Process potential starter”,
“value” : “”,
“description” : “Which user or group, can start the process?”,
“popular” : true
} ]
}
after that I have added a new constant in the StencilConstants.Java
final String PROPERTY_PROCESS_POTENTIALSTARTER = “process_potentialstarter”;
In the clas BPMJson Converter.java I have added the next lines:
Ok, the pronlem was that I was using diferent names that the package standard names on the properties and I didnt add the package names to Diagram object in json.
Now im able to see the field and save the data
Thats the result, now im working on make test tothe restriction that I setup in the BpmJsonConverter.Java at his method called convertToBpmnModel() where I set the values that the user provides on the UI , Here is my code if works for anyone
After that in the same class when create a process instance I set the values.
Process process = new Process();
process.setId(pool.getProcessRef());
process.setName(pool.getName());
process.setExecutable(pool.isExecutable());
///codigo sibok666
process.setCandidateStarterGroups(gruposIniciadores);
process.setCandidateStarterUsers(usuariosIniciadores);
///codigo sibok666
Im going to test and I will tell you how the thing is going.
Ater doing some test, I was cappable of restrict the user wich start the process, I think the problem in the line:
definitionQuery.startableByUser(userId).list();
Was that need access to LDAP Configuration wich im not using.
So I solved the problem in the next way, I think is not an elegant solution but solves my problem and I hope to help somebody else, here is the code:
public ResultListDataRepresentation getProcessDefinitions(Boolean latest, String deploymentKey) {
ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
if (deploymentKey != null) {
Deployment deployment = repositoryService.createDeploymentQuery().deploymentKey(deploymentKey).latest().singleResult();
if (deployment != null) {
definitionQuery.deploymentId(deployment.getId());
} else {
return new ResultListDataRepresentation(new ArrayList<ProcessDefinitionRepresentation>());
}
} else {
if (latest != null && latest) {
definitionQuery.latestVersion();
}
}
///sibok666 code
///getting logged user
User currentUser = SecurityUtils.getCurrentUserObject();
String userId=currentUser.getId();
///getting all the processes of the app
List<ProcessDefinition> definitions = definitionQuery.list();
List<ProcessDefinition> definitionsFiltered=new ArrayList();
///getting the groups by user
List<RemoteGroup> listaGruposXUsuario=remoteIdmService.getUser(userId).getGroups();
for(ProcessDefinition pd:definitions){
BpmnModel bpmnModel=repositoryService.getBpmnModel(pd.getId());
List<Process> listaProcesos=bpmnModel.getProcesses();
for(Process p:listaProcesos){
///get the new properties of restriction added in the modeler app by process
List<String> listaGrupos=p.getCandidateStarterGroups();
List<String> listaUsuarios=p.getCandidateStarterUsers();
///checking if user is contained as potential user
if(listaUsuarios.contains(userId)){
definitionsFiltered.add(pd);
}
///comparing the groups of the user and the groups defined in the modeler app
//if the gruops are the same and dont exist in the current list of process so we addit to the response
for(String g:listaGrupos){
for(RemoteGroup rg: listaGruposXUsuario){
if(rg.getId().equals(g)){
if(!definitionsFiltered.contains(pd)){
definitionsFiltered.add(pd);
}
}
}
}
}
}
///sibok666
ResultListDataRepresentation result = new ResultListDataRepresentation(convertDefinitionList(definitionsFiltered));
return result;
}
That’s not the case. The startableByUser does try to retrieve the groups from the remote IDM service I guess. Does it maybe fail there? The solution you came up with works as well of course.
This is also something I would like as well. I’d be willing to complete the implementation in the flowable-task app if that would help.
@Sibok666@tijs Its a bit hard to follow the current status of this. It seems that it has been implemented in the modeler and in the process Engine, but not in the flowable-task front/backend. Does this sound correct?
If I was to implement this I Think a filter based on the potential user/Group when listing process definitions to start and a permission check when actually starting a process would suffice.
Please let me know if you’d like me to proceed and I can take a look during this week.
I have taken a closer look at this and there are two problems when implementing in the flowable-task app.
1 - IdmIdentityService is null
When setting org.flowable.engine.impl.ProcessDefinitionQueryImpl#startableByUser(String userId) to a non-null value when making the Query a lookup is made to ProcessDefinitionQueryImpl#getAuthorizationGroups() and this makes use of the CandidateManager#getGroupsForCandidateUser(String candidateUser) method.
In the flowable-task app this is the class org.flowable.engine.DefaultCandidateManager. The implementation then makes use of the IdentityService and IdmIdentityService which is null - causing the null pointer exception reported above by @Sibok666
A simple solution to this is to provide an alternative CandidateManager implementation using the RemoteIdmService instead of the IdentityService.
(I Think a better solution would be if RemoteIdmService was an implementation of IdmIdentityService and registered within the process Engine - but this would be a lot more work).
2 - No potential starter user/group in the process definition means no-one can start.
The next problem after fixing the above error is how we handle processes which have not set a potential starter user/Group.
As the ProcessDefinitionQueryImpl#startableByUser(String userId) is currently implemented, if we provide a value then that user or one of their Groups must be defined as a potential starter. Otherwise the process definition is filtered out.
However, this implies that a process without a potential starter defined will always be filtered out and not be startable by anyone. Is this the correct behvaiour? Or should no potential starter being defined allow the process to be available to everyone?
(And use a special ‘no-one’ Group for processes that should not be startable by anyone).
Without fixing this issue, when users run flowable-task, if no potential starter has been defined the process definition will not be displayed. I can imagine this will cause a lot of confusion to new users of flowable, as its not a field they will likely use immediately in the modeller. This would also require that every process has a potential starter defined which seems unnecessarily difficult.
Any thoughts on the above points? particularily number 2?
Imo, a process definition without a potential starter should be startable by everyone, that’s also the way that’s backwards compatible with the existing functionality.
If you need help with this, feel free to reach out here. The changes shouldn’t be extremely complex, I hope.
I have now made the changes and created a pull request https://github.com/flowable/flowable-engine/pull/516 containing them.
I have outlined what I have done in the pull request. Please let me know if they require any additional Changes.