001/** 002 * Copyright 2005-2014 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 */ 016package org.kuali.rice.kew.actions; 017 018import org.junit.Test; 019import org.kuali.rice.kew.actionrequest.ActionRequestValue; 020import org.kuali.rice.kew.actions.BlanketApproveTest.NotifySetup; 021import org.kuali.rice.kew.api.KewApiServiceLocator; 022import org.kuali.rice.kew.api.WorkflowDocument; 023import org.kuali.rice.kew.api.WorkflowDocumentFactory; 024import org.kuali.rice.kew.api.action.ActionRequest; 025import org.kuali.rice.kew.api.action.ActionType; 026import org.kuali.rice.kew.api.action.ReturnPoint; 027import org.kuali.rice.kew.api.document.DocumentStatus; 028import org.kuali.rice.kew.service.KEWServiceLocator; 029import org.kuali.rice.kew.test.KEWTestCase; 030import org.kuali.rice.kew.test.TestUtilities; 031import org.kuali.rice.test.BaselineTestCase; 032 033import java.util.Iterator; 034import java.util.List; 035 036import static org.junit.Assert.*; 037 038/** 039 * Tests the super user actions available on the API. 040 */ 041@BaselineTestCase.BaselineMode(BaselineTestCase.Mode.NONE) 042public 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<ActionRequestValue> 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 ( ActionRequestValue request : requests ) { 060 if (request.isApproveOrCompleteRequest()) { 061 fail("There should be no approve or complete requests after su approve"); 062 } 063 } 064 } 065 066 // SUApprove == SUBlanketApprove...what? 067 @Test public void testSuperUserApproveDisallowedOnFinalNode() throws Exception { 068 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "SUApproveFinalNodeDisallowed"); 069 document.route(""); 070 071 // approve down to last node, at every step (except the last) jhopf should be able to su_approve 072 // omit "bmcgough", the last approver 073 String nodeBeforeLast = null; 074 for (String user: new String[] { "jhopf", "ewestfal", "rkirkend", "natjohns" }) { 075 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId()); 076 System.err.println(document.getCurrentNodeNames()); 077 nodeBeforeLast = document.getCurrentNodeNames().iterator().next(); 078 assertTrue("jhopf should be able to SU Approve", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 079 080 WorkflowDocumentFactory.loadDocument(getPrincipalIdForName(user), document.getDocumentId()).approve(""); 081 } 082 083 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId()); 084 // it's the last node, no SU Approve for you! 085 assertFalse("jhopf should NOT be able to SU Approve", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 086 087 // move back a step 088 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId()); 089 document.superUserReturnToPreviousNode(ReturnPoint.create("Split"), "returning to non-final node"); 090 // now we can SU Approve 091 assertTrue("jhopf should be able to SU Approve", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 092 document.superUserBlanketApprove("blanket approving as jhopf"); 093 094 assertEquals("Document status incorrect", DocumentStatus.PROCESSED, document.getStatus()); 095 assertFalse("jhopf should NOT be able to SU Approve", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 096 097 List<ActionRequestValue> requests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 098 assertEquals("Should be active requests still", 5, requests.size());//number of acks and fyi's configured through rules 099 for (ActionRequestValue request: requests) { 100 System.err.println(request.getActionRequestedLabel() + " -> " + request.getPrincipal().getPrincipalName()); 101 if (request.isApproveOrCompleteRequest()) { 102 fail("There should be no approve or complete requests after su approve. Found: " + request); 103 } 104 } 105 } 106 107 @Test public void testSuperUserApproveExceptionCases() throws Exception { 108 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "SUApproveDocument"); 109 document.route(""); 110 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), document.getDocumentId()); 111 try { 112 document.approve(""); 113 } catch (Exception e) { 114 } 115 TestUtilities.getExceptionThreader().join(); 116 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId()); 117 assertEquals("Document status incorrect", DocumentStatus.EXCEPTION, document.getStatus()); 118 document.superUserBlanketApprove(""); 119 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId()); 120 assertEquals("Document status incorrect", DocumentStatus.FINAL, document.getStatus()); 121 122 List<ActionRequestValue> actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 123 assertEquals("Should be no active requests for SU Approved document. Found: " + actionRequests, 0, actionRequests.size()); 124 } 125 126 @Test public void testSuperUserApproveExceptionCasesWithNotifications() throws Exception { 127 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "SUApproveDocumentNotifications"); 128 document.route(""); 129 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), document.getDocumentId()); 130 try { 131 document.approve(""); 132 } catch (Exception e) { 133 } 134 TestUtilities.getExceptionThreader().join(); 135 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId()); 136 assertEquals("Document status incorrect", DocumentStatus.EXCEPTION, document.getStatus()); 137 document.superUserBlanketApprove(""); 138 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId()); 139 assertEquals("Document status incorrect after blanket approve", DocumentStatus.PROCESSED, document.getStatus()); 140 141 List<ActionRequestValue> actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 142 assertFalse("Should be active requests for SU Approved document", actionRequests.isEmpty()); 143 for (ActionRequestValue request: actionRequests) { 144 assertEquals("Should be an ack notification request", ActionType.ACKNOWLEDGE, ActionType.fromCode(request.getActionRequested()) ); 145 } 146 } 147 148 @Test public void testSuperUserInitiatorApprove() throws Exception { 149 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), NotifySetup.DOCUMENT_TYPE_NAME); 150 assertTrue("WorkflowDocument should indicate ewestfal as SuperUser", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 151 document.superUserBlanketApprove(""); 152 assertEquals("Document status incorrect after super user approve", DocumentStatus.PROCESSED, document.getStatus()); 153 List<ActionRequestValue> requests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 154 assertEquals("Should be active requests still", 2, requests.size() );//number of acks and fyi's configured through rules 155 for (ActionRequestValue request: requests) { 156 if (request.isApproveOrCompleteRequest()) { 157 fail("There should be no approve or complete requests after su approve"); 158 } 159 } 160 } 161 162 @Test public void testSuperUserApproveWithNotifications() throws Exception { 163 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "NotificationTestChild"); 164 assertTrue("WorkflowDocument should indicate ewestfal as SuperUser", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 165 document.superUserBlanketApprove(""); 166 assertEquals("Document status incorrect after super user approve", DocumentStatus.PROCESSED, document.getStatus()); 167 List requests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); 168 assertTrue("Should be active requests still", requests.size() > 2);//number of acks and fyi's configured through rules - we need these for approvals too 169 for (Iterator iter = requests.iterator(); iter.hasNext();) { 170 ActionRequestValue request = (ActionRequestValue) iter.next(); 171 if (request.isApproveOrCompleteRequest()) { 172 fail("There should be no approve or complete requests after su approve"); 173 } 174 } 175 } 176 177 @Test public void testSuperUserApproveInvalidUser() throws Exception { 178 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), NotifySetup.DOCUMENT_TYPE_NAME); 179 document.route(""); 180 181 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("quickstart"), document.getDocumentId()); 182 try { 183 assertFalse("WorkflowDocument should not indicate quickstart as SuperUser", document.isValidAction(ActionType.SU_BLANKET_APPROVE)); 184 document.superUserBlanketApprove(""); 185 fail("invalid user attempted to SuperUserApprove"); 186 } catch (Exception e) { 187 } 188 189 } 190 191 @Test public void testSuperUserActionDisregardPostProcessing() throws Exception { 192 193 String bmcgoughPrincipalId = getPrincipalIdForName("bmcgough"); 194 195 // verify that the post processor class still throws exceptions when post processing document 196 WorkflowDocument document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 197 try { 198 document.superUserBlanketApprove(""); 199 fail("Document should throw exception from post processor"); 200 } catch (Exception e) { 201 } 202 203 // test that ignoring the post processor works correctly 204 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 205 try { 206 KEWServiceLocator.getWorkflowDocumentService().superUserCancelAction(bmcgoughPrincipalId, KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()), "", false); 207 } catch (Exception e) { 208 LOG.error("Exception Found:", e); 209 fail("Document should not throw an exception when ignoring post processor during superUserCancelAction " + e.getClass().getName() + " : " + e.getMessage() ); 210 } 211 212 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 213 try { 214 KEWServiceLocator.getWorkflowDocumentService().superUserDisapproveAction(bmcgoughPrincipalId, KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()), "", false); 215 } catch (Exception e) { 216 LOG.error("Exception Found:", e); 217 fail("Document should not throw an exception when ignoring post processor during superUserDisapproveAction"); 218 } 219 220 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 221 try { 222 KEWServiceLocator.getWorkflowDocumentService().superUserApprove(bmcgoughPrincipalId, KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()), "", false); 223 } catch (Exception e) { 224 LOG.error("Exception Found:", e); 225 fail("Document should not throw an exception when ignoring post processor during superUserApprove"); 226 } 227 228 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 229 try { 230 KEWServiceLocator.getWorkflowDocumentService().superUserNodeApproveAction(bmcgoughPrincipalId, document.getDocumentId(), "Acknowledge1", "", false); 231 } catch (Exception e) { 232 LOG.error("Exception Found:", e); 233 fail("Document should not throw an exception when ignoring post processor during superUserNodeApprove"); 234 } 235 236 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 237 try { 238 KEWServiceLocator.getWorkflowDocumentService().superUserReturnDocumentToPreviousNode(bmcgoughPrincipalId, document.getDocumentId(), "WorkflowDocumentTemplate", "", false); 239 } catch (Exception e) { 240 LOG.error("Exception Found:", e); 241 fail("Document should not throw an exception when ignoring post processor during superUserReturnDocumentToPreviousNode"); 242 } 243 244 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), generateDummyEnrouteDocument("ewestfal").getDocumentId()); 245 try { 246 String actionRequestId = null; 247 // get actionRequestId to use... there should only be one active action request 248 List<ActionRequest> actionRequests = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(document.getDocumentId()); 249 for (ActionRequest actionRequest : actionRequests) { 250 if (actionRequest.isActivated()) { 251 // if we already found an active action request fail the test 252 if (actionRequestId != null) { 253 fail("Found two active action requests for document. Ids: " + actionRequestId + " & " + actionRequest.getId()); 254 } 255 actionRequestId = actionRequest.getId(); 256 } 257 } 258 259 KEWServiceLocator.getWorkflowDocumentService().superUserActionRequestApproveAction(bmcgoughPrincipalId, document.getDocumentId(), actionRequestId, "", false); 260 } catch (Exception e) { 261 LOG.error("Exception Found:", e); 262 fail("Document should not throw an exception when ignoring post processor during superUserActionRequestApproveAction"); 263 } 264 265 } 266 267 private WorkflowDocument generateDummyEnrouteDocument(String initiatorNetworkId) throws Exception { 268 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName(initiatorNetworkId), "SuperUserActionInvalidPostProcessor"); 269 assertEquals("Document should be at start node","AdHoc", document.getNodeNames().iterator().next()); 270 document.route(""); 271 assertEquals("Document should be at WorkflowDocument2 node","WorkflowDocument2", document.getNodeNames().iterator().next()); 272 assertEquals("Document should be enroute", DocumentStatus.ENROUTE, document.getStatus()); 273 return document; 274 } 275 276 277}