View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.docsearch;
17  
18  import org.junit.Test;
19  import org.kuali.rice.kew.api.WorkflowDocument;
20  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
21  import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
22  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
23  import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
24  import org.kuali.rice.kew.docsearch.service.DocumentSearchService;
25  import org.kuali.rice.kew.engine.RouteContext;
26  import org.kuali.rice.kew.service.KEWServiceLocator;
27  import org.kuali.rice.kew.test.KEWTestCase;
28  import org.kuali.rice.kim.api.KimConstants;
29  import org.kuali.rice.kim.api.group.Group;
30  import org.kuali.rice.kim.api.identity.Person;
31  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
32  
33  import static org.junit.Assert.*;
34  
35  /**
36   * This is a description of what this class does - jjhanso don't forget to fill this in. 
37   * 
38   * @author Kuali Rice Team (rice.collab@kuali.org)
39   *
40   */
41  public class DocumentSearchSecurityTest extends KEWTestCase {
42  	private static final String WORKFLOW_ADMIN_USER_NETWORK_ID = "bmcgough";
43      private static final String APPROVER_USER_NETWORK_ID = "user2";
44      private static final String STANDARD_USER_NETWORK_ID = "user1";
45  	DocumentSearchService docSearchService;
46  	
47  	@Override
48  	protected void setUpAfterDataLoad() throws Exception {
49          docSearchService = (DocumentSearchService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_SEARCH_SERVICE);
50      }
51  	
52  	@Override
53  	protected void loadTestData() throws Exception {
54      	loadXmlFile("SearchSecurityConfig.xml");
55          
56      }
57  	
58      /**
59       * Test for https://test.kuali.org/jira/browse/KULRICE-1968 - Document search fails when users are missing
60       * Tests that we can safely search on docs whose initiator no longer exists in the identity management system
61       * This test searches by doc type name criteria.
62       * @throws Exception
63       */
64      @Test public void testDocSearchSecurityPermissionDocType() throws Exception {
65          String documentTypeName = "SecurityDoc_PermissionOnly";
66          String userNetworkId = "arh14";
67          // route a document to enroute and route one to final
68          WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalId(userNetworkId), documentTypeName);
69          workflowDocument.setTitle("testDocSearch_PermissionSecurity");
70          workflowDocument.route("routing this document.");
71  
72          Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("edna");
73          DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
74          criteria.setDocumentTypeName(documentTypeName);
75          DocumentSearchResults results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
76          assertEquals(0, results.getNumberOfSecurityFilteredResults());
77          assertEquals("Search returned invalid number of documents", 1, results.getSearchResults().size());
78      }
79      
80      @Test public void testDocSearchBadPermission() throws Exception {
81          String documentTypeName = "SecurityDoc_InvalidPermissionOnly";
82          String userNetworkId = "arh14";
83          // route a document to enroute and route one to final
84          WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalId(userNetworkId), documentTypeName);
85          workflowDocument.setTitle("testDocSearch_PermissionSecurity");
86          workflowDocument.route("routing this document.");
87  
88          Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("edna");
89          DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
90          criteria.setDocumentTypeName(documentTypeName);
91          DocumentSearchResults results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
92          assertEquals("Search returned invalid number of documents", 0, results.getSearchResults().size());
93      }
94  	
95      @Test public void testFilteringInitiator() throws Exception {    	
96          String documentType = "SecurityDoc_InitiatorOnly";
97          String initiator = getPrincipalId(STANDARD_USER_NETWORK_ID);
98          WorkflowDocument document = WorkflowDocumentFactory.createDocument(initiator, documentType);
99          document.route("");
100         assertFalse("Document should not be in init status after routing", document.isInitiated());
101 
102         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
103         criteria.setDocumentId(document.getDocumentId());
104         DocumentSearchResults results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(initiator, criteria.build());
105         assertEquals("Should retrive one record from search", 1, results.getSearchResults().size());
106         assertEquals("No rows should have been filtered due to security", 0, results.getNumberOfSecurityFilteredResults());
107 
108         criteria = DocumentSearchCriteria.Builder.create();
109         criteria.setDocumentId(document.getDocumentId());
110         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId("user3"), criteria.build());
111         assertEquals("Should retrive no records from search", 0, results.getSearchResults().size());
112         assertEquals("One row should have been filtered due to security", 1, results.getNumberOfSecurityFilteredResults());
113 
114         criteria = DocumentSearchCriteria.Builder.create();
115         criteria.setDocumentId(document.getDocumentId());
116         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId(WORKFLOW_ADMIN_USER_NETWORK_ID), criteria.build());
117         assertEquals("Should retrive one record from search", 1, results.getSearchResults().size());
118         assertEquals("No rows should have been filtered due to security", 0, results.getNumberOfSecurityFilteredResults());
119     }
120     
121     @Test public void testFiltering_Workgroup() throws Exception {
122         String documentType = "SecurityDoc_WorkgroupOnly";
123         String initiator = getPrincipalId(STANDARD_USER_NETWORK_ID);
124         WorkflowDocument document = WorkflowDocumentFactory.createDocument(initiator, documentType);
125         document.route("");
126         assertFalse("Document should not be in init status after routing", document.isInitiated());
127 
128         // verify that initiator cannot see the document
129         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
130         criteria.setDocumentId(document.getDocumentId());
131         DocumentSearchResults results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(initiator, criteria.build());
132         assertEquals("Should retrive no records from search", 0, results.getSearchResults().size());
133         assertEquals("One row should have been filtered due to security", 1, results.getNumberOfSecurityFilteredResults());
134 
135         // verify that workgroup can see the document
136         String workgroupName = "Test_Security_Group";
137         Group group = KimApiServiceLocator.getGroupService().getGroupByNamespaceCodeAndName(
138                 KimConstants.KIM_GROUP_WORKFLOW_NAMESPACE_CODE, workgroupName);
139         assertNotNull("Workgroup '" + workgroupName + "' should be valid", group);
140         for (String workgroupUserId : KimApiServiceLocator.getGroupService().getMemberPrincipalIds(group.getId())) {
141             Person workgroupUser = KimApiServiceLocator.getPersonService().getPerson(workgroupUserId);
142             criteria = DocumentSearchCriteria.Builder.create();
143             criteria.setDocumentId(document.getDocumentId());
144             results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(workgroupUser.getPrincipalId(), criteria.build());
145             assertEquals("Should retrive one record from search for user " + workgroupUser, 1, results.getSearchResults().size());
146             assertEquals("No rows should have been filtered due to security for user " + workgroupUser, 0, results.getNumberOfSecurityFilteredResults());
147         }
148 
149         // verify that user3 cannot see the document
150         criteria = DocumentSearchCriteria.Builder.create();
151         criteria.setDocumentId(document.getDocumentId());
152         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId("user3"), criteria.build());
153         assertEquals("Should retrive no records from search", 0, results.getSearchResults().size());
154         assertEquals("One row should have been filtered due to security", 1, results.getNumberOfSecurityFilteredResults());
155 
156         // verify that WorkflowAdmin can see the document
157         criteria = DocumentSearchCriteria.Builder.create();
158         criteria.setDocumentId(document.getDocumentId());
159         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId(WORKFLOW_ADMIN_USER_NETWORK_ID), criteria.build());
160         assertEquals("Should retrive one record from search", 1, results.getSearchResults().size());
161         assertEquals("No rows should have been filtered due to security", 0, results.getNumberOfSecurityFilteredResults());
162     }
163 
164     @Test public void testFiltering_SearchAttribute() throws Exception {
165 
166         String searchAttributeName = "UserEmployeeId";
167         String searchAttributeFieldName = "employeeId";
168         String documentTypeName = "SecurityDoc_SearchAttributeOnly";
169         String initiatorNetworkId = STANDARD_USER_NETWORK_ID;
170         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalId(initiatorNetworkId), documentTypeName);
171         WorkflowAttributeDefinition.Builder definition = WorkflowAttributeDefinition.Builder.create(searchAttributeName);
172         definition.addPropertyDefinition(searchAttributeFieldName, "user3");
173         document.addSearchableDefinition(definition.build());
174         document.route("");
175         assertFalse("Document should not be in init status after routing", document.isInitiated());
176 
177         // verify that initiator cannot see the document
178         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
179         criteria.setDocumentId(document.getDocumentId());
180         DocumentSearchResults results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId(initiatorNetworkId), criteria.build());
181         assertEquals("Should retrive no records from search", 0, results.getSearchResults().size());
182         assertEquals("One row should have been filtered due to security", 1, results.getNumberOfSecurityFilteredResults());
183 
184         // verify that user3 can see the document
185         criteria = DocumentSearchCriteria.Builder.create();
186         criteria.setDocumentId(document.getDocumentId());
187         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId("user3"), criteria.build());
188         assertEquals("Should retrive one record from search", 1, results.getSearchResults().size());
189         assertEquals("No rows should have been filtered due to security", 0, results.getNumberOfSecurityFilteredResults());
190 
191         // verify that user2 cannot see the document
192         criteria = DocumentSearchCriteria.Builder.create();
193         criteria.setDocumentId(document.getDocumentId());
194         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId("user2"), criteria.build());
195         assertEquals("Should retrive no records from search", 0, results.getSearchResults().size());
196         assertEquals("One row should have been filtered due to security", 1, results.getNumberOfSecurityFilteredResults());
197 
198         // verify that WorkflowAdmin can see the document
199         criteria = DocumentSearchCriteria.Builder.create();
200         criteria.setDocumentId(document.getDocumentId());
201         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId(WORKFLOW_ADMIN_USER_NETWORK_ID), criteria.build());
202         assertEquals("Should retrive one record from search", 1, results.getSearchResults().size());
203         assertEquals("No rows should have been filtered due to security", 0, results.getNumberOfSecurityFilteredResults());
204 
205         RouteContext.clearCurrentRouteContext();
206         document = WorkflowDocumentFactory.loadDocument(getPrincipalId(APPROVER_USER_NETWORK_ID), document.getDocumentId());
207         document.clearSearchableContent();
208         definition = WorkflowAttributeDefinition.Builder.create(searchAttributeName);
209         definition.addPropertyDefinition(searchAttributeFieldName, "user2");
210         document.addSearchableDefinition(definition.build());
211         document.saveDocumentData();
212 
213         // verify that user2 can see the document
214         criteria = DocumentSearchCriteria.Builder.create();
215         criteria.setDocumentId(document.getDocumentId());
216         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId("user2"), criteria.build());
217         assertEquals("Should retrive one record from search", 1, results.getSearchResults().size());
218         assertEquals("No rows should have been filtered due to security", 0, results.getNumberOfSecurityFilteredResults());
219 
220         // verify that user3 cannot see the document
221         criteria = DocumentSearchCriteria.Builder.create();
222         criteria.setDocumentId(document.getDocumentId());
223         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId("user3"), criteria.build());
224         assertEquals("Should retrive no records from search", 0, results.getSearchResults().size());
225         assertEquals("One row should have been filtered due to security", 1, results.getNumberOfSecurityFilteredResults());
226 
227         // verify that initiator cannot see the document
228         criteria = DocumentSearchCriteria.Builder.create();
229         criteria.setDocumentId(document.getDocumentId());
230         results = KEWServiceLocator.getDocumentSearchService().lookupDocuments(getPrincipalId(initiatorNetworkId), criteria.build());
231         assertEquals("Should retrive no records from search", 0, results.getSearchResults().size());
232         assertEquals("One row should have been filtered due to security", 1, results.getNumberOfSecurityFilteredResults());
233     }
234 
235     private String getPrincipalId(String principalName) {
236     	return KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(principalName).getPrincipalId();
237     }
238 	
239 }