From f560db8d5587406099066803789d16374ec7dbb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Socha?= <31014760+lukaszsocha2@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:55:12 +0100 Subject: [PATCH] feat: Add `signer_group_id` for signer in sign request (#1220) Closes: SDK-3518 --- .../box/sdk/BoxCollaborationAllowlistIT.java | 3 +- .../sdk/BoxRetentionPolicyAssignmentIT.java | 4 +- .../java/com/box/sdk/BoxSignRequestIT.java | 78 +++++++++++++++++++ src/intTest/java/com/box/sdk/BoxUserIT.java | 2 +- .../java/com/box/sdk/CleanupTools.java | 6 ++ .../com/box/sdk/BoxSignRequestSigner.java | 27 +++++++ .../com/box/sdk/BoxSignTemplateSigner.java | 29 +++++++ 7 files changed, 145 insertions(+), 4 deletions(-) diff --git a/src/intTest/java/com/box/sdk/BoxCollaborationAllowlistIT.java b/src/intTest/java/com/box/sdk/BoxCollaborationAllowlistIT.java index d69f8b86d..9ee46585b 100644 --- a/src/intTest/java/com/box/sdk/BoxCollaborationAllowlistIT.java +++ b/src/intTest/java/com/box/sdk/BoxCollaborationAllowlistIT.java @@ -2,6 +2,7 @@ import static com.box.sdk.BoxApiProvider.jwtApiForServiceAccount; import static com.box.sdk.CleanupTools.removeAllowedDomains; +import static com.box.sdk.UniqueTestFolder.randomizeName; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -15,7 +16,7 @@ import org.junit.Test; public class BoxCollaborationAllowlistIT { - private static final String DOMAIN_NAME = "test14.com"; + private static final String DOMAIN_NAME = randomizeName("test") + ".com"; @Before public void beforeClass() { diff --git a/src/intTest/java/com/box/sdk/BoxRetentionPolicyAssignmentIT.java b/src/intTest/java/com/box/sdk/BoxRetentionPolicyAssignmentIT.java index 5c56b40e3..c2c5b5f17 100644 --- a/src/intTest/java/com/box/sdk/BoxRetentionPolicyAssignmentIT.java +++ b/src/intTest/java/com/box/sdk/BoxRetentionPolicyAssignmentIT.java @@ -75,7 +75,7 @@ public void attachPolicyToFileAndGetFilesUnderRetentionAndDeleteAttachment() thr .filter(f -> f.getID().equals(boxFile.getID())) .collect(Collectors.toList()); assertTrue(matchingFileWithRetention2.isEmpty()); - }, 3, 1000); + }, 5, 2000); } finally { //cleanup deleteFolder(folder.getResource()); @@ -123,7 +123,7 @@ public void attachPolicyToFileAndGetFileVersionsUnderRetentionAndDeleteAttachmen .filter(f -> f.getID().equals(boxFile.getID())) .collect(Collectors.toList()); assertTrue(matchingFileWithRetention2.isEmpty()); - }, 3, 1000); + }, 5, 2000); } finally { //cleanup deleteFolder(folder); diff --git a/src/intTest/java/com/box/sdk/BoxSignRequestIT.java b/src/intTest/java/com/box/sdk/BoxSignRequestIT.java index 6e26b40d4..23e03bd8f 100644 --- a/src/intTest/java/com/box/sdk/BoxSignRequestIT.java +++ b/src/intTest/java/com/box/sdk/BoxSignRequestIT.java @@ -3,19 +3,23 @@ import static com.box.sdk.BoxApiProvider.jwtApiForServiceAccount; import static com.box.sdk.CleanupTools.deleteFile; import static com.box.sdk.CleanupTools.deleteFolder; +import static com.box.sdk.CleanupTools.deleteUser; import static com.box.sdk.Retry.retry; import static com.box.sdk.UniqueTestFolder.getUniqueFolder; +import static com.box.sdk.UniqueTestFolder.randomizeName; import static com.box.sdk.UniqueTestFolder.removeUniqueFolder; import static com.box.sdk.UniqueTestFolder.setupUniqeFolder; import static com.box.sdk.UniqueTestFolder.uploadSampleFileToUniqueFolder; import static java.time.ZoneOffset.UTC; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.time.Instant; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -146,5 +150,79 @@ public void createListAndCancelSignRequest() throws InterruptedException { deleteFolder(signedFileFolder); } } + + @Test + public void createignRequestForGroup() throws InterruptedException { + // Test Setup + BoxAPIConnection api = jwtApiForServiceAccount(); + BoxFolder uniqueFolder = getUniqueFolder(api); + BoxFile file = null; + BoxFolder signedFileFolder = null; + BoxUser groupMemberUser1 = null; + BoxUser groupMemberUser2 = null; + String userName1 = randomizeName("login1") + "@boz.com"; + String userName2 = randomizeName("login2") + "@boz.com"; + AtomicReference signRequestInfoCancel = new AtomicReference<>(); + String signerGroupName = randomizeName("GroupName"); + + try { + groupMemberUser1 = BoxUser.createEnterpriseUser(api, userName1, "userName1").getResource(); + groupMemberUser2 = BoxUser.createEnterpriseUser(api, userName2, "userName2").getResource(); + + file = uploadSampleFileToUniqueFolder(api, "file_to_sign.pdf"); + List files = Collections.singletonList(new BoxSignRequestFile(file.getID())); + + List signers = new ArrayList<>(); + signers.add(new BoxSignRequestSigner(userName1).setSignerGroupId(signerGroupName)); + signers.add(new BoxSignRequestSigner(userName2).setSignerGroupId(signerGroupName)); + + signedFileFolder = uniqueFolder.createFolder("Folder - signRequestGroupIntegrationTest").getResource(); + + // Do Create + BoxSignRequest.Info signRequestInfoCreate = BoxSignRequest + .createSignRequest(api, files, signers, signedFileFolder.getID()); + + String signRequestIdCreate = signRequestInfoCreate.getID(); + List createdSigners = signRequestInfoCreate.getSigners(); + BoxSignRequestSigner createdSigner1 = createdSigners.get(1); + BoxSignRequestSigner createdSigner2 = createdSigners.get(2); + + // Test Create + assertNotNull(signRequestInfoCreate.getID()); + assertEquals(createdSigners.size(), 3); + assertEquals(createdSigner1.getSignerGroupId(), createdSigner2.getSignerGroupId()); + assertNotEquals(createdSigner1.getSignerGroupId(), signerGroupName); + + // Do Get by ID + BoxSignRequest signRequestGetByID = new BoxSignRequest(api, signRequestIdCreate); + + List signersGet = signRequestGetByID.getInfo().getSigners(); + BoxSignRequestSigner signer1Get = signersGet.get(1); + BoxSignRequestSigner signer2Get = createdSigners.get(2); + + // Test Get + assertNotNull(signRequestInfoCreate.getID()); + assertEquals(signersGet.size(), 3); + assertEquals(signer1Get.getSignerGroupId(), signer2Get.getSignerGroupId()); + assertEquals(signer1Get.getSignerGroupId(), createdSigner1.getSignerGroupId()); + + retry(() -> signRequestInfoCancel.set(signRequestGetByID.cancel()), 5, 1000); + + } finally { + deleteUser(groupMemberUser1); + deleteUser(groupMemberUser2); + + if (signRequestInfoCancel.get() != null) { + // Clean up + List signRequestFiles = signRequestInfoCancel.get().getSignFiles().getFiles(); + for (BoxFile.Info signRequestFile : signRequestFiles) { + BoxFile fileToDelete = new BoxFile(api, signRequestFile.getID()); + fileToDelete.delete(); + } + } + deleteFile(file); + deleteFolder(signedFileFolder); + } + } } diff --git a/src/intTest/java/com/box/sdk/BoxUserIT.java b/src/intTest/java/com/box/sdk/BoxUserIT.java index f2ee2a231..eeeefe520 100644 --- a/src/intTest/java/com/box/sdk/BoxUserIT.java +++ b/src/intTest/java/com/box/sdk/BoxUserIT.java @@ -42,7 +42,7 @@ public class BoxUserIT { public static void cleanup() { BoxAPIConnection api = jwtApiForServiceAccount(); for (BoxUser.Info user : BoxUser.getAllEnterpriseUsers(api, NEW_USER_LOGIN)) { - user.getResource().delete(false, false); + user.getResource().delete(false, true); } Logger.getLogger(OkHttpClient.class.getName()).setLevel(Level.FINE); } diff --git a/src/intTest/java/com/box/sdk/CleanupTools.java b/src/intTest/java/com/box/sdk/CleanupTools.java index cc832786b..3d5bacf2a 100644 --- a/src/intTest/java/com/box/sdk/CleanupTools.java +++ b/src/intTest/java/com/box/sdk/CleanupTools.java @@ -41,4 +41,10 @@ static void deleteGroup(BoxGroup group) { group.delete(); } } + + static void deleteUser(BoxUser user) { + if (user != null) { + user.delete(false, false); + } + } } diff --git a/src/main/java/com/box/sdk/BoxSignRequestSigner.java b/src/main/java/com/box/sdk/BoxSignRequestSigner.java index c35a104a9..112a76e84 100644 --- a/src/main/java/com/box/sdk/BoxSignRequestSigner.java +++ b/src/main/java/com/box/sdk/BoxSignRequestSigner.java @@ -26,6 +26,7 @@ public class BoxSignRequestSigner extends BoxJSONObject { private String redirectUrl; private String declinedRedirectUrl; private String iframeableEmedUrl; + private String signerGroupId; private BoxAPIConnection api; /** @@ -272,6 +273,28 @@ public BoxSignRequestSigner setIframeableEmedUrl(String iframeableEmedUrl) { return this; } + /** + * Gets the signer group id. It is sufficient for only one signer from the group to sign the document. + * + * @return id of the group to which the sign request will be sent. + */ + public String getSignerGroupId() { + return this.signerGroupId; + } + + /** + * Sets the group id. If specified, signers sharing the same group ID will be assigned to the same input. + * The group ID can be any string value, but it must be consistent across all signers. + * It is sufficient for only one signer from the group to sign the document. + * + * @param signerGroupId id of the group to which the sign request will be sent + * @return this BoxSignRequestSigner object for chaining. + */ + public BoxSignRequestSigner setSignerGroupId(String signerGroupId) { + this.signerGroupId = signerGroupId; + return this; + } + /** * {@inheritDoc} */ @@ -326,6 +349,9 @@ void parseJSONMember(JsonObject.Member member) { case "iframeable_embed_url": this.iframeableEmedUrl = value.asString(); break; + case "signer_group_id": + this.signerGroupId = value.asString(); + break; default: return; } @@ -348,6 +374,7 @@ public JsonObject getJSONObject() { JsonUtils.addIfNotNull(jsonObj, "embed_url_external_user_id", this.embedUrlExternalUserId); JsonUtils.addIfNotNull(jsonObj, "redirect_url", this.redirectUrl); JsonUtils.addIfNotNull(jsonObj, "declined_redirect_url", this.declinedRedirectUrl); + JsonUtils.addIfNotNull(jsonObj, "signer_group_id", this.signerGroupId); return jsonObj; } diff --git a/src/main/java/com/box/sdk/BoxSignTemplateSigner.java b/src/main/java/com/box/sdk/BoxSignTemplateSigner.java index 89f3588a8..0c18101e3 100644 --- a/src/main/java/com/box/sdk/BoxSignTemplateSigner.java +++ b/src/main/java/com/box/sdk/BoxSignTemplateSigner.java @@ -18,6 +18,7 @@ public class BoxSignTemplateSigner extends BoxJSONObject { private Boolean isInPerson; private int order; private BoxSignRequestSignerRole role; + private String signerGroupId; private BoxAPIConnection api; /** @@ -31,11 +32,27 @@ public class BoxSignTemplateSigner extends BoxJSONObject { */ public BoxSignTemplateSigner(String email, List inputs, Boolean isInPerson, int order, BoxSignRequestSignerRole role) { + this(email, inputs, isInPerson, order, role, null); + } + + /** + * Constructs a BoxSignTemplateSigner object with the provided information. + * + * @param email the email. + * @param inputs the inputs. + * @param isInPerson whether the signer is in person or not. + * @param order the order. + * @param role the role. + * @param signerGroupId the signer group id. + */ + public BoxSignTemplateSigner(String email, List inputs, Boolean isInPerson, + int order, BoxSignRequestSignerRole role, String signerGroupId) { this.email = email; this.inputs = inputs; this.isInPerson = isInPerson; this.order = order; this.role = role; + this.signerGroupId = signerGroupId; } /** @@ -94,6 +111,15 @@ public BoxSignRequestSignerRole getRole() { return this.role; } + /** + * Gets the signer group id. It is sufficient for only one signer from the group to sign the document. + * + * @return the id of the group signer. + */ + public String getSignerGroupId() { + return this.signerGroupId; + } + /** * {@inheritDoc} */ @@ -121,6 +147,9 @@ void parseJSONMember(JsonObject.Member member) { case "role": this.role = BoxSignRequestSignerRole.fromJSONString(value.asString()); break; + case "signer_group_id": + this.signerGroupId = value.asString(); + break; default: return; }