Skip to content

Commit bceddc2

Browse files
DD-2023 Missing body entity with Pre-Workflow POST of AuthorizedExternalStep (#11895)
Co-authored-by: Ali Sheikhi <aliassheikh@users.noreply.github.com> Co-authored-by: Jan van Mansum <janvanmansum@gmail.com>
1 parent ad8d686 commit bceddc2

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

src/main/java/edu/harvard/iq/dataverse/workflow/internalspi/AuthorizedExternalStep.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package edu.harvard.iq.dataverse.workflow.internalspi;
22

33
import edu.harvard.iq.dataverse.util.BundleUtil;
4+
import edu.harvard.iq.dataverse.util.json.JsonUtil;
45
import edu.harvard.iq.dataverse.workflow.PendingWorkflowInvocation;
56
import edu.harvard.iq.dataverse.workflow.WorkflowContext;
67
import edu.harvard.iq.dataverse.workflow.WorkflowContext.TriggerType;
@@ -21,7 +22,12 @@
2122
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
2223
import org.apache.hc.client5.http.impl.classic.HttpClients;
2324
import org.apache.hc.core5.http.ClassicHttpRequest;
25+
import org.apache.hc.core5.http.ContentType;
26+
import org.apache.hc.core5.http.HttpEntity;
2427
import org.apache.hc.core5.net.URIBuilder;
28+
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
29+
import org.apache.hc.core5.http.io.entity.StringEntity;
30+
//import org.apache.http.entity.StringEntity;
2531

2632
/**
2733
* A workflow step that sends a HTTP request, and then pauses, waiting for an
@@ -127,7 +133,18 @@ ClassicHttpRequest buildMethod(boolean rollback, WorkflowContext ctxt) throws Ex
127133
}
128134

129135
request.setHeader("Content-Type", params.getOrDefault("contentType", "text/plain"));
130-
136+
137+
138+
String bodyKey = (rollback ? "rollbackBody" : "body");
139+
if (params.containsKey(bodyKey) && (request instanceof HttpPost || request instanceof HttpPut)) {
140+
String body = params.get(bodyKey);
141+
request.setEntity(
142+
new StringEntity(process(body, templateParams),
143+
ContentType.create(request.getFirstHeader("Content-Type").getValue())
144+
)
145+
);
146+
}
147+
131148
return request;
132149
}
133150

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package edu.harvard.iq.dataverse.workflow.internalspi;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import edu.harvard.iq.dataverse.branding.BrandingUtil;
6+
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
7+
import edu.harvard.iq.dataverse.workflow.WorkflowContext;
8+
import org.apache.hc.client5.http.classic.methods.HttpPost;
9+
import org.apache.hc.core5.http.io.entity.StringEntity;
10+
import org.junit.jupiter.api.Test;
11+
12+
import java.lang.reflect.Field;
13+
import java.util.ArrayList;
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
17+
import static org.junit.jupiter.api.Assertions.*;
18+
import static org.mockito.Mockito.*;
19+
20+
class AuthorizedExternalStepTest {
21+
22+
@Test
23+
void testRequestEntityIsSetCorrectly() throws Exception {
24+
// Mock the static field before any code that uses it
25+
// Mock and set BrandingUtil.dataverseService
26+
edu.harvard.iq.dataverse.DataverseServiceBean mockDataverseService = mock(edu.harvard.iq.dataverse.DataverseServiceBean.class);
27+
when(mockDataverseService.getRootDataverseName()).thenReturn("Root");
28+
29+
Field dataverseServiceField = BrandingUtil.class.getDeclaredField("dataverseService");
30+
dataverseServiceField.setAccessible(true);
31+
dataverseServiceField.set(null, mockDataverseService);
32+
33+
SettingsServiceBean mockSettings = mock(SettingsServiceBean.class);
34+
when(mockSettings.getValueForKey(any())).thenReturn(null);
35+
36+
Field field = BrandingUtil.class.getDeclaredField("settingsService");
37+
field.setAccessible(true);
38+
field.set(null, mockSettings);
39+
40+
41+
// Prepare parameters
42+
Map<String, String> params = new HashMap<>();
43+
params.put("method", "POST");
44+
params.put("url", "http://example.com/api");
45+
params.put("contentType", "application/json");
46+
params.put("body", "{\"invocationId\": \"${invocationId}\"}");
47+
48+
// Mock context
49+
WorkflowContext context = mock(WorkflowContext.class);
50+
when(context.getInvocationId()).thenReturn("12345");
51+
when(context.getDataset()).thenReturn(MockDataset.create());
52+
53+
// Create the step
54+
AuthorizedExternalStep step = new AuthorizedExternalStep(params);
55+
56+
57+
// Directly test buildMethod to verify the request entity
58+
HttpPost request = (HttpPost) step.buildMethod(false, context);
59+
StringEntity entity = (StringEntity) request.getEntity();
60+
assertNotNull(entity);
61+
assertEquals("application/json", entity.getContentType());
62+
String body = new String(entity.getContent().readAllBytes());
63+
assertTrue(body.contains("\"invocationId\": \"12345\""));
64+
}
65+
66+
static class MockDataverse extends edu.harvard.iq.dataverse.Dataverse {
67+
@Override
68+
public java.util.List getCitationDatasetFieldTypes() {
69+
return new ArrayList<>();
70+
}
71+
}
72+
73+
// Helper mock dataset
74+
static class MockDataset extends edu.harvard.iq.dataverse.Dataset {
75+
private edu.harvard.iq.dataverse.GlobalId globalId;
76+
private edu.harvard.iq.dataverse.Dataverse owner = mock(edu.harvard.iq.dataverse.Dataverse.class);
77+
78+
static MockDataset create() {
79+
MockDataset ds = new MockDataset();
80+
ds.setId(1L);
81+
ds.setIdentifier("ds1");
82+
ds.globalId = new edu.harvard.iq.dataverse.GlobalId("doi", "10.1234/DS1", null, null, null, null);
83+
return ds;
84+
}
85+
86+
@Override
87+
public edu.harvard.iq.dataverse.GlobalId getGlobalId() {
88+
return globalId;
89+
}
90+
91+
@Override
92+
public edu.harvard.iq.dataverse.Dataverse getOwner() {
93+
return owner;
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)