Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for additional fields in SignRequest #919

Merged
merged 2 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion BoxSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -119,6 +119,8 @@
05F6C90226F137B9008F38C0 /* Quick.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 056FE12726EF6F6800098F00 /* Quick.xcframework */; };
05F770D426F337FA00BDECA2 /* FileLogDestinationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05F770D326F337FA00BDECA2 /* FileLogDestinationSpec.swift */; };
05FA797527D793B100669B6D /* CCGAuthSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05FA797427D793B100669B6D /* CCGAuthSession.swift */; };
05FAB0C72B9782AE000B22E0 /* SignRequestSignatureColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05FAB0C62B9782AE000B22E0 /* SignRequestSignatureColor.swift */; };
05FAB0CA2B9861B3000B22E0 /* SignRequestSignatureColorSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05FAB0C82B98614C000B22E0 /* SignRequestSignatureColorSpecs.swift */; };
0BD51EDC28CF257E000DE69E /* RetentionPoliciesModuleIntegrationSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BD51EDB28CF257E000DE69E /* RetentionPoliciesModuleIntegrationSpecs.swift */; };
0C00835C229C06FE0067C1AF /* GetFolderInfo.json in Resources */ = {isa = PBXBuildFile; fileRef = 0C00835B229C06FE0067C1AF /* GetFolderInfo.json */; };
0C00836E229C41CA0067C1AF /* FolderCollaborations.json in Resources */ = {isa = PBXBuildFile; fileRef = 0C00836D229C41CA0067C1AF /* FolderCollaborations.json */; };
Expand Down Expand Up @@ -741,6 +743,8 @@
05F59F1026FCAB4E00D9A539 /* ArrayInputStreamSpecs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayInputStreamSpecs.swift; sourceTree = "<group>"; };
05F770D326F337FA00BDECA2 /* FileLogDestinationSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileLogDestinationSpec.swift; sourceTree = "<group>"; };
05FA797427D793B100669B6D /* CCGAuthSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CCGAuthSession.swift; sourceTree = "<group>"; };
05FAB0C62B9782AE000B22E0 /* SignRequestSignatureColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignRequestSignatureColor.swift; sourceTree = "<group>"; };
05FAB0C82B98614C000B22E0 /* SignRequestSignatureColorSpecs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignRequestSignatureColorSpecs.swift; sourceTree = "<group>"; };
0BD51EDB28CF257E000DE69E /* RetentionPoliciesModuleIntegrationSpecs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RetentionPoliciesModuleIntegrationSpecs.swift; sourceTree = "<group>"; };
0C00835B229C06FE0067C1AF /* GetFolderInfo.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = GetFolderInfo.json; sourceTree = "<group>"; };
0C00835F229C08F40067C1AF /* FolderUploadEmail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderUploadEmail.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1694,6 +1698,7 @@
225639202253897D00D951B5 /* SharedLink.swift */,
05610A942710612A009F92CC /* SignRequest.swift */,
05610A9A271099A7009F92CC /* SignRequestPrefillTag.swift */,
05FAB0C62B9782AE000B22E0 /* SignRequestSignatureColor.swift */,
05610A9627106ACA009F92CC /* SignRequestSigner.swift */,
054D789827158DAB00E1E273 /* SignRequestSignerDecision.swift */,
05610A9C27109BFB009F92CC /* SignRequestSignerInput.swift */,
Expand Down Expand Up @@ -2147,6 +2152,7 @@
F99DB496233C41440065317F /* RetentionPolicySpecs.swift */,
05F59F0826FC871A00D9A539 /* SharedItemSpecs.swift */,
05EE814B2718658F006A2329 /* SignRequestPrefillTagSpecs.swift */,
05FAB0C82B98614C000B22E0 /* SignRequestSignatureColorSpecs.swift */,
05EE814927186427006A2329 /* SignRequestSignerDecisionTypeSpecs.swift */,
050E725028BE54C000213B4D /* SignRequestSignerInputContentTypeSpecs.swift */,
05EE814D27186880006A2329 /* SignRequestSignerInputTypeSpecs.swift */,
Expand Down Expand Up @@ -2983,6 +2989,7 @@
225639AA2253897D00D951B5 /* FilesModule.swift in Sources */,
2263863E2306D5BD002CE1BE /* UploadPart.swift in Sources */,
9717866B22F0B868004A5F6D /* LockData.swift in Sources */,
05FAB0C72B9782AE000B22E0 /* SignRequestSignatureColor.swift in Sources */,
9D9C80A422D8E11000AFC18C /* NullableParameter.swift in Sources */,
225639322253897D00D951B5 /* Coders.swift in Sources */,
22C41459231FDB4B00D3992C /* MetadataCascadePolicy.swift in Sources */,
Expand Down Expand Up @@ -3131,6 +3138,7 @@
0C506CA922A6AA76007F18A4 /* CollaborationsModuleSpecs.swift in Sources */,
97F04DBA22B981430034B9A3 /* GroupSpecs.swift in Sources */,
9771D4DF22B01CC200B76DF8 /* CollaborationSpecs.swift in Sources */,
05FAB0CA2B9861B3000B22E0 /* SignRequestSignatureColorSpecs.swift in Sources */,
0C63989F2253A536004021D3 /* FolderModuleSpecs.swift in Sources */,
9DB4F7BC22E1EBAA002C4697 /* BoxModelSpecs.swift in Sources */,
8053E2D022B04534000B42E1 /* SharedItemsModuleSpecs.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Cartfile.private
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
github "Quick/Quick" "v7.0.0"
github "Quick/Nimble" "v12.0.0"
github "AliSoftware/OHHTTPStubs" "9.1.0"
github "AliSoftware/OHHTTPStubs" "master"
2 changes: 1 addition & 1 deletion Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
github "AliSoftware/OHHTTPStubs" "9.1.0"
github "AliSoftware/OHHTTPStubs" "c582400a38590a3dabb4353416d9d46cb7278d06"
github "Quick/Nimble" "v12.0.0"
github "Quick/Quick" "v7.0.0"
54 changes: 46 additions & 8 deletions IntegrationTests/SignRequestsModuleIntegrationSpecs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,40 @@ class SignRequestsModuleIntegrationSpecs: QuickSpec {
return
}

let signer = SignRequestCreateSigner(
email: "sdk_integration_test@boxdemo.com",
role: .signer,
redirectUrl: "https://www.box.com/redirect_url_signer_1",
declinedRedirectUrl: "https://www.box.com/declined_redirect_url_singer_1"
)
let signers = [
SignRequestCreateSigner(
email: "sdk_integration_test_1@boxdemo.com",
role: .signer,
redirectUrl: "https://www.box.com/redirect_url_signer_1",
declinedRedirectUrl: "https://www.box.com/declined_redirect_url_singer_1",
loginRequired: false,
password: "password",
signerGroupId: "SignerGroup"
),
SignRequestCreateSigner(
email: "sdk_integration_test_2@boxdemo.com",
role: .signer,
redirectUrl: "https://www.box.com/redirect_url_signer_2",
declinedRedirectUrl: "https://www.box.com/declined_redirect_url_singer_2",
loginRequired: false,
verificationPhoneNumber: "+48123456789",
password: "password",
signerGroupId: "SignerGroup"
)
]

let signParameters = SignRequestCreateParameters(
redirectUrl: "https://www.box.com/redirect_url",
declinedRedirectUrl: "https://www.box.com/declined_redirect_url"
declinedRedirectUrl: "https://www.box.com/declined_redirect_url",
name: "Sign created by iOS SDK",
isPhoneVerificationRequiredToView: false,
signatureColor: .black
)

// Create
waitUntil(timeout: .seconds(Constants.Timeout.large)) { done in
client.signRequests.create(
signers: [signer],
signers: signers,
sourceFiles: [
SignRequestCreateSourceFile(id: fileToSign1.id),
SignRequestCreateSourceFile(id: fileToSign2.id)
Expand All @@ -73,10 +91,30 @@ class SignRequestsModuleIntegrationSpecs: QuickSpec {
switch result {
case let .success(signRequestResult):
signRequest = signRequestResult
expect(signRequest?.name).to(equal(signParameters.name))
expect(signRequest?.isPhoneVerificationRequiredToView).to(equal(signParameters.isPhoneVerificationRequiredToView))
expect(signRequest?.signatureColor).to(equal(signParameters.signatureColor))
expect(signRequest?.redirectUrl).to(equal(signParameters.redirectUrl))
expect(signRequest?.declinedRedirectUrl).to(equal(signParameters.declinedRedirectUrl))
expect(signRequest?.parentFolder.id).to(equal(rootFolder.id))
expect(signRequest?.signFiles?.files?.count).to(equal(2))
// first signer is the sender with role final_copy_reader, second and third is the recipient with role signer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it also possible to assert roles in this test?

expect(signRequest?.signers.count).to(equal(3))
expect(signRequest?.signers[0].role).to(equal(.finalCopyReader))
expect(signRequest?.signers[1].signerGroupId).notTo(beNil())
expect(signRequest?.signers[1].signerGroupId).to(equal(signRequest?.signers[2].signerGroupId))
expect(signRequest?.signers[1].role).to(equal(.signer))
expect(signRequest?.signers[1].email).to(equal(signers[0].email))
expect(signRequest?.signers[1].redirectUrl).to(equal(signers[0].redirectUrl))
expect(signRequest?.signers[1].declinedRedirectUrl).to(equal(signers[0].declinedRedirectUrl))
expect(signRequest?.signers[1].loginRequired).to(equal(signers[0].loginRequired))
expect(signRequest?.signers[2].signerGroupId).notTo(beNil())
expect(signRequest?.signers[2].role).to(equal(.signer))
expect(signRequest?.signers[2].email).to(equal(signers[1].email))
expect(signRequest?.signers[2].redirectUrl).to(equal(signers[1].redirectUrl))
expect(signRequest?.signers[2].declinedRedirectUrl).to(equal(signers[1].declinedRedirectUrl))
expect(signRequest?.signers[2].loginRequired).to(equal(signers[1].loginRequired))
expect(signRequest?.signers[2].verificationPhoneNumber).to(equal(signers[1].verificationPhoneNumber))
case let .failure(error):
fail("Expected create call to succeed, but instead got \(error)")
}
Expand Down
52 changes: 50 additions & 2 deletions Sources/Requests/BodyData/SignRequestCreateParameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ public struct SignRequestCreateSigner: Encodable {
public let redirectUrl: String?
/// The URL that a signer will be redirect to after declining to sign a document.
public let declinedRedirectUrl: String?
/// 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.
public let loginRequired: Bool?
/// If set, this phone number is be used to verify the signer via two factor authentication before they are able to sign the document.
public let verificationPhoneNumber: String?
/// If set, the signer is required to enter the password before they are able to sign a document. This field is write only.
public let password: String?
/// If set, signers who have the same value will be assigned to the same input and to the same signer group.
/// A signer group is expected to have more than one signer.
/// If the provided value is only used for one signer, this value will be ignored and request will be handled
/// as it was intended for an individual signer. The value provided can be any string and only used to
/// determine which signers belongs to same group. A successful response will provide a generated UUID value
/// instead for signers in the same signer group.
public let signerGroupId: String?

/// Initializer.
///
Expand All @@ -121,14 +135,24 @@ public struct SignRequestCreateSigner: Encodable {
/// - embedUrlExternalUserId: User ID for the signer in an external application responsible for authentication when accessing the embed URL.
/// - redirectUrl: The URL that the signer will be redirected to after signing.
/// - declinedRedirectUrl: The URL that a signer will be redirect to after declining to sign a document.
/// - loginRequired: 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.
/// - verificationPhoneNumber: If set, the signer is required to enter the password before they are able to sign a document. This field is write only.
/// - password: If set, the signer is required to enter the password before they are able to sign a document. This field is write only.
/// - signerGroupId: If set, signers who have the same value will be assigned to the same input and to the same signer group.
/// A signer group is expected to have more than one signer.
public init(
email: String,
role: SignRequestSignerRole? = nil,
isInPerson: Bool? = nil,
order: Int? = nil,
embedUrlExternalUserId: String? = nil,
redirectUrl: String? = nil,
declinedRedirectUrl: String? = nil
declinedRedirectUrl: String? = nil,
loginRequired: Bool? = nil,
verificationPhoneNumber: String? = nil,
password: String? = nil,
signerGroupId: String? = nil
) {
self.email = email
self.role = role
Expand All @@ -137,6 +161,10 @@ public struct SignRequestCreateSigner: Encodable {
self.embedUrlExternalUserId = embedUrlExternalUserId
self.redirectUrl = redirectUrl
self.declinedRedirectUrl = declinedRedirectUrl
self.loginRequired = loginRequired
self.verificationPhoneNumber = verificationPhoneNumber
self.password = password
self.signerGroupId = signerGroupId
}
}

Expand Down Expand Up @@ -170,6 +198,14 @@ public struct SignRequestCreateParameters: Encodable {
public let redirectUrl: String?
/// The URL that the signer will be redirected to after declining to sign a document.
public let declinedRedirectUrl: String?
/// Name of the sign request.
public let name: String?
/// Forces signers to verify a text message prior to viewing the document. You must specify the phone number of signers to have this setting apply to them.
public let isPhoneVerificationRequiredToView: Bool?
/// When a signature request is created from a template this field will indicate the id of that template.
public let templateId: String?
/// Specific color for the signature (blue, black, or red).
public let signatureColor: SignRequestSignatureColor?

/// Initializer.
///
Expand All @@ -184,6 +220,10 @@ public struct SignRequestCreateParameters: Encodable {
/// - externalId: ID that serve as reference in an external system that the sign request is related to.
/// - redirectUrl: The URL that a signer will be redirected to after signing a document.
/// - declinedRedirectUrl: The URL that the signer will be redirected to after declining to sign a document.
/// - name: Name of the sign request.
/// - isPhoneVerificationRequiredToView: Forces signers to verify a text message prior to viewing the document. You must specify the phone number of signers to have this setting apply to them.
/// - templateId: When a signature request is created from a template this field will indicate the id of that template.
/// - signatureColor: Force a specific color for the signature (blue, black, or red).
public init(
isDocumentPreparationNeeded: Bool? = nil,
areTextSignaturesEnabled: Bool? = nil,
Expand All @@ -194,7 +234,11 @@ public struct SignRequestCreateParameters: Encodable {
daysValid: Int? = nil,
externalId: String? = nil,
redirectUrl: String? = nil,
declinedRedirectUrl: String? = nil
declinedRedirectUrl: String? = nil,
name: String? = nil,
isPhoneVerificationRequiredToView: Bool? = nil,
templateId: String? = nil,
signatureColor: SignRequestSignatureColor? = nil
) {
self.isDocumentPreparationNeeded = isDocumentPreparationNeeded
self.areTextSignaturesEnabled = areTextSignaturesEnabled
Expand All @@ -206,5 +250,9 @@ public struct SignRequestCreateParameters: Encodable {
self.externalId = externalId
self.redirectUrl = redirectUrl
self.declinedRedirectUrl = declinedRedirectUrl
self.name = name
self.isPhoneVerificationRequiredToView = isPhoneVerificationRequiredToView
self.templateId = templateId
self.signatureColor = signatureColor
}
}
12 changes: 12 additions & 0 deletions Sources/Responses/SignRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ public class SignRequest: BoxModel {
public let redirectUrl: String?
/// The URL that a signer will be redirected to after declined signing a document.
public let declinedRedirectUrl: String?
/// Name of the sign request.
public let name: String?
/// Forces signers to verify a text message prior to viewing the document. You must specify the phone number of signers to have this setting apply to them.
public let isPhoneVerificationRequiredToView: Bool?
/// When a signature request is created from a template this field will indicate the id of that template.
public let templateId: String?
/// Specific color for the signature (blue, black, or red).
public let signatureColor: SignRequestSignatureColor?

/// Initializer.
///
Expand Down Expand Up @@ -198,5 +206,9 @@ public class SignRequest: BoxModel {
externalId = try BoxJSONDecoder.optionalDecode(json: json, forKey: "external_id")
redirectUrl = try BoxJSONDecoder.optionalDecode(json: json, forKey: "redirect_url")
declinedRedirectUrl = try BoxJSONDecoder.optionalDecode(json: json, forKey: "declined_redirect_url")
name = try BoxJSONDecoder.optionalDecode(json: json, forKey: "name")
isPhoneVerificationRequiredToView = try BoxJSONDecoder.optionalDecode(json: json, forKey: "is_phone_verification_required_to_view")
templateId = try BoxJSONDecoder.optionalDecode(json: json, forKey: "template_id")
signatureColor = try BoxJSONDecoder.optionalDecodeEnum(json: json, forKey: "signature_color")
}
}
47 changes: 47 additions & 0 deletions Sources/Responses/SignRequestSignatureColor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// SignRequestSignatureColor.swift
// BoxSDK-iOS
//
// Created by Artur Jankowski on 05/03/2024.
// Copyright © 2024 box. All rights reserved.
//

import Foundation

/// Force a specific color for the signature
public enum SignRequestSignatureColor: BoxEnum {
/// blue color
case blue
/// black color
case black
/// red color
case red
/// A custom value not implemented in this version of SDK.
case customValue(String)

public init(_ value: String) {
switch value {
case "blue":
self = .blue
case "black":
self = .black
case "red":
self = .red
default:
self = .customValue(value)
}
}

public var description: String {
switch self {
case .blue:
return "blue"
case .black:
return "black"
case .red:
return "red"
case let .customValue(userValue):
return userValue
}
}
}
Loading
Loading