1919 * =====
2020 */
2121
22+ import com .fasterxml .jackson .databind .ObjectMapper ;
2223import com .walmartlabs .concord .client2 .*;
2324import org .junit .jupiter .api .BeforeAll ;
2425import org .junit .jupiter .api .Test ;
2526
2627import javax .naming .Context ;
2728import javax .naming .NameAlreadyBoundException ;
2829import javax .naming .directory .*;
30+ import java .io .InputStream ;
31+ import java .net .URI ;
32+ import java .net .http .HttpClient ;
33+ import java .net .http .HttpRequest ;
34+ import java .net .http .HttpResponse ;
35+ import java .util .Base64 ;
36+ import java .util .Map ;
2937import java .util .Properties ;
38+ import java .util .UUID ;
3039
3140import static com .walmartlabs .concord .it .common .ITUtils .archive ;
3241import static com .walmartlabs .concord .it .common .ServerClient .assertLog ;
3342import static com .walmartlabs .concord .it .common .ServerClient .waitForCompletion ;
43+ import static com .walmartlabs .concord .it .common .ServerClient .waitForStatus ;
3444import static org .junit .jupiter .api .Assertions .assertEquals ;
3545import static org .junit .jupiter .api .Assertions .assertFalse ;
3646import static org .junit .jupiter .api .Assertions .assertNotNull ;
47+ import static org .junit .jupiter .api .Assertions .assertThrows ;
3748import static org .junit .jupiter .api .Assertions .assertTrue ;
3849import static org .junit .jupiter .api .Assumptions .assumeTrue ;
3950
@@ -44,6 +55,7 @@ public class LdapIT extends AbstractServerIT {
4455 private static final String GROUP_OU = "ou=groups,dc=example,dc=org" ;
4556 private static final String USER_OU = "ou=users,dc=example,dc=org" ;
4657 private static DirContext ldapCtx ;
58+ private static final HttpClient HTTP_CLIENT = HttpClient .newBuilder ().build ();
4759
4860 @ BeforeAll
4961 public static void createLdapStructure () throws Exception {
@@ -92,7 +104,6 @@ public void testLdapUserGroups() throws Exception {
92104 byte [] ab = getLog (pir .getInstanceId ());
93105 String groupDn = "cn=" + groupName + "," + GROUP_OU ;
94106 assertLog (".*" + groupDn + ".*" , ab );
95-
96107 }
97108
98109 @ Test
@@ -136,6 +147,140 @@ void testDisableLdapUser() throws Exception {
136147 assertTrue (ue .getPermanentlyDisabled ());
137148 }
138149
150+ @ Test
151+ void testSubmitFormRunAsGroupWithApiKey () throws Exception {
152+ // create users in ldap
153+ String noGroupUser = "noGroupUser" + randomString ();
154+ createLdapUser (noGroupUser );
155+
156+ String username = "runAsUser" + randomString ();
157+ createLdapUser (username );
158+
159+ // create group
160+ String groupName = "RunAsGroup" + randomString ();
161+ createLdapGroupWithUser (groupName , username );
162+
163+ UsersApi usersApi = new UsersApi (getApiClient ());
164+ usersApi .createOrUpdateUser (new CreateUserRequest ()
165+ .username (username )
166+ .type (CreateUserRequest .TypeEnum .LDAP ));
167+ usersApi .createOrUpdateUser (new CreateUserRequest ()
168+ .username (noGroupUser )
169+ .type (CreateUserRequest .TypeEnum .LDAP ));
170+
171+ String noGroupApiKey = createApiKey (noGroupUser );
172+ String validUserApiKey = createApiKey (username );
173+
174+ setApiKey (validUserApiKey );
175+
176+ // --- execute form
177+
178+ byte [] payload = archive (LdapIT .class .getResource ("ldapFormRunAs" ).toURI ());
179+ StartProcessResponse spr = start (Map .of (
180+ "archive" , payload ,
181+ "arguments.ldapGroupName" , groupName
182+ ));
183+ assertNotNull (spr .getInstanceId ());
184+
185+
186+ // ---
187+
188+ ProcessEntry pir = waitForStatus (getApiClient (), spr .getInstanceId (), ProcessEntry .StatusEnum .SUSPENDED );
189+
190+ // --- try to get with user not in group (expect no permission)
191+
192+ ApiException noGroupEx = assertThrows (ApiException .class , () ->
193+ new ProcessFormsApi (getApiClientForKey (noGroupApiKey )).getProcessForm (pir .getInstanceId (), "myForm" ));
194+
195+ assertEquals (403 , noGroupEx .getCode ());
196+ assertTrue (noGroupEx .getMessage ().contains ("doesn't have the necessary permissions to resume process. Expected LDAP group(s) '[CN=RunAsGroup" ));
197+
198+ // --- get form with user in expected ldap group
199+
200+ ProcessFormsApi formsApi = new ProcessFormsApi (getApiClientForKey (validUserApiKey ));
201+
202+ FormInstanceEntry form = formsApi .getProcessForm (pir .getInstanceId (), "myForm" );
203+
204+ assertEquals ("myForm" , form .getName ());
205+ assertEquals (1 , form .getFields ().size ());
206+ assertEquals ("inputName" , form .getFields ().get (0 ).getName ());
207+ assertEquals ("string" , form .getFields ().get (0 ).getType ());
208+
209+ // --- submit form with user in expected ldap group
210+
211+ formsApi .submitForm (pir .getInstanceId (), "myForm" , Map .of ("inputName" , "testuser" ));
212+
213+ waitForStatus (getApiClient (), spr .getInstanceId (), ProcessEntry .StatusEnum .FINISHED );
214+
215+ byte [] ab = getLog (pir .getInstanceId ());
216+ assertLog (".*Submitted name: testuser.*" , ab );
217+ }
218+
219+ @ Test
220+ void testSubmitFormRunAsGroupWithPassword () throws Exception {
221+ // create users in ldap
222+ String noGroupUser = "noGroupUser" + randomString ();
223+ createLdapUser (noGroupUser );
224+
225+ String username = "runAsUser" + randomString ();
226+ createLdapUser (username );
227+
228+ // create group
229+ String groupName = "RunAsGroup" + randomString ();
230+ createLdapGroupWithUser (groupName , username );
231+
232+ UsersApi usersApi = new UsersApi (getApiClient ());
233+ usersApi .createOrUpdateUser (new CreateUserRequest ()
234+ .username (username )
235+ .type (CreateUserRequest .TypeEnum .LDAP ));
236+ usersApi .createOrUpdateUser (new CreateUserRequest ()
237+ .username (noGroupUser )
238+ .type (CreateUserRequest .TypeEnum .LDAP ));
239+
240+ String validUserApiKey = createApiKey (username );
241+
242+ setApiKey (validUserApiKey );
243+
244+ // --- execute form
245+
246+ byte [] payload = archive (LdapIT .class .getResource ("ldapFormRunAs" ).toURI ());
247+ StartProcessResponse spr = start (Map .of (
248+ "archive" , payload ,
249+ "arguments.ldapGroupName" , groupName
250+ ));
251+ assertNotNull (spr .getInstanceId ());
252+
253+ // ---
254+
255+ ProcessEntry pir = waitForStatus (getApiClient (), spr .getInstanceId (), ProcessEntry .StatusEnum .SUSPENDED );
256+
257+ // --- try to get with user not in group (expect no permission)
258+
259+ ApiException noGroupEx = assertThrows (ApiException .class , () ->
260+ getFormHttpClient (getApiClient ().getBaseUrl (), pir .getInstanceId (), "myForm" , noGroupUser , noGroupUser ));
261+
262+ assertEquals (403 , noGroupEx .getCode ());
263+ assertTrue (noGroupEx .getResponseBody ().contains ("doesn't have the necessary permissions to resume process. Expected LDAP group(s) '[CN=RunAsGroup" ));
264+
265+ // --- get form with user in expected ldap group
266+
267+ FormInstanceEntry form = getFormHttpClient (getApiClient ().getBaseUrl (), pir .getInstanceId (), "myForm" , username , username );
268+
269+ assertEquals ("myForm" , form .getName ());
270+ assertEquals (1 , form .getFields ().size ());
271+ assertEquals ("inputName" , form .getFields ().get (0 ).getName ());
272+ assertEquals ("string" , form .getFields ().get (0 ).getType ());
273+
274+ // --- submit form with user in expected ldap group
275+
276+ submitFormHttpClient (getApiClient ().getBaseUrl (), pir .getInstanceId (), "myForm" , Map .of ("inputName" , "testuser" ), username , username );
277+
278+ waitForStatus (getApiClient (), spr .getInstanceId (), ProcessEntry .StatusEnum .FINISHED );
279+
280+ byte [] ab = getLog (pir .getInstanceId ());
281+ assertLog (".*Submitted name: testuser.*" , ab );
282+ }
283+
139284 public static DirContext createContext () throws Exception {
140285 String url = System .getenv ("IT_LDAP_URL" );
141286 String connectionType = "simple" ;
@@ -176,6 +321,7 @@ private static void createLdapUser(String username) throws Exception {
176321 Attribute uid = new BasicAttribute ("uid" , username );
177322 Attribute cn = new BasicAttribute (COMMON_NAME , username );
178323 Attribute sn = new BasicAttribute ("sn" , username );
324+ Attribute userPassword = new BasicAttribute ("userPassword" , username );
179325
180326 Attribute objectClass = new BasicAttribute (OBJECT_CLASS );
181327 objectClass .add ("top" );
@@ -186,6 +332,7 @@ private static void createLdapUser(String username) throws Exception {
186332 attributes .put (uid );
187333 attributes .put (cn );
188334 attributes .put (sn );
335+ attributes .put (userPassword );
189336 attributes .put (objectClass );
190337
191338 try {
@@ -216,4 +363,49 @@ private static void createLdapGroupWithUser(String groupName, String username) t
216363 // already exists, ignore
217364 }
218365 }
366+
367+ private String createApiKey (String username ) throws Exception {
368+ ApiKeysApi apiKeyResource = new ApiKeysApi (getApiClient ());
369+ CreateApiKeyResponse cakr = apiKeyResource .createUserApiKey (new CreateApiKeyRequest ()
370+ .username (username )
371+ .userType (CreateApiKeyRequest .UserTypeEnum .LDAP ));
372+
373+ return cakr .getKey ();
374+ }
375+
376+ private FormInstanceEntry getFormHttpClient (String baseUrl , UUID instanceId , String formName , String username , String password ) throws Exception {
377+ HttpRequest req = HttpRequest .newBuilder (URI .create (baseUrl + "/api/v1/process/" + instanceId + "/form/" + formName ))
378+ .GET ()
379+ .header ("Authorization" , "Basic " + Base64 .getEncoder ().encodeToString ((username + ":" + password ).getBytes ()))
380+ .build ();
381+
382+ HttpResponse <InputStream > resp = HTTP_CLIENT .send (req , HttpResponse .BodyHandlers .ofInputStream ());
383+
384+ try (InputStream is = resp .body ()) {
385+ if (resp .statusCode () != 200 ) {
386+ throw new ApiException (resp .statusCode (), resp .headers (), new String (is .readAllBytes ()));
387+ }
388+
389+ return new ObjectMapper ().readValue (resp .body (), FormInstanceEntry .class );
390+ }
391+ }
392+
393+ private void submitFormHttpClient (String baseUrl , UUID instanceId , String formName , Map <String , Object > data , String username , String password ) throws Exception {
394+ ObjectMapper mapper = new ObjectMapper ();
395+ String requestBody = mapper .writeValueAsString (data );
396+
397+ HttpRequest req = HttpRequest .newBuilder (URI .create (baseUrl + "/api/v1/process/" + instanceId + "/form/" + formName ))
398+ .POST (HttpRequest .BodyPublishers .ofString (requestBody ))
399+ .header ("Content-Type" , "application/json" )
400+ .header ("Authorization" , "Basic " + Base64 .getEncoder ().encodeToString ((username + ":" + password ).getBytes ()))
401+ .build ();
402+
403+ HttpResponse <InputStream > resp = HTTP_CLIENT .send (req , HttpResponse .BodyHandlers .ofInputStream ());
404+
405+ try (InputStream is = resp .body ()) {
406+ if (resp .statusCode () != 200 ) {
407+ throw new ApiException (resp .statusCode (), resp .headers (), new String (resp .body ().readAllBytes ()));
408+ }
409+ }
410+ }
219411}
0 commit comments