Swiftpack.co - cryptomator/cloud-access-swift as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
cryptomator/cloud-access-swift 0.13.5
Swift library for accessing various cloud providers incl. Cryptomator vaults
⭐️ 6
🕓 1 week ago
iOS
.package(url: "https://github.com/cryptomator/cloud-access-swift.git", from: "0.13.5")

Swift Compatibility Platform Compatibility Codacy Code Quality Codacy Coverage

Cloud Access Swift

This library defines the cloud access API used by Cryptomator for iOS.

The API is implemented once for each cloud. It also forms the foundation for decoration layers for the various vault formats that can be applied to get a cleartext view for cloud-stored vaults.

Requirements

  • iOS 13.0 or higher
  • Swift 5

Installation

Swift Package Manager

You can use Swift Package Manager.

.package(url: "https://github.com/cryptomator/cloud-access-swift.git", .upToNextMinor(from: "1.0.0"))

Usage

Core

The core package contains several protocols, structs, and enums that build the foundation of this library. Asynchronous calls are implemented using the Promises library. CloudProvider is the main protocol that defines the cloud access:

func fetchItemMetadata(at cloudPath: CloudPath) -> Promise<CloudItemMetadata>
func fetchItemList(forFolderAt cloudPath: CloudPath, withPageToken pageToken: String?) -> Promise<CloudItemList>
func downloadFile(from cloudPath: CloudPath, to localURL: URL) -> Promise<Void>
func uploadFile(from localURL: URL, to cloudPath: CloudPath, replaceExisting: Bool) -> Promise<CloudItemMetadata>
func createFolder(at cloudPath: CloudPath) -> Promise<Void>
func deleteFile(at cloudPath: CloudPath) -> Promise<Void>
func deleteFolder(at cloudPath: CloudPath) -> Promise<Void>
func moveFile(from sourceCloudPath: CloudPath, to targetCloudPath: CloudPath) -> Promise<Void>
func moveFolder(from sourceCloudPath: CloudPath, to targetCloudPath: CloudPath) -> Promise<Void>

Crypto

A vault provider decorates a cloud provider and allows transparent access to vaults based on Cryptomator's encryption scheme. It depends on cryptolib-swift for cryptographic functions and GRDB for thread-safe caching. For more information on the Cryptomator encryption scheme, visit the security architecture page on docs.cryptomator.org.

In order to create a vault provider, you need a Masterkey instance from cryptolib-swift. Check out its documentation on how to create a masterkey. And since vault format 8, you also need a UnverifiedVaultConfig instance:

let provider = ... // any other cloud provider
let vaultPath = ...
let masterkey = ...
let token = ...
let unverifiedVaultConfig = try UnverifiedVaultConfig(token: token)
let cryptoDecorator = try VaultProviderFactory.createVaultProvider(from: unverifiedVaultConfig, masterkey: masterkey, vaultPath: vaultPath, with: provider)

And to create a legacy vault provider for vault version 6 or 7:

let provider = ... // any other cloud provider
let vaultVersion = ... // use `version` from the `MasterkeyFile` instance
let vaultPath = ...
let masterkey = ...
let cryptoDecorator = try VaultProviderFactory.createLegacyVaultProvider(from: masterkey, vaultVersion: vaultVersion, vaultPath: vaultPath, with: provider)

:warning: This library supports vault version 6 and higher.

Dropbox

Set up the Info.plist as described in the official Dropbox Objective-C SDK. In addition, the following constants must be set once, e.g. in your app delegate:

let appKey = ... // your Dropbox app key
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `DropboxProvider` in an app extension and set `forceForegroundSession = false`
let keychainService = ... // the service name for the keychain, use `nil` to use default
let forceForegroundSession = ... // if set to `true`, all network requests are made on foreground sessions (by default, most download/upload operations are performed with a background session)
DropboxSetup.constants = DropboxSetup(appKey: appKey, sharedContainerIdentifier: sharedContainerIdentifier, keychainService: keychainService, forceForegroundSession: forceForegroundSession)

Begin the authentication flow:

let dropboxAuthenticator = DropboxAuthenticator()
let viewController = ... // the presenting `UIViewController`
dropboxAuthenticator.authenticate(from: viewController).then { credential in
  // do something with `DropboxCredential`
  // you probably want to save `credential.tokenUID` to re-create the credential later
}.catch { error in
  // error handling
}

Handle redirection once the authentication flow is complete in your app delegate:

func application(_: UIApplication, open url: URL, options _: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
  let canHandle = DBClientsManager.handleRedirectURL(url) { authResult in
    guard let authResult = authResult else {
      return
    }
    if authResult.isSuccess() {
      let tokenUID = authResult.accessToken.uid
      let credential = DropboxCredential(tokenUID: tokenUID)
      DropboxAuthenticator.pendingAuthentication?.fulfill(credential)
      } else if authResult.isCancel() {
        DropboxAuthenticator.pendingAuthentication?.reject(DropboxAuthenticatorError.userCanceled)
      } else if authResult.isError() {
        DropboxAuthenticator.pendingAuthentication?.reject(authResult.nsError)
      }
    }
  return canHandle
}

Create a Dropbox provider with a credential:

let tokenUID = ... // the `tokenUID` you saved after the successful authentication flow
let credential = DropboxCredential(tokenUID: tokenUID)
let provider = DropboxCloudProvider(credential: credential)

Google Drive

Modify your app delegate as described in AppAuth. In addition, the following constants must be set once, e.g. in your app delegate:

let clientId = ... // your Google Drive client identifier
let redirectURL = ...
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `GoogleDriveProvider` with a background `URLSession` in an app extension 
GoogleDriveSetup.constants = GoogleDriveSetup(clientId: clientId, redirectURL: redirectURL, sharedContainerIdentifier: sharedContainerIdentifier)

Begin the authentication flow:

let tokenUID = ... // optional: you might want to give this credential an identifier, defaults to a random UUID
let credential = GoogleDriveCredential(tokenUID: tokenUID)
let viewController = ... // the presenting `UIViewController`
GoogleDriveAuthenticator.authenticate(credential: credential, from: viewController).then { 
  // authentication successful
}.catch { error in
  // error handling
}

You can then use the credential to create a Google Drive provider:

let useBackgroundSession = ... // optional: only needed if you want to create a `GoogleDriveProvider` with a background `URLSession`, defaults to `false`
let provider = GoogleDriveCloudProvider(credential: credential, useBackgroundSession: useBackgroundSession)

OneDrive

Set up the Info.plist and your app delegate as described in MSAL. In addition, the following constants must be set once, e.g. in your app delegate:

OneDriveSetup.sharedContainerIdentifier = ... // optional: only needed if you want to create a `OneDriveProvider` with a background `URLSession` in an app extension
OneDriveSetup.clientApplication = ... // your `MSALPublicClientApplication`

Begin the authentication flow:

let viewController = ... // the presenting `UIViewController`
OneDriveAuthenticator.authenticate(from: viewController).then { credential in
  // do something with `OneDriveCredential`
  // you probably want to save `credential.identifier` to re-create the credential later
}.catch { error in
  // error handling
}

You can then use the credential to create a OneDrive provider:

let useBackgroundSession = ... // optional: only needed if you want to create a `OneDriveProvider` with a background `URLSession`, defaults to `false`
let provider = OneDriveCloudProvider(credential: credential, useBackgroundSession: useBackgroundSession)

WebDAV

Create a WebDAV credential:

let baseURL = ...
let username = ...
let password = ...
let allowedCertificate = ... // optional: you might want to allowlist a TLS certificate
let identifier = ... // optional: you might want to give this credential an identifier, defaults to a random UUID
let credential = WebDAVCredential(baseURL: baseURL, username: username, password: password, allowedCertificate: allowedCertificate, identifier: identifier)

You can then use the credential to create a WebDAV provider.

Create a WebDAV provider with a WebDAV client:

let client = WebDAVClient(credential: credential)
let provider = WebDAVProvider(with: client)

Create a WebDAV provider with a WebDAV client using a background URLSession:

let sharedContainerIdentifier = ... // optional: only needed if you want to create a `WebDAVProvider` in an app extension 
let client = WebDAVClient.withBackgroundSession(credential: credential, sharedContainerIdentifier: sharedContainerIdentifier)
let provider = WebDAVProvider(with: client)

In theory, you could use the provider without further checks. However, you should verify the WebDAV client and its credential using the WebDAV authenticator:

let client = ...
WebDAVAuthenticator.verifyClient(client: client).then {
  // client validation successful
}.catch { error in
  // error handling
}

Furthermore, for allowlisting a certificate, you can use the TLS certificate validator:

let baseURL = ...
let validator = TLSCertificateValidator(baseURL: baseURL)
validator.validate().then { certificate in
  // certificate of type `TLSCertificate` contains several properties for further handling
}.catch { error in
  // error handling
}

Local File System

Since the local file system is not actually a cloud, the naming might be confusing. Even though this library is dedicated to provide access to many cloud storage services, access to the local file system still might be useful.

Create a local file system provider with a root URL:

let rootURL = ... // rootURL.isFileURL must be `true`
let provider = LocalFileSystemProvider(rootURL: rootURL)

When calling the functions of this provider, the cloud paths should be provided relative to the root URL.

This provider uses NSFileCoordinator for its operations and supports asynchronous access.

Integration Tests

You can learn more about cloud provider integration tests here.

Contributing

Please read our contribution guide, if you would like to report a bug, ask a question or help us with coding.

This project uses SwiftFormat and SwiftLint to enforce code style and conventions. Install these tools if you haven't already.

Please make sure that your code is correctly formatted and passes linter validations. The easiest way to do that is to set up a pre-commit hook. Create a file at .git/hooks/pre-commit with this content:

./Scripts/process.sh --staged
exit $?

And make your pre-commit hook executable:

chmod +x .git/hooks/pre-commit

Code of Conduct

Help us keep Cryptomator open and inclusive. Please read and follow our Code of Conduct.

License

Distributed under the AGPLv3. See the LICENSE file for more info.

GitHub

link
Stars: 6
Last commit: 3 days ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Submit a free job ad (while I'm testing this). The analytics numbers for this website are here.

Release Notes

0.13.5
1 week ago
  • Updated cryptolib-swift dependency

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics