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    }