View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.fit.core;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assertions.fail;
26  import static org.junit.jupiter.api.Assumptions.assumeFalse;
27  import static org.junit.jupiter.api.Assumptions.assumeTrue;
28  
29  import java.io.IOException;
30  import java.util.List;
31  import javax.ws.rs.core.GenericType;
32  import javax.ws.rs.core.MediaType;
33  import org.apache.cxf.helpers.IOUtils;
34  import org.apache.cxf.jaxrs.client.WebClient;
35  import org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit;
36  import org.apache.syncope.client.lib.SyncopeClient;
37  import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
38  import org.apache.syncope.common.lib.SyncopeClientException;
39  import org.apache.syncope.common.lib.to.PagedResult;
40  import org.apache.syncope.common.lib.to.ProvisioningResult;
41  import org.apache.syncope.common.lib.to.RelationshipTO;
42  import org.apache.syncope.common.lib.to.UserRequest;
43  import org.apache.syncope.common.lib.to.UserRequestForm;
44  import org.apache.syncope.common.lib.to.UserTO;
45  import org.apache.syncope.common.lib.to.WorkflowTaskExecInput;
46  import org.apache.syncope.common.lib.types.ClientExceptionType;
47  import org.apache.syncope.common.rest.api.beans.UserRequestQuery;
48  import org.apache.syncope.common.rest.api.service.UserRequestService;
49  import org.apache.syncope.fit.AbstractITCase;
50  import org.junit.jupiter.api.AfterAll;
51  import org.junit.jupiter.api.BeforeAll;
52  import org.junit.jupiter.api.BeforeEach;
53  import org.junit.jupiter.api.Test;
54  
55  public class UserRequestITCase extends AbstractITCase {
56  
57      @BeforeAll
58      public static void loadBpmnProcesses() throws IOException {
59          assumeFalse(CLIENT_FACTORY.getContentType() == SyncopeClientFactoryBean.ContentType.YAML);
60          assumeTrue(IS_FLOWABLE_ENABLED);
61  
62          WebClient.client(BPMN_PROCESS_SERVICE).type(MediaType.APPLICATION_XML_TYPE);
63          BPMN_PROCESS_SERVICE.set("directorGroupRequest",
64                  IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/directorGroupRequest.bpmn20.xml")));
65          BPMN_PROCESS_SERVICE.set("assignPrinterRequest",
66                  IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/assignPrinterRequest.bpmn20.xml")));
67          BPMN_PROCESS_SERVICE.set("verifyAddedVariables",
68                  IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/verifyAddedVariables.bpmn20.xml")));
69  
70          WebClient.getConfig(WebClient.client(USER_REQUEST_SERVICE)).
71                  getRequestContext().put(AsyncHTTPConduit.USE_ASYNC, Boolean.FALSE);
72      }
73  
74      @AfterAll
75      public static void reset() {
76          WebClient.getConfig(WebClient.client(USER_REQUEST_SERVICE)).
77                  getRequestContext().put(AsyncHTTPConduit.USE_ASYNC, Boolean.TRUE);
78      }
79  
80      @BeforeEach
81      public void check() {
82          assumeFalse(CLIENT_FACTORY.getContentType() == SyncopeClientFactoryBean.ContentType.YAML);
83          assumeTrue(IS_FLOWABLE_ENABLED);
84      }
85  
86      @Test
87      public void twoLevelsApproval() {
88          UserTO user = createUser(UserITCase.getUniqueSample("twoLevelsApproval@tirasa.net")).getEntity();
89          assertNotNull(user);
90          assertFalse(user.getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
91  
92          // start request
93          UserRequest req = USER_REQUEST_SERVICE.startRequest("directorGroupRequest", user.getKey(), null);
94          assertNotNull(req);
95          assertEquals("directorGroupRequest", req.getBpmnProcess());
96          assertNotNull(req.getExecutionId());
97          assertEquals(req.getUsername(), user.getUsername());
98  
99          // check that user can see the ongoing request
100         SyncopeClient client = CLIENT_FACTORY.create(user.getUsername(), "password123");
101         PagedResult<UserRequest> requests = client.getService(UserRequestService.class).
102                 listRequests(new UserRequestQuery.Builder().user(user.getKey()).build());
103         assertEquals(1, requests.getTotalCount());
104         assertEquals("directorGroupRequest", requests.getResult().get(0).getBpmnProcess());
105 
106         // 1st approval -> reject
107         UserRequestForm form = USER_REQUEST_SERVICE.listForms(
108                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().get(0);
109         form = USER_REQUEST_SERVICE.claimForm(form.getTaskId());
110         form.getProperty("firstLevelApprove").get().setValue(Boolean.FALSE.toString());
111         USER_REQUEST_SERVICE.submitForm(form);
112 
113         // no more forms, group not assigned
114         assertTrue(USER_REQUEST_SERVICE.listForms(
115                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().isEmpty());
116         assertFalse(USER_SERVICE.read(user.getKey()).getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
117 
118         // start request again
119         req = USER_REQUEST_SERVICE.startRequest("directorGroupRequest", user.getKey(), null);
120         assertNotNull(req);
121 
122         // 1st approval -> accept
123         form = USER_REQUEST_SERVICE.listForms(
124                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().get(0);
125         form = USER_REQUEST_SERVICE.claimForm(form.getTaskId());
126         form.getProperty("firstLevelApprove").get().setValue(Boolean.TRUE.toString());
127         USER_REQUEST_SERVICE.submitForm(form);
128 
129         // 2nd approval -> reject
130         form = USER_REQUEST_SERVICE.listForms(
131                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().get(0);
132         form = USER_REQUEST_SERVICE.claimForm(form.getTaskId());
133         form.getProperty("secondLevelApprove").get().setValue(Boolean.FALSE.toString());
134         user = USER_REQUEST_SERVICE.submitForm(form).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
135         }).getEntity();
136 
137         // no more forms, group not assigned
138         assertTrue(USER_REQUEST_SERVICE.listForms(
139                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().isEmpty());
140         assertFalse(USER_SERVICE.read(user.getKey()).getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
141 
142         // start request again
143         req = USER_REQUEST_SERVICE.startRequest("directorGroupRequest", user.getKey(), null);
144         assertNotNull(req);
145 
146         // 1st approval -> accept
147         form = USER_REQUEST_SERVICE.listForms(
148                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().get(0);
149         form = USER_REQUEST_SERVICE.claimForm(form.getTaskId());
150         form.getProperty("firstLevelApprove").get().setValue(Boolean.TRUE.toString());
151         USER_REQUEST_SERVICE.submitForm(form);
152 
153         // 2nd approval -> accept
154         form = USER_REQUEST_SERVICE.listForms(
155                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().get(0);
156         form = USER_REQUEST_SERVICE.claimForm(form.getTaskId());
157         form.getProperty("secondLevelApprove").get().setValue(Boolean.TRUE.toString());
158         user = USER_REQUEST_SERVICE.submitForm(form).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
159         }).getEntity();
160 
161         // check that the director group was effectively assigned
162         assertTrue(user.getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
163         assertTrue(USER_SERVICE.read(user.getKey()).getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
164     }
165 
166     @Test
167     public void cancel() {
168         PagedResult<UserRequestForm> forms =
169                 USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
170         int preForms = forms.getTotalCount();
171 
172         UserTO user = createUser(UserITCase.getUniqueSample("twoLevelsApproval@tirasa.net")).getEntity();
173         assertNotNull(user);
174         assertFalse(user.getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
175 
176         // start request
177         UserRequest req = USER_REQUEST_SERVICE.startRequest("directorGroupRequest", user.getKey(), null);
178         assertNotNull(req);
179 
180         // check that form was generated
181         forms = USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
182         assertEquals(preForms + 1, forms.getTotalCount());
183 
184         assertEquals(1, USER_REQUEST_SERVICE.listForms(
185                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().size());
186 
187         // cancel request
188         USER_REQUEST_SERVICE.cancelRequest(req.getExecutionId(), "nothing in particular");
189 
190         // check that form was removed
191         forms = USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
192         assertEquals(preForms, forms.getTotalCount());
193 
194         assertTrue(USER_REQUEST_SERVICE.listForms(
195                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().isEmpty());
196     }
197 
198     @Test
199     public void userSelection() {
200         PagedResult<UserRequestForm> forms =
201                 USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
202         int preForms = forms.getTotalCount();
203 
204         UserTO user = createUser(UserITCase.getUniqueSample("userSelection@tirasa.net")).getEntity();
205         assertNotNull(user);
206         List<RelationshipTO> relationships = USER_SERVICE.read(user.getKey()).getRelationships();
207         assertTrue(relationships.isEmpty());
208 
209         SyncopeClient client = CLIENT_FACTORY.create(user.getUsername(), "password123");
210 
211         // start request as user
212         UserRequestService service = client.getService(UserRequestService.class);
213         WebClient.getConfig(WebClient.client(service)).
214                 getRequestContext().put(AsyncHTTPConduit.USE_ASYNC, Boolean.FALSE);
215 
216         UserRequest req = service.startRequest("assignPrinterRequest", null, null);
217         assertNotNull(req);
218         WebClient.getConfig(WebClient.client(service)).
219                 getRequestContext().put(AsyncHTTPConduit.USE_ASYNC, Boolean.TRUE);
220 
221         // check (as admin) that a new form is available
222         forms = USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
223         assertEquals(preForms + 1, forms.getTotalCount());
224 
225         // get (as user) the form, claim and submit
226         PagedResult<UserRequestForm> userForms = service.listForms(
227                 new UserRequestQuery.Builder().user(user.getKey()).build());
228         assertEquals(1, userForms.getTotalCount());
229 
230         UserRequestForm form = userForms.getResult().get(0);
231         assertEquals("assignPrinterRequest", form.getBpmnProcess());
232         form = service.claimForm(form.getTaskId());
233 
234         assertFalse(form.getProperty("printer").get().getDropdownValues().isEmpty());
235         form.getProperty("printer").ifPresent(printer -> printer.setValue("8559d14d-58c2-46eb-a2d4-a7d35161e8f8"));
236 
237         assertFalse(form.getProperty("printMode").get().getEnumValues().isEmpty());
238         form.getProperty("printMode").ifPresent(printMode -> printMode.setValue("color"));
239 
240         service.submitForm(form);
241 
242         userForms = service.listForms(new UserRequestQuery.Builder().user(user.getKey()).build());
243         assertEquals(0, userForms.getTotalCount());
244 
245         // check that user can see the ongoing request
246         PagedResult<UserRequest> requests = service.listRequests(
247                 new UserRequestQuery.Builder().user(user.getKey()).build());
248         assertEquals(1, requests.getTotalCount());
249         assertEquals("assignPrinterRequest", requests.getResult().get(0).getBpmnProcess());
250 
251         // get (as admin) the new form, claim and submit
252         form = USER_REQUEST_SERVICE.listForms(
253                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().get(0);
254         assertEquals("assignPrinterRequest", form.getBpmnProcess());
255         form = USER_REQUEST_SERVICE.claimForm(form.getTaskId());
256 
257         assertEquals("8559d14d-58c2-46eb-a2d4-a7d35161e8f8", form.getProperty("printer").get().getValue());
258 
259         form.getProperty("approve").get().setValue(Boolean.TRUE.toString());
260         USER_REQUEST_SERVICE.submitForm(form);
261 
262         // no more forms available
263         forms = USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
264         assertEquals(preForms, forms.getTotalCount());
265 
266         assertTrue(service.listRequests(
267                 new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().isEmpty());
268 
269         // check that relationship was made effective by approval
270         relationships = USER_SERVICE.read(user.getKey()).getRelationships();
271         assertFalse(relationships.isEmpty());
272         assertTrue(relationships.stream().
273                 anyMatch(relationship -> "8559d14d-58c2-46eb-a2d4-a7d35161e8f8".equals(relationship.getOtherEndKey())));
274     }
275 
276     @Test
277     public void addVariablesToUserRequestAtStart() {
278         PagedResult<UserRequestForm> forms = USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
279         int preForms = forms.getTotalCount();
280 
281         UserTO user = createUser(UserITCase.getUniqueSample("addVariables@tirasa.net")).getEntity();
282         assertNotNull(user);
283 
284         SyncopeClient client = CLIENT_FACTORY.create(user.getUsername(), "password123");
285 
286         WorkflowTaskExecInput testInput = new WorkflowTaskExecInput();
287         testInput.getVariables().put("providedVariable", "test");
288 
289         // start request as user
290         UserRequest req = client.getService(UserRequestService.class).
291                 startRequest("verifyAddedVariables", null, testInput);
292         assertNotNull(req);
293 
294         // check that a new form is available
295         forms = USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
296         assertEquals(preForms + 1, forms.getTotalCount());
297 
298         // get the form and verify the property value
299         PagedResult<UserRequestForm> userForms = USER_REQUEST_SERVICE.listForms(
300                 new UserRequestQuery.Builder().user(user.getKey()).build());
301         assertEquals(1, userForms.getTotalCount());
302 
303         UserRequestForm form = userForms.getResult().get(0);
304         form = USER_REQUEST_SERVICE.claimForm(form.getTaskId());
305         assertEquals(form.getProperty("providedVariable").get().getValue(), "test");
306 
307         // cancel request
308         USER_REQUEST_SERVICE.cancelRequest(req.getExecutionId(), "nothing in particular");
309 
310         // no more forms available
311         forms = USER_REQUEST_SERVICE.listForms(new UserRequestQuery.Builder().build());
312         assertEquals(preForms, forms.getTotalCount());
313 
314         assertTrue(client.getService(UserRequestService.class).
315                 listRequests(new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().isEmpty());
316     }
317 
318     @Test
319     public void invalid() throws IOException {
320         WebClient.client(BPMN_PROCESS_SERVICE).type(MediaType.APPLICATION_XML_TYPE);
321         try {
322             BPMN_PROCESS_SERVICE.set("invalid",
323                     IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/invalidRequest.bpmn20.xml")));
324             fail();
325         } catch (SyncopeClientException e) {
326             assertEquals(ClientExceptionType.Workflow, e.getType());
327         }
328     }
329 }