Skip to content

Commit

Permalink
Revise and improve documentation (#17)
Browse files Browse the repository at this point in the history
# Revise and improve documentation

## ♻️ Current situation & Problem
This PR revises some of the documentation of `SpeziStorage`. Further, we
tag the latest 1.0 releases of the Spezi frameworks.


## ⚙️ Release Notes 
* Update documentation
* Tag latest 1.0 Spezi releases
* **Breaking**: The enum case `encyptionNotPossible` of the type
`LocalStorageError` was renamed to `encryptionNotPossible` to fix a
spelling mistake.

## 📝 Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
Supereg authored Jan 9, 2024
1 parent e9be3c2 commit eaed222
Show file tree
Hide file tree
Showing 10 changed files with 40 additions and 36 deletions.
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ let package = Package(
.library(name: "SpeziSecureStorage", targets: ["SpeziSecureStorage"])
],
dependencies: [
.package(url: "https://github.com/StanfordSpezi/Spezi", .upToNextMinor(from: "0.8.0")),
.package(url: "https://github.com/StanfordBDHG/XCTRuntimeAssertions", .upToNextMinor(from: "0.2.5"))
.package(url: "https://github.com/StanfordSpezi/Spezi", from: "1.0.0"),
.package(url: "https://github.com/StanfordBDHG/XCTRuntimeAssertions", from: "1.0.0")
],
targets: [
.target(
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ SPDX-License-Identifier: MIT
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStanfordSpezi%2FSpeziStorage%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/StanfordSpezi/SpeziStorage)
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStanfordSpezi%2FSpeziStorage%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/StanfordSpezi/SpeziStorage)

The Spezi Storage module consists of two sub-modules that enable on-disk storage of information.
The Spezi Storage framework provides two Modules that enable on-disk storage of information.
The [`LocalStorage`](https://swiftpackageindex.com/stanfordspezi/spezistorage/documentation/spezilocalstorage/localstorage) module can be used to store information that does not need to be encrypted.
Credentials, keys, and other sensitive information that needs to be encrypted may be stored by using the [`SecureStorage`](https://swiftpackageindex.com/StanfordSpezi/SpeziStorage/documentation/spezisecurestorage) module.

Expand Down Expand Up @@ -62,7 +62,7 @@ struct ExampleStorageView: View {
}
```

Alternatively, it is common to use the [`LocalStorage`](https://swiftpackageindex.com/stanfordspezi/spezistorage/documentation/spezilocalstorage/localstorage) or [`SecureStorage`](https://swiftpackageindex.com/StanfordSpezi/SpeziStorage/documentation/spezisecurestorage) module in other modules as a dependency: [Spezi component dependencies](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/component#Dependencies).
Alternatively, it is common to use the [`LocalStorage`](https://swiftpackageindex.com/stanfordspezi/spezistorage/documentation/spezilocalstorage/localstorage) or [`SecureStorage`](https://swiftpackageindex.com/StanfordSpezi/SpeziStorage/documentation/spezisecurestorage) module in other modules as a dependency: [Spezi Module dependencies](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/module-dependency).


## Local Storage
Expand Down
15 changes: 9 additions & 6 deletions Sources/SpeziLocalStorage/LocalStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import Spezi
import SpeziSecureStorage


/// The ``LocalStorage/`` module enables the on-disk storage of data in mobile applications.
/// The module relies on the `SecureStorage` module to enable an encrypted on-disk storage as defined by the ``LocalStorageSetting`` configuration.
/// On-disk storage of data in mobile applications.
///
/// The module relies on the [`SecureStorage`](https://swiftpackageindex.com/StanfordSpezi/SpeziStorage/documentation/spezisecurestorage)
/// module to enable an encrypted on-disk storage as defined by the ``LocalStorageSetting`` configuration.
///
/// Use ``LocalStorage/store(_:storageKey:settings:)`` to store elements on disk and define the settings using a ``LocalStorageSetting`` instance.
///
Expand All @@ -25,7 +27,7 @@ public final class LocalStorage: Module, DefaultInitializable, EnvironmentAccess

private var localStorageDirectory: URL {
// We store the files in the application support directory as described in
// https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
// [File System Basics](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html).
let paths = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
let localStoragePath = paths[0].appendingPathComponent("edu.stanford.spezi/LocalStorage")
if !FileManager.default.fileExists(atPath: localStoragePath.path) {
Expand Down Expand Up @@ -103,12 +105,12 @@ public final class LocalStorage: Module, DefaultInitializable, EnvironmentAccess

// Encryption enabled:
guard SecKeyIsAlgorithmSupported(keys.publicKey, .encrypt, encryptionAlgorithm) else {
throw LocalStorageError.encyptionNotPossible
throw LocalStorageError.encryptionNotPossible
}

var encryptError: Unmanaged<CFError>?
guard let encryptedData = SecKeyCreateEncryptedData(keys.publicKey, encryptionAlgorithm, data as CFData, &encryptError) as Data? else {
throw LocalStorageError.encyptionNotPossible
throw LocalStorageError.encryptionNotPossible
}

try encryptedData.write(to: fileURL)
Expand All @@ -128,6 +130,7 @@ public final class LocalStorage: Module, DefaultInitializable, EnvironmentAccess
/// ```
///
/// - Parameters:
/// - type: The `Decodable` type that is used to decode the data from disk.
/// - storageKey: An optional storage key to identify the file.
/// - settings: The ``LocalStorageSetting``s used to retrieve the file on disk.
/// - Returns: The element conforming to `Decodable`.
Expand Down Expand Up @@ -180,7 +183,7 @@ public final class LocalStorage: Module, DefaultInitializable, EnvironmentAccess
/// Use ``delete(storageKey:)`` to manually define the storage key.
///
/// - Parameters:
/// - type: The `Decodable` type that is used to derive the storage key from.
/// - type: The `Encodable` type that is used to store the type originally.
public func delete<C: Encodable>(_ type: C.Type = C.self) throws {
try delete(C.self, storageKey: nil)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SpeziLocalStorage/LocalStorageError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/// An error thrown by the ``LocalStorage`` module.
enum LocalStorageError: Error {
/// Encryption of the file was not possible, did not store the data on disk.
case encyptionNotPossible
case encryptionNotPossible
/// Adding the file descriptor to exclude the file from backup could not be achieved.
case couldNotExcludedFromBackup
/// Decrypting the file was not possible with the given ``LocalStorageSetting``, please check that this is the ``LocalStorageSetting`` that you used to store the element.
Expand Down
4 changes: 2 additions & 2 deletions Sources/SpeziLocalStorage/LocalStorageSetting.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Spezi
import SpeziSecureStorage


/// The ``LocalStorageSetting`` enables configuring how data in the ``LocalStorage`` module can be stored and retrieved.
/// Configure how data in the ``LocalStorage`` module can be stored and retrieved.
public enum LocalStorageSetting {
/// Unencrypted
case unencrypted(excludedFromBackup: Bool = true)
Expand Down Expand Up @@ -57,7 +57,7 @@ public enum LocalStorageSetting {

let privateKey = try secureStorage.createKey(tag)
guard let publicKey = try secureStorage.retrievePublicKey(forTag: tag) else {
throw LocalStorageError.encyptionNotPossible
throw LocalStorageError.encryptionNotPossible
}

return (privateKey, publicKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ Store data encryped on-disk.

## Overview

The ``LocalStorage`` module enables the on-disk storage of data in mobile applications.
The `LocalStorage` module enables the on-disk storage of data in mobile applications.

The ``LocalStorage`` module defaults to storing data encrypted supported by the [`SecureStorage`](https://swiftpackageindex.com/StanfordSpezi/SpeziStorage/documentation/spezisecurestorage) module.
The ``LocalStorageSetting`` enables configuring how data in the ``LocalStorage`` module can be stored and retrieved.
The module defaults to storing data encrypted supported by the [`SecureStorage`](https://swiftpackageindex.com/StanfordSpezi/SpeziStorage/documentation/spezisecurestorage) module.
The ``LocalStorageSetting`` enables configuring how data in the `LocalStorage` module can be stored and retrieved.


## Setup
Expand All @@ -28,7 +28,7 @@ You need to add the Spezi Storage Swift package to

> Important: If your application is not yet configured to use Spezi, follow the [Spezi setup article](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/initial-setup) to set up the core Spezi infrastructure.
You can configure the ``LocalStorage`` module in the [`SpeziAppDelegate`](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/speziappdelegate).
You can configure the `LocalStorage` module in the [`SpeziAppDelegate`](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/speziappdelegate).

```swift
import Spezi
Expand All @@ -50,15 +50,14 @@ You can then use the ``LocalStorage`` class in any SwiftUI view.
```swift
struct ExampleStorageView: View {
@Environment(LocalStorage.self) var localStorage



var body: some View {
// ...
}
}
```

Alternatively, it is common to use the ``LocalStorage`` module in other modules as a dependency: [Spezi component dependencies](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/component#Dependencies).
Alternatively, it is common to use the ``LocalStorage`` module in other modules as a dependency: [Spezi Module dependencies](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/module-dependency).


## Use the LocalStorage Module
Expand Down
7 changes: 4 additions & 3 deletions Sources/SpeziSecureStorage/SecureStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import Spezi
import XCTRuntimeAssertions


/// The ``SecureStorage`` serves as a reusable `Module` that can be used to store small chunks of data such as credentials and keys.
/// Securely store small chunks of data such as credentials and keys.
///
/// The storing of credentials and keys follows the Keychain documentation provided by Apple: https://developer.apple.com/documentation/security/keychain_services/keychain_items/using_the_keychain_to_manage_user_secrets.
/// The storing of credentials and keys follows the Keychain documentation provided by Apple:
/// [Using the keychain to manage user secrets](https://developer.apple.com/documentation/security/keychain_services/keychain_items/using_the_keychain_to_manage_user_secrets).
public final class SecureStorage: Module, DefaultInitializable, EnvironmentAccessible {
/// The ``SecureStorage`` serves as a reusable `Module` that can be used to store store small chunks of data such as credentials and keys.
///
/// The storing of credentials and keys follows the Keychain documentation provided by Apple:
/// https://developer.apple.com/documentation/security/keychain_services/keychain_items/using_the_keychain_to_manage_user_secrets.
/// [Using the keychain to manage user secrets](https://developer.apple.com/documentation/security/keychain_services/keychain_items/using_the_keychain_to_manage_user_secrets).
public required init() {}


Expand Down
6 changes: 3 additions & 3 deletions Sources/SpeziSecureStorage/SecureStorageError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ public enum SecureStorageError: Error {
case notFound
/// The error is thrown if an entitlement is missing to use the KeyChain.
/// Refer to
/// https://developer.apple.com/documentation/security/keychain_services/keychain_items/using_the_keychain_to_manage_user_secrets
/// [Using the keychain to manage user secrets](https://developer.apple.com/documentation/security/keychain_services/keychain_items/using_the_keychain_to_manage_user_secrets)
/// about more information about the KeyChain services.
///
/// If you try to use an access group to which your app doesnt belong, the operation also fails and returns the `missingEntitlement` error.
/// If you try to use an access group to which your app doesn't belong, the operation also fails and returns the `missingEntitlement` error.
/// Please refer to
/// https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps
/// [Sharing access to keychain items among a collection of apps](https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps)
/// for more information about KeyChain access groups.
/// Remove the ``SecureStorageScope``'s `accessGroup` configuration value if you do not intend to use KeyChain access groups.
case missingEntitlement
Expand Down
12 changes: 6 additions & 6 deletions Sources/SpeziSecureStorage/SecureStorageScope.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ public enum SecureStorageScope: Equatable, Identifiable {
case secureEnclave(userPresence: Bool = false)
/// Store the element in the Keychain
///
/// The `userPresence` flag indicates if a retrieval of the item requires user presence.
/// https://developer.apple.com/documentation/security/keychain_services/keychain_items/restricting_keychain_item_accessibility
/// The `userPresence` flag indicates if a retrieval of the item requires user presence
/// (see [Restricting keychain item accessibility](https://developer.apple.com/documentation/security/keychain_services/keychain_items/restricting_keychain_item_accessibility)).
///
/// The `accessGroup` defines the access group used to store the element and share it across different applications:
/// https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps
/// [Sharing access to keychain items among a collection of apps](https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps).
case keychain(userPresence: Bool = false, accessGroup: String? = nil)
/// Store the element in the Keychain and enable it to be synchronizable between different instances of user devices.
///
/// The `userPresence` flag indicates if a retrieval of the item requires user presence.
/// https://developer.apple.com/documentation/security/keychain_services/keychain_items/restricting_keychain_item_accessibility
/// The `userPresence` flag indicates if a retrieval of the item requires user presence
/// (see [Restricting keychain item accessibility](https://developer.apple.com/documentation/security/keychain_services/keychain_items/restricting_keychain_item_accessibility)).
///
/// The `accessGroup` defines the access group used to store the element and share it across different applications:
/// https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps
/// [Sharing access to keychain items among a collection of apps](https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps).
case keychainSynchronizable(accessGroup: String? = nil)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ Securely store small chunks of data, such as credentials and keys.

## Overview

The ``SecureStorage`` module allows for the encrypted storage of small chunks of sensitive user data, such as usernames and passwords for internet services, using Apple's [Keychain documentation](https://developer.apple.com/documentation/security/keychain_services/keychain_items/using_the_keychain_to_manage_user_secrets).
The `SecureStorage` module allows for the encrypted storage of small chunks of sensitive user data, such as usernames and passwords for internet services,
using Apple's [Keychain](https://developer.apple.com/documentation/security/keychain_services/keychain_items/using_the_keychain_to_manage_user_secrets).

Credentials can be stored in the Secure Enclave (if available) or the Keychain. Credentials stored in the Keychain can be made synchronizable between different instances of user devices.
Credentials can be stored in the Secure Enclave (if available) or the Keychain. Credentials stored in the Keychain can be made synchronizable between different instances of user devices.


## Setup
Expand Down Expand Up @@ -50,15 +52,14 @@ You can then use the ``SecureStorage`` class in any SwiftUI view.
```swift
struct ExampleStorageView: View {
@Environment(SecureStorage.self) var secureStorage



var body: some View {
// ...
}
}
```

Alternatively, it is common to use the ``SecureStorage`` module in other modules as a dependency: [Spezi component dependencies](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/component#Dependencies).
Alternatively, it is common to use the ``SecureStorage`` module in other modules as a dependency: [Spezi Module dependencies](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/module-dependency).


## Use the SecureStorage Module
Expand Down

0 comments on commit eaed222

Please sign in to comment.