001 /** 002 * Copyright 2005-2011 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.kew.actions; 017 018 import org.junit.Test; 019 import org.kuali.rice.kew.actionrequest.ActionRequestValue; 020 import org.kuali.rice.kew.actions.BlanketApproveTest.NotifySetup; 021 import org.kuali.rice.kew.api.KewApiServiceLocator; 022 import org.kuali.rice.kew.api.WorkflowDocument; 023 import org.kuali.rice.kew.api.WorkflowDocumentFactory; 024 import org.kuali.rice.kew.api.action.ActionRequest; 025 import org.kuali.rice.kew.api.action.ActionType; 026 import org.kuali.rice.kew.api.action.ReturnPoint; 027 import org.kuali.rice.kew.api.document.DocumentStatus; 028 import org.kuali.rice.kew.service.KEWServiceLocator; 029 import org.kuali.rice.kew.test.KEWTestCase; 030 import org.kuali.rice.kew.test.TestUtilities; 031 import org.kuali.rice.test.BaselineTestCase; 032 033 import java.util.Iterator; 034 import java.util.List; 035 036 import static org.junit.Assert.*; 037 038 /** 039 * Tests the super user actions available on the API. 040 */ 041 @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.NONE) 042 public class SuperUserActionTest extends KEWTestCase { 043 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SuperUserActionTest.class); 044 045 protected void loadTestData() throws Exception { 046 loadXmlFile("ActionsConfig.xml"); 047 } 048 049 @Test public void testSuperUserApprove() throws Exception { 050 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), NotifySetup.DOCUMENT_TYPE_NAME); 051 document.route(""); 052 053 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId()); 054 assertTrue("WorkflowDocument should indicate jhopf as SuperUser", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 055 document.superUserBlanketApprove(""); 056 assertTrue("Document should be 'processed' after Super User Approve", document.isProcessed()); 057 List requests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 058 assertTrue("Should be active requests still", requests.size() == 2);//number of acks and fyi's configured through rules 059 for (Iterator iter = requests.iterator(); iter.hasNext();) { 060 ActionRequestValue request = (ActionRequestValue) iter.next(); 061 if (request.isApproveOrCompleteRequest()) { 062 fail("There should be no approve or complete requests after su approve"); 063 } 064 } 065 } 066 067 // SUApprove == SUBlanketApprove...what? 068 @Test public void testSuperUserApproveDisallowedOnFinalNode() throws Exception { 069 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "SUApproveFinalNodeDisallowed"); 070 document.route(""); 071 072 // approve down to last node, at every step (except the last) jhopf should be able to su_approve 073 // omit "bmcgough", the last approver 074 String nodeBeforeLast = null; 075 for (String user: new String[] { "jhopf", "ewestfal", "rkirkend", "natjohns" }) { 076 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId()); 077 System.err.println(document.getCurrentNodeNames()); 078 nodeBeforeLast = document.getCurrentNodeNames().iterator().next(); 079 assertTrue("jhopf should be able to SU Approve", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 080 081 WorkflowDocumentFactory.loadDocument(getPrincipalIdForName(user), document.getDocumentId()).approve(""); 082 } 083 084 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId()); 085 // it's the last node, no SU Approve for you! 086 assertFalse("jhopf should NOT be able to SU Approve", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 087 088 // move back a step 089 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId()); 090 document.superUserReturnToPreviousNode(ReturnPoint.create("Split"), "returning to non-final node"); 091 // now we can SU Approve 092 assertTrue("jhopf should be able to SU Approve", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 093 document.superUserBlanketApprove("blanket approving as jhopf"); 094 095 //assertTrue(document.isFinal()); 096 assertTrue(document.isProcessed()); 097 assertTrue(document.isApproved()); 098 assertFalse("jhopf should NOT be able to SU Approve", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 099 100 List<ActionRequestValue> requests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 101 assertEquals("Should be active requests still", 5, requests.size());//number of acks and fyi's configured through rules 102 for (ActionRequestValue request: requests) { 103 System.err.println(request.getActionRequestedLabel() + " -> " + request.getPrincipal().getPrincipalName()); 104 if (request.isApproveOrCompleteRequest()) { 105 fail("There should be no approve or complete requests after su approve"); 106 } 107 } 108 } 109 110 @Test public void testSuperUserApproveExceptionCases() throws Exception { 111 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "SUApproveDocument"); 112 document.route(""); 113 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), document.getDocumentId()); 114 try { 115 document.approve(""); 116 } catch (Exception e) { 117 } 118 TestUtilities.getExceptionThreader().join(); 119 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId()); 120 assertTrue("Document should be in exception routing", document.isException()); 121 document.superUserBlanketApprove(""); 122 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId()); 123 assertTrue("Document should be final", document.isFinal()); 124 125 List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 126 assertTrue("Should be no active requests for SU Approved document", actionRequests.isEmpty()); 127 } 128 129 @Test public void testSuperUserApproveExceptionCasesWithNotifications() throws Exception { 130 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "SUApproveDocumentNotifications"); 131 document.route(""); 132 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), document.getDocumentId()); 133 try { 134 document.approve(""); 135 } catch (Exception e) { 136 } 137 TestUtilities.getExceptionThreader().join(); 138 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId()); 139 assertTrue("Document should be in exception routing", document.isException()); 140 document.superUserBlanketApprove(""); 141 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId()); 142 assertTrue("Document should be 'processed'", document.isProcessed()); 143 144 List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 145 assertFalse("Should be active requests for SU Approved document", actionRequests.isEmpty()); 146 for (Iterator iter = actionRequests.iterator(); iter.hasNext();) { 147 ActionRequestValue request = (ActionRequestValue) iter.next(); 148 assertTrue("Should be an ack notification request", request.isAcknowledgeRequest()); 149 } 150 } 151 152 @Test public void testSuperUserInitiatorApprove() throws Exception { 153 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), NotifySetup.DOCUMENT_TYPE_NAME); 154 assertTrue("WorkflowDocument should indicate ewestfal as SuperUser", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 155 document.superUserBlanketApprove(""); 156 assertTrue("Document should be 'processed' after Super User Approve", document.isProcessed()); 157 List requests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 158 assertTrue("Should be active requests still", requests.size() == 2);//number of acks and fyi's configured through rules 159 for (Iterator iter = requests.iterator(); iter.hasNext();) { 160 ActionRequestValue request = (ActionRequestValue) iter.next(); 161 if (request.isApproveOrCompleteRequest()) { 162 fail("There should be no approve or complete requests after su approve"); 163 } 164 } 165 } 166 167 @Test public void testSuperUserApproveWithNotifications() throws Exception { 168 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "NotificationTestChild"); 169 assertTrue("WorkflowDocument should indicate ewestfal as SuperUser", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 170 document.superUserBlanketApprove(""); 171 assertTrue("Document should be 'processed' after Super User Approve", document.isProcessed()); 172 List requests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 173 assertTrue("Should be active requests still", requests.size() > 2);//number of acks and fyi's configured through rules - we need these for approvals too 174 for (Iterator iter = requests.iterator(); iter.hasNext();) { 175 ActionRequestValue request = (ActionRequestValue) iter.next(); 176 if (request.isApproveOrCompleteRequest()) { 177 fail("There should be no approve or complete requests after su approve"); 178 } 179 } 180 } 181 182 @Test public void testSuperUserApproveInvalidUser() throws Exception { 183 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), NotifySetup.DOCUMENT_TYPE_NAME); 184 document.route(""); 185 186 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("quickstart"), document.getDocumentId()); 187 try { 188 assertFalse("WorkflowDocument should not indicate quickstart as SuperUser", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 189 document.superUserBlanketApprove(""); 190 fail("invalid user attempted to SuperUserApprove"); 191 } catch (Exception e) { 192 } 193 194 } 195 196 @Test public void testSuperUserActionDisregardPostProcessing() throws Exception { 197 198 String bmcgoughPrincipalId = getPrincipalIdForName("bmcgough"); 199 200 // verify that the post processor class still throws exceptions when post processing document 201 WorkflowDocument document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 202 try { 203 document.superUserBlanketApprove(""); 204 fail("Document should throw exception from post processor"); 205 } catch (Exception e) { 206 } 207 208 // test that ignoring the post processor works correctly 209 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 210 try { 211 KEWServiceLocator.getWorkflowDocumentService().superUserCancelAction(bmcgoughPrincipalId, KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()), "", false); 212 } catch (Exception e) { 213 LOG.error("Exception Found:", e); 214 fail("Document should not throw an exception when ignoring post processor during superUserCancelAction"); 215 } 216 217 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 218 try { 219 KEWServiceLocator.getWorkflowDocumentService().superUserDisapproveAction(bmcgoughPrincipalId, KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()), "", false); 220 } catch (Exception e) { 221 LOG.error("Exception Found:", e); 222 fail("Document should not throw an exception when ignoring post processor during superUserDisapproveAction"); 223 } 224 225 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 226 try { 227 KEWServiceLocator.getWorkflowDocumentService().superUserApprove(bmcgoughPrincipalId, KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()), "", false); 228 } catch (Exception e) { 229 LOG.error("Exception Found:", e); 230 fail("Document should not throw an exception when ignoring post processor during superUserApprove"); 231 } 232 233 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 234 try { 235 KEWServiceLocator.getWorkflowDocumentService().superUserNodeApproveAction(bmcgoughPrincipalId, document.getDocumentId(), "Acknowledge1", "", false); 236 } catch (Exception e) { 237 LOG.error("Exception Found:", e); 238 fail("Document should not throw an exception when ignoring post processor during superUserNodeApprove"); 239 } 240 241 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 242 try { 243 KEWServiceLocator.getWorkflowDocumentService().superUserReturnDocumentToPreviousNode(bmcgoughPrincipalId, document.getDocumentId(), "WorkflowDocumentTemplate", "", false); 244 } catch (Exception e) { 245 LOG.error("Exception Found:", e); 246 fail("Document should not throw an exception when ignoring post processor during superUserReturnDocumentToPreviousNode"); 247 } 248 249 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 250 try { 251 String actionRequestId = null; 252 // get actionRequestId to use... there should only be one active action request 253 List<ActionRequest> actionRequests = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(document.getDocumentId()); 254 for (ActionRequest actionRequest : actionRequests) { 255 if (actionRequest.isActivated()) { 256 // if we already found an active action request fail the test 257 if (actionRequestId != null) { 258 fail("Found two active action requests for document. Ids: " + actionRequestId + " & " + actionRequest.getId()); 259 } 260 actionRequestId = actionRequest.getId(); 261 } 262 } 263 264 KEWServiceLocator.getWorkflowDocumentService().superUserActionRequestApproveAction(bmcgoughPrincipalId, document.getDocumentId(), actionRequestId, "", false); 265 } catch (Exception e) { 266 LOG.error("Exception Found:", e); 267 fail("Document should not throw an exception when ignoring post processor during superUserActionRequestApproveAction"); 268 } 269 270 } 271 272 private WorkflowDocument generateDummyEnrouteDocument(String initiatorNetworkId) throws Exception { 273 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName(initiatorNetworkId), "SuperUserActionInvalidPostProcessor"); 274 assertEquals("Document should be at start node","AdHoc", document.getNodeNames().iterator().next()); 275 document.route(""); 276 assertEquals("Document should be at WorkflowDocument2 node","WorkflowDocument2", document.getNodeNames().iterator().next()); 277 assertEquals("Document should be enroute", DocumentStatus.ENROUTE, document.getStatus()); 278 return document; 279 } 280 281 282 }