Skip to content

Commit

Permalink
feat: Add support for additional fields in SignRequest (#919)
Browse files Browse the repository at this point in the history
  • Loading branch information
arjankowski authored Mar 8, 2024
1 parent a05b243 commit 36f464c
Show file tree
Hide file tree
Showing 14 changed files with 351 additions and 25 deletions.
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: "[email protected]",
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: "[email protected]",
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: "[email protected]",
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
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

0 comments on commit 36f464c

Please sign in to comment.