/* 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.
*/
package org.activiti.examples.bpmn.authorization;
import java.util.List;
import org.activiti.engine.IdentityService;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.test.Deployment;
/**
* @author Saeid Mirzaei
* @author Tijs Rademakers
*/
public class StartAuthorizationTest extends PluggableActivitiTestCase {
IdentityService identityService;
User userInGroup1;
User userInGroup2;
User userInGroup3;
Group group1;
Group group2;
Group group3;
protected void setUpUsersAndGroups() throws Exception {
identityService = processEngine.getIdentityService();
identityService.saveUser(identityService.newUser("user1"));
identityService.saveUser(identityService.newUser("user2"));
identityService.saveUser(identityService.newUser("user3"));
// create users
userInGroup1 = identityService.newUser("userInGroup1");
identityService.saveUser(userInGroup1);
userInGroup2 = identityService.newUser("userInGroup2");
identityService.saveUser(userInGroup2);
userInGroup3 = identityService.newUser("userInGroup3");
identityService.saveUser(userInGroup3);
// create groups
group1 = identityService.newGroup("group1");
identityService.saveGroup(group1);
group2 = identityService.newGroup("group2");
identityService.saveGroup(group2);
group3 = identityService.newGroup("group3");
identityService.saveGroup(group3);
// relate users to groups
identityService.createMembership(userInGroup1.getId(), group1.getId());
identityService.createMembership(userInGroup2.getId(), group2.getId());
identityService.createMembership(userInGroup3.getId(), group3.getId());
}
protected void tearDownUsersAndGroups() throws Exception {
identityService.deleteMembership(userInGroup1.getId(), group1.getId());
identityService.deleteMembership(userInGroup2.getId(), group2.getId());
identityService.deleteMembership(userInGroup3.getId(), group3.getId());
identityService.deleteGroup(group1.getId());
identityService.deleteGroup(group2.getId());
identityService.deleteGroup(group3.getId());
identityService.deleteUser(userInGroup1.getId());
identityService.deleteUser(userInGroup2.getId());
identityService.deleteUser(userInGroup3.getId());
identityService.deleteUser("user1");
identityService.deleteUser("user2");
identityService.deleteUser("user3");
}
@Deployment
public void testIdentityLinks() throws Exception {
setUpUsersAndGroups();
try {
ProcessDefinition latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("process1")
.singleResult();
assertNotNull(latestProcessDef);
List<IdentityLink> links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(0, links.size());
latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("process2")
.singleResult();
assertNotNull(latestProcessDef);
links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(2, links.size());
assertEquals(true, containsUserOrGroup("user1", null, links));
assertEquals(true, containsUserOrGroup("user2", null, links));
latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("process3")
.singleResult();
assertNotNull(latestProcessDef);
links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(1, links.size());
assertEquals("user1", links.get(0).getUserId());
latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("process4")
.singleResult();
assertNotNull(latestProcessDef);
links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(4, links.size());
assertEquals(true, containsUserOrGroup("userInGroup2", null, links));
assertEquals(true, containsUserOrGroup(null, "group1", links));
assertEquals(true, containsUserOrGroup(null, "group2", links));
assertEquals(true, containsUserOrGroup(null, "group3", links));
} finally {
tearDownUsersAndGroups();
}
}
@Deployment
public void testAddAndRemoveIdentityLinks() throws Exception {
setUpUsersAndGroups();
try {
ProcessDefinition latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("potentialStarterNoDefinition")
.singleResult();
assertNotNull(latestProcessDef);
List<IdentityLink> links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(0, links.size());
repositoryService.addCandidateStarterGroup(latestProcessDef.getId(), "group1");
links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(1, links.size());
assertEquals("group1", links.get(0).getGroupId());
repositoryService.addCandidateStarterUser(latestProcessDef.getId(), "user1");
links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(2, links.size());
assertEquals(true, containsUserOrGroup(null, "group1", links));
assertEquals(true, containsUserOrGroup("user1", null, links));
repositoryService.deleteCandidateStarterGroup(latestProcessDef.getId(), "nonexisting");
links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(2, links.size());
repositoryService.deleteCandidateStarterGroup(latestProcessDef.getId(), "group1");
links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(1, links.size());
assertEquals("user1", links.get(0).getUserId());
repositoryService.deleteCandidateStarterUser(latestProcessDef.getId(), "user1");
links = repositoryService.getIdentityLinksForProcessDefinition(latestProcessDef.getId());
assertEquals(0, links.size());
} finally {
tearDownUsersAndGroups();
}
}
private boolean containsUserOrGroup(String userId, String groupId, List<IdentityLink> links) {
boolean found = false;
for (IdentityLink identityLink : links) {
if(userId != null && userId.equals(identityLink.getUserId())) {
found = true;
break;
} else if(groupId != null && groupId.equals(identityLink.getGroupId())) {
found = true;
break;
}
}
return found;
}
@Deployment
public void testPotentialStarter() throws Exception {
// first check an unauthorized user. An exception is expected
setUpUsersAndGroups();
try {
// Authentication should not be done. So an unidentified user should also be able to start the process
identityService.setAuthenticatedUserId("unauthorizedUser");
try {
runtimeService.startProcessInstanceByKey("potentialStarter");
} catch (Exception e) {
fail("No StartAuthorizationException expected, " + e.getClass().getName() + " caught.");
}
// check with an authorized user obviously it should be no problem starting the process
identityService.setAuthenticatedUserId("user1");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("potentialStarter");
assertProcessEnded(processInstance.getId());
assertTrue(processInstance.isEnded());
} finally {
tearDownUsersAndGroups();
}
}
/*
* if there is no security definition, then user authorization check is not
* done. This ensures backward compatibility
*/
@Deployment
public void testPotentialStarterNoDefinition() throws Exception {
identityService = processEngine.getIdentityService();
identityService.setAuthenticatedUserId("someOneFromMars");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("potentialStarterNoDefinition");
assertNotNull(processInstance.getId());
assertProcessEnded(processInstance.getId());
assertTrue(processInstance.isEnded());
}
// this test checks the list without user constraint
@Deployment
public void testProcessDefinitionList() throws Exception {
setUpUsersAndGroups();
try {
// Process 1 has no potential starters
ProcessDefinition latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("process1")
.singleResult();
List<User> authorizedUsers = identityService.createUserQuery().potentialStarter(latestProcessDef.getId()).list();
assertEquals(0, authorizedUsers.size());
// user1 and user2 are potential Startes of Process2
latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("process2")
.singleResult();
authorizedUsers = identityService.createUserQuery().potentialStarter(latestProcessDef.getId()).orderByUserId().asc().list();
assertEquals(2, authorizedUsers.size());
assertEquals("user1", authorizedUsers.get(0).getId());
assertEquals("user2", authorizedUsers.get(1).getId());
// Process 2 has no potential starter groups
latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("process2")
.singleResult();
List<Group> authorizedGroups = identityService.createGroupQuery().potentialStarter(latestProcessDef.getId()).list();
assertEquals(0, authorizedGroups.size());
// Process 3 has 3 groups as authorized starter groups
latestProcessDef = repositoryService
.createProcessDefinitionQuery().processDefinitionKey("process4")
.singleResult();
authorizedGroups = identityService.createGroupQuery().potentialStarter(latestProcessDef.getId()).orderByGroupId().asc().list();
assertEquals(3, authorizedGroups.size());
assertEquals("group1", authorizedGroups.get(0).getId());
assertEquals("group2", authorizedGroups.get(1).getId());
assertEquals("group3", authorizedGroups.get(2).getId());
// do not mention user, all processes should be selected
List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery()
.orderByProcessDefinitionName().asc().list();
assertEquals(4, processDefinitions.size());
assertEquals("process1", processDefinitions.get(0).getKey());
assertEquals("process2", processDefinitions.get(1).getKey());
assertEquals("process3", processDefinitions.get(2).getKey());
assertEquals("process4", processDefinitions.get(3).getKey());
// check user1, process3 has "user1" as only authorized starter, and
// process2 has two authorized starters, of which one is "user1"
processDefinitions = repositoryService.createProcessDefinitionQuery()
.orderByProcessDefinitionName().asc().startableByUser("user1").list();
assertEquals(2, processDefinitions.size());
assertEquals("process2", processDefinitions.get(0).getKey());
assertEquals("process3", processDefinitions.get(1).getKey());
// "user2" can only start process2
processDefinitions = repositoryService.createProcessDefinitionQuery().startableByUser("user2").list();
assertEquals(1, processDefinitions.size());
assertEquals("process2", processDefinitions.get(0).getKey());
// no process could be started with "user4"
processDefinitions = repositoryService.createProcessDefinitionQuery().startableByUser("user4").list();
assertEquals(0, processDefinitions.size());
// "userInGroup3" is in "group3" and can start only process4 via group authorization
processDefinitions = repositoryService.createProcessDefinitionQuery().startableByUser("userInGroup3").list();
assertEquals(1, processDefinitions.size());
assertEquals("process4", processDefinitions.get(0).getKey());
// "userInGroup2" can start process4, via both user and group authorizations
// but we have to be sure that process4 appears only once
processDefinitions = repositoryService.createProcessDefinitionQuery().startableByUser("userInGroup2").list();
assertEquals(1, processDefinitions.size());
assertEquals("process4", processDefinitions.get(0).getKey());
} finally {
tearDownUsersAndGroups();
}
}
}