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

SpeziStorage #108

Merged
merged 24 commits into from
Oct 27, 2024
Merged

SpeziStorage #108

merged 24 commits into from
Oct 27, 2024

Conversation

pauljohanneskraft
Copy link
Contributor

SpeziStorage

♻️ Current situation & Problem

This pull request adds SpeziStorage functionality to this repository.

⚙️ Release Notes

Add a bullet point list summary of the feature and possible migration guides if this is a breaking change so this section can be added to the release notes.
Include code snippets that provide examples of the feature implemented or links to the documentation if it appends or changes the public interface.

📚 Documentation

Please ensure that you properly document any additions in conformance to Spezi Documentation Guide.
You can use this section to describe your solution, but we encourage contributors to document your reasoning and changes using in-line documentation.

✅ Testing

Please ensure that the PR meets the testing requirements set by CodeCov and that new functionality is appropriately tested.
This section describes important information about the tests and why some elements might not be testable.

📝 Code of Conduct & Contributing Guidelines

By submitting creating this pull request, you agree to follow our Code of Conduct and Contributing Guidelines:

Copy link

codecov bot commented Sep 21, 2024

Codecov Report

Attention: Patch coverage is 86.60714% with 30 lines in your changes missing coverage. Please review.

Project coverage is 39.50%. Comparing base (0148cf3) to head (9da53d7).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...stanford/spezi/modules/storage/local/KeyStorage.kt 75.00% 3 Missing and 8 partials ⚠️
...zi/modules/storage/credential/CredentialStorage.kt 82.86% 4 Missing and 2 partials ⚠️
...anford/spezi/modules/storage/local/LocalStorage.kt 92.73% 1 Missing and 3 partials ⚠️
...d/spezi/modules/storage/key/KeyValueStorageImpl.kt 90.33% 1 Missing and 2 partials ⚠️
...ezi/modules/storage/key/InMemoryKeyValueStorage.kt 71.43% 2 Missing ⚠️
...i/core/bluetooth/domain/BLEPairedDevicesStorage.kt 75.00% 0 Missing and 1 partial ⚠️
...pezi/modules/storage/credential/CredentialTypes.kt 85.72% 1 Missing ⚠️
...stanford/spezi/modules/storage/di/StorageModule.kt 90.00% 1 Missing ⚠️
...d/spezi/modules/storage/key/KeyValueStorageType.kt 66.67% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##               main     #108      +/-   ##
============================================
+ Coverage     38.91%   39.50%   +0.60%     
+ Complexity      797      768      -29     
============================================
  Files           256      261       +5     
  Lines         10358    10388      +30     
  Branches       1442     1457      +15     
============================================
+ Hits           4030     4103      +73     
+ Misses         5946     5916      -30     
+ Partials        382      369      -13     
Flag Coverage Δ
uitests 33.45% <86.82%> (+2.65%) ⬆️
unittests 33.45% <75.00%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ord/spezi/modules/storage/credential/Credential.kt 100.00% <100.00%> (ø)
...pezi/modules/storage/key/KeyValueStorageFactory.kt 100.00% <100.00%> (ø)
...spezi/modules/storage/local/LocalStorageSetting.kt 100.00% <100.00%> (ø)
...i/core/bluetooth/domain/BLEPairedDevicesStorage.kt 98.42% <75.00%> (+1.23%) ⬆️
...pezi/modules/storage/credential/CredentialTypes.kt 85.72% <85.72%> (ø)
...stanford/spezi/modules/storage/di/StorageModule.kt 90.91% <90.00%> (+90.91%) ⬆️
...d/spezi/modules/storage/key/KeyValueStorageType.kt 66.67% <66.67%> (ø)
...ezi/modules/storage/key/InMemoryKeyValueStorage.kt 93.34% <71.43%> (-6.66%) ⬇️
...d/spezi/modules/storage/key/KeyValueStorageImpl.kt 90.33% <90.33%> (ø)
...anford/spezi/modules/storage/local/LocalStorage.kt 92.73% <92.73%> (ø)
... and 2 more

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0148cf3...9da53d7. Read the comment docs.

@pauljohanneskraft pauljohanneskraft self-assigned this Oct 3, 2024
@pauljohanneskraft pauljohanneskraft added the enhancement New feature or request label Oct 3, 2024
@pauljohanneskraft pauljohanneskraft marked this pull request as ready for review October 3, 2024 04:47
@pauljohanneskraft
Copy link
Contributor Author

Currently, Android uses a different encryption mechanism than iOS for the files, but otherwise it pretty much follows the existing interface from iOS (couldn't find an exact match fast). I left out some of the platform-specific features of iOS (accessGroups, userPresence check, secure enclave, etc), if you know about Android-specific features that should be integrated or could replace the equivalent(s) in iOS, let me know!

eldcn and others added 6 commits October 21, 2024 14:24
# SpeziStorage - Review and API proposals

## What was done

We have aligned with @pauljohanneskraft that I will bring my proposals
in the former PR #108 in a new PR.

- In previous PRs we already implemented `KeyValueStorage` which
provides an API to write encrypted data for primitive types in
[SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences).
This component now got customized to write in shared preferences in
encrypted and unencrypted way via
`KeyValueStorageFactory#create(fileName, KeyValueStorageType)`. Consumer
of the API have the opportunity to either use the default storages, or
create a custom one via the factory. Furthermore, since we were using
data store in the previous version of LocalKeyValueStorage, it got
removed now and all the functions of the key value storage are not
suspending anymore - This is safe as shared preferences caches all the
changes in memory first, and writes in the disc asynchronously.
- `SecureStorage` - 
<img width="738" alt="image"
src="https://github.com/user-attachments/assets/dfbb4573-16d1-40fa-ae69-1e1f012a7b4e">

- This component was breaking single responsibility principle in my
opinion. On one hand, it was providing methods to store, read, delete
and update `Credentials`, on the other hand was providing some methods
to create public and private keys from key store (key chain in iOS). Key
related methods however, were solely used in the context of
`LocalStorage` when using `LocalStorageSetting.EncryptedUsingKeyStore`
setting to store a data in a file.
- Removes key related from `SecureStorage` and solely provides CRUD
methods to it to handle Credentials. Furthermore, the api got extended
to retrieve all credentials of a user, and delete credentials per user
and per server separately. Under the hood, the `SecureStorage` uses an
encrypted `KeyValueStorage` that persists the encrypted json of
`Credentials` object.
- I would propose to rename this component to `CredentialsSecureStorage`
or `CredentialsStorage`, but it requires alignment with iOS
-
![image](https://github.com/user-attachments/assets/f517d380-2736-49b8-9a9d-e3b1973279fa)
- Introduces public component `AndroidKeyStore` which can be used to
create public/private key pairs which then can later on be used in the
context of `LocalStorageSetting.Encrypted(KeyPair)`
-
![image](https://github.com/user-attachments/assets/fe021ed8-af45-4e3b-a245-b69ff20f3aad)
- Each method of `SecureStorage` was requesting `server` as a separate
parameter, while it in my opinion belongs to the `Credentials` type - A
hint comes also from this [swiftlin
disable](https://github.com/StanfordSpezi/SpeziStorage/blob/main/Sources/SpeziSecureStorage/SecureStorage.swift#L310).
Hence, `Credentials` now receives a nullable server property as well.
- `SecureStorageItemType` was indicating three cases `KEY;
SERVER_CREDENTIALS; NON_SERVER_CREDENTIALS;`, however `KEY` was never
used in the context of `SecureStorage`. Furthermore, the storage is
offering a method to `deleteAllCredentials(SecureStorageItemType)`, if
`KEY` would be part of the types, we would be all the `PrivateKey` and
`PublicKey`s of the keystore, which is a side effect and a buggy
behaviour. I removed `KEY` from `SecureStorageItemType` which complies
semantically with `Credentials` type, which can either have a `server`
property or not (`null`).
- `LocalStorage` - Keeps similar API as iOS by using kotlin
serialization
-
![image](https://github.com/user-attachments/assets/df0cdbde-1ffa-413c-bdae-45cb8b559334)
- Every public component of the library is provides as an interface, and
the corresponding implementation as an internal component which is bound
by default in hilt graph in `StorageModule.kt`. `StorageModule` (hilt
module) serves at the same time also as the public api of the module
itself.
- All components have been tested
- A recording of the public API and generated files and their content:


https://github.com/user-attachments/assets/45bfad64-22b4-436f-976c-b136642b5395


## ⚙️ Release Notes 
*Add a bullet point list summary of the feature and possible migration
guides if this is a breaking change so this section can be added to the
release notes.*
*Include code snippets that provide examples of the feature implemented
or links to the documentation if it appends or changes the public
interface.*


## 📚 Documentation
*Please ensure that you properly document any additions in conformance
to [Spezi Documentation
Guide](https://github.com/StanfordSpezi/.github/blob/main/DOCUMENTATIONGUIDE.md).*
*You can use this section to describe your solution, but we encourage
contributors to document your reasoning and changes using in-line
documentation.*


## ✅ Testing
*Please ensure that the PR meets the testing requirements set by CodeCov
and that new functionality is appropriately tested.*
*This section describes important information about the tests and why
some elements might not be testable.*


## 📝 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):
- [ ] 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).

---------

Co-authored-by: Kilian Schneider <48420258+Basler182@users.noreply.github.com>
Co-authored-by: Paul Kraft <pauljohanneskraft@users.noreply.github.com>
Copy link
Contributor

@Basler182 Basler182 left a comment

Choose a reason for hiding this comment

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

from my point of view, everything looks great in terms of code. regarding api adaptation to iOS, you and eldi are deeper into it. thank you for the adjustments and the implementation of the feedback. good work @pauljohanneskraft & @eldcn

@pauljohanneskraft pauljohanneskraft merged commit 156f738 into main Oct 27, 2024
11 checks passed
@pauljohanneskraft pauljohanneskraft deleted the feature/spezi-storage branch October 27, 2024 19:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants