Skip to content

Commit 6a934d4

Browse files
author
nianiB9
authoredApr 11, 2025
Merge pull request #154 from docusign/feature/added-set-connected-fields-example
Set connected fields example
2 parents 3ae925d + 73b6dc1 commit 6a934d4

File tree

14 files changed

+559
-22
lines changed

14 files changed

+559
-22
lines changed
 

‎pom.xml

+37-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<oauth2.version>2.5.6</oauth2.version>
2727
<commonsio.version>2.16.1</commonsio.version>
2828

29-
<esignature.version>6.0.0</esignature.version>
29+
<esignature.version>6.1.0-RC1</esignature.version>
3030
<rooms.version>1.4.3</rooms.version>
3131
<click.version>1.5.0</click.version>
3232
<monitor.version>1.4.0</monitor.version>
@@ -63,8 +63,9 @@
6363
<groupId>org.projectlombok</groupId>
6464
<artifactId>lombok</artifactId>
6565
<version>1.18.34</version>
66-
<optional>true</optional>
66+
<scope>provided</scope>
6767
</dependency>
68+
6869
<dependency>
6970
<groupId>org.apache.commons</groupId>
7071
<artifactId>commons-lang3</artifactId>
@@ -224,6 +225,22 @@
224225
</configuration>
225226
</plugin>
226227

228+
<plugin>
229+
<groupId>org.apache.maven.plugins</groupId>
230+
<artifactId>maven-compiler-plugin</artifactId>
231+
<configuration>
232+
<source>${java.version}</source>
233+
<target>${java.version}</target>
234+
<annotationProcessorPaths>
235+
<path>
236+
<groupId>org.projectlombok</groupId>
237+
<artifactId>lombok</artifactId>
238+
<version>1.18.34</version>
239+
</path>
240+
</annotationProcessorPaths>
241+
</configuration>
242+
</plugin>
243+
227244
<plugin>
228245
<groupId>org.apache.maven.plugins</groupId>
229246
<artifactId>maven-checkstyle-plugin</artifactId>
@@ -275,6 +292,24 @@
275292
<version>5.7.12</version>
276293
</dependency>
277294

295+
<dependency>
296+
<groupId>org.glassfish.jersey.core</groupId>
297+
<artifactId>jersey-client</artifactId>
298+
<version>${jersey2.version}</version>
299+
</dependency>
300+
301+
<dependency>
302+
<groupId>org.glassfish.jersey.inject</groupId>
303+
<artifactId>jersey-hk2</artifactId>
304+
<version>${jersey2.version}</version>
305+
</dependency>
306+
307+
<dependency>
308+
<groupId>org.glassfish.jersey.core</groupId>
309+
<artifactId>jersey-common</artifactId>
310+
<version>${jersey2.version}</version>
311+
</dependency>
312+
278313
<dependency>
279314
<groupId>ch.qos.logback</groupId>
280315
<artifactId>logback-core</artifactId>

‎src/main/java/com/docusign/common/ApiIndex.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ public enum ApiIndex {
88
ADMIN("/pages/admin/index", "/management", "/a001", "/a"),
99
CONNECT("/pages/connect/index", "", "/con001", "/con"),
1010
NOTARY("/pages/notary/index", "/restapi", "/n004", "/n"),
11-
WEBFORMS("/pages/webforms/index", "/restapi", "/web001", "/web");
11+
WEBFORMS("/pages/webforms/index", "/restapi", "/web001", "/web"),
12+
CONNECTEDFIELDS("/pages/connectedfields/index", "/restapi", "/cf001", "/cf");
1213

1314
private final String indexPath;
1415

‎src/main/java/com/docusign/common/WorkArguments.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import java.util.UUID;
99

10-
1110
@Component
1211
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
1312
@Data
@@ -66,6 +65,8 @@ public class WorkArguments {
6665

6766
private String profileId;
6867

68+
private String appId;
69+
6970
private String groupId;
7071

7172
private String permissionProfileName;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.docusign.controller.connectedFields.examples;
2+
3+
import com.docusign.DSConfiguration;
4+
import com.docusign.esign.api.EnvelopesApi;
5+
import com.docusign.esign.client.ApiClient;
6+
import com.docusign.core.controller.AbstractController;
7+
import com.docusign.core.model.Session;
8+
import com.docusign.core.model.User;
9+
import org.springframework.http.HttpHeaders;
10+
import org.springframework.stereotype.Controller;
11+
12+
/**
13+
* Abstract base class for all Connected fields controllers.
14+
*/
15+
@Controller
16+
public abstract class AbstractConnectedFieldsController extends AbstractController {
17+
18+
private static final String EXAMPLE_PAGES_PATH = "pages/connectedfields/examples/";
19+
20+
protected final User user;
21+
22+
protected final Session session;
23+
24+
public AbstractConnectedFieldsController(DSConfiguration config, String exampleName, User user, Session session) {
25+
super(config, exampleName);
26+
this.user = user;
27+
this.session = session;
28+
}
29+
30+
/**
31+
* Creates new instance of the eSignature API client.
32+
*
33+
* @param accessToken user's access token
34+
* @param basePath basePath to the server
35+
* @return an instance of the {@link ApiClient}
36+
*/
37+
protected static ApiClient createApiClient(
38+
String accessToken,
39+
String basePath) {
40+
ApiClient apiClient = new ApiClient(basePath);
41+
apiClient.addDefaultHeader(
42+
HttpHeaders.AUTHORIZATION,
43+
BEARER_AUTHENTICATION + accessToken);
44+
45+
return apiClient;
46+
}
47+
48+
/**
49+
* Creates a new instance of the EnvelopesApi. This method
50+
* creates an instance of the EnvelopesApi class silently.
51+
*
52+
* @param accessToken user's access token
53+
* @param basePath basePath to the server
54+
* @return an instance of the {@link EnvelopesApi}
55+
*/
56+
protected EnvelopesApi createEnvelopesApi(String basePath, String userAccessToken) {
57+
ApiClient apiClient = createApiClient(userAccessToken, basePath);
58+
return new EnvelopesApi(apiClient);
59+
}
60+
61+
protected String getExamplePagesPath() {
62+
return AbstractConnectedFieldsController.EXAMPLE_PAGES_PATH;
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.docusign.controller.connectedFields.examples;
2+
3+
import com.docusign.DSConfiguration;
4+
import com.docusign.admin.client.ApiException;
5+
import com.docusign.common.WorkArguments;
6+
import com.docusign.controller.connectedFields.services.SetConnectedFieldsService;
7+
import com.docusign.core.model.DoneExample;
8+
import com.docusign.core.model.Session;
9+
import com.docusign.core.model.User;
10+
import com.docusign.esign.api.EnvelopesApi;
11+
import com.docusign.esign.model.EnvelopeDefinition;
12+
import com.docusign.esign.model.EnvelopeSummary;
13+
import com.fasterxml.jackson.databind.JsonNode;
14+
15+
import org.springframework.stereotype.Controller;
16+
import org.springframework.ui.ModelMap;
17+
import org.springframework.web.bind.annotation.RequestMapping;
18+
import org.slf4j.Logger;
19+
import org.slf4j.LoggerFactory;
20+
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
import javax.servlet.http.HttpServletResponse;
25+
26+
/**
27+
* This example demonstrates how to set connected fields from extension.
28+
*/
29+
@Controller
30+
@RequestMapping("/cf001")
31+
public class CF001SetConnectedFields extends AbstractConnectedFieldsController {
32+
33+
private static final Logger LOGGER = LoggerFactory.getLogger(CF001SetConnectedFields.class);
34+
35+
private static final String MODEL_APPS_LIST = "appsList";
36+
37+
public CF001SetConnectedFields(DSConfiguration config, Session session, User user) {
38+
super(config, "cf001", user, session);
39+
}
40+
41+
@Override
42+
protected void onInitModel(WorkArguments args, ModelMap model) throws Exception {
43+
44+
try {
45+
super.onInitModel(args, model);
46+
47+
String extensionApps = SetConnectedFieldsService.getConnectedFieldsTabGroups(
48+
session.getAccountId(),
49+
user.getAccessToken());
50+
String filteredExtensionApps = SetConnectedFieldsService.filterData(extensionApps);
51+
this.session.setExtensionApps(filteredExtensionApps);
52+
53+
List<Map<String, String>> appsList = SetConnectedFieldsService.convertJsonToList(filteredExtensionApps);
54+
model.addAttribute(MODEL_APPS_LIST, appsList);
55+
} catch (ApiException e) {
56+
LOGGER.info(String.valueOf(e));
57+
}
58+
}
59+
60+
@Override
61+
protected Object doWork(WorkArguments args, ModelMap model, HttpServletResponse response) throws Exception {
62+
63+
JsonNode extensionApp = SetConnectedFieldsService.findAppById(
64+
this.session.getExtensionApps(),
65+
args.getAppId());
66+
67+
EnvelopesApi envelopesApi = createEnvelopesApi(session.getBasePath(), user.getAccessToken());
68+
69+
EnvelopeDefinition envelope = SetConnectedFieldsService.makeEnvelope(
70+
args.getSignerEmail(),
71+
args.getSignerName(),
72+
extensionApp);
73+
EnvelopeSummary envelopeSummary = SetConnectedFieldsService.signingViaEmail(
74+
envelopesApi,
75+
session.getAccountId(),
76+
envelope);
77+
78+
DoneExample.createDefault(getTextForCodeExampleByApiType().ExampleName)
79+
.withMessage(getTextForCodeExampleByApiType().ResultsPageText
80+
.replaceFirst("\\{0}", envelopeSummary.getEnvelopeId()))
81+
.addToModel(model, config);
82+
return DONE_EXAMPLE_PAGE;
83+
}
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
package com.docusign.controller.connectedFields.services;
2+
3+
import com.docusign.controller.eSignature.examples.EnvelopeHelpers;
4+
import com.docusign.esign.api.EnvelopesApi;
5+
import com.docusign.esign.client.ApiException;
6+
import com.docusign.esign.model.ConnectionInstance;
7+
import com.docusign.esign.model.Document;
8+
import com.docusign.esign.model.EnvelopeDefinition;
9+
import com.docusign.esign.model.EnvelopeSummary;
10+
import com.docusign.esign.model.ExtensionData;
11+
import com.docusign.esign.model.Recipients;
12+
import com.docusign.esign.model.SignHere;
13+
import com.docusign.esign.model.Signer;
14+
import com.docusign.esign.model.Tabs;
15+
import com.docusign.esign.model.Text;
16+
import com.fasterxml.jackson.databind.JsonNode;
17+
import com.fasterxml.jackson.databind.ObjectMapper;
18+
import com.fasterxml.jackson.databind.node.ArrayNode;
19+
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
20+
21+
import java.io.IOException;
22+
import java.net.URI;
23+
import java.net.http.HttpClient;
24+
import java.net.http.HttpRequest;
25+
import java.net.http.HttpResponse;
26+
import java.util.ArrayList;
27+
import java.util.Collections;
28+
import java.util.HashMap;
29+
import java.util.List;
30+
import java.util.Map;
31+
32+
public class SetConnectedFieldsService {
33+
private static final String ACTION_CONTRACT = "actionContract";
34+
35+
private static final String TAB_LABEL = "tabLabel";
36+
37+
private static final String APPLICATION_NAME = "applicationName";
38+
39+
private static final String EXTENSION_DATA = "extensionData";
40+
41+
private static final String TABS = "tabs";
42+
43+
private static final String APP_ID = "appId";
44+
45+
private static final String EXPECTED_A_JSON_ARRAY = "Expected a JSON array";
46+
47+
private static final HttpClient client = HttpClient.newHttpClient();
48+
49+
private static final ObjectMapper objectMapper = new ObjectMapper();
50+
51+
private static final String PDF_DOCUMENT_FILE_NAME = "World_Wide_Corp_lorem.pdf";
52+
53+
private static final String PDF_DOCUMENT_NAME = "Lorem Ipsum";
54+
55+
public static EnvelopeSummary signingViaEmail(
56+
EnvelopesApi envelopesApi,
57+
String accountId,
58+
EnvelopeDefinition envelope) throws ApiException {
59+
return envelopesApi.createEnvelope(accountId, envelope);
60+
}
61+
62+
public static String getConnectedFieldsTabGroups(String accountId, String accessToken) throws Exception {
63+
String url = String.format(
64+
"https://api-d.docusign.com/v1/accounts/%s/connected-fields/tab-groups",
65+
accountId);
66+
67+
HttpRequest request = HttpRequest.newBuilder()
68+
.uri(URI.create(url))
69+
.GET()
70+
.header("Authorization", "Bearer " + accessToken)
71+
.header("Accept", "application/json")
72+
.build();
73+
74+
try {
75+
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
76+
77+
if (response.statusCode() >= 200 && response.statusCode() < 300) {
78+
return response.body();
79+
} else {
80+
throw new IOException("Unexpected response code: " + response.statusCode());
81+
}
82+
} catch (IOException | InterruptedException e) {
83+
throw new Exception("DocuSign API Request failed: " + e.getMessage(), e);
84+
}
85+
}
86+
87+
public static EnvelopeDefinition makeEnvelope(String signerEmail, String signerName, JsonNode selectedApp)
88+
throws Exception {
89+
String appId = selectedApp.has(APP_ID) ? selectedApp.get(APP_ID).asText() : "";
90+
JsonNode tabLabels = selectedApp.get(TABS);
91+
92+
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
93+
envelopeDefinition.setEmailSubject("Please sign this document set");
94+
envelopeDefinition.setStatus("sent");
95+
96+
Document document = EnvelopeHelpers.createDocumentFromFile(
97+
PDF_DOCUMENT_FILE_NAME,
98+
PDF_DOCUMENT_NAME,
99+
"1");
100+
101+
envelopeDefinition.setDocuments(Collections.singletonList(document));
102+
103+
Signer signer = new Signer();
104+
signer.setEmail(signerEmail);
105+
signer.setName(signerName);
106+
signer.setRecipientId("1");
107+
signer.setRoutingOrder("1");
108+
109+
SignHere signHere = new SignHere();
110+
signHere.setAnchorString("/sn1/");
111+
signHere.setAnchorUnits("pixels");
112+
signHere.setAnchorYOffset("10");
113+
signHere.setAnchorXOffset("20");
114+
115+
List<Text> textTabs = new ArrayList<Text>();
116+
117+
if (tabLabels != null && tabLabels.isArray()) {
118+
for (JsonNode tab : tabLabels) {
119+
JsonNode extensionData = tab.get(EXTENSION_DATA);
120+
121+
String connectionKey = "";
122+
String connectionValue = "";
123+
124+
JsonNode connectionInstances = extensionData != null ? extensionData.get("connectionInstances") : null;
125+
if (connectionInstances != null && connectionInstances.isArray() && connectionInstances.size() > 0) {
126+
JsonNode firstInstance = connectionInstances.get(0);
127+
connectionKey = getText(firstInstance, "connectionKey");
128+
connectionValue = getText(firstInstance, "connectionValue");
129+
}
130+
131+
String extensionGroupId = getText(extensionData, "extensionGroupId");
132+
String publisherName = getText(extensionData, "publisherName");
133+
String applicationName = getText(extensionData, APPLICATION_NAME);
134+
String actionName = getText(extensionData, "actionName");
135+
String actionInputKey = getText(extensionData, "actionInputKey");
136+
String actionContract = getText(extensionData, ACTION_CONTRACT);
137+
String extensionName = getText(extensionData, "extensionName");
138+
String extensionContract = getText(extensionData, "extensionContract");
139+
String requiredForExtension = getText(extensionData, "requiredForExtension");
140+
String tabLabel = getText(tab, TAB_LABEL);
141+
142+
Text textTab = new Text();
143+
textTab.setRequireInitialOnSharedChange("false");
144+
textTab.setRequireAll("false");
145+
textTab.setName(applicationName);
146+
textTab.setRequired("false");
147+
textTab.setLocked("false");
148+
textTab.setDisableAutoSize("false");
149+
textTab.setMaxLength("4000");
150+
textTab.setTabLabel(tabLabel);
151+
textTab.setFont("lucidaconsole");
152+
textTab.setFontColor("black");
153+
textTab.setFontSize("size9");
154+
textTab.setDocumentId("1");
155+
textTab.setRecipientId("1");
156+
textTab.setPageNumber("1");
157+
textTab.setXPosition("273");
158+
textTab.setYPosition("191");
159+
textTab.setWidth("84");
160+
textTab.setHeight("22");
161+
textTab.setTemplateRequired("false");
162+
textTab.setTabType("text");
163+
164+
ExtensionData extension = new ExtensionData();
165+
extension.setExtensionGroupId(extensionGroupId);
166+
extension.setPublisherName(publisherName);
167+
extension.setApplicationId(appId);
168+
extension.setApplicationName(applicationName);
169+
extension.setActionName(actionName);
170+
extension.setActionContract(actionContract);
171+
extension.setExtensionName(extensionName);
172+
extension.setExtensionContract(extensionContract);
173+
extension.setRequiredForExtension(requiredForExtension);
174+
extension.setActionInputKey(actionInputKey);
175+
extension.setExtensionPolicy("None");
176+
177+
ConnectionInstance connectionInstance = new ConnectionInstance();
178+
connectionInstance.setConnectionKey(connectionKey);
179+
connectionInstance.setConnectionValue(connectionValue);
180+
extension.setConnectionInstances(Collections.singletonList(connectionInstance));
181+
182+
textTab.setExtensionData(extension);
183+
textTabs.add(textTab);
184+
}
185+
}
186+
187+
Tabs tabs = new Tabs();
188+
tabs.setSignHereTabs(Collections.singletonList(signHere));
189+
tabs.setTextTabs(textTabs);
190+
signer.setTabs(tabs);
191+
192+
Recipients recipients = new Recipients();
193+
recipients.setSigners(Collections.singletonList(signer));
194+
envelopeDefinition.setRecipients(recipients);
195+
196+
return envelopeDefinition;
197+
}
198+
199+
public static List<Map<String, String>> convertJsonToList(String jsonString) throws Exception {
200+
JsonNode root = objectMapper.readTree(jsonString);
201+
List<Map<String, String>> result = new ArrayList<>();
202+
203+
if (root.isArray()) {
204+
for (JsonNode app : root) {
205+
String appId = app.has(APP_ID) ? app.get(APP_ID).asText() : null;
206+
String applicationName = "";
207+
208+
JsonNode tabs = app.get(TABS);
209+
if (tabs != null && tabs.isArray() && tabs.size() > 0) {
210+
JsonNode extensionData = tabs.get(0).get(EXTENSION_DATA);
211+
if (extensionData != null && extensionData.has(APPLICATION_NAME)) {
212+
applicationName = extensionData.get(APPLICATION_NAME).asText();
213+
}
214+
}
215+
216+
if (appId != null && applicationName != null) {
217+
Map<String, String> map = new HashMap<>();
218+
map.put(APP_ID, appId);
219+
map.put(APPLICATION_NAME, applicationName);
220+
result.add(map);
221+
}
222+
}
223+
}
224+
225+
return result;
226+
}
227+
228+
private static String getText(JsonNode node, String fieldName) {
229+
return node != null && node.has(fieldName) ? node.get(fieldName).asText() : "";
230+
}
231+
232+
public static String filterData(String jsonData) throws Exception {
233+
JsonNode rootNode = objectMapper.readTree(jsonData);
234+
235+
if (!rootNode.isArray()) {
236+
throw new IllegalArgumentException(EXPECTED_A_JSON_ARRAY);
237+
}
238+
239+
ArrayNode filteredArray = JsonNodeFactory.instance.arrayNode();
240+
241+
for (JsonNode item : rootNode) {
242+
JsonNode tabs = item.get(TABS);
243+
244+
if (tabs != null && tabs.isArray()) {
245+
for (JsonNode tab : tabs) {
246+
JsonNode extensionData = tab.get(EXTENSION_DATA);
247+
String tabLabel = tab.has(TAB_LABEL) ? tab.get(TAB_LABEL).asText() : null;
248+
249+
boolean hasVerify = extensionData != null &&
250+
extensionData.has(ACTION_CONTRACT) &&
251+
extensionData.get(ACTION_CONTRACT).asText().contains("Verify");
252+
253+
boolean hasConnectedData = tabLabel != null && tabLabel.contains("connecteddata");
254+
255+
if (hasVerify || hasConnectedData) {
256+
filteredArray.add(item);
257+
break;
258+
}
259+
}
260+
}
261+
}
262+
263+
return objectMapper.writeValueAsString(filteredArray);
264+
}
265+
266+
public static JsonNode findAppById(String extensionAppsJson, String appId) throws Exception {
267+
JsonNode root = objectMapper.readTree(extensionAppsJson);
268+
if (!root.isArray()) {
269+
throw new IllegalArgumentException(EXPECTED_A_JSON_ARRAY);
270+
}
271+
272+
for (JsonNode app : root) {
273+
JsonNode appIdNode = app.get(APP_ID);
274+
if (appIdNode != null && appId.equals(appIdNode.asText())) {
275+
return app;
276+
}
277+
}
278+
279+
return null;
280+
}
281+
}

‎src/main/java/com/docusign/core/controller/AbstractController.java

+18-15
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import java.util.List;
2929
import java.util.Objects;
3030

31-
3231
/**
3332
* Abstract base class for all controllers. It handles all requests which are
3433
* registered by the derived classes and delegates an example specific action
@@ -104,7 +103,8 @@ public String get(WorkArguments args, ModelMap model) {
104103
return REDIRECT_AUTHENTICATION_PAGE;
105104
}
106105

107-
if(ApiType.giveTypeByName(this.exampleName) == ApiType.MONITOR && session.getAuthTypeSelected() != AuthType.JWT){
106+
if (ApiType.giveTypeByName(this.exampleName) == ApiType.MONITOR
107+
&& session.getAuthTypeSelected() != AuthType.JWT) {
108108
session.setMonitorExampleRedirect("/" + this.exampleName);
109109
return REDIRECT_AUTHENTICATION_PAGE;
110110
}
@@ -113,7 +113,8 @@ public String get(WorkArguments args, ModelMap model) {
113113
onInitModel(args, model);
114114
return pagePath;
115115
} catch (Exception exception) {
116-
if (config.getQuickstart().equals("true") && exception.getMessage() == config.getCodeExamplesText().getSupportingTexts().getCFRError()) {
116+
if (config.getQuickstart().equals("true")
117+
&& exception.getMessage() == config.getCodeExamplesText().getSupportingTexts().getCFRError()) {
117118
config.setQuickstart("false");
118119
return handleRedirectToCfr(model);
119120
} else {
@@ -152,8 +153,7 @@ protected void onInitModel(WorkArguments args, ModelMap model) throws Exception
152153
String viewSourceFile = config.getCodeExamplesText().SupportingTexts
153154
.getViewSourceFile().replaceFirst(
154155
"\\{0}",
155-
"<a target='_blank' href='" + srcPath + "'>" + clazz.getSimpleName() + ".java" + "</a>"
156-
);
156+
"<a target='_blank' href='" + srcPath + "'>" + clazz.getSimpleName() + ".java" + "</a>");
157157
model.addAttribute("csrfToken", "");
158158
model.addAttribute("title", title);
159159
model.addAttribute("viewSourceFile", viewSourceFile);
@@ -164,8 +164,9 @@ protected void onInitModel(WorkArguments args, ModelMap model) throws Exception
164164

165165
public void setTheCurrentApiTypeAndBaseUrl() {
166166
config.setSelectedApiType(ApiType.giveTypeByName(this.exampleName).toString());
167-
String basePath = session.getOauthAccount() != null ?
168-
this.config.getBaseUrl(config.getSelectedApiIndex(), session.getOauthAccount()) + config.getSelectedApiIndex().getBaseUrlSuffix()
167+
String basePath = session.getOauthAccount() != null
168+
? this.config.getBaseUrl(config.getSelectedApiIndex(), session.getOauthAccount())
169+
+ config.getSelectedApiIndex().getBaseUrlSuffix()
169170
: null;
170171
session.setBasePath(basePath);
171172
}
@@ -178,12 +179,14 @@ public void setTheCurrentApiTypeAndBaseUrl() {
178179
* @param model page model holder
179180
* @param response for HTTP-specific functionality in sending a response
180181
* @return {@link Object}. Possible types and values: <code>null</code>,
181-
* {@link String} representation of the URL or Spring RedirectView object,
182-
* (see {@link org.springframework.web.servlet.view.RedirectView RedirectView})
182+
* {@link String} representation of the URL or Spring RedirectView
183+
* object,
184+
* (see {@link org.springframework.web.servlet.view.RedirectView
185+
* RedirectView})
183186
* @throws Exception if calling API has failed or if I/O operation has failed
184187
*/
185188
protected abstract Object doWork(WorkArguments args, ModelMap model,
186-
HttpServletResponse response) throws Exception;
189+
HttpServletResponse response) throws Exception;
187190

188191
private String handleException(Exception exception, ModelMap model) {
189192
model.addAttribute(LAUNCHER_TEXTS, config.getCodeExamplesText().SupportingTexts);
@@ -194,8 +197,9 @@ private String handleException(Exception exception, ModelMap model) {
194197
if (exception != null) {
195198
exceptionMessage = exception.getMessage();
196199
if (model.getAttribute("caseForInstructions") != null) {
197-
fixingInstructions = exceptionMessage.contains((CharSequence) model.getAttribute("caseForInstructions")) ?
198-
(String) model.getAttribute("fixingInstructions") : null;
200+
fixingInstructions = exceptionMessage.contains((CharSequence) model.getAttribute("caseForInstructions"))
201+
? (String) model.getAttribute("fixingInstructions")
202+
: null;
199203
}
200204
}
201205
new DoneExample()
@@ -219,8 +223,7 @@ private boolean isTokenExpired() {
219223
OAuth2User oauthUser = oauth.getPrincipal();
220224
OAuth2AuthorizedClient oauthClient = authorizedClientService.loadAuthorizedClient(
221225
oauth.getAuthorizedClientRegistrationId(),
222-
oauthUser.getName()
223-
);
226+
oauthUser.getName());
224227

225228
if (oauthClient != null) {
226229
OAuth2AccessToken accessToken = oauthClient.getAccessToken();
@@ -237,7 +240,7 @@ private boolean isTokenExpired() {
237240

238241
protected CodeExampleText getTextForCodeExample() {
239242
List<ManifestGroup> manifestGroups = config.getCodeExamplesText().APIs.stream()
240-
.filter(x -> ApiType.giveTypeByName(this.exampleName).name().toLowerCase().contains(x.Name.toLowerCase()))
243+
.filter(x -> ApiType.giveTypeByName(this.exampleName).name().trim().equalsIgnoreCase(x.Name.trim()))
241244
.findFirst()
242245
.orElse(null).Groups;
243246

‎src/main/java/com/docusign/core/controller/IndexController.java

+1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ private String getRedirectURLForJWTAuthentication(HttpServletRequest req, HttpSe
204204
ApiIndex.MONITOR.getExamplesPathCode(),
205205
ApiIndex.ADMIN.getExamplesPathCode(),
206206
ApiIndex.ROOMS.getExamplesPathCode(),
207+
ApiIndex.CONNECTEDFIELDS.getExamplesPathCode()
207208
};
208209

209210
if (savedRequest != null) {

‎src/main/java/com/docusign/core/model/ApiType.java

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public enum ApiType {
1010
"dtr.documents.write", "dtr.profile.read", "dtr.profile.write", "dtr.company.read",
1111
"dtr.company.write", "room_forms" }, "r"),
1212
CONNECT("Connect", new String[] {}, "con"),
13+
CONNECTEDFIELDS("Connected Fields API", new String[] { "signature", "adm_store_unified_repo_read" }, "cf"),
1314
CLICK("Click API", new String[] { "click.manage", "click.send" }, "c"),
1415
MONITOR("Monitor API", new String[] { "signature", "impersonation" }, "m"),
1516
ADMIN("Admin API", new String[] { "user_write", "signature", "impersonation", "group_read", "organization_read",

‎src/main/java/com/docusign/core/model/Session.java

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public class Session implements Serializable {
7171

7272
private String workflowId;
7373

74+
private String extensionApps;
75+
7476
private String instanceId;
7577

7678
private Boolean isPKCEWorking = true;

‎src/main/resources/application.example.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"client-authentication-method": "client_secret_basic",
3131
"authorization-grant-type": "authorization_code",
3232
"redirect-uri": "{baseUrl}/login/oauth2/code/acg",
33-
"scope": "user_write, signature, impersonation, group_read, organization_read, permission_read, user_read, account_read, domain_read, identity_provider_read, user_data_redact, click.manage, click.send, dtr.rooms.read, dtr.rooms.write, dtr.documents.read, dtr.documents.write, dtr.profile.read, dtr.profile.write, dtr.company.read, dtr.company.write, room_forms, asset_group_account_read, asset_group_account_clone_write, asset_group_account_clone_read, webforms_read, webforms_instance_read, webforms_instance_write, aow_manage, organization_sub_account_write, organization_sub_account_read"
33+
"scope": "user_write, signature, impersonation, group_read, organization_read, permission_read, user_read, account_read, domain_read, identity_provider_read, user_data_redact, click.manage, click.send, dtr.rooms.read, dtr.rooms.write, dtr.documents.read, dtr.documents.write, dtr.profile.read, dtr.profile.write, dtr.company.read, dtr.company.write, room_forms, asset_group_account_read, asset_group_account_clone_write, asset_group_account_clone_read, webforms_read, webforms_instance_read, webforms_instance_write, aow_manage, organization_sub_account_write, organization_sub_account_read, adm_store_unified_repo_read"
3434
},
3535
"jwt": {
3636
"client-id": "{INTEGRATION_KEY_JWT}",

‎src/main/resources/public/assets/search.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
ROOMS: 'rooms',
77
ADMIN: 'admin',
88
CONNECT: 'connect',
9-
CONNECT: 'connect',
109
WEBFORMS: 'webforms',
11-
NOTARY: 'notary'
10+
NOTARY: 'notary',
11+
CONNECTEDFIELDS: 'connectedfields',
1212
};
1313

1414
let processJSONData = function () {
@@ -132,6 +132,8 @@
132132
return "web";
133133
case API_TYPES.NOTARY:
134134
return "n";
135+
case API_TYPES.CONNECTEDFIELDS:
136+
return "cf";
135137
}
136138
}
137139

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2+
<jsp:include page="../../../partials/head.jsp" />
3+
4+
<c:set var="formNumber" value="0" scope="page" />
5+
<c:set var="signerEmailInputNumber" value="0" scope="page" />
6+
<c:set var="signerNameInputNumber" value="1" scope="page" />
7+
<c:set var="extensionInputNumber" value="2" scope="page" />
8+
9+
<h4>${example.getExampleName()}</h4>
10+
<p>${example.getExampleDescription()}</p>
11+
<c:if test="${showDoc}">
12+
<p><a target='_blank' href='${documentation}'>Documentation</a> about this example.</p>
13+
</c:if>
14+
15+
<jsp:include page="../../links_to_api_methods.jsp" />
16+
17+
<p>
18+
${viewSourceFile}
19+
</p>
20+
21+
<form class="eg" action="" method="post" data-busy="form">
22+
<div class="form-group">
23+
<label for="signerEmail">
24+
${example.getForms().get(formNumber).getInputs().get(signerEmailInputNumber).getInputName()}
25+
</label>
26+
27+
<input type="email" class="form-control" id="signerEmail" name="signerEmail" aria-describedby="emailHelp"
28+
placeholder="${example.getForms().get(formNumber).getInputs().get(signerEmailInputNumber).getInputPlaceholder()}"
29+
required value="${locals.dsConfig.signerEmail}">
30+
31+
<small id="emailHelp" class="form-text text-muted">
32+
${launcherTexts.getHelpingTexts().getEmailWontBeShared()}
33+
</small>
34+
</div>
35+
<div class="form-group">
36+
<label for="signerName">
37+
${example.getForms().get(formNumber).getInputs().get(signerNameInputNumber).getInputName()}
38+
</label>
39+
40+
<input type="text" class="form-control" id="signerName"
41+
placeholder="${example.getForms().get(formNumber).getInputs().get(signerNameInputNumber).getInputPlaceholder()}"
42+
name="signerName" value="${locals.dsConfig.signerName}" required>
43+
</div>
44+
<div class="form-group">
45+
<label for="apps">
46+
${example.getForms().get(formNumber).getInputs().get(extensionInputNumber).getInputName()}
47+
</label>
48+
49+
<select id="appId" name="appId" class="form-control">
50+
<c:forEach var="app" items="${appsList}">
51+
<option value="${app.appId}">${app.applicationName}</option>
52+
</c:forEach>
53+
</select>
54+
</div>
55+
<input type="hidden" name="_csrf" value="${csrfToken}">
56+
<button type="submit" class="btn btn-docu">${launcherTexts.getSubmitButton()}</button>
57+
</form>
58+
59+
<jsp:include page="../../../partials/foot.jsp" />

‎src/main/webapp/WEB-INF/templates/views/pages/esignature/index.jsp

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
<c:when test="${apis.getName().equals('Notary')}">
5858
<c:set var="linkToCodeExample" value="n" scope="page" />
5959
</c:when>
60+
<c:when test="${apis.getName().equals('ConnectedFields')}">
61+
<c:set var="linkToCodeExample" value="cf" scope="page" />
62+
</c:when>
6063
<c:otherwise>
6164
<c:set var="linkToCodeExample" value="a" scope="page" />
6265
</c:otherwise>

0 commit comments

Comments
 (0)
Please sign in to comment.