From e37c0dce86a422de5e8e6ed26fd93f1324f4b3e3 Mon Sep 17 00:00:00 2001 From: Minh Nguyen Cong Date: Tue, 29 Aug 2023 11:23:06 +0200 Subject: [PATCH] feat: Support sign template and new sign status (#1197) --- doc/sign_templates.md | 51 ++ src/main/java/com/box/sdk/BoxSignRequest.java | 71 +- .../box/sdk/BoxSignRequestCreateParams.java | 22 + .../java/com/box/sdk/BoxSignTemplate.java | 621 ++++++++++++++++++ .../BoxSignRequest/CancelSignRequest200.json | 3 +- .../BoxSignRequest/CreateSignRequest200.json | 3 +- .../BoxSignRequest/GetAllSignRequests200.json | 3 +- .../BoxSignRequest/GetSignRequest200.json | 3 +- .../GetAllSignTemplates200.json | 107 +++ .../GetSignTemplateInfo200.json | 100 +++ .../java/com/box/sdk/BoxSignRequestTest.java | 9 + .../java/com/box/sdk/BoxSignTemplateTest.java | 72 ++ 12 files changed, 1040 insertions(+), 25 deletions(-) create mode 100644 doc/sign_templates.md create mode 100644 src/main/java/com/box/sdk/BoxSignTemplate.java create mode 100644 src/test/Fixtures/BoxSignTemplate/GetAllSignTemplates200.json create mode 100644 src/test/Fixtures/BoxSignTemplate/GetSignTemplateInfo200.json create mode 100644 src/test/java/com/box/sdk/BoxSignTemplateTest.java diff --git a/doc/sign_templates.md b/doc/sign_templates.md new file mode 100644 index 000000000..9f2e5d192 --- /dev/null +++ b/doc/sign_templates.md @@ -0,0 +1,51 @@ +Sign Templates +================== + +Box Sign enables you to create templates so you can automatically add the same fields and formatting to requests for signature. With templates, you don't need to repetitively add the same fields to each request every time you send a new document for signature. + +Making and testing a template takes a few minutes, but when done it makes working with Box Sign easier and faster. + + + + +- [Get all Sign Templates](#get-all-sign-templates) +- [Get Sign Template by ID](#get-sign-template-by-id) + + + +Get All Sign Templates +------------------------ + +Calling the static [`getAll(BoxAPIConnection api)`][get-all-sign-templates] +will return an iterable that will page through all the Sign Templates. + +The static +[`getAll(BoxAPIConnection api, int limit)`][get-all-sign-templates-with-limit] +method offers `limit` parameter. The `limit` parameter specifies the maximum number of items to be returned in a single response. + + +```java +Iterable signTemplates = BoxSignTemplate.getAll(api); +for (BoxSignTemplate.Info signTemplateInfo : signTemplates) { + // Do something with each `signTemplateInfo`. +} +``` + +[get-all-sign-templates]: http://opensource.box.com/box-java-sdk/javadoc/com/box/sdk/BoxSignTemplate.html#getAll-com.box.sdk.BoxAPIConnection- +[get-all-sign-templates-with-limit]: http://opensource.box.com/box-java-sdk/javadoc/com/box/sdk/BoxSignTemplate.html#getAll-com.box.sdk.BoxAPIConnection-int- + +Get Sign Template by ID +------------------------ + +Calling [`getInfo()`][get-sign-template-by-id] will return a [`BoxSignTemplate.Info`][box-sign-template-info] object +containing information about the Sign Template. + + + +```java +BoxSignTemplate signTemplate = new BoxSignTemplate(api, id); +BoxSignTemplate.Info signTemplateInfo = signTemplate.getInfo(); +``` + +[get-sign-template-by-id]:http://opensource.box.com/box-java-sdk/javadoc/com/box/sdk/BoxSignTemplate.html#getInfo- +[box-sign-template-info]:http://opensource.box.com/box-java-sdk/javadoc/com/box/sdk/BoxSignTemplate.Info.html diff --git a/src/main/java/com/box/sdk/BoxSignRequest.java b/src/main/java/com/box/sdk/BoxSignRequest.java index 150c256b6..2627c759f 100644 --- a/src/main/java/com/box/sdk/BoxSignRequest.java +++ b/src/main/java/com/box/sdk/BoxSignRequest.java @@ -299,7 +299,17 @@ public enum BoxSignRequestStatus { /** * Expired status. */ - Expired("expired"); + Expired("expired"), + + /** + * Finalizing status. + */ + Finalizing("finalizing"), + + /** + * Error finalizing status. + */ + ErrorFinalizing("error_finalizing"); private final String jsonValue; @@ -308,26 +318,32 @@ public enum BoxSignRequestStatus { } static BoxSignRequestStatus fromJSONString(String jsonValue) { - if ("converting".equals(jsonValue)) { - return Converting; - } else if ("created".equals(jsonValue)) { - return Created; - } else if ("sent".equals(jsonValue)) { - return Sent; - } else if ("viewed".equals(jsonValue)) { - return Viewed; - } else if ("signed".equals(jsonValue)) { - return Signed; - } else if ("cancelled".equals(jsonValue)) { - return Cancelled; - } else if ("declined".equals(jsonValue)) { - return Declined; - } else if ("error_converting".equals(jsonValue)) { - return ErrorConverting; - } else if ("error_sending".equals(jsonValue)) { - return ErrorSending; - } else if ("expired".equals(jsonValue)) { - return Expired; + switch (jsonValue) { + case "converting": + return Converting; + case "created": + return Created; + case "sent": + return Sent; + case "viewed": + return Viewed; + case "signed": + return Signed; + case "cancelled": + return Cancelled; + case "declined": + return Declined; + case "error_converting": + return ErrorConverting; + case "error_sending": + return ErrorSending; + case "expired": + return Expired; + case "finalizing": + return Finalizing; + case "error_finalizing": + return ErrorFinalizing; + default: } throw new IllegalArgumentException("The provided JSON value isn't a valid BoxSignRequestStatus value."); } @@ -359,6 +375,7 @@ public class Info extends BoxResource.Info { private Date autoExpireAt; private String redirectUrl; private String declinedRedirectUrl; + private String templateId; /** * Constructs an empty Info object. @@ -578,6 +595,15 @@ public String getDeclinedRedirectUrl() { return this.declinedRedirectUrl; } + /** + * Gets the id of the template that was used to create this sign request. + * + * @return sign template id. + */ + public String getTemplateId() { + return this.templateId; + } + /** * {@inheritDoc} */ @@ -680,6 +706,9 @@ void parseJSONMember(JsonObject.Member member) { case "declined_redirect_url": this.declinedRedirectUrl = value.asString(); break; + case "template_id": + this.templateId = value.asString(); + break; default: } } catch (Exception e) { diff --git a/src/main/java/com/box/sdk/BoxSignRequestCreateParams.java b/src/main/java/com/box/sdk/BoxSignRequestCreateParams.java index f0cf8d1df..e3751b279 100644 --- a/src/main/java/com/box/sdk/BoxSignRequestCreateParams.java +++ b/src/main/java/com/box/sdk/BoxSignRequestCreateParams.java @@ -25,6 +25,7 @@ public class BoxSignRequestCreateParams { private String externalId; private String redirectUrl; private String declinedRedirectUrl; + private String templateId; /** * Gets the flag indicating if the sender should be taken into the builder flow to prepare the document. @@ -296,6 +297,26 @@ public BoxSignRequestCreateParams setDeclinedRedirectUrl(String declinedRedirect return this; } + /** + * Gets the Sign Template ID of the Sign Request. + * + * @return template id. + */ + public String getTemplateId() { + return this.templateId; + } + + /** + * Sets the Sign Template ID will be use to create the sign request. + * + * @param templateId for this sign request. + * @return this BoxSignRequestCreateParams object for chaining. + */ + public BoxSignRequestCreateParams setTemplateId(String templateId) { + this.templateId = templateId; + return this; + } + /** * Used to append BoxSignRequestCreateParams to request. * @@ -315,6 +336,7 @@ public void appendParamsAsJson(JsonObject requestJSON) { JsonUtils.addIfNotNull(requestJSON, "external_id", this.externalId); JsonUtils.addIfNotNull(requestJSON, "redirect_url", this.redirectUrl); JsonUtils.addIfNotNull(requestJSON, "declined_redirect_url", this.declinedRedirectUrl); + JsonUtils.addIfNotNull(requestJSON, "template_id", this.templateId); if (this.prefillTags != null) { JsonArray prefillTagsJSON = new JsonArray(); diff --git a/src/main/java/com/box/sdk/BoxSignTemplate.java b/src/main/java/com/box/sdk/BoxSignTemplate.java new file mode 100644 index 000000000..b60075f1f --- /dev/null +++ b/src/main/java/com/box/sdk/BoxSignTemplate.java @@ -0,0 +1,621 @@ +package com.box.sdk; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + + +/** + * Represents a Sign Template used in the Box Sign API. + * + * @see Box Sign Templates + * + *

Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked + * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error + * handling for errors related to the Box REST API, you should capture this exception explicitly.

+ */ +@BoxResourceType("sign_template") +public class BoxSignTemplate extends BoxResource { + + /** + * The URL template for Sign Templates. + */ + public static final URLTemplate SIGN_TEMPLATES_URL_TEMPLATE = new URLTemplate("sign_templates"); + + /** + * The URL template for Sign Templates operations with a given ID. + */ + public static final URLTemplate SIGN_TEMPLATE_URL_TEMPLATE = new URLTemplate("sign_templates/%s"); + + /** + * The default limit of entries per response. + */ + public static final int DEFAULT_LIMIT = 100; + + /** + * Constructs a BoxSignTemplate for a resource with a given ID. + * + * @param api the API connection to be used by the resource. + * @param id the ID of the resource. + */ + public BoxSignTemplate(BoxAPIConnection api, String id) { + super(api, id); + } + + /** + * Return all Sign Templates. + * + * @param api the API connection to be used by the resource. + * @return an iterable with all Sign Templates. + */ + public static Iterable getAll(BoxAPIConnection api) { + return getAll(api, DEFAULT_LIMIT); + } + + /** + * Return all Sign Templates. + * + * @param api the API connection to be used by the resource. + * @param limit the limit of entries per response. + * @return an iterable with all Sign Templates. + */ + public static Iterable getAll(BoxAPIConnection api, int limit) { + QueryStringBuilder builder = new QueryStringBuilder(); + URL url = SIGN_TEMPLATES_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString()); + return new BoxResourceIterable(api, url, limit) { + + @Override + protected BoxSignTemplate.Info factory(JsonObject jsonObject) { + BoxSignTemplate template = new BoxSignTemplate(api, jsonObject.get("id").asString()); + return template.new Info(jsonObject); + } + }; + + } + + /** + * Return information about this Sign Template. + * + * @return information about this Sign Template. + */ + public BoxSignTemplate.Info getInfo() { + URL url = SIGN_TEMPLATE_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID()); + BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); + try (BoxJSONResponse response = (BoxJSONResponse) request.send()) { + JsonObject jsonObject = Json.parse(response.getJSON()).asObject(); + return new Info(jsonObject); + } + } + + /** + * Contains information about a BoxSignTemplate. + */ + public class Info extends BoxResource.Info { + + private BoxSignTemplateAdditionalInfo additionalInfo; + private boolean areEmailSettingsLocked; + private boolean areFieldsLocked; + private boolean areOptionsLocked; + private boolean areFilesLocked; + private boolean areRecipientsLocked; + private BoxSignTemplateCustomBranding customBranding; + private Integer daysValid; + private String emailMessage; + private String emailSubject; + private String name; + private BoxFolder.Info parentFolder; + private BoxSignTemplateReadySignLink readySignLink; + private List signers; + private List sourceFiles; + + /** + * Constructs an empty Info object. + */ + public Info() { + super(); + } + + /** + * Constructs an Info object with the provided JSON string. + * + * @param json the JSON string representing the Sign Template. + */ + public Info(String json) { + super(json); + } + + /** + * Constructs an Info object with the provided JSON object. + * + * @param jsonObject the JSON object representing the Sign Template. + */ + Info(JsonObject jsonObject) { + super(jsonObject); + } + + /** + * {@inheritDoc} + */ + @Override + public BoxSignTemplate getResource() { + return BoxSignTemplate.this; + } + + /** + * Gets the additional information about this Sign Template. + * + * @return the additional information about this Sign Template. + */ + public BoxSignTemplateAdditionalInfo getAdditionalInfo() { + return this.additionalInfo; + } + + /** + * Gets whether the templates email settings are editable or not. + * + * @return true if the email settings are locked; otherwise false. + */ + public boolean getAreEmailSettingsLocked() { + return this.areEmailSettingsLocked; + } + + /** + * Gets whether the templates input fields are editable or not. + * This includes deleting or renaming template files. + * + * @return true if the fields are locked; otherwise false. + */ + public boolean getAreFieldsLocked() { + return this.areFieldsLocked; + } + + /** + * Gets weather the templates input options are editable or not. + * + * @return true if the options are editable; otherwise false. + */ + public boolean getAreOptionsLocked() { + return this.areOptionsLocked; + } + + /** + * Gets whether the template document options are editable or not, + * for example renaming the document. + * + * @return true if the files are locked; otherwise false. + */ + public boolean getAreFilesLocked() { + return this.areFilesLocked; + } + + /** + * Gets whether the template signers are editable or not. + * + * @return true if the recipients are locked; otherwise false. + */ + public boolean getAreRecipientsLocked() { + return this.areRecipientsLocked; + } + + /** + * Gets the custom branding applied to notifications and signature requests. + * + * @return the custom branding for this Sign Template. + */ + public BoxSignTemplateCustomBranding getCustomBranding() { + return this.customBranding; + } + + /** + * Gets the number of days after which the created signature request + * will automatically expire if not completed. + * By default, we do not apply any expiration date on signature requests, + * and the signature request does not expire. + * + * @return the number of days the template is valid for. + */ + public Integer getDaysValid() { + return this.daysValid; + } + + /** + * Gets the email message that will be sent to all signers. + * + * @return the email message for this Sign Template. + */ + public String getEmailMessage() { + return this.emailMessage; + } + + /** + * Gets the email subject that will be sent to all signers. + * + * @return the email subject for this Sign Template. + */ + public String getEmailSubject() { + return this.emailSubject; + } + + /** + * Gets the name of this Sign Template. + * + * @return the name of this Sign Template. + */ + public String getName() { + return this.name; + } + + /** + * Gets the parent folder of this Sign Template. + * + * @return the parent folder of this Sign Template. + */ + public BoxFolder.Info getParentFolder() { + return this.parentFolder; + } + + /** + * Gets the ready sign link for this Sign Template. + * + * @return the ready sign link for this Sign Template. + */ + public BoxSignTemplateReadySignLink getReadySignLink() { + return this.readySignLink; + } + + /** + * Gets the signers for this Sign Template. + * + * @return the signers for this Sign Template. + */ + public List getSigners() { + return this.signers; + } + + /** + * Gets the source files for this Sign Template. + * + * @return the source files for this Sign Template. + */ + public List getSourceFiles() { + return this.sourceFiles; + } + + /** + * {@inheritDoc} + */ + @Override + void parseJSONMember(JsonObject.Member member) { + super.parseJSONMember(member); + String memberName = member.getName(); + JsonValue value = member.getValue(); + try { + switch (memberName) { + case "additional_info": + this.additionalInfo = this.parseAdditionalInfo(value.asObject()); + break; + case "are_email_settings_locked": + this.areEmailSettingsLocked = value.asBoolean(); + break; + case "are_fields_locked": + this.areFieldsLocked = value.asBoolean(); + break; + case "are_options_locked": + this.areOptionsLocked = value.asBoolean(); + break; + case "are_files_locked": + this.areFilesLocked = value.asBoolean(); + break; + case "are_recipients_locked": + this.areRecipientsLocked = value.asBoolean(); + break; + case "custom_branding": + this.customBranding = this.parseCustomBranding(value.asObject()); + break; + case "days_valid": + this.daysValid = value.asInt(); + break; + case "email_message": + this.emailMessage = value.asString(); + break; + case "email_subject": + this.emailSubject = value.asString(); + break; + case "name": + this.name = value.asString(); + break; + case "parent_folder": + JsonObject parentFolderJSON = value.asObject(); + String parentFolderID = parentFolderJSON.get("id").asString(); + BoxFolder parentFolder = new BoxFolder(getAPI(), parentFolderID); + this.parentFolder = parentFolder.new Info(parentFolderJSON); + break; + case "ready_sign_link": + this.readySignLink = this.parseReadySignLink(value.asObject()); + break; + case "signers": + this.signers = this.parseSigners(value.asArray()); + break; + case "source_files": + this.sourceFiles = this.parseSourceFiles(value.asArray()); + break; + default: + } + } catch (Exception e) { + throw new BoxDeserializationException(memberName, value.toString(), e); + } + } + + private BoxSignTemplateAdditionalInfo parseAdditionalInfo(JsonValue additionalInfoJSON) { + List nonEditableFields = new ArrayList(); + for (JsonValue fieldJSON : additionalInfoJSON.asObject().get("non_editable").asArray()) { + nonEditableFields.add(fieldJSON.asString()); + } + BoxSignTemplateAdditionalInfoRequired required = this.parseAdditionalInfoRequired( + additionalInfoJSON.asObject().get("required").asObject() + ); + return new BoxSignTemplateAdditionalInfo(nonEditableFields, required); + } + + private BoxSignTemplateAdditionalInfoRequired parseAdditionalInfoRequired(JsonObject requiredJSON) { + List> signers = new ArrayList>(); + for (JsonValue signerJSON : requiredJSON.get("signers").asArray()) { + List signer = new ArrayList(); + for (JsonValue fieldJSON : signerJSON.asArray()) { + signer.add(fieldJSON.asString()); + } + signers.add(signer); + } + return new BoxSignTemplateAdditionalInfoRequired(signers); + } + + private List parseSourceFiles(JsonValue filesArray) { + List files = new ArrayList(); + for (JsonValue fileJSON : filesArray.asArray()) { + JsonObject fileObj = fileJSON.asObject(); + String fileID = fileObj.get("id").asString(); + BoxFile file = new BoxFile(getAPI(), fileID); + files.add(file.new Info(fileObj)); + } + return files; + } + + private List parseSigners(JsonValue signersArray) { + List signers = new ArrayList(); + for (JsonValue signerJSON : signersArray.asArray()) { + JsonObject signerObj = signerJSON.asObject(); + signers.add(new BoxSignRequestSigner(signerObj, getAPI())); + } + return signers; + } + + private BoxSignTemplateCustomBranding parseCustomBranding(JsonObject customBrandingJSON) { + String brandingColor = customBrandingJSON.get("branding_color").asString(); + String companyName = customBrandingJSON.get("company_name").asString(); + String emailFooterText = customBrandingJSON.get("email_footer_text").asString(); + String logoUri = customBrandingJSON.get("logo_uri").asString(); + return new BoxSignTemplateCustomBranding(brandingColor, companyName, emailFooterText, logoUri); + } + + private BoxSignTemplateReadySignLink parseReadySignLink(JsonObject readySignLinkJSON) { + String folderID = readySignLinkJSON.get("folder_id").asString(); + String instructions = readySignLinkJSON.get("instructions").asString(); + boolean isActive = readySignLinkJSON.get("is_active").asBoolean(); + boolean isNofiticationDisabled = readySignLinkJSON.get("is_notification_disabled").asBoolean(); + String name = readySignLinkJSON.get("name").asString(); + String url = readySignLinkJSON.get("url").asString(); + return new BoxSignTemplateReadySignLink(folderID, instructions, isActive, + isNofiticationDisabled, name, url); + } + + /** + * Box Sign Template additional information on which fields are required + * and which fields are not editable. + */ + public class BoxSignTemplateAdditionalInfo { + private final List nonEditable; + private final BoxSignTemplateAdditionalInfoRequired required; + + public BoxSignTemplateAdditionalInfo(List nonEditable, + BoxSignTemplateAdditionalInfoRequired required) { + this.nonEditable = nonEditable; + this.required = required; + } + + /** + * Get non-editable fields. + * + * @return list of non-editable fields.\ + */ + public List getNonEditable() { + return this.nonEditable; + } + + /** + * Gets the required fields. + * + * @return the required fields. + */ + public BoxSignTemplateAdditionalInfoRequired getRequired() { + return this.required; + } + } + + /** + * Box Sign Template additional information on which fields are required. + */ + public class BoxSignTemplateAdditionalInfoRequired { + private final List> signers; + + /** + * Constructs a BoxSignTemplateAdditionalInfoRequired object with the provided list of signers. + */ + public BoxSignTemplateAdditionalInfoRequired(List> signers) { + this.signers = signers; + } + + /** + * Gets the required signer fields. + * + * @return the required signer fields. + */ + public List> getSigners() { + return this.signers; + } + } + + /** + * Custom branding applied to notifications and signature requests. + */ + public class BoxSignTemplateCustomBranding { + private final String brandingColor; + private final String companyName; + private final String emailFooterText; + private final String logoUri; + + /** + * Constructs a BoxSignTemplateCustomBranding object with the provided information. + * + * @param brandingColor the branding color. + * @param companyName the company name. + * @param emailFooterText the email footer text. + * @param logoUri the logo URI. + */ + public BoxSignTemplateCustomBranding(String brandingColor, String companyName, String emailFooterText, + String logoUri) { + this.brandingColor = brandingColor; + this.companyName = companyName; + this.emailFooterText = emailFooterText; + this.logoUri = logoUri; + } + + /** + * Gets the branding color. + * + * @return the branding color. + */ + public String getBrandingColor() { + return this.brandingColor; + } + + /** + * Gets the company name. + * + * @return the company name. + */ + public String getCompanyName() { + return this.companyName; + } + + /** + * Gets the email footer text. + * + * @return the email footer text. + */ + public String getEmailFooterText() { + return this.emailFooterText; + } + + /** + * Gets the logo URI. + * + * @return the logo URI. + */ + public String getLogoUri() { + return this.logoUri; + } + } + + /** + * Box's ready-sign link feature enables you to create a link to a signature request that you've created from a template. + * Use this link when you want to post a signature request on a public form — such as an email, + * social media post, or web page — without knowing who the signers will be. + * Note: The ready-sign link feature is limited to Enterprise Plus customers and not available to Box Verified Enterprises. + */ + public class BoxSignTemplateReadySignLink { + private final String folderID; + private final String instructions; + private final boolean isActive; + private final boolean isNofiticationDisabled; + private final String name; + private final String url; + + /** + * Constructs a BoxSignTemplateReadySignLink object with the provided information. + * + * @param folderID the folder ID. + * @param instructions the instructions. + * @param isActive whether the link is active or not. + * @param isNofiticationDisabled whether the notification is disabled or not. + * @param name the name. + * @param url the URL. + */ + public BoxSignTemplateReadySignLink(String folderID, String instructions, boolean isActive, + boolean isNofiticationDisabled, String name, String url) { + this.folderID = folderID; + this.instructions = instructions; + this.isActive = isActive; + this.isNofiticationDisabled = isNofiticationDisabled; + this.name = name; + this.url = url; + } + + /** + * Gets the folder ID. + * + * @return the folder ID. + */ + public String getFolderID() { + return this.folderID; + } + + /** + * Gets the instructions. + * + * @return the instructions. + */ + public String getInstructions() { + return this.instructions; + } + + /** + * Gets whether the link is active or not. + * + * @return true if the link is active; otherwise false. + */ + public boolean getIsActive() { + return this.isActive; + } + + /** + * Gets whether the notification is disabled or not. + * + * @return true if the notification is disabled; otherwise false. + */ + public boolean getIsNofiticationDisabled() { + return this.isNofiticationDisabled; + } + + /** + * Gets the name of the ready-sign link. + * + * @return the name. + */ + public String getName() { + return this.name; + } + + /** + * Gets the URL of the ready-sign link. + * + * @return the URL. + */ + public String getUrl() { + return this.url; + } + } + } +} diff --git a/src/test/Fixtures/BoxSignRequest/CancelSignRequest200.json b/src/test/Fixtures/BoxSignRequest/CancelSignRequest200.json index 5a5f8260b..d9e3a7477 100644 --- a/src/test/Fixtures/BoxSignRequest/CancelSignRequest200.json +++ b/src/test/Fixtures/BoxSignRequest/CancelSignRequest200.json @@ -105,5 +105,6 @@ ], "is_ready_for_download": true }, - "auto_expire_at": "2021-04-26T08:12:13.982Z" + "auto_expire_at": "2021-04-26T08:12:13.982Z", + "template_id": "93153068-5420-467b-b8ef-aaaaaaaaaaa" } diff --git a/src/test/Fixtures/BoxSignRequest/CreateSignRequest200.json b/src/test/Fixtures/BoxSignRequest/CreateSignRequest200.json index c72feb8e4..9a66d8985 100644 --- a/src/test/Fixtures/BoxSignRequest/CreateSignRequest200.json +++ b/src/test/Fixtures/BoxSignRequest/CreateSignRequest200.json @@ -105,5 +105,6 @@ ], "is_ready_for_download": true }, - "auto_expire_at": "2021-04-26T08:12:13.982Z" + "auto_expire_at": "2021-04-26T08:12:13.982Z", + "template_id": "93153068-5420-467b-b8ef-aaaaaaaaaaa" } diff --git a/src/test/Fixtures/BoxSignRequest/GetAllSignRequests200.json b/src/test/Fixtures/BoxSignRequest/GetAllSignRequests200.json index fc989f016..a31ef68ac 100644 --- a/src/test/Fixtures/BoxSignRequest/GetAllSignRequests200.json +++ b/src/test/Fixtures/BoxSignRequest/GetAllSignRequests200.json @@ -127,7 +127,8 @@ ], "is_ready_for_download": true }, - "auto_expire_at": "2021-04-26T08:12:13.982Z" + "auto_expire_at": "2021-04-26T08:12:13.982Z", + "template_id": "93153068-5420-467b-b8ef-aaaaaaaaaaa" } ] } diff --git a/src/test/Fixtures/BoxSignRequest/GetSignRequest200.json b/src/test/Fixtures/BoxSignRequest/GetSignRequest200.json index 67d308656..af64b2b4d 100644 --- a/src/test/Fixtures/BoxSignRequest/GetSignRequest200.json +++ b/src/test/Fixtures/BoxSignRequest/GetSignRequest200.json @@ -123,5 +123,6 @@ ], "is_ready_for_download": true }, - "auto_expire_at": "2021-04-26T08:12:13.982Z" + "auto_expire_at": "2021-04-26T08:12:13.982Z", + "template_id": "93153068-5420-467b-b8ef-aaaaaaaaaaa" } diff --git a/src/test/Fixtures/BoxSignTemplate/GetAllSignTemplates200.json b/src/test/Fixtures/BoxSignTemplate/GetAllSignTemplates200.json new file mode 100644 index 000000000..52a697185 --- /dev/null +++ b/src/test/Fixtures/BoxSignTemplate/GetAllSignTemplates200.json @@ -0,0 +1,107 @@ +{ + "limit": 100, + "next_marker": null, + "prev_marker": null, + "entries": [ + { + "id": "93153068-5420-467b-b8ef-aaaaaaaaaaa", + "name": "contract.pdf", + "email_message": "Please sign this document.\n\nKind regards,\n\nSomeone", + "email_subject": "Someone has requested your signature on a document", + "parent_folder": { + "id": "1234567890", + "etag": "0", + "type": "folder", + "sequence_id": "0", + "name": "My Sign Requests" + }, + "auto_expire_days": null, + "source_files": [ + { + "id": "1234567890", + "etag": "0", + "type": "file", + "sequence_id": "0", + "sha1": "082c9540e82e9c465309367a32404054b13aaaaaa", + "file_version": { + "id": "1234567890", + "type": "file_version", + "sha1": "082c9540e82e9c465309367a32404054b13aaaaaa" + } + } + ], + "are_email_settings_locked": false, + "are_fields_locked": false, + "are_files_locked": false, + "are_options_locked": false, + "are_recipients_locked": false, + "signers": [ + { + "email": "", + "label": "", + "public_id": "18K8KAAA", + "role": "final_copy_reader", + "is_in_person": false, + "order": 1, + "inputs": [] + }, + { + "email": "", + "label": "", + "public_id": "13XQXAAA", + "role": "signer", + "is_in_person": false, + "order": 1, + "inputs": [ + { + "document_tag_id": null, + "id": "0260f921-3b52-477f-ae74-aaaaaaaaaaa", + "type": "signature", + "text_value": null, + "is_required": true, + "coordinates": { + "x": 0.27038464059712, + "y": 0.10051756244533624 + }, + "dimensions": { + "width": 0.23570031566618235, + "height": 0.04781003891921971 + }, + "date_value": null, + "page_index": 0, + "checkbox_value": null, + "document_id": "2fdf9003-d798-40ee-be7f-aaaaaaaaaaa", + "content_type": "signature", + "dropdown_choices": null, + "group_id": null, + "label": null + } + ] + } + ], + "ready_sign_link": { + "url": "https://app.box.com/sign/ready-sign-link/59917816-c12b-4ef6-8f1d-aaaaaaaaaaa", + "name": "contract.pdf", + "instructions": "Hello", + "folder_id": "1234567890", + "is_notification_disabled": true, + "is_active": true + }, + "custom_branding": null, + "days_valid": 0, + "additional_info": { + "non_editable": [], + "required": { + "signers": [ + [ + "email" + ], + [ + "email" + ] + ] + } + } + } + ] +} \ No newline at end of file diff --git a/src/test/Fixtures/BoxSignTemplate/GetSignTemplateInfo200.json b/src/test/Fixtures/BoxSignTemplate/GetSignTemplateInfo200.json new file mode 100644 index 000000000..f4d9aa495 --- /dev/null +++ b/src/test/Fixtures/BoxSignTemplate/GetSignTemplateInfo200.json @@ -0,0 +1,100 @@ +{ + "id": "93153068-5420-467b-b8ef-aaaaaaaaaaa", + "name": "contract.pdf", + "email_message": "Please sign this document.\n\nKind regards,\n\nSomeone", + "email_subject": "Someone has requested your signature on a document", + "parent_folder": { + "id": "1234567890", + "etag": "0", + "type": "folder", + "sequence_id": "0", + "name": "My Sign Requests" + }, + "auto_expire_days": null, + "source_files": [ + { + "id": "1234567890", + "etag": "0", + "type": "file", + "sequence_id": "0", + "sha1": "082c9540e82e9c465309367a32404054b13aaaaaa", + "file_version": { + "id": "1234567890", + "type": "file_version", + "sha1": "082c9540e82e9c465309367a32404054b13aaaaaa" + } + } + ], + "are_email_settings_locked": false, + "are_fields_locked": false, + "are_files_locked": false, + "are_options_locked": false, + "are_recipients_locked": false, + "signers": [ + { + "email": "", + "label": "", + "public_id": "18K8KAAA", + "role": "final_copy_reader", + "is_in_person": false, + "order": 1, + "inputs": [] + }, + { + "email": "", + "label": "", + "public_id": "13XQXAAA", + "role": "signer", + "is_in_person": false, + "order": 1, + "inputs": [ + { + "document_tag_id": null, + "id": "0260f921-3b52-477f-ae74-aaaaaaaaaaa", + "type": "signature", + "text_value": null, + "is_required": true, + "coordinates": { + "x": 0.27038464059712, + "y": 0.10051756244533624 + }, + "dimensions": { + "width": 0.23570031566618235, + "height": 0.04781003891921971 + }, + "date_value": null, + "page_index": 0, + "checkbox_value": null, + "document_id": "2fdf9003-d798-40ee-be7f-aaaaaaaaaaa", + "content_type": "signature", + "dropdown_choices": null, + "group_id": null, + "label": null + } + ] + } + ], + "ready_sign_link": { + "url": "https://app.box.com/sign/ready-sign-link/59917816-c12b-4ef6-8f1d-aaaaaaaaaaa", + "name": "contract.pdf", + "instructions": "Hello", + "folder_id": "1234567890", + "is_notification_disabled": true, + "is_active": true + }, + "custom_branding": null, + "days_valid": 0, + "additional_info": { + "non_editable": [], + "required": { + "signers": [ + [ + "email" + ], + [ + "email" + ] + ] + } + } +} \ No newline at end of file diff --git a/src/test/java/com/box/sdk/BoxSignRequestTest.java b/src/test/java/com/box/sdk/BoxSignRequestTest.java index fd9dc452e..6129fbb7e 100644 --- a/src/test/java/com/box/sdk/BoxSignRequestTest.java +++ b/src/test/java/com/box/sdk/BoxSignRequestTest.java @@ -41,6 +41,7 @@ public void createSignRequestSucceeds() { final String signerEmail = "example@gmail.com"; final String signRequestId = "12345"; final BoxSignRequestInputContentType contentType = BoxSignRequestInputContentType.Checkbox; + final String templateId = "93153068-5420-467b-b8ef-aaaaaaaaaaa"; final String prepareUrl = "https://prepareurl.com"; final String redirectUrl = "https://box.com/redirect_url"; @@ -67,6 +68,7 @@ public void createSignRequestSucceeds() { String parentFolderId = "55555"; BoxSignRequestCreateParams params = new BoxSignRequestCreateParams(); + params.setTemplateId(templateId); params.setPrefillTags(Collections.singletonList(new BoxSignRequestPrefillTag("id", "text"))); BoxSignRequest.Info signRequestInfo = BoxSignRequest.createSignRequest(this.api, files, signers, parentFolderId, params); @@ -85,6 +87,8 @@ public void createSignRequestSucceeds() { assertEquals(signerEmail, signer.getEmail()); assertEquals(signRequestId, signRequestInfo.getID()); assertEquals(contentType, input.getContentType()); + assertEquals(templateId, signRequestInfo.getTemplateId()); + } @Test @@ -102,6 +106,8 @@ public void getSignRequestInfoSucceeds() { final String signerRedirectUrl = "https://box.com/redirect_url_signer_1"; final String signerDeclinedRedirectUrl = "https://box.com/declined_redirect_url_signer_1"; + final String templateId = "93153068-5420-467b-b8ef-aaaaaaaaaaa"; + final String requestUrl = "/2.0/sign_requests/" + signRequestId; String result = TestUtils.getFixture("BoxSignRequest/GetSignRequest200"); @@ -128,6 +134,7 @@ public void getSignRequestInfoSucceeds() { assertEquals(signerEmail, signer.getEmail()); assertEquals(signRequestId, signRequestInfo.getID()); assertEquals(contentType, input.getContentType()); + assertEquals(templateId, signRequestInfo.getTemplateId()); } @Test @@ -144,6 +151,7 @@ public void getAllSignRequestsSucceeds() { final String signerRedirectUrl = "https://box.com/redirect_url_signer_1"; final String signerDeclinedRedirectUrl = "https://box.com/declined_redirect_url_signer_1"; + final String templateId = "93153068-5420-467b-b8ef-aaaaaaaaaaa"; final String requestUrl = "/2.0/sign_requests"; @@ -171,6 +179,7 @@ public void getAllSignRequestsSucceeds() { assertEquals(signerEmail, signer.getEmail()); assertEquals(signRequestId, firstSignRequest.getID()); assertEquals(contentType, input.getContentType()); + assertEquals(templateId, firstSignRequest.getTemplateId()); } @Test diff --git a/src/test/java/com/box/sdk/BoxSignTemplateTest.java b/src/test/java/com/box/sdk/BoxSignTemplateTest.java new file mode 100644 index 000000000..7f01052cc --- /dev/null +++ b/src/test/java/com/box/sdk/BoxSignTemplateTest.java @@ -0,0 +1,72 @@ +package com.box.sdk; + + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Iterator; + +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static java.lang.String.format; +import static org.junit.Assert.assertEquals; + +public class BoxSignTemplateTest { + + @Rule + public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicHttpsPort().httpDisabled(true)); + private final BoxAPIConnection api = TestUtils.getAPIConnection(); + + @Before + public void setUpBaseUrl() { + api.setMaxRetryAttempts(1); + api.setBaseURL(format("https://localhost:%d", wireMockRule.httpsPort())); + } + + @Test + public void getSignTemplateInfoSucceeds() { + final String templateId = "93153068-5420-467b-b8ef-aaaaaaaaaaa"; + final String name = "contract.pdf"; + final String parentFolderId = "1234567890"; + + final String requestUrl = "/2.0/sign_templates/" + templateId; + + String result = TestUtils.getFixture("BoxSignTemplate/GetSignTemplateInfo200"); + + wireMockRule.stubFor(WireMock.get(WireMock.urlPathEqualTo(requestUrl)) + .willReturn(WireMock.aResponse() + .withHeader("Content-Type", "application/json") + .withBody(result))); + + BoxSignTemplate template = new BoxSignTemplate(api, templateId); + BoxSignTemplate.Info info = template.getInfo(); + + assertEquals(templateId, info.getID()); + assertEquals(name, info.getName()); + assertEquals(parentFolderId, info.getParentFolder().getID()); + } + + @Test + public void getAllSignTemplatesSucceeds() { + final String templateId = "93153068-5420-467b-b8ef-aaaaaaaaaaa"; + final String name = "contract.pdf"; + final String parentFolderId = "1234567890"; + + final String requestUrl = "/2.0/sign_templates"; + String result = TestUtils.getFixture("BoxSignTemplate/GetAllSignTemplates200"); + + wireMockRule.stubFor(WireMock.get(WireMock.urlPathEqualTo(requestUrl)) + .willReturn(WireMock.aResponse() + .withHeader("Content-Type", "application/json") + .withBody(result))); + + Iterator iterator = BoxSignTemplate.getAll(api).iterator(); + BoxSignTemplate.Info info = iterator.next(); + + assertEquals(templateId, info.getID()); + assertEquals(name, info.getName()); + assertEquals(parentFolderId, info.getParentFolder().getID()); + } +}