From 7c7ec1d62352fd500ebd2c8c9457c3dd08d4eb70 Mon Sep 17 00:00:00 2001 From: Minh Nguyen Cong Date: Fri, 26 Jan 2024 00:13:31 +0100 Subject: [PATCH] feat: Support sign request signer group ID --- .../BoxSignRequestManagerIntegrationTest.cs | 31 ++++++++++++++-- .../BoxWebhookManagerIntegrationTest.cs | 2 +- .../Configuration/IntegrationTestBase.cs | 4 +- Box.V2.Test/BoxSignRequestsManagerTest.cs | 35 +++++++++++++++--- .../BoxSignRequest/CreateSignRequest200.json | 37 ++++++++++++++++++- Box.V2/Models/BoxSignRequestSigner.cs | 32 ++++++++++++++++ .../Request/BoxSignRequestCreateRequest.cs | 27 ++++++++++++++ 7 files changed, 156 insertions(+), 12 deletions(-) diff --git a/Box.V2.Test.Integration/BoxSignRequestManagerIntegrationTest.cs b/Box.V2.Test.Integration/BoxSignRequestManagerIntegrationTest.cs index 8f40470bd..ba5cb0a72 100644 --- a/Box.V2.Test.Integration/BoxSignRequestManagerIntegrationTest.cs +++ b/Box.V2.Test.Integration/BoxSignRequestManagerIntegrationTest.cs @@ -36,7 +36,19 @@ public async Task CreateSignRequestAsync_ForCorrectSignRequestCreateRequest_Shou Email = "sdk_integration_test@boxdemo.com", RedirectUrl = new Uri("https://www.box.com/redirect_url_signer_1"), DeclinedRedirectUrl = new Uri("https://www.box.com/declined_redirect_url_singer_1"), - EmbedUrlExternalUserId = UserId + EmbedUrlExternalUserId = UserId, + SignerGroupId = "SignerGroup", + Password = "password", + LoginRequired = false, + }, + new BoxSignRequestSignerCreate() + { + Email = "sdk_integration_test_2@boxdemo.com", + RedirectUrl = new Uri("https://www.box.com/redirect_url_signer_2"), + DeclinedRedirectUrl = new Uri("https://www.box.com/declined_redirect_url_singer_2"), + SignerGroupId = "SignerGroup", + Password = "password", + LoginRequired = false, } }, ParentFolder = new BoxRequestEntity() @@ -56,8 +68,21 @@ public async Task CreateSignRequestAsync_ForCorrectSignRequestCreateRequest_Shou Assert.AreEqual(signRequestCreateRequest.ParentFolder.Id, signRequest.ParentFolder.Id); // first signer is the sender with role final_copy_reader, second is the recipient with role signer - Assert.AreEqual(2, signRequest.Signers.Count); + Assert.AreEqual(3, signRequest.Signers.Count); Assert.IsNotNull(signRequest.Signers[1].IframeableEmbedUrl); + + var signerGroupId = ""; + for (var i = 0; i < signRequest.Signers.Count; i++) + { + if (signRequest.Signers[i].Role == BoxSignRequestSignerRole.signer) + { + if (string.IsNullOrEmpty(signerGroupId)) + { + signerGroupId = signRequest.Signers[i].SignerGroupId; + } + Assert.AreEqual(signerGroupId, signRequest.Signers[i].SignerGroupId); + } + } await UserClient.SignRequestsManager.CancelSignRequestAsync(signRequest.Id); @@ -68,7 +93,7 @@ public async Task CreateSignRequestAsync_ForCorrectSignRequestCreateRequest_Shou [TestMethod] public async Task GetSignRequestAsync_ForExistingSignRequest_ShouldReturnSignRequest() { - var signRequest = await CreateSignRequest(); + var signRequest = await CreateSignRequest("sdk_integration_test@boxdemo.com", FolderId); var fetchedSignRequest = await UserClient.SignRequestsManager.GetSignRequestByIdAsync(signRequest.Id); Assert.AreEqual(signRequest.Id, fetchedSignRequest.Id); diff --git a/Box.V2.Test.Integration/BoxWebhookManagerIntegrationTest.cs b/Box.V2.Test.Integration/BoxWebhookManagerIntegrationTest.cs index da2dfaedb..74d63752e 100644 --- a/Box.V2.Test.Integration/BoxWebhookManagerIntegrationTest.cs +++ b/Box.V2.Test.Integration/BoxWebhookManagerIntegrationTest.cs @@ -85,7 +85,7 @@ public async Task DeleteWebhookAsync_ForExistingWebhook_ShouldDeleteWebhookAndEx [TestMethod] public async Task AddWebhook_ForSignRequest_ShouldCreateSuccess() { - var signRequest = await CreateSignRequest(); + var signRequest = await CreateSignRequest("sdk_integration_test@boxdemo.com", FolderId); var signFileId = signRequest.SignFiles.Files[0].Id; var webhookRequest = new BoxWebhookRequest() { diff --git a/Box.V2.Test.Integration/Configuration/IntegrationTestBase.cs b/Box.V2.Test.Integration/Configuration/IntegrationTestBase.cs index 03c6f72f2..499c1f921 100644 --- a/Box.V2.Test.Integration/Configuration/IntegrationTestBase.cs +++ b/Box.V2.Test.Integration/Configuration/IntegrationTestBase.cs @@ -389,10 +389,10 @@ public static async Task Retry(Func action, int retries = 5, int sleep = 5 } } - public static async Task CreateSignRequest(string signerEmail = "sdk_integration_test@boxdemo.com") + public static async Task CreateSignRequest(string signerEmail = "sdk_integration_test@boxdemo.com", string folderId = "0") { var file = await CreateSmallFile(); - var createSignRequestCommand = new CreateSignRequestCommand(signerEmail, file.Id); + var createSignRequestCommand = new CreateSignRequestCommand(signerEmail, file.Id, folderId); await ExecuteCommand(createSignRequestCommand); return createSignRequestCommand.SignRequest; } diff --git a/Box.V2.Test/BoxSignRequestsManagerTest.cs b/Box.V2.Test/BoxSignRequestsManagerTest.cs index 64eb1e55e..5ee74e81f 100644 --- a/Box.V2.Test/BoxSignRequestsManagerTest.cs +++ b/Box.V2.Test/BoxSignRequestsManagerTest.cs @@ -48,7 +48,12 @@ public async Task CreateSignRequest_RequiredParams_Success() { Email = "example@gmail.com", Role = BoxSignRequestSignerRole.signer - } + }, + new BoxSignRequestSignerCreate() + { + Email = "example@gmail.com", + Role = BoxSignRequestSignerRole.signer + }, }; var parentFolder = new BoxRequestEntity() @@ -77,7 +82,7 @@ public async Task CreateSignRequest_RequiredParams_Success() // Response check Assert.AreEqual(1, response.SourceFiles.Count); Assert.AreEqual("12345", response.SourceFiles[0].Id); - Assert.AreEqual(1, response.Signers.Count); + Assert.AreEqual(2, response.Signers.Count); Assert.AreEqual("example@gmail.com", response.Signers[0].Email); Assert.AreEqual("12345", response.ParentFolder.Id); Assert.AreEqual(1, response.Signers[0].Inputs.Count); @@ -113,7 +118,19 @@ public async Task CreateSignRequest_OptionalParams_Success() Email = "example@gmail.com", Role = BoxSignRequestSignerRole.signer, RedirectUrl = new Uri("https://box.com/redirect_url_signer_1"), - DeclinedRedirectUrl = new Uri("https://box.com/declined_redirect_url_signer_1") + DeclinedRedirectUrl = new Uri("https://box.com/declined_redirect_url_signer_1"), + LoginRequired = false, + Password = "abcdefg", + SignerGroupId = "SignerGroup", + VerificationPhoneNumber = "1234567890", + }, new BoxSignRequestSignerCreate() + { + Email = "other-example@gmail.com", + Role = BoxSignRequestSignerRole.signer, + RedirectUrl = new Uri("https://box.com/redirect_url_signer_1"), + DeclinedRedirectUrl = new Uri("https://box.com/declined_redirect_url_signer_1"), + SignerGroupId = "SignerGroup", + VerificationPhoneNumber = "1234567890", } }; @@ -145,7 +162,7 @@ public async Task CreateSignRequest_OptionalParams_Success() "text" ) }, - TemplateId = "12345" + TemplateId = "12345", }; /*** Act ***/ @@ -160,7 +177,7 @@ public async Task CreateSignRequest_OptionalParams_Success() // Response check Assert.AreEqual(1, response.SourceFiles.Count); Assert.AreEqual("12345", response.SourceFiles[0].Id); - Assert.AreEqual(1, response.Signers.Count); + Assert.AreEqual(2, response.Signers.Count); Assert.AreEqual("example@gmail.com", response.Signers[0].Email); Assert.AreEqual("https://box.com/redirect_url_signer_1", response.Signers[0].RedirectUrl.ToString()); Assert.AreEqual("https://box.com/declined_redirect_url_signer_1", response.Signers[0].DeclinedRedirectUrl.ToString()); @@ -183,6 +200,14 @@ public async Task CreateSignRequest_OptionalParams_Success() Assert.AreEqual("https://box.com/redirect_url", response.RedirectUrl.ToString()); Assert.AreEqual("https://box.com/declined_redirect_url", response.DeclinedRedirectUrl.ToString()); Assert.AreEqual("12345", response.TemplateId); + Assert.AreEqual("cd4ff89-8fc1-42cf-8b29-1890dedd26d7", response.Signers[0].SignerGroupId); + Assert.AreEqual("1234567890", response.Signers[0].VerificationPhoneNumber); + Assert.AreEqual("cd4ff89-8fc1-42cf-8b29-1890dedd26d7", response.Signers[1].SignerGroupId); + Assert.AreEqual("1234567890", response.Signers[1].VerificationPhoneNumber); + Assert.IsFalse(response.Signers[0].LoginRequired); + Assert.AreEqual("abcdefg", response.Signers[0].Password); + Assert.IsFalse(response.Signers[1].LoginRequired); + Assert.AreEqual("abcdefg", response.Signers[1].Password); } [TestMethod] diff --git a/Box.V2.Test/Fixtures/BoxSignRequest/CreateSignRequest200.json b/Box.V2.Test/Fixtures/BoxSignRequest/CreateSignRequest200.json index 69a076924..06e8955f8 100644 --- a/Box.V2.Test/Fixtures/BoxSignRequest/CreateSignRequest200.json +++ b/Box.V2.Test/Fixtures/BoxSignRequest/CreateSignRequest200.json @@ -71,7 +71,42 @@ "embed_url": "https://example.com", "redirect_url": "https://box.com/redirect_url_signer_1", "declined_redirect_url": "https://box.com/declined_redirect_url_signer_1", - "iframeable_embed_url": "https://app.box.com/embed/sign/document/bf7aaac6/" + "iframeable_embed_url": "https://app.box.com/embed/sign/document/bf7aaac6/", + "login_required": false, + "password": "abcdefg", + "signer_group_id": "cd4ff89-8fc1-42cf-8b29-1890dedd26d7", + "verification_phone_number": "1234567890" + }, + { + "email": "other-example@gmail.com", + "role": "signer", + "is_in_person": true, + "order": 2, + "embed_url_external_user_id": 1234, + "has_viewed_document": true, + "signer_decision": { + "type": "signed", + "finalized_at": "2021-04-26T08:12:13.982Z" + }, + "inputs": [ + { + "document_tag_id": 1234, + "text_value": "text", + "checkbox_value": true, + "date_value": "2021-04-26T08:12:13.982Z", + "type": "text", + "page_index": 4, + "content_type": "checkbox" + } + ], + "embed_url": "https://example.com", + "redirect_url": "https://box.com/redirect_url_signer_1", + "declined_redirect_url": "https://box.com/declined_redirect_url_signer_1", + "iframeable_embed_url": "https://app.box.com/embed/sign/document/bf7aaac6/", + "login_required": false, + "password": "abcdefg", + "signer_group_id": "cd4ff89-8fc1-42cf-8b29-1890dedd26d7", + "verification_phone_number": "1234567890" } ], "signing_log": { diff --git a/Box.V2/Models/BoxSignRequestSigner.cs b/Box.V2/Models/BoxSignRequestSigner.cs index 818253bdc..a513414e1 100644 --- a/Box.V2/Models/BoxSignRequestSigner.cs +++ b/Box.V2/Models/BoxSignRequestSigner.cs @@ -22,6 +22,11 @@ public class BoxSignRequestSigner public const string FieldDeclinedRedirectUrl = "declined_redirect_url"; public const string FieldRedirectUrl = "redirect_url"; public const string FieldIframeableEmbedUrl = "iframeable_embed_url"; + public const string FieldLoginRequired = "login_required"; + public const string FieldPassword = "password"; + public const string FieldSignerGroupId = "signer_group_id"; + public const string FieldVerificationPhoneNumber = "verification_phone_number"; + /// /// Email address of the signer. @@ -97,6 +102,33 @@ public class BoxSignRequestSigner /// [JsonProperty(PropertyName = FieldIframeableEmbedUrl)] public virtual string IframeableEmbedUrl { get; private set; } + + /// + /// If set to true, signer will need to login to a Box account before signing the request. + /// If the signer does not have an existing account, they will have an option to create a free Box account. + /// + [JsonProperty(PropertyName = FieldLoginRequired)] + public virtual bool LoginRequired { get; private set; } + + /// + /// If set, the signer is required to enter the password before they are able to sign a document. This field is write only. + /// + [JsonProperty(PropertyName = FieldPassword)] + public virtual string Password { get; private set; } + + /// + /// If set, signers who have the same group ID will be assigned to the same input. + /// A signer group is expected to have more than one signer. + /// When a group contains fewer than two signers, it will be converted to a single signer and the group will be removed. + /// + [JsonProperty(PropertyName = FieldSignerGroupId)] + public virtual string SignerGroupId { get; private set; } + + /// + /// If set, this phone number is be used to verify the signer via two factor authentication before they are able to sign the document. + /// + [JsonProperty(PropertyName = FieldVerificationPhoneNumber)] + public virtual string VerificationPhoneNumber { get; private set; } } /// diff --git a/Box.V2/Models/Request/BoxSignRequestCreateRequest.cs b/Box.V2/Models/Request/BoxSignRequestCreateRequest.cs index f3fbfc4ca..e3a57519b 100644 --- a/Box.V2/Models/Request/BoxSignRequestCreateRequest.cs +++ b/Box.V2/Models/Request/BoxSignRequestCreateRequest.cs @@ -190,5 +190,32 @@ public class BoxSignRequestSignerCreate /// [JsonProperty(PropertyName = "redirect_url")] public Uri RedirectUrl { get; set; } + + /// + /// If set to true, signer will need to login to a Box account before signing the request. + /// If the signer does not have an existing account, they will have an option to create a free Box account. + /// + [JsonProperty(PropertyName = "login_required")] + public bool? LoginRequired { get; set; } + + /// + /// If set, the signer is required to enter the password before they are able to sign a document. This field is write only. + /// + [JsonProperty(PropertyName = "password")] + public string Password { get; set; } + + /// + /// If set, signers who have the same group ID will be assigned to the same input. + /// A signer group is expected to have more than one signer. + /// When a group contains fewer than two signers, it will be converted to a single signer and the group will be removed. + /// + [JsonProperty(PropertyName = "signer_group_id")] + public string SignerGroupId { get; set; } + + /// + /// If set, this phone number is be used to verify the signer via two factor authentication before they are able to sign the document. + /// + [JsonProperty(PropertyName = "verification_phone_number")] + public string VerificationPhoneNumber { get; set; } } }