Skip to content

Commit ccc45e1

Browse files
committed
Initial draft of external signature generation
1 parent 0606c35 commit ccc45e1

File tree

2 files changed

+219
-181
lines changed

2 files changed

+219
-181
lines changed

Sources/TransloaditKit/Transloadit.swift

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ import Foundation
33

44
/// The errors that `Transloadit` can return
55
public enum TransloaditError: Error {
6-
76
case couldNotFetchStatus(underlyingError: Error)
87
case couldNotCreateAssembly(underlyingError: Error)
98
case couldNotUploadFile(underlyingError: Error)
109
case couldNotClearCache(underlyingError: Error)
1110
}
1211

12+
public enum SDKConfigurationError: Error {
13+
case missingClientSecret
14+
}
15+
1316
public protocol TransloaditFileDelegate: AnyObject {
1417

1518
func didStartUpload(assembly: Assembly, client: Transloadit)
@@ -31,6 +34,9 @@ public protocol TransloaditFileDelegate: AnyObject {
3134
func didError(error: Error, client: Transloadit)
3235
}
3336

37+
public typealias SignatureCompletion = (Result<String, Error>) -> Void
38+
public typealias SignatureGenerator = (String, SignatureCompletion) -> Void
39+
3440
/// Use the `Transloadit` class to upload files using the underlying TUS protocol.
3541
/// You can either create an Assembly by itself, or create an Assembly and upload files to it right away.
3642
///
@@ -42,9 +48,9 @@ public final class Transloadit {
4248

4349
public struct Credentials {
4450
let key: String
45-
let secret: String
51+
let secret: String?
4652

47-
public init(key: String, secret: String) {
53+
public init(key: String, secret: String?) {
4854
self.key = key
4955
self.secret = secret
5056
}
@@ -84,7 +90,18 @@ public final class Transloadit {
8490
/// then TUS will make a directory, whether one you specify or a default one in the documents directory.
8591
@available(*, deprecated, message: "Use the new init(credentials:sessionConfig:storageDir:) instead.")
8692
public init(credentials: Transloadit.Credentials, session: URLSession, storageDir: URL? = nil) {
87-
self.api = TransloaditAPI(credentials: credentials, session: session)
93+
self.api = TransloaditAPI(
94+
credentials: credentials,
95+
session: session,
96+
signatureGenerator: { parameterString, generationComplete in
97+
guard let secret = credentials.secret, !secret.isEmpty else {
98+
generationComplete(.failure(SDKConfigurationError.missingClientSecret))
99+
return
100+
}
101+
102+
generationComplete(.success("sha384:" + parameterString.hmac(key: secret)))
103+
}
104+
)
88105
self.storageDir = storageDir
89106
self.tusSessionConfig = session.configuration.copy(withIdentifier: "com.transloadit.tus.bg")
90107
}
@@ -97,7 +114,47 @@ public final class Transloadit {
97114
/// If left empty, no directory will be made when performing non-file related tasks, such as creating assemblies. However, if you start uploading files,
98115
/// then TUS will make a directory, whether one you specify or a default one in the documents directory.
99116
public init(credentials: Transloadit.Credentials, sessionConfiguration: URLSessionConfiguration, storageDir: URL? = nil) {
100-
self.api = TransloaditAPI(credentials: credentials, sessionConfiguration: sessionConfiguration)
117+
self.api = TransloaditAPI(
118+
credentials: credentials,
119+
sessionConfiguration: sessionConfiguration,
120+
signatureGenerator: { parameterString, generationComplete in
121+
guard let secret = credentials.secret, !secret.isEmpty else {
122+
generationComplete(.failure(SDKConfigurationError.missingClientSecret))
123+
return
124+
}
125+
126+
generationComplete(.success("sha384:" + parameterString.hmac(key: secret)))
127+
}
128+
)
129+
self.storageDir = storageDir
130+
self.tusSessionConfig = sessionConfiguration.copy(withIdentifier: "com.transloadit.tus.bg")
131+
}
132+
133+
/// Initialize Transloadit without a secret, providing a signature generator.
134+
/// - Parameters:
135+
/// - apiKey: Transloadit API key.
136+
/// - sessionConfiguration: A URLSessionConfiguration to use.
137+
/// - storageDir: A storagedirectory to use. Used by underlying TUSKit mechanism to store files.
138+
/// If left empty, no directory will be made when performing non-file related tasks, such as creating assemblies. However, if you start uploading files,
139+
/// then TUS will make a directory, whether one you specify or a default one in the documents directory.
140+
/// - signatureGenerator: A closure that's invoked to generate the signature for the API request. Implement your own logic to generate a valid
141+
/// signature. Call the provided completion handler with your signed string or an error as needed.
142+
///
143+
/// For example, you can make a request to your backend to generate the signature for you. The closure is passed a string that holds all request params
144+
/// that need to be signed. See https://transloadit.com/docs/api/authentication/ for more information on signature authentication.
145+
/// The closure is invoked by the TransloaditAPI when needed.
146+
///
147+
/// ** Important:** It's up to the caller to ensure that all codepaths (eventually) call the completion handler. The SDK does not implement any timeouts or fallbacks.
148+
public init(
149+
apiKey: String, sessionConfiguration: URLSessionConfiguration,
150+
storageDir: URL? = nil, signatureGenerator: @escaping SignatureGenerator
151+
) {
152+
let credentials = Transloadit.Credentials(key: apiKey, secret: nil)
153+
self.api = TransloaditAPI(
154+
credentials: credentials,
155+
sessionConfiguration: sessionConfiguration,
156+
signatureGenerator: signatureGenerator
157+
)
101158
self.storageDir = storageDir
102159
self.tusSessionConfig = sessionConfiguration.copy(withIdentifier: "com.transloadit.tus.bg")
103160
}

0 commit comments

Comments
 (0)